DoormasterSDK-V1.4.js 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367
  1. /**
  2. * 1. 获取本机蓝牙适配器状态 wx.getBluetoothAdapterState
  3. * 2. 初始化蓝牙适配器 wx.openBluetoothAdapter()
  4. * 3. 启动蓝牙发现 wx.wx.startBluetoothDevicesDiscovery()
  5. * 4. 获取扫描到的所有设备 wx.getBluetoothDevices()
  6. *
  7. *
  8. * 参数:
  9. * @callback function 回调函数,用于接收返回值
  10. *
  11. * 返回值:
  12. * ret:{isBluetoothAvailable:true, isBluetoothSearching:true, scanList:[]}
  13. * isBluetoothAvailable boolean 蓝牙适配器状态,true表示初始化蓝牙适配器成功
  14. * isBluetoothSearching boolean 蓝牙搜索状态,true表示开启蓝牙发现成功
  15. * scanList array 搜索的设备列表
  16. */
  17. function scanDevices(callback) {
  18. if (typeof callback != "function") {
  19. // console.log('Parameter callback is not a function');
  20. return;
  21. }
  22. ; //scanList格式如下:
  23. //[{RSSI:-xx, advertisServiceUUIDs:[], deviceId:'', name:''},{...}]
  24. //注意:Android系统的deviceId是设备的mac地址,iOS系统的deviceId是设备的UUID
  25. var ret = {
  26. isBluetoothAvailable: false,
  27. isBluetoothSearching: false,
  28. scanList: []
  29. };
  30. /**
  31. * 获取蓝牙适配器状态
  32. *
  33. */
  34. uni.getBluetoothAdapterState({
  35. success: function (res) {
  36. // console.log("---getBluetoothAdapterState--success:", res)
  37. ret.isBluetoothAvailable = res.available;
  38. ret.isBluetoothSearching = res.discovering;
  39. },
  40. fail: function (res) {
  41. console.log("---getBluetoothAdapterState--fail:", res);
  42. },
  43. complete: function (res) {
  44. /**
  45. * 初始化蓝牙
  46. */
  47. if (!ret.isBluetoothAvailable) {
  48. uni.openBluetoothAdapter({
  49. success: function (res) {
  50. // console.log("---openBluetoothAdapter--success:", res);
  51. ret.isBluetoothAvailable = true;
  52. startBluetoothDiscoveryAndScanDevice(ret, callback);
  53. },
  54. fail: function (res) {
  55. // console.log("---openBluetoothAdapter--fail:", res);
  56. callback(ret); //蓝牙初始化失败,直接返回,不进行后续搜索操作
  57. return;
  58. }
  59. });
  60. } else {
  61. startBluetoothDiscoveryAndScanDevice(ret, callback);
  62. }
  63. }
  64. });
  65. }
  66. function startBluetoothDiscoveryAndScanDevice(ret, callback) {
  67. /**
  68. * 开启蓝牙发现
  69. */
  70. if (!ret.isBluetoothSearching) {
  71. uni.startBluetoothDevicesDiscovery({
  72. services: [],
  73. allowDuplicatesKey: true,
  74. success: function (res) {
  75. // console.log("---startBluetoothDevicesDiscovery--success: ", res);
  76. ret.isBluetoothSearching = res.isDiscovering;
  77. },
  78. fail: function (res) {// console.log('---startBluetoothDevicesDiscovery--fail:', res);
  79. // 刷新页面后,开启蓝牙发现失败,暂时忽略10008错误
  80. // if (res.errCode != 10008) {
  81. // callback(ret);
  82. // }
  83. },
  84. complete: function (res) {
  85. // console.log('---startBluetoothDevicesDiscovery--complete:', res)
  86. if (res.errCode === 0 || res.errCode === 10008) {
  87. scanBluetoothDevice(ret, callback);
  88. } else {
  89. callback(ret);
  90. }
  91. }
  92. });
  93. } else {
  94. scanBluetoothDevice(ret, callback);
  95. }
  96. }
  97. function scanBluetoothDevice(ret, callback) {
  98. /**
  99. * 获取扫描到的所有设备
  100. */
  101. setTimeout(function () {
  102. uni.getBluetoothDevices({
  103. success: function (res) {
  104. //{devices: Array[11], errMsg: "getBluetoothDevices:ok"}
  105. // console.log('---getBluetoothDevices--success:', res);
  106. console.log('---getBluetoothDevices--success:', res.devices);
  107. var devArr = []; //根据广播UUID进行设备列表筛选
  108. for (var i = 0; i < res.devices.length; i++) {
  109. if (!('advertisServiceUUIDs' in res.devices[i])) {
  110. delete res.devices[i];
  111. continue;
  112. }
  113. for (let j = 0; j < res.devices[i].advertisServiceUUIDs.length; j++) {
  114. if (res.devices[i].advertisServiceUUIDs[j].toUpperCase().indexOf('FEF5') != -1) {
  115. var devSn = res.devices[i].name; // console.log("devSn:", devSn);
  116. if (devSn.indexOf("-") >= 0) {
  117. devArr.push({
  118. "deviceId": res.devices[i].deviceId,
  119. "name": devSn.split("-")[1],
  120. "RSSI": res.devices[i].RSSI
  121. });
  122. }
  123. }
  124. }
  125. }
  126. ret.scanList = devArr;
  127. callback(ret);
  128. },
  129. fail: function (res) {
  130. console.log('---getBluetoothDevices--fail:', res);
  131. callback(ret);
  132. }
  133. });
  134. }, 3000);
  135. }
  136. /**
  137. *
  138. * 参数:
  139. * @deviceid String 参考scanDevices方法
  140. * @sendData String 发送到设备的开门指令
  141. * @callback function 回调函数,用于处理返回值
  142. *
  143. * 返回值:
  144. * ret{errCode:'', errMsg:'', receiveData:''}
  145. * errCode: 错误码, 0表示开门成功
  146. * errMsg: 错误信息,Ok表示开门成功
  147. * receiveData: 接收的设备消息,消息内容为ac1c8表示开门成功
  148. */
  149. function openDoor(deviceid, sendData, callback) {
  150. var ret = {
  151. errCode: 0,
  152. errMsg: 'Ok',
  153. receiveData: ''
  154. };
  155. if (typeof callback != "function") {
  156. ret.errCode = 6;
  157. ret.errMsg = 'parameter callback is not a function';
  158. callback(ret);
  159. return;
  160. } else if (typeof deviceid != "string" || deviceid === '') {
  161. ret.errCode = 4;
  162. ret.errMsg = 'deviceId is not a string type or is empty';
  163. callback(ret);
  164. return;
  165. } else if (typeof sendData != "string" || sendData === '') {
  166. ret.errCode = 5;
  167. ret.errMsg = 'sendData is not a string type or is empty';
  168. callback(ret);
  169. return;
  170. }
  171. var serviceId = '';
  172. var characteristics = [];
  173. var notifyCharacter = '';
  174. var writeCharacter = '';
  175. var readCharacter = '';
  176. var deviceId = deviceid.toUpperCase(); //BLE蓝牙连接
  177. uni.createBLEConnection({
  178. deviceId: deviceId,
  179. success: function (res) {
  180. // console.log('---createBLEConnection--success:', res);
  181. /**
  182. * 监听特定BLE设备连接状态变化
  183. */
  184. uni.onBLEConnectionStateChange(function (res) {// 该方法回调中可以用于处理连接意外断开等异常情况
  185. // console.log(`device ${res.deviceId} state has changed, connected: ${res.connected}`);
  186. }); //获取指定设备的所有服务
  187. uni.getBLEDeviceServices({
  188. deviceId: deviceId,
  189. success: function (res) {
  190. //筛选指定的服务UUID
  191. for (var i = 0; i < res.services.length; i++) {
  192. if (res.services[i].uuid.toLowerCase().indexOf('0886') != -1 || res.services[i].uuid.toLowerCase().indexOf('ffe0') != -1) {
  193. serviceId = res.services[i].uuid;
  194. break;
  195. }
  196. }
  197. /**
  198. * 获取指定服务下的所有特征值
  199. */
  200. uni.getBLEDeviceCharacteristics({
  201. deviceId: deviceId,
  202. serviceId: serviceId,
  203. success: function (res) {
  204. for (var i = 0; i < res.characteristics.length; i++) {
  205. if (res.characteristics[i].uuid.toLowerCase().indexOf('878b') != -1) {
  206. notifyCharacter = res.characteristics[i].uuid;
  207. } else if (res.characteristics[i].uuid.toLowerCase().indexOf('878c') != -1) {
  208. writeCharacter = res.characteristics[i].uuid;
  209. readCharacter = res.characteristics[i].uuid;
  210. }
  211. }
  212. /**
  213. * 启用低功耗蓝牙设备特征值变化时的 notify 功能
  214. */
  215. uni.notifyBLECharacteristicValueChange({
  216. deviceId: deviceId,
  217. serviceId: serviceId,
  218. characteristicId: notifyCharacter,
  219. state: true,
  220. success: function (res) {// console.log('---notifyBLECharacteristicValueChange--success:', res.errMsg);
  221. }
  222. });
  223. /**
  224. * 监听低功耗蓝牙设备的特征值变化
  225. */
  226. uni.onBLECharacteristicValueChange(function (res) {
  227. // console.log(`characteristic ${res.characteristicId} has changed, now is ${res.value}`);
  228. let buffer = res.value;
  229. let dataView = new DataView(buffer);
  230. let receiveData = '';
  231. for (let i = 0; i < buffer.byteLength; i++) {
  232. receiveData += dataView.getUint8(i).toString(16);
  233. }
  234. if (sendData.length <= 20) {
  235. // 向蓝牙设备发送20字节16进制数据,如果不超过20字节数据,监听低功耗蓝牙设备的特征值变化,如果超过,就不监听
  236. if (receiveData != 'ac1c8') {
  237. ret.errCode = 7;
  238. ret.errMsg = "paramater 'sendData' is incorrect.";
  239. }
  240. ret.receiveData = receiveData;
  241. callback(ret);
  242. }
  243. }); //向蓝牙设备发送20字节16进制数据,超过20字节数据,分包续传
  244. var data = sendData;
  245. var buffer_size = data.length > 20 ? data.length / 2 : 20;
  246. var buffer = new ArrayBuffer(buffer_size);
  247. var dataView = new DataView(buffer);
  248. for (let i = 0; i < data.length / 2; i++) {
  249. var subData = data.slice(2 * i, 2 * i + 2);
  250. dataView.setUint8(i, parseInt('0x' + subData));
  251. }
  252. /**
  253. * 写入特征值下的二进制数据
  254. *
  255. */
  256. setTimeout(function () {
  257. var count = 0;
  258. if (buffer_size == 20) {
  259. count = 1;
  260. } else {
  261. count = 2;
  262. }
  263. var send_data_array = new Array();
  264. for (let i = 0; i < count; i++) {
  265. var start_buffer = i * 20;
  266. var end_buffer = (i + 1) * 20;
  267. if (end_buffer > buffer.byteLength) {
  268. end_buffer = buffer.byteLength;
  269. }
  270. var buffer_content = buffer.slice(start_buffer, end_buffer);
  271. if (buffer_content.byteLength > 0) {
  272. send_data_array.push(buffer_content);
  273. }
  274. }
  275. var send_index = 0;
  276. send_bledata_device(send_index, send_data_array);
  277. function send_bledata_device(send_index, send_data_array) {
  278. // console.log("----deviceId=" + deviceId + "--serviceId=" + serviceId + "--send_index=" + send_index);
  279. uni.writeBLECharacteristicValue({
  280. deviceId: deviceId,
  281. serviceId: serviceId,
  282. characteristicId: writeCharacter,
  283. value: send_data_array[send_index],
  284. success: function (res) {
  285. console.log('++++++++writeBLECharacteristicValue-success:', res);
  286. if (send_index < send_data_array.length - 1) {
  287. setTimeout(function () {
  288. send_index += 1;
  289. send_bledata_device(send_index, send_data_array);
  290. }, 250);
  291. } else {
  292. ret.errCode = 0;
  293. callback(ret);
  294. }
  295. },
  296. fail: function (res) {
  297. ret.errCode = res.errCode; //3
  298. ret.errMsg = 'writeBLECharacteristicValue fail';
  299. console.log('++++++++writeBLECharacteristicValue-fail-errorCode:', ret.errCode);
  300. callback(ret);
  301. }
  302. });
  303. }
  304. }, 500);
  305. },
  306. fail: function (res) {
  307. ret.errCode = res.errCode; //2
  308. ret.errMsg = 'getBLEDeviceCharacteristics fail';
  309. callback(ret);
  310. }
  311. });
  312. }
  313. });
  314. },
  315. fail: function (res) {
  316. ret.errCode = res.errCode; //1
  317. ret.errMsg = 'createBLEConnection fail';
  318. callback(ret);
  319. }
  320. });
  321. }
  322. module.exports = {
  323. scanDevices: scanDevices,
  324. openDoor: openDoor
  325. };