蓝牙模块--OTA升级

  蓝牙固件升级模块:OAT升级又称空中升级、DFU 升级,

这里使用的是Nordic Semiconductor公司开源提供的第三方升级库:https://github.com/NordicSemiconductor/Android-DFU-Library

官方的使用文档:https://github.com/NordicSemiconductor/Android-DFU-Library/blob/5c2d28e9db2ba28b3df67fd61d01a2ce1419fcf0/documentation/README.md

参考的其他博主的博客:https://www.jianshu.com/p/4017e7389804

OAT升级的流程:

1、使硬件设备进入DFU升级模式,进入升级模式的方式有很多,(每个项目可能都不一样,需要与硬件进行协商确定)

例如目前的项目:

         1.设置设备的Indication

 public boolean enableIndication(boolean enable) {


        BluetoothGattService RxService = mBluetoothGatt.getService(UUID.fromString("0000fe59-0000-1000-8000-00805f9b34fb"));
        if (RxService == null) {
            showMessage("Rx service not found!");
            broadcastUpdate(DEVICE_DOES_NOT_SUPPORT_UART);
        }
        BluetoothGattCharacteristic characteristic = RxService.getCharacteristic(UUID.fromString("8ec90003-f315-4f60-9fb8-838830daea50"));
        if (characteristic == null) {
            showMessage("Tx charateristic not found!");
            broadcastUpdate(DEVICE_DOES_NOT_SUPPORT_UART);
        }


        if (mBluetoothGatt == null || characteristic == null)
            return false;
        if (!mBluetoothGatt.setCharacteristicNotification(characteristic,
                enable))
            return false;
        BluetoothGattDescriptor clientConfig = characteristic
                .getDescriptor(UUID.fromString("00002902-0000-1000-8000-00805f9b34fb"));
        if (clientConfig == null)
            return false;

        if (enable) {
            clientConfig
                    .setValue(BluetoothGattDescriptor.ENABLE_INDICATION_VALUE);
        } else {
            clientConfig
                    .setValue(BluetoothGattDescriptor.DISABLE_NOTIFICATION_VALUE);
        }
        return mBluetoothGatt.writeDescriptor(clientConfig);
    }

           2.发送进入设备DFU模式的指令

  byte[] value = new byte[1];
  value[0] =0x01;
  mService.writeDFUCharacteristic(value);
    @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
    public void writeDFUCharacteristic(byte[] value)
    {
//        Log.e("蓝牙写入查看工作状态的命令", "写入的命令:" +value.toString());
        if (mBluetoothGatt == null) {
            showMessage("mBluetoothGatt null" + mBluetoothGatt);
            broadcastUpdate(DEVICE_DOES_NOT_SUPPORT_UART);
            return;
        }
        BluetoothGattService RxService = mBluetoothGatt.getService(UUID.fromString("0000fe59-0000-1000-8000-00805f9b34fb"));
        showMessage("mBluetoothGatt null"+ mBluetoothGatt);
        if (RxService == null) {
            showMessage("Rx service not found!");
            broadcastUpdate(DEVICE_DOES_NOT_SUPPORT_UART);
            return;
        }
        BluetoothGattCharacteristic RxChar = RxService.getCharacteristic(UUID.fromString("8ec90003-f315-4f60-9fb8-838830daea50"));
        if (RxChar == null) {
            showMessage("Rx charateristic not found!");
            broadcastUpdate(DEVICE_DOES_NOT_SUPPORT_UART);
            return;
        }
        RxChar.setValue(value);
        boolean status = mBluetoothGatt.writeCharacteristic(RxChar);

        Log.d(TAG, "write TXchar - status=" + status);
    }

2、重新扫描,获取DFU模式下的MAC地址

     重新进行扫描操作,因为当进入到DFU模式的时候,蓝牙的名称和MAC地址都会发生改变,获取DFU模式下的MAC地址。

