ElinkThings小程序蓝牙插件SDK集合:aifresh、ailink http://doc.elinkthings.com/web/#/36?page_id=127
Nelze vybrat více než 25 témat Téma musí začínat písmenem nebo číslem, může obsahovat pomlčky („-“) a může být dlouhé až 35 znaků.

index.js 14KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431
  1. // const plugin = requirePlugin("myPlugin").AiFresh;
  2. const {BM16His: plugin} = requirePlugin("sdkPlugin");
  3. function inArray(arr, key, val) {
  4. for (let i = 0; i < arr.length; i++) {
  5. if (arr[i][key] === val) {
  6. return i;
  7. }
  8. }
  9. return -1;
  10. }
  11. // ArrayBuffer转16进度字符串示例
  12. function ab2hex(buffer) {
  13. var hexArr = Array.prototype.map.call(
  14. new Uint8Array(buffer),
  15. function (bit) {
  16. return ('00' + bit.toString(16)).slice(-2)
  17. }
  18. )
  19. return hexArr.join(',');
  20. }
  21. // var information = []
  22. Page({
  23. data: {
  24. devices: [],
  25. mac: "",
  26. connected: false,
  27. text: "",
  28. unitList_all: ['g', 'ml', 'lb:oz', 'oz', 'kg', '斤', '牛奶 ml', '水 ml', '牛奶 floz', '水 floz', 'lb'],
  29. unitList: ['g', 'ml', 'lb:oz', 'oz'],
  30. weight: 0,
  31. unit: 'g',
  32. unitIndex: 0,
  33. min: 0,
  34. second: 0,
  35. showWriteInput: false,
  36. connected: false,
  37. chs: [],
  38. cmd: '',
  39. name: '',
  40. deviceId: null,
  41. historyList: [],
  42. height:0,
  43. information:[],
  44. },
  45. onLoad: function () {
  46. let screenHeight = wx.getSystemInfoSync().windowHeight;
  47. this.setData({
  48. height: screenHeight - 344,
  49. });
  50. },
  51. clearDevices() {
  52. this.setData({
  53. devices: []
  54. })
  55. this.closeBluetoothAdapter()
  56. wx.nextTick(()=>{
  57. this.openBluetoothAdapter()
  58. })
  59. },
  60. // 初始化蓝牙模块
  61. openBluetoothAdapter() {
  62. wx.openBluetoothAdapter({
  63. success: (res) => {
  64. console.log('openBluetoothAdapter success', res)
  65. this.startBluetoothDevicesDiscovery()
  66. },
  67. fail: (res) => {
  68. if (res.errCode === 10001) {
  69. wx.showToast({
  70. title: '请打开蓝牙',
  71. icon: "none"
  72. })
  73. wx.onBluetoothAdapterStateChange(function (res) {
  74. console.log('onBluetoothAdapterStateChange', res)
  75. if (res.available) {
  76. this.startBluetoothDevicesDiscovery()
  77. }
  78. })
  79. }
  80. }
  81. })
  82. },
  83. // 获取本机蓝牙适配器状态
  84. getBluetoothAdapterState() {
  85. wx.getBluetoothAdapterState({
  86. success: (res) => {
  87. console.log('getBluetoothAdapterState', res)
  88. if (res.discovering) {
  89. this.onBluetoothDeviceFound()
  90. } else if (res.available) {
  91. this.startBluetoothDevicesDiscovery()
  92. }
  93. }
  94. })
  95. },
  96. // 开始搜寻附近的蓝牙外围设备
  97. startBluetoothDevicesDiscovery() {
  98. if (this._discoveryStarted) {
  99. return
  100. }
  101. this._discoveryStarted = true
  102. wx.startBluetoothDevicesDiscovery({
  103. allowDuplicatesKey: true,
  104. services: [
  105. "FFE0",
  106. "F0A0", // BM30广播模块需加上,如使用连接模块可忽略
  107. ],
  108. powerLevel: 'high',
  109. success: (res) => {
  110. console.log('startBluetoothDevicesDiscovery success', res)
  111. this.onBluetoothDeviceFound()
  112. },
  113. })
  114. },
  115. // 停止搜寻附近的蓝牙外围设备
  116. stopBluetoothDevicesDiscovery() {
  117. wx.stopBluetoothDevicesDiscovery()
  118. },
  119. // 监听寻找到新设备的事件
  120. onBluetoothDeviceFound() {
  121. wx.onBluetoothDeviceFound((res) => {
  122. console.log('res',res);
  123. res.devices.forEach(device => {
  124. if (!device.name && !device.localName) {
  125. return
  126. }
  127. const foundDevices = this.data.devices
  128. console.log('foundDevices',foundDevices);
  129. const idx = inArray(foundDevices, 'deviceId', device.deviceId)
  130. let advertisDatas = ab2hex(device.advertisData).split(',').toString()
  131. let index = advertisDatas.indexOf('6e,49')
  132. let cid = advertisDatas[index + 9] + advertisDatas[index + 10]
  133. const data = {}
  134. // console.log(device)
  135. // console.log(ab2hex(device.advertisData))
  136. // 此处判断是否BM30广播模块,如使用连接模块请删除此 if ,只保留 else 内容
  137. if (cid == 14 ||cid == '0e') {
  138. if (device.advertisServiceUUIDs[0].indexOf("F0A0") !== -1) {
  139. let parseDataRes = plugin.parseBroadcastData(device.advertisData)
  140. // console.log(parseDataRes)
  141. if (parseDataRes.status == 1) {
  142. let analyzeData = plugin.analyzeBroadcastScaleData(parseDataRes)
  143. device.analyzeDataText = analyzeData.text
  144. console.log(analyzeData.data.weight)
  145. }
  146. } else {
  147. let buff = device.advertisData.slice(8, 14)
  148. device.mac = new Uint8Array(buff) // 保存广播数据中的mac地址,这是由于iOS不直接返回mac地址
  149. let tempMac = Array.from(device.mac)
  150. tempMac.reverse()
  151. device.macAddr = ab2hex(tempMac, ':').toUpperCase()
  152. }
  153. if (idx === -1) {
  154. data[`devices[${foundDevices.length}]`] = device
  155. } else {
  156. data[`devices[${idx}]`] = device
  157. }
  158. this.setData(data)
  159. }
  160. })
  161. })
  162. },
  163. // 连接低功耗蓝牙设备
  164. createBLEConnection(e) {
  165. this._connLoading = true
  166. wx.showLoading({
  167. title: '连接中',
  168. })
  169. setTimeout(() => {
  170. if (this._connLoading) {
  171. this._connLoading = false
  172. wx.hideLoading()
  173. }
  174. }, 6000)
  175. const ds = e.currentTarget.dataset
  176. const index = ds.index
  177. // 保存当前连接的设备,注意不能从wxml的dataset中直接返回该对象,因为ArrarBuffer类型的数据无法保留
  178. const deviceId = ds.deviceId
  179. const name = ds.name
  180. this._device = this.data.devices[index]
  181. console.log(this._device)
  182. wx.createBLEConnection({
  183. deviceId,
  184. success: (res) => {
  185. // console.log('this._device',this._device);
  186. let buff = this._device.advertisData.slice(-6)
  187. let arr = new Uint8Array(buff).reverse()
  188. let mac = ab2hex(arr).replace(/,/g,":")
  189. // console.log('mac',mac);
  190. this.setData({
  191. connected: true,
  192. name,
  193. deviceId,
  194. mac
  195. })
  196. console.log("createBLEConnection:success")
  197. this.log('蓝牙连接成功!')
  198. wx.stopBluetoothDevicesDiscovery()
  199. this.onBLEConnectionStateChange()
  200. this.getBLEDeviceServices(deviceId)
  201. },
  202. fail: res => {
  203. this._connLoading = false
  204. wx.hideLoading()
  205. wx.showToast({
  206. title: '连接失败',
  207. icon: 'none'
  208. })
  209. }
  210. })
  211. // 连接上设备就可以停止蓝牙搜索,减少功耗。
  212. this.stopBluetoothDevicesDiscovery()
  213. },
  214. onBLEConnectionStateChange() {
  215. wx.onBLEConnectionStateChange((res) => {
  216. console.log('wx.onBLEConnectionStateChange() ', res.deviceId, res.connected, res.errorCode, res.errorMsg)
  217. // 该方法回调中可以用于处理连接意外断开等异常情况
  218. // console.log(`%c device ${res.deviceId} state has changed, connected: ${res.connected}`, 'color: #F26363')
  219. if (!res.connected) {
  220. wx.showToast({
  221. title: '连接已断开',
  222. icon: 'none'
  223. })
  224. this.log(this.data.mac + '蓝牙已断开连接....')
  225. this.setData({
  226. showWriteInput: false,
  227. })
  228. }
  229. })
  230. },
  231. // 断开与低功耗蓝牙设备的连接
  232. closeBLEConnection() {
  233. wx.closeBLEConnection({
  234. deviceId: this._deviceId
  235. })
  236. this.log(this.data.mac + '蓝牙已断开连接....')
  237. this.setData({
  238. showWriteInput: false,
  239. })
  240. },
  241. quit(){
  242. this.closeBLEConnection()
  243. this.setData({
  244. connected: false,
  245. information:[]
  246. })
  247. },
  248. // 获取蓝牙设备的 serviceId
  249. getBLEDeviceServices(deviceId) {
  250. wx.getBLEDeviceServices({
  251. deviceId,
  252. success: (res) => {
  253. for (let i = 0; i < res.services.length; i++) {
  254. if (res.services[i].isPrimary && res.services[i].uuid.indexOf('FFE0') > -1) {
  255. this.getBLEDeviceCharacteristics(deviceId, res.services[i].uuid)
  256. return
  257. }
  258. }
  259. }
  260. })
  261. },
  262. // 获取蓝牙设备某个服务中所有特征值(characteristic)
  263. getBLEDeviceCharacteristics(deviceId, serviceId) {
  264. this._deviceId = deviceId
  265. this._serviceId = serviceId
  266. this._device.serviceId = serviceId
  267. wx.getBLEDeviceCharacteristics({
  268. deviceId,
  269. serviceId,
  270. success: (res) => {
  271. console.log('getBLEDeviceCharacteristics success', res.characteristics)
  272. console.log('plugin',plugin);
  273. // 初始化插件
  274. plugin.initPlugin(res.characteristics, this._device)
  275. wx.onBLECharacteristicValueChange((characteristic) => {
  276. // 解析特征值,返回解密后的数据
  277. let bleData = plugin.parseBleData(characteristic.value)
  278. console.log(bleData)
  279. if (bleData.status == 0) {
  280. console.log("握手成功")
  281. this._connLoading = false
  282. wx.hideLoading()
  283. wx.showToast({
  284. title: '连接成功',
  285. })
  286. } else if (bleData.status == 2) {
  287. let payload = bleData.data //对应协议中的payload数据,可以自行解析该数据
  288. // console.log(ab2hex(payload, ' '))
  289. // console.log(ab2hex(bleData.completeData, ' '))
  290. switch (payload[0]) {
  291. case 0x1B:
  292. if (payload[1] == 0) {
  293. this.log('设置系统时间成功')
  294. }else if (payload[1] == 1) {
  295. this.log('设置系统时间失败')
  296. }else{
  297. this.log('系统不支持时间设置')
  298. }
  299. break;
  300. case 0x1C:
  301. if (payload[1] == 1) {
  302. let {year,month,day,hour,min,second} = plugin.analyzeSystemTime(payload)
  303. this.log(`系统时间为:${year}/${month}/${day} ${hour}:${min}:${second}`)
  304. } else {
  305. this.log('系统时间无效')
  306. }
  307. break;
  308. case 0x2B:
  309. if (payload[1] == 0x05) {
  310. if (payload[2] == 0) {
  311. this.log('无用户历史记录')
  312. } else if(payload[2] == 1) {
  313. this.log('开始发送历史记录')
  314. }else{
  315. this.log('结束发送历史记录')
  316. }
  317. }
  318. if (payload[1] == 0x06) {
  319. if (payload[2] == 0x01) {
  320. plugin.analyzeMCUBodyData(payload)
  321. } else if (payload[2] == 0x02){
  322. plugin.analyzeMCUBodyData(payload)
  323. }else if (payload[2] == 0x03) {
  324. let { year,month,day,hour,min,second,id,userCharacteristics,sex,age,height,weight,metabolicBasisRate,bodyAge ,uint,symbol,impedance,compute,bodyFat,subcutaneousFat,visceralFat,musclesRate,boneMass,waterContent,proteinRate,heartRate } = plugin.analyzeMCUBodyData(payload)
  325. this.log(`时间为:${year}/${month}/${day} ${hour}:${min}:${second}
  326. id:${id} 用户特征:${userCharacteristics},性别:${sex},年龄:${age},身高:${height},
  327. 体重:${weight},单前单位:${uint},重量数据精度:${symbol},阻抗:${impedance},
  328. 心率数据:${heartRate},体脂:${bodyFat},皮下脂肪:${subcutaneousFat}
  329. ,内脏脂肪:${visceralFat},肌肉率:${musclesRate},基础代谢率:${metabolicBasisRate},
  330. 骨量:${boneMass},水含量:${waterContent},蛋白率:${proteinRate},身体年龄:${bodyAge}`)
  331. }
  332. }
  333. if (payload[1] == 0x07) {
  334. if (payload[2] == 0x01) {
  335. plugin.analyzeAPPBodyData(payload)
  336. } else if (payload[2] == 0x02){
  337. let { year,month,day,hour,min,second,id,userCharacteristics,sex,age,height,weight,uint,symbol,impedance,compute,heartRate } = plugin.analyzeAPPBodyData(payload)
  338. this.log(`时间为:${year}/${month}/${day} ${hour}:${min}:${second}
  339. id:${id} 用户特征:${userCharacteristics},性别:${sex},年龄:${age},身高:${height},
  340. 体重:${weight},单前单位:${uint},重量数据精度:${symbol},阻抗:${impedance},
  341. 算法标识:${compute},心率数据:${heartRate}`)
  342. }
  343. }
  344. if (payload[1] == 0x04) {
  345. if (payload[2] == 0) {
  346. this.log('更新列表成功')
  347. } else if(payload[2] == 1){
  348. this.log('更新个人用户成功')
  349. }else if(payload[2] == 2){
  350. this.log('更新列表失败')
  351. }else if(payload[2] == 3){
  352. this.log('更新个人用户失败')
  353. }else{
  354. this.log('未知指令')
  355. }
  356. }
  357. }
  358. } else if (bleData.status == 1){
  359. }
  360. })
  361. },
  362. fail(res) {
  363. console.error('getBLEDeviceCharacteristics', res)
  364. }
  365. })
  366. },
  367. log(data){
  368. let info = this.data.information
  369. info.unshift(data)
  370. this.setData({
  371. information:info
  372. })
  373. },
  374. writeBLECharacteristicValue(buffer, uuid, deviceId, serviceId) {
  375. // 向蓝牙设备发送一个二进制流数据
  376. wx.writeBLECharacteristicValue({
  377. deviceId,
  378. serviceId,
  379. characteristicId: uuid,
  380. value: buffer,
  381. success(res) {
  382. console.log('writeBLECharacteristicValue success', res)
  383. console.log('下发指令==> ' + ab2hex(buffer))
  384. }
  385. })
  386. },
  387. closeBluetoothAdapter() {
  388. wx.closeBluetoothAdapter()
  389. this._discoveryStarted = false
  390. },
  391. setSystemTime(){
  392. // console.log('设置时间');
  393. plugin.setSystemTime()
  394. },
  395. getSystemTime(){
  396. // console.log('获取时间');
  397. plugin.getSystemTime()
  398. },
  399. updateUserList(){
  400. // console.log('更新用户列表');
  401. let userInfo = { identity:0,id:7,sex:1,age:21,height:176,weight:77.5,impedance:450}
  402. let userInfo1 = { identity:1,id:2,sex:0,age:29,height:162,weight:66.1,impedance:420 }
  403. let userInfo2 = { identity:0,id:1,sex:1,age:22,height:168,weight:71.1,impedance:430 }
  404. let userList = []
  405. userList.push(userInfo)
  406. userList.push(userInfo1)
  407. userList.push(userInfo2)
  408. plugin.updateUserList(userList)
  409. },
  410. updateUserInformation(){
  411. //console.log('更新用户个人信息');
  412. let userInfo ={ identity:0,id:7,sex:1,age:21,height:176,weight:77.5,impedance:450}
  413. plugin.updateUserInformation(userInfo)
  414. },
  415. requestHis(){
  416. plugin.requestHis()
  417. }
  418. });