微信小程序蓝牙通讯蓝牙模块demo

开发微信小程序蓝牙的项目,第一次搞,遇到2个坑:

1.安卓和苹果获取的硬件服务UUID顺序不同

2.目前用的这一版 “启用低功耗蓝牙设备特征值变化时的 notify 功能”在安卓和苹果的测试机上都返回启动失败,其实是已经启动成功,在我同事安卓手机上返回的正常。

index.wxml

[html]  view plain  copy
  1. <!--index.wxml-->  
  2. <view class="content">  
  3.   <text class="status">适配器状态:{{ status }}</text>  
  4.   <text class="sousuo">是否搜索:{{ sousuo }}</text>  
  5.   <text class="msg">消息:{{ msg }} </text>  
  6.   <text class="msg1">消息:{{ msg1 }}</text>  
  7.   <button type="primary" class="button" bindtap="lanya1">1初始化蓝牙适配器</button>  
  8.   <button type="primary" class="button" bindtap="lanya2">2本机蓝牙适配状态</button>  
  9.   <button type="primary" class="button" bindtap="lanya3">3搜索周边设备</button>  
  10.   <button type="primary" class="button" bindtap="lanya4">4获取设备后在列表中连接</button>  
  11.   <button type="primary" class="button" bindtap="lanya5">5停止搜索周边设备</button>  
  12.   <button type="primary" class="button" bindtap="lanya6">6获取连接设备所有service</button>  
  13.   <button type="primary" class="button" bindtap="lanya7">7获取连接设备所有特征值</button>  
  14.   <button type="primary" class="button" bindtap="lanya8">8发送指定消息</button>  
  15.   <button type="primary" class="button" bindtap="lanya9">9启用设备特征值变化时的notify</button>  
  16.   <button type="primary" class="button" bindtap="lanya10">10接收消息</button>  
  17.   <view class="section">  
  18.     <text class="status">接收到消息:{{ jieshou }}</text>  
  19.   
  20.   </view>  
  21.   
  22.   <button type="primary" class="button" bindtap="lanya0">0断开蓝牙连接</button>  
  23. </view>  
  24. <view class="venues_list">  
  25.   <block wx:for="{{devices}}" wx:key="{{test}}">  
  26.     <view class="venues_item">  
  27.       <text class="status">设备名称:{{item.name}}</text>  
  28.       <text class="status">设备ID:{{item.deviceId}}</text>  
  29.       <text class="status">连接状态:{{connectedDeviceId == item.deviceId?"已连接":"未连接"}}</text>  
  30.       <view class="section">  
  31.       </view>  
  32.       <view class="section">  
  33.         <button type="warn" class="button" id="{{item.deviceId}}" bindtap="connectTO">连接</button>  
  34.       </view>  
  35.     </view>  
  36.   </block>  
  37. </view>  

index.js

