bluetoolth.js 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323
  1. /**
  2. * @export
  3. * @param {string} name 微信api的名称 ,如 uniAsyncPromise("getSystemInfo",options)
  4. * @param {object} options 除了success 和 fail 的其他参数
  5. * @returns
  6. */
  7. export function uniAsyncPromise(name, options) {
  8. return new Promise((resolve, reject) => {
  9. uni[name]({
  10. ...(options || {}),
  11. // ...options,
  12. success: (res) => {
  13. resolve(res);
  14. },
  15. fail: (err) => {
  16. reject(err);
  17. }
  18. });
  19. });
  20. }
  21. //微信小程序向蓝牙打印机发送数据进行打印的坑:
  22. //小程序api向蓝牙打印机发送数据打印,发送的任何内容都应该要转成二进制数据,而且蓝牙打印的文本编码是GBK的,发送中文需转成GBK编码再转成二进制数据发送
  23. //发送打印机指令也要转成二进制数据发送
  24. //蓝牙打印机一次接收的二级制数据有限制,不同的系统不同的蓝牙设备限制可能不同,微信建议一次20个字节,需做递归分包发送
  25. //发送完要打印的内容后,一定要发送一个打印的指令才能顺利打印 (有些指令就不需要)
  26. //一、初始化蓝牙、开始检索蓝牙设备
  27. // { allowDuplicatesKey: true, interval: 500}
  28. export function openBlue() {
  29. return uniAsyncPromise('openBluetoothAdapter')
  30. }
  31. export function startBluetoothDevicesDiscovery(option) {
  32. console.log('开始蓝牙扫描');
  33. uniAsyncPromise('startBluetoothDevicesDiscovery', option).then((res) => {
  34. console.log('正在搜寻蓝牙设备', res);
  35. });
  36. }
  37. export function getConnectedBluetoothDevices(option) {
  38. console.log('开始获取已连接设备');
  39. return uniAsyncPromise('getConnectedBluetoothDevices', option)
  40. }
  41. //二、
  42. /**
  43. *
  44. *
  45. * @export
  46. * @param {function} getDevices uni.getBluetoothDevices的监听回调函数
  47. */
  48. export function onfindBlueDevices(getDevices) {
  49. //监听寻找到新设备的事件
  50. uni.onBluetoothDeviceFound((devices)=>{
  51. //获取在蓝牙模块生效期间所有已发现的蓝牙设备
  52. uniAsyncPromise('getBluetoothDevices').then((res) => {
  53. getDevices && getDevices(res.devices);
  54. });
  55. });
  56. }
  57. /**
  58. * @export
  59. * @param {function} stopBlueDevicesDiscovery 关闭蓝牙扫描
  60. */
  61. export function stopBlueDevicesDiscovery() {
  62. //监听寻找到新设备的事件
  63. console.log('停止蓝牙扫描');
  64. return uniAsyncPromise('stopBluetoothDevicesDiscovery').then((res) => {
  65. console.log('停止搜寻蓝牙设备', res);
  66. });
  67. }
  68. //三、连接蓝牙设备
  69. /**
  70. * @export
  71. * @param {function} createBLEConnection
  72. * @param {number} deviceId 蓝牙设备id
  73. */
  74. export function createBLEConnection(deviceId, sucess, fail) {
  75. //连接蓝牙设备
  76. console.log('连接蓝牙设备', deviceId);
  77. uniAsyncPromise("createBLEConnection", {
  78. deviceId
  79. })
  80. .then(res => {
  81. //连接成功可选择停止搜索蓝牙
  82. stopBlueDevicesDiscovery();
  83. console.log('连接成功');
  84. sucess && sucess({
  85. res: res,
  86. });
  87. })
  88. .catch(res => {
  89. console.log('连接设备异常' + res);
  90. fail && fail({
  91. res: res,
  92. });
  93. })
  94. /*.finally(res=>{
  95. console.log('连接成功');
  96. sucess && sucess({
  97. res: res,
  98. });
  99. });*/
  100. }
  101. export function closeBLEConnection(deviceId) {
  102. console.log('断开蓝牙设备', deviceId);
  103. uniAsyncPromise("closeBLEConnection", {
  104. deviceId
  105. })
  106. .then(res => {
  107. console.log('BLEDisconnect complete', res);
  108. })
  109. .catch(res => {
  110. console.log('断开设备异常' + res);
  111. })
  112. /*.finally(res=>{
  113. console.log('BLEDisconnect complete', res);
  114. }); */
  115. }
  116. //四、连接成功后, 获取蓝牙设备的service服务
  117. // uniAsyncPromise("getBLEDeviceServices",{deviceId:""}).then(res=>{})
  118. export function getBLEDeviceServices(deviceId, success, fail) {
  119. console.log('获取ServiceId', deviceId);
  120. //加延迟避免取不到service
  121. setTimeout(()=>{
  122. uniAsyncPromise("getBLEDeviceServices", {
  123. deviceId:deviceId
  124. })
  125. .then(res => {
  126. console.log('服务', res);
  127. success && success({
  128. serviceId: res.services,
  129. });
  130. })
  131. .catch((res) => {
  132. //getBLEDeviceServices(deviceId, success, fail);
  133. console.log('获取ServiceId异常' + res);
  134. fail && fail({
  135. res: res,
  136. });
  137. });
  138. },1000)
  139. }
  140. //五、获取的service服务可能有多个,递归获取特征值(最后要用的是能读,能写,能监听的那个值的uuid作为特征值id)
  141. /**
  142. *
  143. *
  144. * @export
  145. * @param {number} deviceId 蓝牙设备id
  146. * @param {array} services uniAsyncPromise("getBLEDeviceServices",{deviceId:""}).then(res=>{})获取的res.services
  147. * @param {function} success 成功取得有用特征值uuid的回调函数
  148. */
  149. export function getDeviceCharacteristics(deviceId, services, success, fail) {
  150. //services = services.slice(0);
  151. console.log('获取Characteristics', deviceId, services);
  152. if (services.length) {
  153. const serviceId = services.shift().uuid;
  154. console.log('ServceID ', serviceId);
  155. uniAsyncPromise('getBLEDeviceCharacteristics', {
  156. deviceId,
  157. serviceId,
  158. })
  159. .then((res) => {
  160. console.log('getBLEDeviceCharacteristics', deviceId, serviceId, res);
  161. let finished = false;
  162. let write = false;
  163. let notify = false;
  164. let indicate = false;
  165. var readId;
  166. var writeId;
  167. //有斑马品牌的一款打印机中res.characteristics的所有uuid都是相同的,找所有的properties存在(notify || indicate) && write这种情况就说明这个uuid是可用的(不确保所有的打印机都能用这种方式取得uuid,在主要测试得凯盛诺打印机res.characteristic只有一个uuid,所以也能用这个方式)
  168. for (var i = 0; i < res.characteristics.length; i++) {
  169. if (!notify) {
  170. notify = res.characteristics[i].properties.notify;
  171. if (notify) readId = res.characteristics[i].uuid;
  172. }
  173. if (!indicate) {
  174. indicate = res.characteristics[i].properties.indicate;
  175. if (indicate) readId = res.characteristics[i].uuid;
  176. }
  177. if (!write) {
  178. write = res.characteristics[i].properties.write;
  179. writeId = res.characteristics[i].uuid;
  180. }
  181. if ((notify || indicate) && write) {
  182. /* 获取蓝牙特征值uuid */
  183. success &&
  184. success({
  185. serviceId,
  186. writeId: writeId,
  187. readId: readId,
  188. });
  189. finished = true;
  190. break;
  191. }
  192. }
  193. if (!finished) {
  194. getDeviceCharacteristics(deviceId, services, success, fail);
  195. }
  196. })
  197. .catch((res) => {
  198. getDeviceCharacteristics(deviceId, services, success, fail);
  199. });
  200. } else {
  201. fail && fail();
  202. }
  203. }
  204. //六、启动notify 蓝牙监听功能 然后使用 uni.onBLECharacteristicValueChange用来监听蓝牙设备传递数据
  205. /**
  206. * @export
  207. * @param {object} options
  208. * {
  209. deviceId,//蓝牙设备id
  210. serviceId,//服务id
  211. characteristicId,//可用特征值uuid
  212. }
  213. * @param {function} onChange 监听蓝牙设备传递数据回调函数
  214. */
  215. export function onGetBLECharacteristicValueChange(options, onChange = function() {}) {
  216. console.log('deviceId ', options.deviceId);
  217. console.log('serviceId ', options.serviceId);
  218. console.log('characteristicId ', options.characteristicId);
  219. uniAsyncPromise('notifyBLECharacteristicValueChange', {
  220. state: true,
  221. ...options,
  222. }).then((res) => {
  223. console.log('onBLECharacteristicValueChange ');
  224. uni.onBLECharacteristicValueChange(onChange);
  225. });
  226. }
  227. //七、发送数据(递归分包发送)
  228. /**
  229. * @export
  230. * @param {object} options
  231. * {
  232. deviceId,
  233. serviceId,
  234. characteristicId,
  235. value [ArrayBuffer],
  236. lasterSuccess,
  237. }
  238. */
  239. export function senBlData(deviceId, serviceId, characteristicId,uint8Array,lasterSuccess) {
  240. console.log('************deviceId = [' + deviceId + '] serviceId = [' + serviceId + '] characteristics=[' +characteristicId+ "]")
  241. var uint8Buf = Array.from(uint8Array);
  242. function split_array(datas,size){
  243. var result = {};
  244. var j = 0
  245. if(datas.length < size) {
  246. size = datas.length
  247. }
  248. for (var i = 0; i < datas.length; i += size) {
  249. result[j] = datas.slice(i, i + size)
  250. j++
  251. }
  252. return result
  253. }
  254. var sendloop = split_array(uint8Buf, 20);
  255. console.log(sendloop.length)
  256. function realWriteData(sendloop, i) {
  257. var data = sendloop[i]
  258. if(typeof(data) == "undefined"){
  259. lasterSuccess()
  260. return
  261. }
  262. //console.log("第【" + i + "】次写数据"+data)
  263. var buffer = new ArrayBuffer(data.length)
  264. var dataView = new DataView(buffer)
  265. for (var j = 0; j < data.length; j++) {
  266. dataView.setUint8(j, data[j]);
  267. }
  268. uni.writeBLECharacteristicValue({
  269. deviceId,
  270. serviceId,
  271. characteristicId,
  272. value: buffer,
  273. success(res) {
  274. console.log('发送成功',i)
  275. setTimeout(()=>{
  276. realWriteData(sendloop, i + 1);
  277. },100)
  278. },
  279. fail(e) {
  280. console.log('发送数据失败',e)
  281. }
  282. })
  283. }
  284. var i = 0;
  285. realWriteData(sendloop, i);
  286. }
  287. /**
  288. * toast显示捕获的蓝牙异常
  289. */
  290. export function catchToast(err) {
  291. const errMsg = {
  292. 10000: '未初始化蓝牙模块',
  293. 10001: '蓝牙未打开',
  294. 10002: '没有找到指定设备',
  295. 10003: '连接失败',
  296. 10004: '没有找到指定服务',
  297. 10005: '没有找到指定特征值',
  298. 10006: '当前连接已断开',
  299. 10007: '当前特征值不支持此操作',
  300. 10008: '系统上报异常',
  301. 10009: '系统版本低于 4.3 不支持BLE'
  302. };
  303. let coode = err.errCode ? err.errCode.toString() : '';
  304. let msg = errMsg[coode];
  305. plus.nativeUI.toast(msg || coode, {
  306. align: 'center',
  307. verticalAlign: 'center'
  308. });
  309. }