ecBLEApp.js 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551
  1. const logEnable = false
  2. let isAndroid = false
  3. let ecBluetoothAdapterStateChangeCallback = () => {}
  4. let ecBluetoothDeviceFoundCallback = () => {}
  5. let ecBLEConnectionStateChangeCallback = () => {}
  6. let ecBLECharacteristicValueChangeCallback = () => {}
  7. let ecDeviceId = ''
  8. let ecGattServerUUID = ''
  9. const ecGattServerUUIDOption1 = '0000FFF0-0000-1000-8000-00805F9B34FB'
  10. const ecGattServerUUIDOption2 = 'FFF0'
  11. const yiyuanUUIDOption1 = '0000F536-0000-1000-8000-00805F9B34FB';
  12. const yiyuanUUIDOption2 = 'F536';
  13. let ecGattCharacteristicWriteUUID = ''
  14. const ecGattCharacteristicWriteUUIDOption1 = '0000FFF2-0000-1000-8000-00805F9B34FB'
  15. const ecGattCharacteristicWriteUUIDOption2 = 'FFF2'
  16. const yiyuancharacterID1 = '0000FF15-0000-1000-8000-00805F9B34FB'
  17. const yiyuancharacterID2 = 'FF15'
  18. import i18 from '@/utils/i18.js'
  19. const log = data => {
  20. if (logEnable) {
  21. console.log('[eciot]:' + JSON.stringify(data))
  22. }
  23. }
  24. const onBluetoothAdapterStateChange = cb => {
  25. ecBluetoothAdapterStateChangeCallback = cb
  26. }
  27. const _openBluetoothAdapter = () => {
  28. return new Promise(function(resolve, reject) {
  29. uni.openBluetoothAdapter({
  30. success(res) {
  31. log(res)
  32. resolve({
  33. ok: true,
  34. errCode: 0,
  35. errMsg: ''
  36. })
  37. },
  38. fail(res) {
  39. log(res)
  40. // {"errMsg":"openBluetoothAdapter:fail not available","code":10001}
  41. resolve({
  42. ok: false,
  43. errCode: res.code,
  44. errMsg: res.errMsg,
  45. })
  46. },
  47. })
  48. })
  49. }
  50. uni.onBluetoothAdapterStateChange(res => {
  51. log(res)
  52. // {"discovering":true,"available":true}
  53. if (!res.available) {
  54. ecBluetoothAdapterStateChangeCallback({
  55. ok: false,
  56. errCode: 30005,
  57. errMsg: i18('蓝牙适配器不可用'),
  58. })
  59. }
  60. })
  61. const openBluetoothAdapter = async () => {
  62. await _openBluetoothAdapter()
  63. const systemInfo = uni.getSystemInfoSync()
  64. log(systemInfo)
  65. if (systemInfo.platform.toLowerCase() === 'android') {
  66. isAndroid = true
  67. }
  68. const systemSetting = uni.getSystemSetting()
  69. log(systemSetting)
  70. const appAuthorizeSetting = uni.getAppAuthorizeSetting()
  71. log(appAuthorizeSetting)
  72. if (!systemSetting.bluetoothEnabled) {
  73. ecBluetoothAdapterStateChangeCallback({
  74. ok: false,
  75. errCode: 30001,
  76. errMsg: i18('请打开系统蓝牙开关'),
  77. })
  78. return
  79. }
  80. if (isAndroid && !systemSetting.locationEnabled) {
  81. ecBluetoothAdapterStateChangeCallback({
  82. ok: false,
  83. errCode: 30002,
  84. errMsg: i18('请打开系统定位开关'),
  85. })
  86. return
  87. }
  88. if (isAndroid && (appAuthorizeSetting.locationAuthorized!=='authorized')) {
  89. ecBluetoothAdapterStateChangeCallback({
  90. ok: false,
  91. errCode: 30003,
  92. errMsg: i18('请打开应用定位权限,允许应用使用您的位置信息'),
  93. })
  94. return
  95. }
  96. const openRes = await _openBluetoothAdapter()
  97. ecBluetoothAdapterStateChangeCallback(openRes)
  98. }
  99. uni.onBluetoothDeviceFound(res => {
  100. // log(res)
  101. const device = res.devices[0]
  102. const name = device.name ? device.name : device.localName
  103. if (!name) {
  104. return
  105. }
  106. let id = device.deviceId
  107. let rssi = device.RSSI
  108. ecBluetoothDeviceFoundCallback({
  109. id,
  110. name,
  111. rssi
  112. })
  113. })
  114. const onBluetoothDeviceFound = cb => {
  115. ecBluetoothDeviceFoundCallback = cb
  116. }
  117. const startBluetoothDevicesDiscovery = () => {
  118. uni.startBluetoothDevicesDiscovery({
  119. //services: [ecServerId],
  120. allowDuplicatesKey: true,
  121. // powerLevel: 'high',
  122. complete(res) {
  123. log(res)
  124. },
  125. })
  126. }
  127. const stopBluetoothDevicesDiscovery = () => {
  128. uni.stopBluetoothDevicesDiscovery({
  129. complete(res) {
  130. log(res)
  131. },
  132. })
  133. }
  134. const onBLEConnectionStateChange = cb => {
  135. ecBLEConnectionStateChangeCallback = cb
  136. }
  137. const _createBLEConnection = () => {
  138. return new Promise(function(resolve, reject) {
  139. uni.createBLEConnection({
  140. deviceId: ecDeviceId,
  141. success(res) {
  142. log(res)
  143. resolve({
  144. ok: true,
  145. errCode: 0,
  146. errMsg: ''
  147. })
  148. },
  149. fail(res) {
  150. log(res)
  151. resolve({
  152. ok: false,
  153. errCode: res.code,
  154. errMsg: res.errMsg,
  155. })
  156. },
  157. })
  158. })
  159. }
  160. const getBLEDeviceServices = () => {
  161. return new Promise(function(resolve, reject) {
  162. setTimeout(()=>{
  163. uni.getBLEDeviceServices({
  164. deviceId: ecDeviceId,
  165. success(res) {
  166. log(res)
  167. resolve({
  168. ok: true,
  169. errCode: 0,
  170. errMsg: '',
  171. services: res.services,
  172. })
  173. },
  174. fail(res) {
  175. log(res)
  176. resolve({
  177. ok: false,
  178. errCode: res.code,
  179. errMsg: res.errMsg
  180. })
  181. },
  182. })
  183. },1200)//之前是800ms,要休眠到1200ms
  184. })
  185. }
  186. const getBLEDeviceCharacteristics = serviceId => {
  187. return new Promise(function(resolve, reject) {
  188. uni.getBLEDeviceCharacteristics({
  189. deviceId: ecDeviceId,
  190. serviceId,
  191. success(res) {
  192. log(res)
  193. resolve({
  194. ok: true,
  195. errCode: 0,
  196. errMsg: '',
  197. characteristics: res.characteristics,
  198. })
  199. },
  200. fail(res) {
  201. log(res)
  202. resolve({
  203. ok: false,
  204. errCode: res.code,
  205. errMsg: res.errMsg
  206. })
  207. },
  208. })
  209. })
  210. }
  211. const notifyBLECharacteristicValueChange = (serviceId, characteristicId) => {
  212. return new Promise(function(resolve, reject) {
  213. uni.notifyBLECharacteristicValueChange({
  214. state: true,
  215. deviceId: ecDeviceId,
  216. serviceId,
  217. characteristicId,
  218. success(res) {
  219. log(res)
  220. resolve({
  221. ok: true,
  222. errCode: 0,
  223. errMsg: ''
  224. })
  225. },
  226. fail(res) {
  227. log(res)
  228. resolve({
  229. ok: false,
  230. errCode: res.code,
  231. errMsg: res.errMsg
  232. })
  233. },
  234. })
  235. })
  236. }
  237. const setBLEMTU = mtu => {
  238. return new Promise(function(resolve, reject) {
  239. setTimeout(()=>{
  240. uni.setBLEMTU({
  241. deviceId: ecDeviceId,
  242. mtu,
  243. success(res) {
  244. log(res)
  245. resolve({
  246. ok: true,
  247. errCode: 0,
  248. errMsg: ''
  249. })
  250. },
  251. fail(res) {
  252. log(res)
  253. resolve({
  254. ok: false,
  255. errCode: res.code,
  256. errMsg: res.errMsg
  257. })
  258. },
  259. })
  260. },500)
  261. })
  262. }
  263. uni.onBLEConnectionStateChange(async res => {
  264. log(res)
  265. // {"deviceId":"EC:22:05:13:78:49","connected":true}
  266. if (res.connected) {
  267. console.log("connected successfully")
  268. const servicesResult = await getBLEDeviceServices()
  269. console.log(servicesResult)
  270. if (!servicesResult.ok) {
  271. ecBLEConnectionStateChangeCallback(servicesResult)
  272. closeBLEConnection()
  273. return
  274. }
  275. console.log(servicesResult)
  276. for (const service of servicesResult.services) {
  277. var isRightService = false;
  278. if ((service.uuid.toUpperCase() === ecGattServerUUIDOption1) ||
  279. (service.uuid.toUpperCase() === ecGattServerUUIDOption2)) {
  280. ecGattServerUUID = service.uuid
  281. isRightService = true;
  282. }
  283. if ((service.uuid.toUpperCase() === yiyuanUUIDOption1) ||
  284. (service.uuid.toUpperCase() === yiyuanUUIDOption2)) {
  285. ecGattServerUUID = service.uuid
  286. isRightService = true;
  287. }
  288. if(!isRightService){
  289. continue;
  290. }
  291. console.log("uuid:"+ecGattServerUUID)
  292. const characteristicsResult = await getBLEDeviceCharacteristics(
  293. service.uuid
  294. )
  295. if (!characteristicsResult.ok) {
  296. ecBLEConnectionStateChangeCallback(characteristicsResult)
  297. closeBLEConnection()
  298. return
  299. }
  300. console.log(characteristicsResult)
  301. for (const characteristic of characteristicsResult.characteristics) {
  302. if (
  303. characteristic.properties &&
  304. characteristic.properties.notify
  305. ) {
  306. const notifyResult =
  307. await notifyBLECharacteristicValueChange(
  308. service.uuid,
  309. characteristic.uuid
  310. )
  311. if (!notifyResult.ok) {
  312. ecBLEConnectionStateChangeCallback({
  313. ok: false,
  314. errCode: 30000,
  315. errMsg: 'notify error',
  316. })
  317. closeBLEConnection()
  318. return
  319. }
  320. }
  321. /**
  322. * 14:49:25.419 uuid:0000FFF0-0000-1000-8000-00805F9B34FB at utils/ecBLE/ecBLEApp.js:298
  323. * 14:49:25.427 characteristic.uuid:0000FFF2-0000-1000-8000-00805F9B34FB at utils/ecBLE/ecBLEApp.js:327
  324. * 14:49:25.443 characteristic.uuid:0000FFF1-0000-1000-8000-00805F9B34FB at utils/ecBLE/ecBLEApp.js:327
  325. */
  326. console.log("characteristic.uuid:"+characteristic.uuid)
  327. if ((characteristic.uuid.toUpperCase() ===
  328. ecGattCharacteristicWriteUUIDOption1) ||
  329. (characteristic.uuid.toUpperCase() ===
  330. ecGattCharacteristicWriteUUIDOption2)) {
  331. ecGattCharacteristicWriteUUID = characteristic.uuid
  332. }
  333. if ((characteristic.uuid.toUpperCase() ===
  334. yiyuancharacterID1) ||
  335. (characteristic.uuid.toUpperCase() ===
  336. yiyuancharacterID2)) {
  337. ecGattCharacteristicWriteUUID = characteristic.uuid
  338. }
  339. console.log("rghtCID:"+ecGattCharacteristicWriteUUID);
  340. }
  341. }
  342. if (isAndroid) {
  343. await setBLEMTU(247)
  344. }
  345. ecBLEConnectionStateChangeCallback({
  346. ok: true,
  347. errCode: 0,
  348. errMsg: '',
  349. })
  350. } else {
  351. ecBLEConnectionStateChangeCallback({
  352. ok: false,
  353. errCode: 0,
  354. errMsg: 'disconnect',
  355. })
  356. }
  357. })
  358. const createBLEConnection = async id => {
  359. ecDeviceId = id
  360. const res = await _createBLEConnection()
  361. if (!res.ok) {
  362. ecBLEConnectionStateChangeCallback(res)
  363. }
  364. }
  365. const closeBLEConnection = () => {
  366. uni.closeBLEConnection({
  367. deviceId: ecDeviceId,
  368. complete(res) {
  369. log(res)
  370. },
  371. })
  372. }
  373. uni.onBLECharacteristicValueChange(res => {
  374. log(res)
  375. let x = new Uint8Array(res.value)
  376. log(x)
  377. let str = utf8BytesToStr(x)
  378. let strHex = ''
  379. for (let i = 0; i < x.length; i++) {
  380. strHex = strHex + x[i].toString(16).padStart(2, '0').toUpperCase()
  381. }
  382. log(str)
  383. log(strHex)
  384. ecBLECharacteristicValueChangeCallback(str, strHex)
  385. })
  386. const onBLECharacteristicValueChange = cb => {
  387. ecBLECharacteristicValueChangeCallback = cb
  388. }
  389. const _writeBLECharacteristicValue = buffer => {
  390. return new Promise(function(resolve, reject) {
  391. uni.writeBLECharacteristicValue({
  392. deviceId: ecDeviceId,
  393. serviceId: ecGattServerUUID,
  394. characteristicId: ecGattCharacteristicWriteUUID,
  395. value: buffer,
  396. writeType: 'writeNoResponse',
  397. success(res) {
  398. log(res)
  399. resolve({
  400. ok: true,
  401. errCode: 0,
  402. errMsg: ''
  403. })
  404. },
  405. fail(res) {
  406. log(res)
  407. resolve({
  408. ok: false,
  409. errCode: res.code,
  410. errMsg: res.errMsg
  411. })
  412. },
  413. })
  414. })
  415. }
  416. const writeBLECharacteristicValue = async (str, isHex) => {
  417. if (str.length === 0)
  418. return {
  419. ok: false,
  420. errCode: 30000,
  421. errMsg: 'data is null'
  422. }
  423. let buffer
  424. if (isHex) {
  425. buffer = new ArrayBuffer(str.length / 2)
  426. let x = new Uint8Array(buffer)
  427. for (let i = 0; i < x.length; i++) {
  428. x[i] = parseInt(str.substr(2 * i, 2), 16)
  429. }
  430. } else {
  431. buffer = new Uint8Array(strToUtf8Bytes(str)).buffer
  432. }
  433. return await _writeBLECharacteristicValue(buffer)
  434. }
  435. const utf8BytesToStr = utf8Bytes => {
  436. let unicodeStr = ''
  437. for (let pos = 0; pos < utf8Bytes.length;) {
  438. let flag = utf8Bytes[pos]
  439. let unicode = 0
  440. if (flag >>> 7 === 0) {
  441. unicodeStr += String.fromCharCode(utf8Bytes[pos])
  442. pos += 1
  443. }
  444. // else if ((flag & 0xFC) === 0xFC) {
  445. // unicode = (utf8Bytes[pos] & 0x3) << 30
  446. // unicode |= (utf8Bytes[pos + 1] & 0x3F) << 24
  447. // unicode |= (utf8Bytes[pos + 2] & 0x3F) << 18
  448. // unicode |= (utf8Bytes[pos + 3] & 0x3F) << 12
  449. // unicode |= (utf8Bytes[pos + 4] & 0x3F) << 6
  450. // unicode |= (utf8Bytes[pos + 5] & 0x3F)
  451. // unicodeStr += String.fromCharCode(unicode)
  452. // pos += 6
  453. // }
  454. // else if ((flag & 0xF8) === 0xF8) {
  455. // unicode = (utf8Bytes[pos] & 0x7) << 24
  456. // unicode |= (utf8Bytes[pos + 1] & 0x3F) << 18
  457. // unicode |= (utf8Bytes[pos + 2] & 0x3F) << 12
  458. // unicode |= (utf8Bytes[pos + 3] & 0x3F) << 6
  459. // unicode |= (utf8Bytes[pos + 4] & 0x3F)
  460. // unicodeStr += String.fromCharCode(unicode)
  461. // pos += 5
  462. // }
  463. else if ((flag & 0xf0) === 0xf0) {
  464. unicode = (utf8Bytes[pos] & 0xf) << 18
  465. unicode |= (utf8Bytes[pos + 1] & 0x3f) << 12
  466. unicode |= (utf8Bytes[pos + 2] & 0x3f) << 6
  467. unicode |= utf8Bytes[pos + 3] & 0x3f
  468. unicodeStr += String.fromCharCode(unicode)
  469. pos += 4
  470. } else if ((flag & 0xe0) === 0xe0) {
  471. unicode = (utf8Bytes[pos] & 0x1f) << 12
  472. unicode |= (utf8Bytes[pos + 1] & 0x3f) << 6
  473. unicode |= utf8Bytes[pos + 2] & 0x3f
  474. unicodeStr += String.fromCharCode(unicode)
  475. pos += 3
  476. } else if ((flag & 0xc0) === 0xc0) {
  477. //110
  478. unicode = (utf8Bytes[pos] & 0x3f) << 6
  479. unicode |= utf8Bytes[pos + 1] & 0x3f
  480. unicodeStr += String.fromCharCode(unicode)
  481. pos += 2
  482. } else {
  483. unicodeStr += String.fromCharCode(utf8Bytes[pos])
  484. pos += 1
  485. }
  486. }
  487. return unicodeStr
  488. }
  489. const strToUtf8Bytes = str => {
  490. let bytes = []
  491. for (let i = 0; i < str.length; ++i) {
  492. let code = str.charCodeAt(i)
  493. if (code >= 0x10000 && code <= 0x10ffff) {
  494. bytes.push((code >> 18) | 0xf0) // 第一个字节
  495. bytes.push(((code >> 12) & 0x3f) | 0x80)
  496. bytes.push(((code >> 6) & 0x3f) | 0x80)
  497. bytes.push((code & 0x3f) | 0x80)
  498. } else if (code >= 0x800 && code <= 0xffff) {
  499. bytes.push((code >> 12) | 0xe0)
  500. bytes.push(((code >> 6) & 0x3f) | 0x80)
  501. bytes.push((code & 0x3f) | 0x80)
  502. } else if (code >= 0x80 && code <= 0x7ff) {
  503. bytes.push((code >> 6) | 0xc0)
  504. bytes.push((code & 0x3f) | 0x80)
  505. } else {
  506. bytes.push(code)
  507. }
  508. }
  509. return bytes
  510. }
  511. export default {
  512. onBluetoothAdapterStateChange,
  513. openBluetoothAdapter,
  514. onBluetoothDeviceFound,
  515. startBluetoothDevicesDiscovery,
  516. stopBluetoothDevicesDiscovery,
  517. onBLEConnectionStateChange,
  518. createBLEConnection,
  519. closeBLEConnection,
  520. onBLECharacteristicValueChange,
  521. writeBLECharacteristicValue,
  522. }