[javascript]  view plain  copy
  1. //index.js  
  2. //获取应用实例  
  3. var app = getApp();  
  4. Page({  
  5.     data: {  
  6.         status: "",  
  7.         sousuo: "",  
  8.         connectedDeviceId: ""//已连接设备uuid  
  9.         services: ""// 连接设备的服务  
  10.         characteristics: "",   // 连接设备的状态值  
  11.         writeServicweId: ""// 可写服务uuid  
  12.         writeCharacteristicsId: "",//可写特征值uuid  
  13.         readServicweId: ""// 可读服务uuid  
  14.         readCharacteristicsId: "",//可读特征值uuid  
  15.         notifyServicweId: ""//通知服务UUid  
  16.         notifyCharacteristicsId: ""//通知特征值UUID  
  17.         inputValue: "",  
  18.         characteristics1: ""// 连接设备的状态值  
  19.     },  
  20.     onLoad: function () {  
  21.         if (wx.openBluetoothAdapter) {  
  22.             wx.openBluetoothAdapter()  
  23.         } else {  
  24.             // 如果希望用户在最新版本的客户端上体验您的小程序,可以这样子提示  
  25.             wx.showModal({  
  26.                 title: '提示',  
  27.                 content: '当前微信版本过低,无法使用该功能,请升级到最新微信版本后重试。'  
  28.             })  
  29.         }  
  30.   
  31.     },  
  32.     // 初始化蓝牙适配器  
  33.     lanya1: function () {  
  34.         var that = this;  
  35.         wx.openBluetoothAdapter({  
  36.             success: function (res) {  
  37.                 that.setData({  
  38.                     msg: "初始化蓝牙适配器成功!" + JSON.stringify(res),  
  39.                 })  
  40.                 //监听蓝牙适配器状态  
  41.                 wx.onBluetoothAdapterStateChange(function (res) {  
  42.                     that.setData({  
  43.                         sousuo: res.discovering ? "在搜索。" : "未搜索。",  
  44.                         status: res.available ? "可用。" : "不可用。",  
  45.                     })  
  46.                 })  
  47.             }  
  48.         })  
  49.     },  
  50.     // 本机蓝牙适配器状态  
  51.     lanya2: function () {  
  52.         var that = this;  
  53.         wx.getBluetoothAdapterState({  
  54.             success: function (res) {  
  55.                 that.setData({  
  56.                     msg: "本机蓝牙适配器状态" + "/" + JSON.stringify(res.errMsg),  
  57.                     sousuo: res.discovering ? "在搜索。" : "未搜索。",  
  58.                     status: res.available ? "可用。" : "不可用。",  
  59.                 })  
  60.                 //监听蓝牙适配器状态  
  61.                 wx.onBluetoothAdapterStateChange(function (res) {  
  62.                     that.setData({  
  63.                         sousuo: res.discovering ? "在搜索。" : "未搜索。",  
  64.                         status: res.available ? "可用。" : "不可用。",  
  65.                     })  
  66.                 })  
  67.             }  
  68.         })  
  69.     },  
  70.     //搜索设备  
  71.     lanya3: function () {  
  72.         var that = this;  
  73.         wx.startBluetoothDevicesDiscovery({  
  74.             success: function (res) {  
  75.                 that.setData({  
  76.                     msg: "搜索设备" + JSON.stringify(res),  
  77.                 })  
  78.                 //监听蓝牙适配器状态  
  79.                 wx.onBluetoothAdapterStateChange(function (res) {  
  80.                     that.setData({  
  81.                         sousuo: res.discovering ? "在搜索。" : "未搜索。",  
  82.                         status: res.available ? "可用。" : "不可用。",  
  83.                     })  
  84.                 })  
  85.             }  
  86.         })  
  87.     },  
  88.     // 获取所有已发现的设备  
  89.     lanya4: function () {  
  90.         var that = this;  
  91.         wx.getBluetoothDevices({  
  92.             success: function (res) {  
  93.                 //是否有已连接设备  
  94.                 wx.getConnectedBluetoothDevices({  
  95.                     success: function (res) {  
  96.                         console.log(JSON.stringify(res.devices));  
  97.                         that.setData({  
  98.                             connectedDeviceId: res.deviceId  
  99.                         })  
  100.                     }  
  101.                 })  
  102.   
  103.                 that.setData({  
  104.                     msg: "搜索设备" + JSON.stringify(res.devices),  
  105.                     devices: res.devices,  
  106.                 })  
  107.                 //监听蓝牙适配器状态  
  108.                 wx.onBluetoothAdapterStateChange(function (res) {  
  109.                     that.setData({  
  110.                         sousuo: res.discovering ? "在搜索。" : "未搜索。",  
  111.                         status: res.available ? "可用。" : "不可用。",  
  112.                     })  
  113.                 })  
  114.             }  
  115.         })  
  116.     },  
  117.     //停止搜索周边设备  
  118.     lanya5: function () {  
  119.         var that = this;  
  120.         wx.stopBluetoothDevicesDiscovery({  
  121.             success: function (res) {  
  122.                 that.setData({  
  123.                     msg: "停止搜索周边设备" + "/" + JSON.stringify(res.errMsg),  
  124.                     sousuo: res.discovering ? "在搜索。" : "未搜索。",  
  125.                     status: res.available ? "可用。" : "不可用。",  
  126.                 })  
  127.             }  
  128.         })  
  129.     },  
  130.     //连接设备  
  131.     connectTO: function (e) {  
  132.         var that = this;  
  133.         wx.createBLEConnection({  
  134.             deviceId: e.currentTarget.id,  
  135.             success: function (res) {  
  136.                 console.log(res.errMsg);  
  137.                 that.setData({  
  138.                     connectedDeviceId: e.currentTarget.id,  
  139.                     msg: "已连接" + e.currentTarget.id,  
  140.                     msg1: "",  
  141.                 })  
  142.             },  
  143.             fail: function () {  
  144.                 console.log("调用失败");  
  145.             },  
  146.             complete: function () {  
  147.                 console.log("调用结束");  
  148.             }  
  149.   
  150.         })  
  151.         console.log(that.data.connectedDeviceId);  
  152.     },  
  153.     // 获取连接设备的service服务  
  154.     lanya6: function () {  
  155.         var that = this;  
  156.         wx.getBLEDeviceServices({  
  157.             // 这里的 deviceId 需要在上面的 getBluetoothDevices 或 onBluetoothDeviceFound 接口中获取  
  158.             deviceId: that.data.connectedDeviceId,  
  159.             success: function (res) {  
  160.                 console.log('device services:', JSON.stringify(res.services));  
  161.                 that.setData({  
  162.                     services: res.services,  
  163.                     msg: JSON.stringify(res.services),  
  164.                 })  
  165.             }  
  166.         })  
  167.     },  
  168.     //获取连接设备的所有特征值  for循环获取不到值  
  169.     lanya7: function () {  
  170.         var that = this;  
  171.         wx.getBLEDeviceCharacteristics({  
  172.             // 这里的 deviceId 需要在上面的 getBluetoothDevices 或 onBluetoothDeviceFound 接口中获取  
  173.             deviceId: that.data.connectedDeviceId,  
  174.             // 这里的 serviceId 需要在上面的 getBLEDeviceServices 接口中获取  
  175.             serviceId: that.data.services[0].uuid,  
  176.             success: function (res) {  
  177.                 for (var i = 0; i < res.characteristics.length; i++) {  
  178.                     if (res.characteristics[i].properties.notify) {  
  179.                         console.log("11111111", that.data.services[0].uuid);  
  180.                         console.log("22222222222222222", res.characteristics[i].uuid);  
  181.                         that.setData({  
  182.                             notifyServicweId: that.data.services[0].uuid,  
  183.                             notifyCharacteristicsId: res.characteristics[i].uuid,  
  184.                         })  
  185.                     }  
  186.                     if (res.characteristics[i].properties.write) {  
  187.                         that.setData({  
  188.                             writeServicweId: that.data.services[0].uuid,  
  189.                             writeCharacteristicsId: res.characteristics[i].uuid,  
  190.                         })  
  191.   
  192.                     } else if (res.characteristics[i].properties.read) {  
  193.                         that.setData({  
  194.                             readServicweId: that.data.services[0].uuid,  
  195.                             readCharacteristicsId: res.characteristics[i].uuid,  
  196.                         })  
  197.   
  198.                     }  
  199.                 }  
  200.                 console.log('device getBLEDeviceCharacteristics:', res.characteristics);  
  201.   
  202.                 that.setData({  
  203.                     msg: JSON.stringify(res.characteristics),  
  204.                 })  
  205.             },  
  206.             fail: function () {  
  207.                 console.log("fail");  
  208.             },  
  209.             complete: function () {  
  210.                 console.log("complete");  
  211.             }  
  212.         })  
  213.   
  214.         wx.getBLEDeviceCharacteristics({  
  215.             // 这里的 deviceId 需要在上面的 getBluetoothDevices 或 onBluetoothDeviceFound 接口中获取  
  216.             deviceId: that.data.connectedDeviceId,  
  217.             // 这里的 serviceId 需要在上面的 getBLEDeviceServices 接口中获取  
  218.             serviceId: that.data.services[1].uuid,  
  219.             success: function (res) {  
  220.                 for (var i = 0; i < res.characteristics.length; i++) {  
  221.                     if (res.characteristics[i].properties.notify) {  
  222.                         that.setData({  
  223.                             notifyServicweId: that.data.services[1].uuid,  
  224.                             notifyCharacteristicsId: res.characteristics[i].uuid,  
  225.                         })  
  226.                     }  
  227.                     if (res.characteristics[i].properties.write) {  
  228.                         that.setData({  
  229.                             writeServicweId: that.data.services[1].uuid,  
  230.                             writeCharacteristicsId: res.characteristics[i].uuid,  
  231.                         })  
  232.   
  233.                     } else if (res.characteristics[i].properties.read) {  
  234.                         that.setData({  
  235.                             readServicweId: that.data.services[1].uuid,  
  236.                             readCharacteristicsId: res.characteristics[i].uuid,  
  237.                         })  
  238.   
  239.                     }  
  240.                 }  
  241.                 console.log('device getBLEDeviceCharacteristics1:', res.characteristics);  
  242.   
  243.                 that.setData({  
  244.                     msg1: JSON.stringify(res.characteristics),  
  245.                 })  
  246.             },  
  247.             fail: function () {  
  248.                 console.log("fail1");  
  249.             },  
  250.             complete: function () {  
  251.                 console.log("complete1");  
  252.             }  
  253.         })  
  254.     },  
  255.     //断开设备连接  
  256.     lanya0: function () {  
  257.         var that = this;  
  258.         wx.closeBLEConnection({  
  259.             deviceId: that.data.connectedDeviceId,  
  260.             success: function (res) {  
  261.                 that.setData({  
  262.                     connectedDeviceId: "",  
  263.                 })  
  264.             }  
  265.         })  
  266.     },  
  267.     //监听input表单  
  268.     inputTextchange: function (e) {  
  269.         this.setData({  
  270.             inputValue: e.detail.value  
  271.         })  
  272.     },  
  273.     //发送  
  274.     lanya8: function () {  
  275.         var that = this;  
  276.         // 这里的回调可以获取到 write 导致的特征值改变  
  277.         wx.onBLECharacteristicValueChange(function (characteristic) {  
  278.             console.log('characteristic value changed:1', characteristic)  
  279.         })  
  280.         var buf = new ArrayBuffer(16)  
  281.         var dataView = new DataView(buf)  
  282.         wx.request({  
  283.             url: **/getEncrypt',  
  284.             success: function (data) {  
  285.                 var arr = data.data.data.split(",");  
  286.                 console.log(arr);  
  287.                 for (var i = 0; i < arr.length; i++) {  
  288.                     dataView.setInt8(i, arr[i]);  
  289.                 }  
  290.                 console.log('str', buf);  
  291.                 console.log("writeServicweId", that.data.writeServicweId);  
  292.                 console.log("writeCharacteristicsId", that.data.writeCharacteristicsId);  
  293.                 wx.writeBLECharacteristicValue({  
  294.                     // 这里的 deviceId 需要在上面的 getBluetoothDevices 或 onBluetoothDeviceFound 接口中获取  
  295.                     deviceId: that.data.connectedDeviceId,  
  296.                     // 这里的 serviceId 需要在上面的 getBLEDeviceServices 接口中获取  
  297.                     serviceId: that.data.writeServicweId,  
  298.                     // 这里的 characteristicId 需要在上面的 getBLEDeviceCharacteristics 接口中获取  
  299.                     characteristicId: that.data.writeCharacteristicsId,  
  300.                     // 这里的value是ArrayBuffer类型  
  301.                     value: buf,  
  302.                     success: function (res) {  
  303.                         console.log('writeBLECharacteristicValue success', res.errMsg)  
  304.                     }  
  305.                 })  
  306.             }  
  307.         })  
  308.   
  309.     },  
  310.     //启用低功耗蓝牙设备特征值变化时的 notify 功能  
  311.     lanya9: function () {  
  312.         var that = this;  
  313.         //var notifyServicweId = that.data.notifyServicweId.toUpperCase();  
  314.         //var notifyCharacteristicsId = that.data.notifyCharacteristicsId.toUpperCase();  
  315.         //console.log("11111111", notifyServicweId);  
  316.         //console.log("22222222222222222", notifyCharacteristicsId);  
  317.         wx.notifyBLECharacteristicValueChange({  
  318.             state: true// 启用 notify 功能  
  319.             // 这里的 deviceId 需要在上面的 getBluetoothDevices 或 onBluetoothDeviceFound 接口中获取  
  320.             deviceId: that.data.connectedDeviceId,  
  321.             // 这里的 serviceId 需要在上面的 getBLEDeviceServices 接口中获取  
  322.             serviceId: that.data.notifyServicweId,  
  323.             // 这里的 characteristicId 需要在上面的 getBLEDeviceCharacteristics 接口中获取  
  324.             characteristicId: that.data.notifyCharacteristicsId,  
  325.             success: function (res) {  
  326.                 console.log('notifyBLECharacteristicValueChange success', res.errMsg)  
  327.             },  
  328.             fail: function () {  
  329.                 console.log('shibai');  
  330.                 console.log(that.data.notifyServicweId);  
  331.                 console.log(that.data.notifyCharacteristicsId);  
  332.             },  
  333.         })  
  334.     },  
  335.     //接收消息  
  336.     lanya10: function () {  
  337.         var that = this;  
  338.         // 必须在这里的回调才能获取  
  339.         wx.onBLECharacteristicValueChange(function (characteristic) {  
  340.             let hex = Array.prototype.map.call(new Uint8Array(characteristic.value), x => ('00' + x.toString(16)).slice(-2)).join('');  
  341.             console.log(hex)  
  342.             wx.request({  
  343.                 url: '***/getDecrypt',  
  344.                 data: {hexString:hex},  
  345.                 method:"POST",  
  346.                 header: {  
  347.                     'content-type''application/x-www-form-urlencoded'  
  348.                 },  
  349.                 success:function(data){  
  350.                     //console.log(data)  
  351.                     var res = data.data.data;  
  352.                     that.setData({  
  353.                         jieshou: res,  
  354.                     })  
  355.                 }  
  356.             })  
  357.         })  
  358.         console.log(that.data.readServicweId);  
  359.         console.log(that.data.readCharacteristicsId);  
  360.         wx.readBLECharacteristicValue({  
  361.             // 这里的 deviceId 需要在上面的 getBluetoothDevices 或 onBluetoothDeviceFound 接口中获取  
  362.             deviceId: that.data.connectedDeviceId,  
  363.             // 这里的 serviceId 需要在上面的 getBLEDeviceServices 接口中获取  
  364.             serviceId: that.data.readServicweId,  
  365.             // 这里的 characteristicId 需要在上面的 getBLEDeviceCharacteristics 接口中获取  
  366.             characteristicId: that.data.readCharacteristicsId,  
  367.             success: function (res) {  
  368.                 console.log('readBLECharacteristicValue:', res.errMsg);  
  369.             }  
  370.         })  
  371.     },  
  372.   
  373.   
  374.   
  375. })  
