网站开发与维护好找工作吗,淮安网站优化,苏州建筑网,网页代码教程uniapp小程序连接蓝牙设备 一、初始化蓝牙模块二、开始搜索三、连接蓝牙四、监听特征值变化五、调用示例utils.js文件 一、初始化蓝牙模块 这一步是必须的#xff0c;在开发项目过程中#xff0c;初始化蓝牙模块之后#xff0c;紧接着就要开启一些监听的api#xff0c;供后… uniapp小程序连接蓝牙设备 一、初始化蓝牙模块二、开始搜索三、连接蓝牙四、监听特征值变化五、调用示例utils.js文件 一、初始化蓝牙模块 这一步是必须的在开发项目过程中初始化蓝牙模块之后紧接着就要开启一些监听的api供后续设备读写数据时监听变化。 initBLE(callback) {//提前定义变量直接在uni的api中使用this是不可以的var self this;// 第一步初始化蓝牙模块uni.openBluetoothAdapter({success: function (e) {utils.toast(初始化蓝牙适配器成功);},fail: function (e) {utils.toast(初始化蓝牙适配器失败 : JSON.stringify(e));},});// 检查蓝牙适配器状态变化// 这一步主要是为了在连接成功蓝牙之后关闭蓝牙搜索蓝牙搜索非常耗费性能uni.onBluetoothAdapterStateChange(function (e) {self.bluetooth.available e.available;if (!e.available) {utils.toast(蓝牙适配器不可用);if (self.bluetooth.startDiscovery) {self.bluetooth.startDiscovery false;self.stopBluetoothDevicesDiscovery();}}});// 监听搜索到设备uni.onBluetoothDeviceFound(function (e) {// 当搜索到设备后可以在e.devices中获取到设备信息列表if (!e.devices) return;for (var i 0; i e.devices.length; i) {var device e.devices[i];for (var j 0; j self.discoveryList.length; j) {var item self.discoveryList[j];// 去重if (item.deviceId device.deviceId) {return;}}self.discoveryList.push(device);}});// 监听蓝牙设备连接变化uni.onBLEConnectionStateChange(function (e) {// 该方法回调中可以用于处理连接意外断开等异常情况self.currentDeviceStatus e.connected ? 1 : 2;// 在连续盘点过程中是不允许断开的万一因为其他什么原因断开了则尝试停止连续盘点if (!e.connected self.inventoryLabelForm.looping) {self.sendStopLoopInventoryCmd(); //停止盘点}});// 读数据uni.onBLECharacteristicValueChange(function (e) {if (e.deviceId ! self.currentDevice.deviceId) return;var value self.buffer2Hex(e.value);console.log(e); //查看是否有R20固定返回值utils.toast(读数据178 JSON.stringify(e));self.lastRcvData value;self.doRcvData();});self.historyList utils.getHistoryList();// 如果有cb回调函数则需要停止下拉刷新if (callback) {// setTimeout这里等待一下上面的异步初始化setTimeout(() {callback();}, 1000);}},二、开始搜索 以上只是蓝牙的初始化操作要想真正实现蓝牙连接从第二步开始 // 开启蓝牙搜索服务startBluetoothDevicesDiscovery() {var self this;// 小程序环境需要等待一下不然会报错setTimeout(() {// 开始搜寻附近的蓝牙外围设备uni.startBluetoothDevicesDiscovery({allowDuplicatesKey: false,success: function (e) {self.bluetooth.discoverying true;//开启搜索成功此时初始化中定义的onBluetoothDeviceFound会自动执行},fail: function (e) {utils.toast(开始搜索蓝牙设备失败 : JSON.stringify(e));},});}, 1000);},三、连接蓝牙 目前为止我们已经搜索到蓝牙设备了下面要做的就是在蓝牙列表中选择对应的蓝牙设备进行连接 // 连接设备onConnectDevice(device) {// device是选择的设备对象在这可以取到设备的deviceId供后续使用var self this;this.onCloseDiscoveryDialog();this.onCloseHistoryDialog();this.currentDevice device;this.currentDeviceStatus 3;this.lastRcvData ;// 创建一个BLE连接uni.createBLEConnection({deviceId: device.deviceId,//这里使用设备id来创建连接success: function (e) {// 创建完成后获取服务这在ios中是必须的否则会导致后面读取数据失败uni.getBLEDeviceServices({// 这里的 deviceId 需要已经通过 createBLEConnection 与对应设备建立链接deviceId: device.deviceId,success(res) {// 获取特征值这在ios中是必须的否则会导致后面读取数据失败uni.getBLEDeviceCharacteristics({// 这里的 deviceId 需要已经通过 createBLEConnection 与对应设备建立链接deviceId: device.deviceId,// 这里的 serviceId 需要在 getBLEDeviceServices 接口中获取serviceId: RX_SERVICE_UUID, //因为这里使用的是固定服务所以事先定义过常量了这里直接使用success(res) {// 创建连接-获取服务-获取特征值之后就可以开启nofity功能了self.enableBleNotify(device);},fail() {},});},});// 开启nofity功能self.enableBleNotify(device);},fail: function (e) {utils.toast(连接蓝牙设备失败 : JSON.stringify(e));self.currentDeviceStatus 2;},});// 保存设备到历史记录里var flag true;for (var i 0; i this.historyList.length; i) {var item this.historyList[i];if (item.deviceId device.deviceId) {this.historyList[i] device;flag false;}}if (flag) {this.historyList.push(device);}utils.saveHistoryList(this.historyList);},四、监听特征值变化 enableBleNotify(device) {// 这里监听时,ios测试需要有点延迟,安卓的话,只在测试机上测试过,不需要延迟// 这里延迟1秒兼容,反正差距不大setTimeout(function () {uni.notifyBLECharacteristicValueChange({state: true,deviceId: device.deviceId,serviceId: RX_SERVICE_UUID,characteristicId: R_UUID,success: function (e) {//到了此时蓝牙才算真正的连接成功},fail: function (e) {},});}, 1000);},五、调用示例 这里以单次盘点为例 // 单步盘点标签async onOneStepInventory() {var self this;if (!this.checkDeviceConnect()) return;this.inventoryLabelForm.startTime utils.currentTimeMillis(); //获取盘点时间的// 单步盘点关闭enableRssithis.inventoryLabelForm.enableRssi false;// 发送固定值await this.sendR20Hex(); //这里是定制需要没有可以省去var cmd this.generateUHFProtocl(0x80, utils.number2Hex(5000, 2));self.sendData(cmd);},//发送固定值async sendR20Hex() {await this.sendData(A55A0029F011D75238EE46C3ECFFCE3B9AFC093ACC13F711A6ADF3FF76ACE59A8DF1BA704E22EC0D0A);},//写入操作发送数据连续存盘指令自行实现了不调用该方法async sendData(hexStr, serviceId, characteristicId) {if (utils.isBlank(hexStr)) return;serviceId serviceId || RX_SERVICE_UUID;characteristicId characteristicId || W_UUID;var self this;var sendData;// ble发送数据时需要分包最多20字节if (hexStr.length 40) {sendData hexStr.substr(0, 40);hexStr hexStr.substr(40, hexStr.length - 40);} else {sendData hexStr;hexStr null;}this.logSend(sendData);var buffer new ArrayBuffer(sendData.length / 2);var bufView new Uint8Array(buffer);for (var i 0; i sendData.length; i 2) {bufView[i / 2] parseInt(sendData.substr(i, 2), 16);}//这里写了一个promise是为了在执行正常操作之前先执行固定值操作return new Promise((resolve, reject) {uni.writeBLECharacteristicValue({deviceId: self.currentDevice.deviceId,serviceId: serviceId,characteristicId: characteristicId,value: buffer,success: async function (e) {if (hexStr) {//超过20字节 递归循环写入await self.sendData(hexStr);}console.log(写入数据成功391 sendData);// 由于写字节限制如果还有未发送完的数据接着继续发送resolve();},fail: function (e) {},});});},
utils.js文件 这里主要存放一些转换方法上面用到的utils.xx方法可以在此处查看 export default {alert: function (content, title 提示) {uni.showModal({title,content,showCancel: false,success: function (res) {},});},confirm: function (content, title 提示) {uni.showModal({title,content,success: function (res) {if (res.confirm) {console.log(用户点击确定);} else if (res.cancel) {console.log(用户点击取消);}},});},toast: function (title, duration 1000) {uni.showToast({title,icon: none,duration,});},showWaiting: function (title 加载中) {uni.showLoading({title,});},closeWaiting: function () {uni.hideLoading();},actionSheet: function (itemList) {uni.showActionSheet({itemList,success: function (res) {console.log(选中了第 (res.tapIndex 1) 个按钮);},fail: function (res) {console.log(res.errMsg);},});},saveHistoryList: function (list) {try {uni.setStorageSync(history_list, JSON.stringify(list));} catch (e) {// error}},getHistoryList: function () {try {const value uni.getStorageSync(history_list);if (value) {return JSON.parse(value);} else {return [];}} catch (e) {// error}},clearHistoryList: function () {try {uni.removeStorageSync(history_list);} catch (e) {// error}},leftPad: function (value, length, fill) {while (length - value.length 0) {value fill value;}return value;},number2Hex: function (value, byteLength) {value parseInt(value);var hex value.toString(16).toUpperCase();byteLength byteLength || hex.length / 2 (hex.length % 2);return this.leftPad(hex, byteLength * 2, 0);},bin2Hex: function (value, byteLength) {byteLength byteLength || 1;byteLength Math.max(value.length / 8 (value.length % 8 0 ? 1 : 0),byteLength);value this.leftPad(value, byteLength * 8, 0);var hex ;for (var i 0; i value.length; i 8) {hex this.number2Hex(parseInt(value.substr(i, 8), 2), 1);}return hex;},isNull: function (value) {if (value null) return true;if (undefined typeof value) return true;return false;},isString: function (value) {return [object String] Object.prototype.toString.call(value);},isBlank: function (value) {if (this.isNull(value)) return true;if (!this.isString(value)) return true;if (value.trim().length 0) return true;return false;},str2Hex: function (str) {var hex ;for (var i 0; i str.length; i) {hex this.number2Hex(str.charCodeAt(i), 1);}return hex;},currentTimeMillis: function () {return new Date().getTime();},hex2ByteArray: function (hex) {var result [];for (var i 0; i hex.length; i 2) {var value parseInt(hex.substr(i, 2), 16);if (value 127) {value - 0x100;}result.push(value);}return result;},/*** hex转字符串* param {Object} hex* param {Object} charset 编码格式默认为utf-8*/hex2Str: function (hex, charset utf-8) {var bytesArray this.hex2ByteArray(hex);try {var str;// 创建一个TextDecoder对象指定所需的编码格式const decoder new TextDecoder(charset);// 将ByteArray转换为字符串str decoder.decode(bytesArray);return str;} catch (e) {this.toast(错误的编码格式);}},
};