小程序蓝牙通信例子
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

636 lines
16 KiB

  1. // pages/lanyatest/lanyatest.js
  2. var longUtil = require('./../../utils/long.js');
  3. Page({
  4. /**
  5. * 页面的初始数据
  6. */
  7. data: {
  8. info:"未初始化蓝牙适配器",
  9. deviceName:"yxwl01680000004895",
  10. connectedDeviceId:"",
  11. deviceId:"",
  12. services:"",
  13. mtuSize:512,
  14. servicesUUID:"000018f0-0000-1000-8000-00805f9b34fb",
  15. notifyUUID:"00002af0-0000-1000-8000-00805f9b34fb",
  16. writeUUID:"00002af1-0000-1000-8000-00805f9b34fb",
  17. serviceId:"",
  18. notifyCharacteristicsId:"",
  19. writeCharacteristicsId: "",
  20. userTelephone:"13028878230",
  21. userPassword:"130288",
  22. pwd:"12344321",
  23. openLockType:2,
  24. sendmsg:"8989415B017BC796C6F8001DA0B0AAB7AFABB1B6B9B1BAB7B0BE8989A9AB8BABBE80EEEEE2E2E6E6EFE4",
  25. systemInfo:{},
  26. },
  27. lanyatest1(event){
  28. var that = this;
  29. wx.getSystemInfo({
  30. success: function (res) {
  31. console.log(res.model)
  32. console.log(res.pixelRatio)
  33. console.log(res.windowWidth)
  34. console.log(res.windowHeight)
  35. console.log(res.language)
  36. console.log(res.version)
  37. console.log(res.platform)
  38. console.log(res.environment)
  39. that.setData({
  40. systemInfo:res
  41. });
  42. }
  43. })
  44. checkWechatVersion(that.data.systemInfo)
  45. wx.openBluetoothAdapter({
  46. success: function (res) {
  47. console.log('初始化蓝牙适配器成功')
  48. //页面日志显示
  49. that.setData({
  50. info: '初始化蓝牙适配器成功'
  51. })
  52. },
  53. fail: function (res) {
  54. console.log('请打开蓝牙和定位功能')
  55. that.setData({
  56. info: '请打开蓝牙和定位功能'
  57. })
  58. }
  59. })
  60. },
  61. lanyatest2(event){
  62. var that = this;
  63. wx.getBluetoothAdapterState({
  64. success: function (res) {
  65. //打印相关信息
  66. console.log(JSON.stringify(res.errMsg) + "\n蓝牙是否可用:" + res.available);
  67. that.setData({
  68. info: JSON.stringify(res.errMsg) +"\n蓝牙是否可用:" + res.available
  69. })
  70. },
  71. fail: function (res) {
  72. //打印相关信息
  73. console.log(JSON.stringify(res.errMsg) + "\n蓝牙是否可用:" + res.available);
  74. that.setData({
  75. info: JSON.stringify(res.errMsg) + "\n蓝牙是否可用:" + res.available
  76. })
  77. }
  78. })
  79. },
  80. lanyatest3(event){
  81. var that = this;
  82. wx.startBluetoothDevicesDiscovery({
  83. services: [that.data.servicesUUID], //如果填写了此UUID,那么只会搜索出含有这个UUID的设备
  84. success: function (res) {
  85. that.setData({
  86. info: "搜索设备" + JSON.stringify(res),
  87. })
  88. console.log('搜索设备返回' + JSON.stringify(res))
  89. }
  90. })
  91. },
  92. lanyatest4(event){
  93. var that = this;
  94. var pos;
  95. wx.getBluetoothDevices({
  96. success: function (res) {
  97. for (var i = 0; i < res.devices.length; i++) {
  98. pos = that.data.deviceName.indexOf(res.devices[i].name);
  99. if(pos != -1)
  100. {
  101. that.setData({
  102. connectedDeviceId: res.devices[i].deviceId
  103. })
  104. console.log('设备号:' + res.devices[i].name + " Mac地址: " + that.data.connectedDeviceId + " pos: " + pos + "\n")
  105. break;
  106. }
  107. }
  108. that.setData({
  109. info: "设备列表\n" + JSON.stringify(res.devices),
  110. devices: res.devices
  111. })
  112. console.log('搜设备数目:' + res.devices.length)
  113. console.log('设备信息:\n' + JSON.stringify(res.devices)+"\n")
  114. }
  115. })
  116. },
  117. lanyaconnect(event){
  118. var that = this;
  119. wx.createBLEConnection({
  120. deviceId: that.data.connectedDeviceId,
  121. success: function (res) {
  122. console.log('调试信息:' + res.errMsg);
  123. that.setData({
  124. info: "MAC地址:" + event.currentTarget.id + ' 调试信息:' + res.errMsg,
  125. })
  126. if (that.data.systemInfo.platform == 'android')
  127. {
  128. wx.setBLEMTU({
  129. deviceId: that.data.connectedDeviceId,
  130. mtu:that.data.mtuSize,
  131. success:(res)=>{
  132. console.log("setBLEMTU success >> " + JSON.stringify(res))
  133. },
  134. fail:(res)=>{
  135. console.log("setBLEMTU fail >> " + JSON.stringify(res))
  136. }
  137. })
  138. }
  139. },
  140. fail: function () {
  141. console.log("连接失败");
  142. },
  143. })
  144. },
  145. lanyatest6(event){
  146. var that = this;
  147. wx.stopBluetoothDevicesDiscovery({
  148. success: function (res) {
  149. console.log("停止搜索" + JSON.stringify(res.errMsg));
  150. that.setData({
  151. info: "停止搜索" + JSON.stringify(res.errMsg),
  152. })
  153. }
  154. })
  155. },
  156. lanyatest7(event){
  157. var that = this;
  158. wx.getBLEDeviceServices({
  159. // 这里的 deviceId 需要在上面的 getBluetoothDevices 或 onBluetoothDeviceFound 接口中获取
  160. deviceId: that.data.connectedDeviceId,
  161. success: function (res) {
  162. console.log('services UUID:\n', JSON.stringify(res.services));
  163. for (var i = 0; i < res.services.length; i++) {
  164. console.log("第"+(i+1) + "个UUID:" + res.services[i].uuid+"\n")
  165. }
  166. that.setData({
  167. services: res.services,
  168. info: JSON.stringify(res.services),
  169. })
  170. }
  171. })
  172. },
  173. lanyatest8(event){
  174. var that = this;
  175. var myUUID = toPlatformString(that.data.systemInfo, that.data.servicesUUID);//具有写、通知属性的服务uuid
  176. console.log(' UUID: ' + myUUID + " mac: " + that.data.connectedDeviceId)
  177. wx.getBLEDeviceCharacteristics({
  178. // 这里的 deviceId 需要在上面的接口中获取
  179. deviceId: that.data.connectedDeviceId,
  180. // 这里的 serviceId 需要在上面的 接口中获取
  181. serviceId: myUUID,
  182. success: function (res) {
  183. console.log("%c getBLEDeviceCharacteristics", "color:red;");
  184. for (var i = 0; i < res.characteristics.length; i++) {
  185. console.log('特征值:' + res.characteristics[i].uuid)
  186. if (res.characteristics[i].properties.notify) {
  187. console.log("notifyServicweId:", myUUID);
  188. console.log("notifyCharacteristicsId:", res.characteristics[i].uuid);
  189. that.setData({
  190. notifyServicweId: myUUID,
  191. notifyCharacteristicsId: that.data.notifyUUID,//手动设置notifyCharacteristicsId为这个UUID,为了方便写死在这里
  192. })
  193. }
  194. if (res.characteristics[i].properties.write) {
  195. console.log("writeServicweId:", myUUID);
  196. console.log("writeCharacteristicsId:", res.characteristics[i].uuid);
  197. that.setData({
  198. writeServicweId: myUUID,
  199. //writeCharacteristicsId: res.characteristics[i].uuid,
  200. writeCharacteristicsId: that.data.writeUUID,//手动设置writeCharacteristicsId为这个UUID,为了方便写死在这里
  201. })
  202. }
  203. }
  204. console.log('device getBLEDeviceCharacteristics:', res.characteristics);
  205. that.setData({
  206. msg: JSON.stringify(res.characteristics),
  207. })
  208. },
  209. fail: function () {
  210. console.log("fail");
  211. },
  212. })
  213. },
  214. lanyatest9(event){
  215. var that = this;
  216. var notifyServicweId = toPlatformString(that.data.systemInfo, that.data.servicesUUID); //具有写、通知属性的服务uuid
  217. var notifyCharacteristicsId = toPlatformString(that.data.systemInfo, that.data.notifyCharacteristicsId);
  218. console.log("启用notify的serviceId", notifyServicweId);
  219. console.log("启用notify的notifyCharacteristicsId", notifyCharacteristicsId);
  220. wx.notifyBLECharacteristicValueChange({
  221. state: true, // 启用 notify 功能
  222. deviceId: that.data.connectedDeviceId,
  223. // 这里的 serviceId 就是that.data.servicesUUID
  224. serviceId: notifyServicweId,
  225. characteristicId: notifyCharacteristicsId,
  226. success: function (res) {
  227. console.log('notifyBLECharacteristicValueChange success', res.errMsg)
  228. var msg = '启动notify:' + res.errMsg
  229. that.setData({
  230. info: msg
  231. })
  232. },
  233. fail: function () {
  234. console.log('启动notify:' + res.errMsg);
  235. },
  236. })
  237. },
  238. lanyatest10(event){
  239. var that = this;
  240. console.log("开始接收数据");
  241. wx.onBLECharacteristicValueChange(function (res) {
  242. console.log("characteristicId:" + res.characteristicId)
  243. console.log("serviceId: " + res.serviceId)
  244. console.log("deviceId: " + res.deviceId)
  245. console.log("Length: " + res.value.byteLength)
  246. console.log("hex value: " + ab2hex(res.value))
  247. that.setData({
  248. info: that.data.info + ab2hex(res.value)
  249. })
  250. })
  251. },
  252. lanyatest11(event){
  253. var that = this
  254. //var hex = that.data.sendmsg //要发送的信息
  255. var myUUID = toPlatformString(that.data.systemInfo, that.data.servicesUUID); //具有写、通知属性的服务uuid
  256. var writeCharId = toPlatformString(that.data.systemInfo, that.data.writeCharacteristicsId);
  257. //console.log('要发送的信息是:'+hex)
  258. //var typedArray1 = new Uint8Array(hex.match(/[\da-f]{2}/gi).map(function (h) {
  259. // return parseInt(h, 16)
  260. //}))
  261. //console.log(typedArray1)
  262. var typedArray = packData(that.data.userTelephone, that.data.userPassword, that.data.pwd, that.data.openLockType)
  263. console.log(typedArray)
  264. wx.writeBLECharacteristicValue({
  265. deviceId: that.data.connectedDeviceId,
  266. serviceId: myUUID,
  267. characteristicId: writeCharId,
  268. // 这里的value是ArrayBuffer类型
  269. value: typedArray.buffer,
  270. success: function (res) {
  271. console.log('写入成功', res.errMsg)
  272. },
  273. fail(res){
  274. console.log('写入失败', res.errMsg)
  275. }
  276. })
  277. },
  278. //获取输入框的数据
  279. getmsg(event){
  280. this.setData({
  281. sendmsg:event.detail.value
  282. })
  283. },
  284. lanyatest12(event){
  285. var that = this;
  286. wx.closeBLEConnection({
  287. deviceId: that.data.connectedDeviceId,
  288. success: function (res) {
  289. that.setData({
  290. connectedDeviceId: "",
  291. })
  292. console.log('断开蓝牙设备成功:' + res.errMsg)
  293. },
  294. fail:function(res){
  295. console.log('断开蓝牙设备失败:' + res.errMsg)
  296. }
  297. })
  298. },
  299. })
  300. function toPlatformString(systemInfo, str)
  301. {
  302. if (systemInfo.platform == 'android')
  303. return str.toLowerCase();
  304. else if (systemInfo.platform == 'ios')
  305. return str.toUpperCase();
  306. else
  307. return str;
  308. }
  309. /**
  310. * 版本比较
  311. */
  312. function versionCompare (ver1, ver2) { //版本比较
  313. // console.log("ver1" + ver1 + 'ver2' + ver2);
  314. var version1pre = parseFloat(ver1)
  315. var version2pre = parseFloat(ver2)
  316. var version1next = parseInt(ver1.replace(version1pre + ".", ""))
  317. var version2next = parseInt(ver2.replace(version2pre + ".", ""))
  318. if (version1pre > version2pre)
  319. return true
  320. else if (version1pre < version2pre)
  321. return false
  322. else {
  323. if (version1next > version2next)
  324. return true
  325. else
  326. return false
  327. }
  328. }
  329. /**
  330. * 微信版本检测
  331. * Android从微信 6.5.7 开始支持iOS从微信 6.5.6 开始支持
  332. */
  333. function checkWechatVersion(systemInfo) {
  334. if (systemInfo.platform == 'android' && versionCompare('6.5.7', systemInfo.version)) {
  335. wx.showModal({
  336. title: '提示',
  337. content: '当前微信版本过低,请更新至最新版本体验',
  338. showCancel: false
  339. })
  340. }else if (systemInfo.platform == 'ios' && versionCompare('6.5.6', systemInfo.version)) {
  341. wx.showModal({
  342. title: '提示',
  343. content: '当前微信版本过低,请更新至最新版本体验',
  344. showCancel: false
  345. })
  346. }
  347. }
  348. function Uint8ArrayToString(fileData){
  349. var dataString = "";
  350. for (var i = 0; i < fileData.length; i++) {
  351. dataString += String.fromCharCode(fileData[i]);
  352. }
  353. return dataString
  354. }
  355. // 微信官方给的ArrayBuffer转十六进制示例
  356. function ab2hex(buffer) {
  357. var hexArr = Array.prototype.map.call(
  358. new Uint8Array(buffer),
  359. function (bit) {
  360. return ('00' + bit.toString(16)).slice(-2)
  361. }
  362. )
  363. return hexArr.join(',');
  364. }
  365. //转成可展会的文字
  366. function hexCharCodeToStr(hexCharCodeStr) {
  367. var trimedStr = hexCharCodeStr.trim();
  368. var rawStr = trimedStr.substr(0, 2).toLowerCase() === '0x' ? trimedStr.substr(2) : trimedStr;
  369. var len = rawStr.length;
  370. var curCharCode;
  371. var resultStr = [];
  372. for (var i = 0; i < len; i = i + 2) {
  373. curCharCode = parseInt(rawStr.substr(i, 2), 16);
  374. resultStr.push(String.fromCharCode(curCharCode));
  375. }
  376. return resultStr.join('');
  377. }
  378. //转换成需要的格式
  379. function buf2string(buffer) {
  380. var arr = Array.prototype.map.call(new Uint8Array(buffer), x => x)
  381. return arr.map((char, i) => {
  382. return String.fromCharCode(char);
  383. }).join('');
  384. }
  385. function stringToUint8Array(str){
  386. let arr = [];
  387. for (let i = 0, j = str.length; i < j; ++i) {
  388. arr.push(str.charCodeAt(i));
  389. }
  390. let tmpUint8Array = new Uint8Array(arr);
  391. return tmpUint8Array
  392. }
  393. function decodeHexNibble(c) {
  394. if (c >= 48 && c <= 57) {
  395. return c - 48;
  396. } else if (c >= 65 && c <= 70) {
  397. return c - 65 + 10;
  398. } else {
  399. return c >= 97 && c <= 102 ? c - 97 + 10 : -1;
  400. }
  401. }
  402. function decodeHexByte(s, pos) {
  403. let hi = decodeHexNibble(s.charCodeAt(pos));
  404. let lo = decodeHexNibble(s.charCodeAt(pos + 1));
  405. return ((hi << 4) + lo);
  406. }
  407. function hexStringToBytesWithPadding(str, byteLen, padding) {
  408. let len = str.length
  409. let length = 2 * byteLen
  410. if (length >= len && (length & 1) == 0) {
  411. if (length == 0) {
  412. return [0];
  413. } else {
  414. //let buffer = new ArrayBuffer(length >>> 1);
  415. //let bytes = new Uint8Array(buffer);
  416. let bytes = new Uint8Array(length >>> 1);
  417. for(let i = 0; i < len; i += 2) {
  418. bytes[i >>> 1] = decodeHexByte(str, i);
  419. }
  420. for(let i = 0; i < byteLen-len/2; i++)
  421. bytes[len/2+i] = padding;
  422. return bytes;
  423. }
  424. }
  425. else
  426. return [0];
  427. }
  428. function hexStringToBytes(str) {
  429. let s = str;
  430. if(s.length < 12)
  431. {
  432. let tmp = 12-s.length
  433. for(let i = 0; i< tmp; i++)
  434. s = "0" + s;
  435. }
  436. else
  437. s = str.substr(s.length-12, s.length);
  438. let start = 0
  439. let length = s.length
  440. if (length >= 0 && (length & 1) == 0) {
  441. if (length == 0) {
  442. return new byte[0];
  443. } else {
  444. let bytes = new Uint8Array(length >>> 1);
  445. for(let i = 0; i < length; i += 2) {
  446. bytes[i >>> 1] = decodeHexByte(s, start + i);
  447. }
  448. return bytes;
  449. }
  450. }
  451. else
  452. return [0];
  453. }
  454. function packData(userTelephone, userPassword, pwd, openLockType)
  455. {
  456. let cmd = 0x41
  457. let ut = stringToUint8Array(userTelephone)
  458. let up = stringToUint8Array(userPassword)
  459. let p = hexStringToBytesWithPadding(pwd, 10, 0xff)
  460. let length = 1+11+6+10+1
  461. let b = new Uint8Array(length)
  462. b[0] = cmd
  463. b.set(ut, 1)
  464. b.set(up, 12)
  465. b.set(p, 18)
  466. b[28] = openLockType
  467. console.log(b)
  468. return packMsg(0x41, b, length)
  469. }
  470. function packMsg(cmd, data, payloadLength)
  471. {
  472. let length = 13 + payloadLength
  473. //let buffer = new ArrayBuffer(length);
  474. let b = new Uint8Array(length);
  475. b[0] = 0x89;
  476. b[1] = 0x89;
  477. b[2] = cmd;
  478. let timestamp = new Date().getTime();
  479. let ts = timestamp.toString(16)
  480. let t = hexStringToBytes(ts)
  481. b.set(t, 4)
  482. b[3] = b[9];
  483. b[10] = (payloadLength>>8)&0xff;
  484. b[11] = payloadLength & 0xff;
  485. let key = b[3];
  486. for (let i=0; i<payloadLength; i++) {
  487. data[i] -= (payloadLength - i) ^ key;
  488. data[i] = (data[i] ^ (key ^ i));
  489. }
  490. b.set(data, 12)
  491. let xor = b[0];
  492. for (let i=1; i<length-1; i++)
  493. xor ^= b[i];
  494. b[length-1] = xor;
  495. return b;
  496. }