3、使用Android-DFU-Library,发送升级包,进行DFU升级

     使用Android-DFU-Library的流程:

  1.      添加依赖
    implementation 'no.nordicsemi.android:dfu:1.10.3'
  2. 新建服务:DfuService ,并注册
    package com.gzp.smartclothing.page.equipment.service;
    
    import android.app.Activity;
    import android.app.Service;
    import android.content.Intent;
    import android.os.IBinder;
    
    import androidx.annotation.NonNull;
    import androidx.core.app.NotificationCompat;
    
    import com.gzp.smartclothing.BuildConfig;
    import com.gzp.smartclothing.page.equipment.view.NotificationActivity;
    
    import no.nordicsemi.android.dfu.DfuBaseService;
    
    public class DfuService extends DfuBaseService {
        @Override
        protected Class<? extends Activity> getNotificationTarget() {
            return NotificationActivity.class;
        }
        @Override
        protected boolean isDebug() {
            // Here return true if you want the service to print more logs in LogCat.
            // Library's BuildConfig in current version of Android Studio is always set to DEBUG=false, so
            // make sure you return true or your.app.BuildConfig.DEBUG here.
            return BuildConfig.DEBUG;
        }
    
        @Override
        protected void updateForegroundNotification(@NonNull final NotificationCompat.Builder builder) {
            // Customize the foreground service notification here.
        }
    }
    

     

  3. 通知Activity设置
    package com.gzp.smartclothing.page.equipment.view;
    
    import androidx.appcompat.app.AppCompatActivity;
    
    import android.content.Intent;
    import android.os.Bundle;
    
    /**
     * @author lk
     */
    public class NotificationActivity extends AppCompatActivity {
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            // If this activity is the root activity of the task, the app is not running
            if (isTaskRoot()) {
                // Start the app before finishing
                final Intent intent = new Intent(this, ProductSetUpActivity.class);
                intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                intent.putExtras(getIntent().getExtras()); // copy all extras
                startActivity(intent);
            }
            // Now finish, which will drop you to the activity at which you were at the top of the task stack
            finish();
        }
    }
    

     

  4. 在需要使用固件升级的Activity中创建一个 DfuProgressListener 并进行注册和反注册
     private final DfuProgressListener mDfuProgressListener = new DfuProgressListener() {
            @Override
            public void onDeviceConnecting(String deviceAddress) {
                Log.i("dfu", "onDeviceConnecting");
            }
    
            @Override
            public void onDeviceConnected(String deviceAddress) {
                Log.i("dfu", "onDeviceConnected");
            }
    
            @Override
            public void onDfuProcessStarting(String deviceAddress) {
                Log.i("dfu", "onDfuProcessStarting");
            }
    
            @Override
            public void onDfuProcessStarted(String deviceAddress) {
                Log.i("dfu", "onDfuProcessStarted");
            }
    
            @Override
            public void onEnablingDfuMode(String deviceAddress) {
                Log.i("dfu", "onEnablingDfuMode");
            }
    
            @Override
            public void onProgressChanged(String deviceAddress, int percent, float speed, float avgSpeed, int currentPart, int partsTotal) {
                Log.i("dfu", "onProgressChanged");
                Log.i("dfu", "onProgressChanged" + percent);
            }
    
            @Override
            public void onFirmwareValidating(String deviceAddress) {
                Log.i("dfu", "onFirmwareValidating");
            }
    
            @Override
            public void onDeviceDisconnecting(String deviceAddress) {
    
                Log.i("dfu", "onDeviceDisconnecting");
            }
    
            @Override
            public void onDeviceDisconnected(String deviceAddress) {
                Log.i("dfu", "onDeviceDisconnected");
                mState = UART_PROFILE_DISCONNECTED;
    
            }
    
            @Override
            public void onDfuCompleted(String deviceAddress) {
                Log.i("dfu", "onDfuCompleted");
                //升级成功,重新连接设备
                mSexualMuscleScanHandler.postDelayed(mSexualMuscleScanRunnable, 100);//延时100毫秒
            }
    
            @Override
            public void onDfuAborted(String deviceAddress) {
                Log.i("dfu", "onDfuAborted");
                //升级流产,失败
                Toast.makeText(mContext, "升级流产,失败", Toast.LENGTH_SHORT).show();
            }
    
            @Override
            public void onError(String deviceAddress, int error, int errorType, String message) {
                Log.i("dfu", "onError");
                Toast.makeText(mContext, "升级失败。", Toast.LENGTH_SHORT).show();
            }
        };
     @Override
        protected void onResume() {
            DfuServiceListenerHelper.registerProgressListener(this, mDfuProgressListener);
            super.onResume();
        }
     @Override
        protected void onPause() {
            DfuServiceListenerHelper.unregisterProgressListener(this, mDfuProgressListener);
            super.onPause();
        }

     

  5. 开启 DfuService 进行升级
    writeRXCharacteristicHandler = new Handler(Looper.getMainLooper());
                            writeRXCharacteristicHandler.postDelayed(new Runnable() {
                                @Override
                                public void run() {
                                    if (!curDfuTargMac.equals(dfuTargMac)){
                                        curDfuTargMac = dfuTargMac;
                                        new Thread(new Runnable() {
                                            @Override
                                            public void run() {
                                                DfuServiceInitiator  dfuServiceInitiator = new DfuServiceInitiator(curDfuTargMac);
                                                dfuServiceInitiator.createDfuNotificationChannel(ProductSetUpActivity.this);
                                                dfuServiceInitiator.setDisableNotification(false)
                                                        .setZip(R.raw.test_file)
                                                        .start((getBaseContext()), DfuService.class);
                                            }
                                        }).start();
                                    }
                                }
                            }, 1500);

     

  6. 坐等升级完成

         升级完成后,蓝牙会自动断开,若需使用,重新进行连接。

 

PS:在开启设备的Indication和进行升级操作的时候在可以的情况下,尽量的一些延迟(在升级的过程中会出现各种意外、升级失败、或者无法开启升级的情况)。

 

 

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
HC32F19是一款32位的ARM Cortex-M3内核微控制器,支持OTA(Over-The-Air)升级。下面是一个基本的OTA升级实现流程: 1. 确保HC32F19的固件具有OTA升级功能:OTA升级需要在固件中添加相关代码,以支持通过无线方式接收和更新固件。 2. 配置HC32F19的无线通信模块:根据你选择的通信方式(如Wi-Fi、蓝牙等),配置HC32F19的无线通信模块,使其能够与外部设备进行通信。 3. 设计OTA升级协议:为了实现OTA升级,你需要定义一个OTA升级协议,包括数据包的格式、传输方式、校验机制等。确保协议能够满足你的需求,并在固件中实现相应的解析和处理逻辑。 4. 实现固件端OTA升级逻辑:在固件中添加OTA升级的逻辑,包括接收和解析OTA数据包、校验数据的完整性和正确性、更新固件等。这部分代码需要根据你设计的OTA升级协议来实现。 5. 实现外部设备端OTA升级控制逻辑:在外部设备(如手机、电脑等)上实现OTA升级的控制逻辑,包括与HC32F19进行通信、发送OTA数据包、接收固件信息等。 6. 测试和验证:进行OTA升级功能的测试和验证,确保整个升级过程的稳定性和可靠性。 请注意,以上是一个基本的OTA升级实现流程,具体的实现细节和步骤可能会因具体的需求和硬件平台而有所不同。建议你参考HC32F19的开发文档和相关资料,以获取更详细的OTA升级实现指导。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值