ecBLEApp.js 12 KB

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