蓝牙模块--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
    评论
微信小程序的OTA(Over-the-Air)升级是指通过网络将小程序的更新包传输到用户的设备上进行升级。下面是一个简单的步骤来实现微信小程序的OTA升级: 1. 在小程序的后台管理系统中创建一个OTA管理页面,用于上传和管理小程序的更新包。 2. 在小程序端,创建一个检测更新的方法。可以使用wx.getUpdateManager()方法获取更新管理器实例,在onCheckForUpdate回调中进行判断是否有新版本。 3. 如果有新版本,可以使用wx.showModal()提示用户是否要进行更新。 4. 用户确认更新后,调用更新管理器实例的onUpdateReady回调函数,提示用户重启应用程序。 5. 在小程序的app.json文件中配置"usingComponents"字段,将OTA管理页面注册为一个组件。 6. 在小程序的页面中使用该组件,显示OTA管理页面并提供上传更新包的功能。可以使用wx.uploadFile()方法将更新包上传到服务器。 7. 服务器接收到更新包后,将其保存到指定位置。 8. 在OTA管理页面中,提供查看已上传更新包和选择发布的功能。可以使用wx.request()方法向服务器发送请求,获取已上传的更新包列表。 9. 用户选择要发布的更新包后,可以使用wx.request()方法向服务器发送请求,触发更新流程。 10. 服务器将选择的更新包发送给对应的用户设备。可以使用WebSocket等技术实现实时传输。 11. 设备接收到更新包后,使用wx.getUpdateManager()方法进行更新。 以上是一个简单的微信小程序OTA升级的实现步骤,具体的实现细节还需要根据具体需求进行调整。希望能对你有所帮助!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值