随手精灵小程序,单独为了获取WIFI信息加强围栏告警功能能力
Nie możesz wybrać więcej, niż 25 tematów Tematy muszą się zaczynać od litery lub cyfry, mogą zawierać myślniki ('-') i mogą mieć do 35 znaków.

643 lines
20KB

  1. // 示例demo
  2. const plugin = requirePlugin('ppScale-plugin');
  3. import {
  4. CommandButtonList
  5. } from '../../model/index'
  6. let app = getApp();
  7. Page({
  8. data: {
  9. // 选择的设备对象
  10. selmac: null,
  11. // 是否在测量中
  12. scaleing: false,
  13. // 蓝牙连接状态
  14. devLink: false,
  15. // 扫描筛选出的设备
  16. selectDev: null,
  17. // 设备模型
  18. deviceModel: null,
  19. // 通讯结果
  20. contnectResult: null,
  21. // 发送指令内容
  22. sendData: null,
  23. // 蓝牙设备返回的结果
  24. callBack: null,
  25. // 蓝牙设备下发指令按钮数据
  26. sendBtnList: CommandButtonList.send, //版本号
  27. // 上报数据类型数组:
  28. reportData: CommandButtonList.report,
  29. // 手动输入文本域的值
  30. inputValue: '',
  31. deviceInfo: {
  32. version: '',
  33. battery:'',
  34. chargeState: '',
  35. poleWorkState: '',
  36. workState: '',
  37. error: '',
  38. workStart: '',
  39. workEnd: '',
  40. workResult: '',
  41. }
  42. },
  43. /**
  44. * 页面卸载时调用
  45. */
  46. onUnload() {
  47. // 业务结束后需要调用此方法
  48. wx.offBluetoothAdapterStateChange();
  49. wx.closeBluetoothAdapte();
  50. },
  51. /**
  52. * 页面隐藏时调用
  53. */
  54. onHide() {
  55. },
  56. onLoad() {
  57. let that = this;
  58. //监听蓝牙连接状态
  59. wx.onBLEConnectionStateChange(function (res) {
  60. // 该方法回调中可以用于处理连接意外断开等异常情况
  61. console.log(`设备蓝牙连接状态`, res);
  62. // 如果蓝牙断开
  63. if (!res.connected) {
  64. // 关闭蓝牙连接事件,再重新初始化连接?
  65. that.setData({
  66. devLink: false,
  67. })
  68. wx.showToast({
  69. title: '蓝牙已断开',
  70. });
  71. that.connect();
  72. /* setTimeout(() => {
  73. that.initBlue();
  74. }, 1500) */
  75. } else {
  76. that.setData({
  77. devLink: true,
  78. })
  79. setTimeout(() => {
  80. // 获取蓝牙低功耗设备所有服务 (service)
  81. wx.getBLEDeviceServices({
  82. deviceId: app.globalData.selmac.deviceId,
  83. success: (res) => {
  84. console.log("获取蓝牙低功耗设备所有服务成功", res);
  85. let serviceId = '0000FFF0-0000-1000-8000-00805F9B34FB'
  86. console.log("获取到的serviceId::", serviceId);
  87. // 缓存数据 serviceId
  88. app.globalData.serviceId = serviceId;
  89. //获取蓝牙低功耗设备某个服务中所有特征 (characteristic)。
  90. wx.getBLEDeviceCharacteristics({
  91. deviceId: app.globalData.selmac.deviceId,
  92. serviceId: '0000FFF0-0000-1000-8000-00805F9B34FB',
  93. success: (res) => {
  94. console.log("获取蓝牙低功耗设备某个服务中所有特征", res);
  95. let characteristicId = res.characteristics[0].uuid;
  96. // 缓存数据 characteristicId
  97. app.globalData.characteristicId = characteristicId;
  98. that.notify();
  99. },
  100. fail: (e) => {
  101. console.log("获取蓝牙低功耗设备某个服务中所有特征", e);
  102. }
  103. })
  104. },
  105. fail: (e) => {
  106. console.log("获取蓝牙低功耗设备所有服务失败", e);
  107. }
  108. })
  109. }, 800)
  110. }
  111. })
  112. },
  113. onShow() {
  114. let that = this;
  115. // 记录设备对象
  116. this.setData({
  117. selmac: app.globalData.selmac
  118. })
  119. console.log("selmac", that.data.selmac);
  120. // 连接设备
  121. wx.createBLEConnection({
  122. deviceId: app.globalData.selmac.deviceId,
  123. success: (res) => {
  124. console.log("连接成功", res);
  125. that.setData({
  126. devLink: true
  127. })
  128. // setTimeout(() => {
  129. // // 获取蓝牙低功耗设备所有服务 (service)
  130. // wx.getBLEDeviceServices({
  131. // deviceId: app.globalData.selmac.deviceId,
  132. // success: (res) => {
  133. // console.log("获取蓝牙低功耗设备所有服务成功", res);
  134. // let serviceId = res.services.filter(item => {
  135. // return item.uuid === '0000FEFF-0000-1000-8000-00805F9B34FB'
  136. // })[0];
  137. // // 缓存数据 serviceId
  138. // app.globalData.serviceId = serviceId;
  139. // //获取蓝牙低功耗设备某个服务中所有特征 (characteristic)。
  140. // wx.getBLEDeviceCharacteristics({
  141. // deviceId: app.globalData.selmac.deviceId,
  142. // serviceId: serviceId,
  143. // success: (res) => {
  144. // console.log("获取蓝牙低功耗设备某个服务中所有特征", res);
  145. // let characteristicId = res.characteristics[0].uuid;
  146. // // 缓存数据 characteristicId
  147. // app.globalData.characteristicId = characteristicId;
  148. // },
  149. // fail: (e) => {
  150. // console.log("获取蓝牙低功耗设备某个服务中所有特征", e);
  151. // }
  152. // })
  153. // },
  154. // fail: (e) => {
  155. // console.log("获取蓝牙低功耗设备所有服务失败", e);
  156. // }
  157. // })
  158. // }, 1500)
  159. },
  160. fail: (e) => {
  161. console.log("连接失败", e);
  162. }
  163. })
  164. //this.listenValueChange()
  165. },
  166. connect() {
  167. let that = this;
  168. if (this.data.selmac.deviceId) {
  169. console.log("可以重新初始化蓝牙");
  170. if(!this.data.devLink) {
  171. // 如果已经断开,则重新初始化蓝牙
  172. wx.openBluetoothAdapter({
  173. mode: 'peripheral',
  174. })
  175. // 连接设备
  176. wx.createBLEConnection({
  177. deviceId: that.data.selmac.deviceId,
  178. success: (res) => {
  179. console.log("建立连接成功", res);
  180. },
  181. fail: (e) => {
  182. console.log("建立连接失败", e);
  183. wx.showToast({
  184. title: '重新连接失败',
  185. icon: 'error'
  186. })
  187. }
  188. })
  189. }
  190. }
  191. },
  192. disconnect() {
  193. let that = this;
  194. if (this.data.selmac.deviceId) {
  195. // 连接设备
  196. wx.closeBLEConnection({
  197. deviceId: that.data.selmac.deviceId,
  198. success: (res) => {
  199. console.log("断开连接成功", res);
  200. },
  201. fail: (e) => {
  202. console.log("断开连接失败", e);
  203. }
  204. })
  205. }
  206. },
  207. onClearInput() {
  208. this.setData({
  209. callBack: '',
  210. sendData: '',
  211. });
  212. },
  213. startwrite() {
  214. // 下发指令
  215. /* let text = this.cleanHexString('FE0007010100FF');
  216. let string = this.hexCharCodeToStr(hexData); */
  217. let testdata = new Uint16Array([...'FE0007010100FF'].map(v => v.codePointAt(0)));
  218. console.log("testdata", testdata);
  219. let strToHexCharCode = this.hexToByteString('FE0007010100FF');
  220. let buffer = this.hexStringToArrayBuffer(strToHexCharCode);
  221. let hexData = this.ab2hex(buffer);
  222. console.log("十六进制转成二进制", strToHexCharCode);
  223. console.log("二进制字符串转buffer", buffer);
  224. console.log("buffer转hexData", hexData);
  225. /* console.log("buffer转hexData", hexData);
  226. console.log("hexData转string", string);
  227. console.log("text", text); */
  228. //this.sendMessage(text);
  229. },
  230. hexStringToArrayBuffer(hexStr) {
  231. // 移除前缀并确保字符串长度为偶数
  232. hexStr = hexStr.replace(/\\x/g, '').replace(/^0+/, '');
  233. // 确保字符串长度是偶数,如果不是,前面补0
  234. if (hexStr.length % 2 !== 0) {
  235. hexStr = '0' + hexStr;
  236. }
  237. // 将每两个字符视为一个十六进制数,转换为字节数组
  238. const bytes = new Uint8Array(hexStr.match(/.{1,2}/g).map(byte => parseInt(byte, 16)));
  239. // 从Uint8Array创建ArrayBuffer
  240. return bytes.buffer;
  241. },
  242. bindTextAreaBlur(e) {
  243. this.data.inputValue = e.detail.value;
  244. console.log(e.detail.value)
  245. },
  246. // 十六进制转成二进制
  247. hexToByteString(hexString) {
  248. let bytes = [];
  249. for (let i = 0; i < hexString.length; i += 2) {
  250. bytes.push("\\x" + hexString.substr(i, 2));
  251. }
  252. return bytes.join('');
  253. },
  254. // 手动输入文本域的值
  255. onInputSend() {
  256. console.log("this.data.inputValue", this.data.inputValue);
  257. if (this.data.inputValue) {
  258. this.sendMessage(this.data.inputValue, true);
  259. } else {
  260. wx.showToast({
  261. title: '指令不能为空',
  262. icon: 'error'
  263. })
  264. }
  265. },
  266. // 发送数据
  267. sendMessage(event, type) {
  268. let that = this;
  269. let sendData = '';
  270. if (type) {
  271. console.log("手动输出方式");
  272. sendData = event
  273. } else {
  274. console.log("按钮点击输出方式");
  275. console.log("指令名称::", event.target.dataset.command.name);
  276. sendData = event.target.dataset.command.defaultSendData;
  277. }
  278. if (!that.data.devLink) {
  279. wx.showToast({
  280. title: '蓝牙已断开',
  281. icon: 'error'
  282. })
  283. return
  284. }
  285. if (!sendData) {
  286. wx.showToast({
  287. title: '指令不存在',
  288. icon: 'error'
  289. })
  290. return
  291. }
  292. this.setData({
  293. sendData: sendData
  294. })
  295. /* let strToHexCharCode = this.hexToByteString('FE0007010100FF'); */
  296. /* let strToHexCharCode = this.hexToByteString(sendData); */
  297. console.log("未转换前的十六进制数据::", sendData)
  298. let strToHexCharCode = this.hexToByteString(sendData);
  299. console.log("十六进制转成二进制的数据::", strToHexCharCode);
  300. let buffer = this.hexStringToArrayBuffer(strToHexCharCode);
  301. console.log("二进制转成arrayBuffter的数据::", buffer);
  302. console.log("特征值::", 'E4BAA7E5-908E-E5A1-91E5-BDA2E4BBAA02');
  303. console.log("buffer", buffer);
  304. wx.writeBLECharacteristicValue({
  305. deviceId: app.globalData.selmac.deviceId, // 设备ID
  306. serviceId: /* app.globalData.serviceId */ '0000FFF0-0000-1000-8000-00805F9B34FB', // 服务UUID
  307. characteristicId: /* app.globalData.characteristicId */ 'E4BAA7E5-908E-E5A1-91E5-BDA2E4BBAA02', // 特征值
  308. value: buffer,
  309. success(res) {
  310. console.log("write指令发送成功", res)
  311. },
  312. fail(err) {
  313. console.log("write指令发送失败", err);
  314. that.setData({
  315. callBack: err.errMsg
  316. });
  317. wx.showToast({
  318. title: '指令发送失败',
  319. icon: 'error'
  320. })
  321. }
  322. })
  323. },
  324. string2Hex(str) {
  325. let val = ""
  326. for (let i = 0; i < str.length; i++) {
  327. if (val == "")
  328. val = str.charCodeAt(i).toString(16)
  329. else
  330. val += str.charCodeAt(i).toString(16)
  331. }
  332. return val
  333. },
  334. hex2ArrayBuffer(hex_str) {
  335. // let hex_str = 'AA5504B10000B5'
  336. let typedArray = new Uint8Array(hex_str.match(/[\da-f]{2}/gi).map(function (h) {
  337. return parseInt(h, 16)
  338. }))
  339. let buffer = typedArray.buffer
  340. return buffer
  341. },
  342. cleanHexString(hexStr) {
  343. // 使用正则表达式匹配并移除多余的'0x',并拼接剩下的部分
  344. let cleanedHex = hexStr.replace(/0x/g, '').replace(/\b0+/g, ''); // 第二个正则表达式用于移除前导零
  345. return cleanedHex;
  346. },
  347. // 开启读取蓝牙低功耗设备特征值的二进制数据
  348. read() {
  349. let that = this;
  350. let text = 'fe000f000176657220312e302e31ff'
  351. let string = that.hexCharCodeToStr(text);
  352. console.log("测试", string);
  353. /* wx.readBLECharacteristicValue({
  354. deviceId: app.globalData.selmac.deviceId, // 设备ID,
  355. serviceId: app.globalData.serviceId, // 服务UUID
  356. characteristicId: app.globalData.characteristicId, // 特征值
  357. success (res) {
  358. console.log('readBLECharacteristicValue:', res);
  359. }
  360. }) */
  361. },
  362. // 根据type,向设备写入十六进制数据,
  363. write(data, type) {
  364. let that = this;
  365. let characteristicId = type === 'read' ? 'E4BAA7E5-908E-E5A1-91E5-BDA2E4BBAA01' : 'E4BAA7E5-908E-E5A1-91E5-BDA2E4BBAA02';
  366. console.log("监听到设备有数据上报,回应设备");
  367. console.log("未转换前的十六进制数据::", data)
  368. let strToHexCharCode = this.hexToByteString(data);
  369. console.log("十六进制转成二进制的数据::", strToHexCharCode);
  370. let buffer = this.hexStringToArrayBuffer(strToHexCharCode);
  371. console.log("二进制转成arrayBuffter的数据::", buffer);
  372. console.log("特征值::", characteristicId);
  373. wx.writeBLECharacteristicValue({
  374. deviceId: app.globalData.selmac.deviceId, // 设备ID
  375. serviceId: /* app.globalData.serviceId */ '0000FFF0-0000-1000-8000-00805F9B34FB', // 服务UUID
  376. characteristicId: characteristicId, // 特征值
  377. value: buffer,
  378. success(res) {
  379. console.log("write指令发送成功", res)
  380. //that.read();
  381. },
  382. fail(err) {
  383. console.log("write指令发送失败", err);
  384. that.setData({
  385. callBack: err.errMsg
  386. });
  387. wx.showToast({
  388. title: '指令发送失败',
  389. icon: 'error'
  390. })
  391. }
  392. })
  393. },
  394. // 将一个字符串截取前面多少位,后面多少位,返回中间值
  395. extractMiddleData(encodedStr, startNum, endNum) {
  396. // 前面截取10位
  397. const start = encodedStr.substring(0, startNum);
  398. // 后面截取2位
  399. const end = encodedStr.substring(encodedStr.length - endNum);
  400. // 计算中间部分的起始索引
  401. const middleStartIndex = start.length;
  402. // 总长度减去前后部分的长度得到中间部分的长度
  403. const middleLength = encodedStr.length - middleStartIndex - end.length;
  404. // 提取中间部分
  405. const middlePart = encodedStr.substring(middleStartIndex, middleStartIndex + middleLength);
  406. return middlePart;
  407. },
  408. // 开启设备通知消息监听
  409. notify() {
  410. let that = this;
  411. wx.notifyBLECharacteristicValueChange({
  412. deviceId: app.globalData.selmac.deviceId, // 设备ID,
  413. serviceId: app.globalData.serviceId, // 服务UUID
  414. characteristicId: app.globalData.characteristicId, // 特征值
  415. state: true,
  416. success(res) {
  417. console.log("开启消息监听", res)
  418. // 监听消息变化的方法
  419. that.listenValueChange()
  420. },
  421. fail(err) {
  422. console.error("消息监听失败", err)
  423. }
  424. })
  425. },
  426. // 消息变化
  427. listenValueChange() {
  428. let that = this;
  429. let result = "";
  430. wx.onBLECharacteristicValueChange(res => {
  431. console.log("设备响应", res)
  432. console.log("设备上报的数据", res.value);
  433. // ArrayBuffer转16进制字符串
  434. let resHex = that.ab2hex(res.value);
  435. console.log("设备上报的16进制字符串", resHex);
  436. // 从第六位开始截取,截取10位,拿关键的数据识别上报数据类型
  437. let sliceData = resHex.slice(6, 10);
  438. // 通过截取的到数据区分是下发后上报还是自动上报的数据
  439. console.log("截取到上报数据的关键指令", sliceData);
  440. //console.log("ArrayBuffer转16进制字符串", resHex)
  441. result = that.extractMiddleData(resHex, 10, 2);
  442. console.log("上报截取关键内容::", result);
  443. let isAuto = that.data.reportData.findIndex(item => {
  444. return item.keyWord === sliceData;
  445. })
  446. if (isAuto > -1) {
  447. // 证明是自动上报的数据,否则不是
  448. let report = that.data.reportData.filter(item => {
  449. return item.keyWord === sliceData
  450. });
  451. console.log("上报的数据类型:", report[0].cnName);
  452. // 16进制字符串转字符串,根据情况,有些上报数据需要转字符串,有些则不需要
  453. if (report[0].keyWord === '0001') {
  454. that.setData({
  455. ['deviceInfo.version']: that.hexCharCodeToStr(result)
  456. })
  457. } else if (report[0].keyWord === '0002') {
  458. // 电池电量
  459. that.setData({
  460. ['deviceInfo.battery']: result
  461. })
  462. }else if (report[0].keyWord === '0003') {
  463. // 充电状态
  464. that.setData({
  465. ['deviceInfo.chargeState']: result === '01' ? '以充电' : '未充电'
  466. })
  467. } else if (report[0].keyWord === '0004') {
  468. // 极片工作状态
  469. that.setData({
  470. ['deviceInfo.poleWorkState']: result
  471. })
  472. }else if (report[0].keyWord === '0005') {
  473. // 运行工作状态
  474. that.setData({
  475. ['deviceInfo.workState']: result
  476. })
  477. }else if (report[0].keyWord === '0006') {
  478. // 上报异常
  479. that.setData({
  480. ['deviceInfo.error']: result
  481. })
  482. }else if (report[0].keyWord === '0007') {
  483. // 上报工作开始
  484. that.setData({
  485. ['deviceInfo.workStart']: result
  486. })
  487. }else if (report[0].keyWord === '0008') {
  488. // 上报工作结束
  489. that.setData({
  490. ['deviceInfo.workEnd']: result
  491. })
  492. }else if (report[0].keyWord === '0009') {
  493. // 上报工作结果
  494. that.setData({
  495. ['deviceInfo.workResult']: result
  496. })
  497. }else {
  498. }
  499. // 返回结果后向设备回应
  500. that.write(report[0].response, 'write');
  501. } else {
  502. // 是下发上报的
  503. // 返回结果后向设备回应
  504. /* that.write(report[0].response, 'write'); */
  505. console.log("下发上报");
  506. // 根据上报截取的数据解析下发上报的数据
  507. if(sliceData === '8101'){
  508. // 读取工作强度映射表,以每个字节分割
  509. let resultArr = that.splitStringEveryTwoChars(result, 2);
  510. let workMapList = resultArr.map(item => {
  511. return that.hexToDecimal(item);
  512. })
  513. console.log("resultArr", resultArr);
  514. console.log("workMapList", workMapList);
  515. } else if (sliceData === '8102') {
  516. // 设置设备工作强度映射表响应的
  517. console.log("设置设备工作强度映射表响应", resHex);
  518. }
  519. }
  520. that.setData({
  521. callBack: String(result)
  522. });
  523. })
  524. },
  525. // 将16进制的内容转成我们看得懂的字符串内容
  526. hexCharCodeToStr(hexCharCodeStr) {
  527. var trimedStr = hexCharCodeStr.trim();
  528. var rawStr = trimedStr.substr(0, 2).toLowerCase() === "0x" ? trimedStr.substr(2) : trimedStr;
  529. var len = rawStr.length;
  530. if (len % 2 !== 0) {
  531. alert("存在非法字符!");
  532. return "";
  533. }
  534. var curCharCode;
  535. var resultStr = [];
  536. for (var i = 0; i < len; i = i + 2) {
  537. curCharCode = parseInt(rawStr.substr(i, 2), 16);
  538. resultStr.push(String.fromCharCode(curCharCode));
  539. }
  540. return decodeURIComponent(resultStr.join(""));
  541. },
  542. /*字符串转换16进制buffer*/
  543. stringToCmdBuffer(msg) {
  544. console.log("msg", msg);
  545. const buffer = new ArrayBuffer(msg.length)
  546. const dataView = new DataView(buffer)
  547. //dataView.setUint8(0, 0)
  548. for (let i = 0; i < msg.length; i++) {
  549. dataView.setUint8(i, msg.charAt(i).charCodeAt())
  550. };
  551. return buffer
  552. },
  553. // 十六进制转二进制
  554. strToHexCharCode(str) {
  555. if (str === "")
  556. return "";
  557. var hexCharCode = [];
  558. hexCharCode.push("0x");
  559. for (var i = 0; i < str.length; i++) {
  560. hexCharCode.push((str.charCodeAt(i)).toString(16));
  561. }
  562. return hexCharCode.join("");
  563. },
  564. // 十六进制转十进制
  565. hexToDecimal(hexString) {
  566. return parseInt(hexString, 16);
  567. },
  568. // ArrayBuffer转16进度字符串示例
  569. ab2hex(buffer) {
  570. let hexArr = Array.prototype.map.call(
  571. new Uint8Array(buffer),
  572. function (bit) {
  573. return ('00' + bit.toString(16)).slice(-2)
  574. }
  575. )
  576. return hexArr.join('');
  577. },
  578. // 通过几位分割成数组
  579. splitStringEveryTwoChars(str, splitNumber) {
  580. let result = [];
  581. for (let i = 0; i < str.length; i += splitNumber) {
  582. result.push(str.substring(i, i + splitNumber));
  583. }
  584. return result;
  585. }
  586. })