index.wxss

[css]  view plain  copy
  1. .content {  
  2.   margin0 10px;  
  3. }  
  4.   
  5. .status, .sousuo, .msg, .msg1 {  
  6.   displayblock;  
  7.   line-height35px;  
  8.   margin0 10px;  
  9. }  
  10.   
  11. .button {  
  12.   margin10px;  
  13. }  
  14.   
  15. .sendto {  
  16.   line-height30px;  
  17.   displayblock;  
  18.   margin10px;  
  19. }  

在服务器端做的蓝牙加解密

[java]  view plain  copy
  1. /** 
  2.      * 微信蓝牙加密接口 
  3.      */  
  4.     public void getEncrypt(){  
  5.         byte[] bs = new byte[]{25,1,49};  
  6.         String string = null;  
  7.         try {  
  8.             string = AesEntryDetry.encrypt(bs);  
  9.         } catch (Exception e) {  
  10.             logger.info("加密错误");  
  11.         }  
  12.         if(string != null){  
  13.             setAttr("msg""加密成功!");  
  14.             setAttr("code""200");  
  15.             setAttr("data", string);  
  16.         }else{  
  17.             setAttr("msg""加密失败!");  
  18.             setAttr("code""400");  
  19.         }  
  20.         renderJson();  
  21.     }  
  22.       
  23.     /** 
  24.      * 微信蓝牙解密接口 
  25.      */  
  26.     public void getDecrypt(){  
  27.         String hexString = getPara("hexString");  
  28.         byte[] bs = AesEntryDetry.hex2Bytes(hexString);  
  29.         String resString = null;  
  30.         try {  
  31.             resString = AesEntryDetry.decrypt(bs);  
  32.         } catch (Exception e) {  
  33.             logger.info("解密错误");  
  34.         }  
  35.         if(resString != null){  
  36.             setAttr("msg""加密成功!");  
  37.             setAttr("code""200");  
  38.             setAttr("data", resString);  
  39.         }else{  
  40.             setAttr("msg""加密失败!");  
  41.             setAttr("code""400");  
  42.         }  
  43.         renderJson();  
  44.     }  

