ecBLEApp.js 13 KB

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