[java]  view plain  copy
  1.   
[java]  view plain  copy
  1. import java.util.Arrays;  
  2. import javax.crypto.Cipher;  
  3. import javax.crypto.spec.SecretKeySpec;  
[java]  view plain  copy
  1. public class AesEntryDetry {  
  2.     // 加密秘钥 ,16个字节也就是128 bit  
  3.     private static final byte[] AES_KEY = { 需要和硬件统一 };  
  4.     // 加密方法  
  5.     public static String encrypt(byte[] bs) throws Exception {  
  6.         SecretKeySpec skeySpec = new SecretKeySpec(AES_KEY, "AES");  
  7.         Cipher cipher = Cipher.getInstance("AES/ECB/NoPadding");  
  8.         cipher.init(Cipher.ENCRYPT_MODE, skeySpec);  
  9.         if(bs.length < 16){  
  10.             bs = Arrays.copyOf(bs, 16);  
  11.         }  
  12.         byte[] encrypted = cipher.doFinal(bs);  
  13.         return BytetohexString(encrypted);  
  14.     }  
  15.     // 解密方法  
  16.     public static String decrypt(byte[] bs)throws Exception {  
  17.         SecretKeySpec skeySpec = new SecretKeySpec(AES_KEY, "AES");  
  18.         Cipher cipher = Cipher.getInstance("AES/ECB/NoPadding");  
  19.         cipher.init(Cipher.DECRYPT_MODE, skeySpec);  
  20.         byte[] decrypted = cipher.doFinal(bs);  
  21.         return BytetohexString(decrypted);  
  22.     }  
  23.     // 字节数组按照一定格式转换拼装成字符串  
  24.     private static String BytetohexString(byte[] b) {  
  25.         int len = b.length;  
  26.         StringBuffer sb = new StringBuffer();  
  27.         for (int i = 0; i < len; i++) {  
  28.             if (i < len - 1){  
  29.                 sb.append(b[i]);  
  30.                 sb.append(",");  
  31.             }else{  
  32.                 sb.append(b[i]);  
  33.             }  
  34.         }  
  35.         return sb.toString();  
  36.     }  
  37.       
  38.     public static byte[] hex2Bytes(String src){    
  39.         byte[] res = new byte[src.length()/2];    
  40.         char[] chs = src.toCharArray();    
  41.         int[] b = new int[2];    
  42.     
  43.         for(int i=0,c=0; i<chs.length; i+=2,c++){                
  44.             for(int j=0; j<2; j++){    
  45.                 if(chs[i+j]>='0' && chs[i+j]<='9'){    
  46.                     b[j] = (chs[i+j]-'0');    
  47.                 }else if(chs[i+j]>='A' && chs[i+j]<='F'){    
  48.                     b[j] = (chs[i+j]-'A'+10);    
  49.                 }else if(chs[i+j]>='a' && chs[i+j]<='f'){    
  50.                     b[j] = (chs[i+j]-'a'+10);    
  51.                 }    
  52.             }  
  53.             b[0] = (b[0]&0x0f)<<4;    
  54.             b[1] = (b[1]&0x0f);    
  55.             res[c] = (byte) (b[0] | b[1]);    
  56.         }    
  57.         return res;    
  58.     }   
  59. }  

猜你喜欢

转载自blog.csdn.net/HY_358116732/article/details/80386230