| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682 |
- // 灵敏度
- const BLEDIS = 0.9;
- // 设备Id
- var deviceId = "";
- // 服务Id
- var serviceId = "";
- var notifyCharacteristicId = "";
- var writeCharacteristicId = "";
- var currentInstruction = "";
- var showToast = false;
- var bListenerUpdate = false;
- var bListenerJson = false;
- var bListenerMac = false;
- function initData() {
- // 设备Id
- this.deviceId = "";
- // 服务Id
- this.serviceId = "";
- this.notifyCharacteristicId = "";
- this.writeCharacteristicId = "";
- this.currentInstruction = "";
- this.showToast = false;
- this.bListenerUpdate = false;
- this.bListenerJson = false;
- this.bListenerMac = false;
- }
- function openBluetoothAdapter(context) {
- let {
- success,
- fail,
- complete
- } = context;
- //#ifdef H5
- console.warn('h5不加载蓝牙模块');
- return;
- //#endif
- let self = this;
- // 初始化蓝牙适配器
- uni.openBluetoothAdapter({
- success: res => {
- // console.log("初始化蓝牙成功:", res);
- if (success)
- success(res);
- },
- fail: res => {
- // console.error("openBluetoothAdapter == ", res);
- if (fail)
- fail(res);
- },
- complete: res => {
- // console.warn("************openBluetoothAdapter complete == ", res);
- if (complete)
- complete(res);
- }
- })
- }
- function onBLEConnectionStateChange() {
- //#ifdef H5
- console.warn('h5不加载蓝牙模块');
- return;
- //#endif
- uni.onBLEConnectionStateChange(res => {
- // 该方法回调中可以用于处理连接意外断开等异常情况
- console.log(`蓝牙连接状态 -------------------------->`, JSON.stringify(res));
- if (!res.connected) {
- // if (this.isStop) return;
- // console.log('断开低功耗蓝牙成功:');
- uni.$emit('callbackCloseBLE');
- //todo 在这里尝试重连
- //关闭连接
- // this.closeBluetoothAdapter();
- }
- });
- }
- /**
- * 连接低功耗蓝牙设备。
- * 若APP在之前已有搜索过某个蓝牙设备,并成功建立连接,可直接传入之前搜索获取的 deviceId 直接尝试连接该设备,无需进行搜索操作。
- */
- function createBLEConnection(item, success, fail) {
- let self = this;
- self.initData();
- self.deviceId = item.deviceId;
- let timeout = 10000;
- uni.createBLEConnection({
- // 这里的 deviceId 需要已经通过 createBLEConnection 与对应设备建立链接
- deviceId: self.deviceId,
- timeout,
- success: res => {
- if (success) {
- success(res);
- }
- },
- fail: res => {
- if (fail)
- fail(res);
- }
- });
- }
- /**
- * 获取设备的服务ID
- */
- function getBLEDeviceServices(item, callback,getServiceList) {
- let serviceList = [];
- let self = this;
- // console.log("getBLEDeviceServices");
- uni.getBLEDeviceServices({
- deviceId: item.deviceId,
- success: res => {
- console.log("getBLEDeviceServices==", JSON.stringify(res), item);
- serviceList = res.services;
- if(serviceList.length == 0){
- uni.hideToast();
- uni.showModal({
- title:'失败',
- content:'获取服务失败,请尝试重新连接对应的模式。'
- })
- }
- if(getServiceList){
- getServiceList(serviceList);
- }
- for (let i = 0; i < serviceList.length; i++) {
- let service = serviceList[i];
- //比对service是否是F393服务
- // if (item.primaryUUID && service.uuid.indexOf(item.primaryUUID) != -1)
- if (service.uuid.toLocaleLowerCase() === item.PRIMARY_SERVICE.toLocaleLowerCase()) {
- self.serviceId = service.uuid;
- // console.log("设备的serviceId: " + self.serviceId);
- //开始获取指定服务的特征值
- self.getBLEDeviceCharacteristics(item, callback);
- break;
- }
- }
- },
- fail: failRes => {
- console.log('device services:', failRes.services)
- uni.showModal({
- title:'连接失败',
- content:'未获取到相应服务,请继续尝试连接设备。'
- })
- }
- });
- }
- /**
- * 获取指定服务的特征值
- */
- function getBLEDeviceCharacteristics(item, callback) {
- let deviceId = this.deviceId;
- let serviceId = this.serviceId;
- let characteristicsList = [];
- let self = this;
- uni.getBLEDeviceCharacteristics({
- deviceId,
- serviceId,
- success: res => {
- // console.log(JSON.stringify(res));
- // console.log("获取的" + serviceId + "服务的特征值:" + JSON.stringify(res.characteristics)+JSON.stringify(item));
- // console.log(res.characteristics);
- // console.log(item);
- // characteristicsList = res.characteristics;
- // for (let i = 0; i < characteristicsList.length; i++) {
- // let characteristic = characteristicsList[i];
- // //该特征值是否支持 notify或indicate 操作
- // if (characteristic.properties.notify || characteristic.properties.indicate) {
- // console.log("该特征值支持 notify 操作:" + characteristic.uuid);
- // self.notifyCharacteristicId = characteristic.uuid;
- // self.notifyBLECharacteristicValueChange(deviceId, serviceId);
- // }
- // if (characteristic.properties.write) {
- // console.log("该特征值支持 write 操作:" + characteristic.uuid);
- // self.writeCharacteristicId = characteristic.uuid;
- // // break;
- // }
- // }
- if (item.PRIMARY_NOTIFY != '') {
- self.notifyCharacteristicId = item.PRIMARY_NOTIFY;
- self.notifyBLECharacteristicValueChange(callback);
- }
- if (item.PRIMARY_WRITE != '') {
- self.writeCharacteristicId = item.PRIMARY_WRITE;
- }
- },
- fail: res => {
- console.log('device getBLEDeviceCharacteristics failed:', JSON.stringify(res))
- }
- })
- }
- //启用低功耗蓝牙设备特征值变化时的 notify 功能,订阅特征值。
- //注意:必须设备的特征值支持notify或者indicate才可以成功调用,具体参照 characteristic 的 properties 属性
- function notifyBLECharacteristicValueChange(callback) {
- var _self = this;
- // 启用notify功能
- // console.log("启用notify功能");
- uni.notifyBLECharacteristicValueChange({
- state: true,
- deviceId: _self.deviceId,
- serviceId: _self.serviceId,
- characteristicId: _self.notifyCharacteristicId,
- success: function(res) {
- _self.onBLECharacteristicValueChange(callback); //监听特征值变化
- },
- fail: function(res) {
- uni.showToast({
- title: 'notify启动失败',
- icon: "none",
- mask: true
- });
- }
- })
- }
- //监听低功耗蓝牙设备的特征值变化。必须先启用notify接口才能接收到设备推送的notification。
- function onBLECharacteristicValueChange(callback) {
- var self = this;
- console.log("onBLECharacteristicValueChange success");
- if (callback) {
- callback({
- notifyCharacteristicId: self.notifyCharacteristicId,
- writeCharacteristicId: self.writeCharacteristicId
- })
- }
- uni.onBLECharacteristicValueChange(function(res) {
- let box = {};
- var resValue = ab2hext(res.value); //16进制字符串
- // console.log(self.currentInstruction +","+ self.bListenerUpdate+","+self.bListenerJson);
- if (self.currentInstruction == "V" && self.showToast) {
- var resValueStr = hexToString(resValue);
- // console.log("v resValueStr:" + resValueStr);
- // uni.showToast({
- // title: resValueStr.replace(/\{|}/g,'').trim(),
- // icon: 'none',
- // duration: 5000
- // })
- let _info = {
- type: 'version',
- instruction: 'V',
- value: resValueStr.replace(/\{|}/g, '').trim()
- }
- uni.$emit('listenerBLE', _info);
- self.currentInstruction = "";
- self.showToast = false;
- return;
- } else if (self.currentInstruction == 'M' && self.bListenerMac) {
- var resValueStr = hexToString(resValue);
- // console.log(resValue);
- // console.log("m:", resValueStr.replace(/\{|}/g,''));
- // uni.showToast({
- // title: resValueStr.replace(/\{|}/g,'').trim(),
- // icon: 'none',
- // duration: 5000
- // })
- let _info = {
- type: 'mac',
- instruction: 'M',
- value: resValueStr.replace(/\{|}/g, '').trim()
- }
- uni.$emit('listenerBLE', _info);
- self.currentInstruction = "";
- self.bListenerMac = false;
- return;
- }
- //步数数据解析
- if (self.bListenerJson) {
- var resValueStr = hexToString(resValue);
- // let _info = {
- // type: 'mac',
- // instruction: 'M',
- // value: resValueStr.replace(/\{|}/g, '').trim()
- // }
- console.log(resValueStr);
- box["Json"] = resValueStr;
- uni.$emit('updateBLEDeviceJson', box);
- }
- //原始数据解析
- if (self.bListenerUpdate) {
- // console.log("min:" + min+",s:"+s+",ms:"+ms);
- //R/L 左手还是右手
- let handle = resValue.substr(6, 2);
- let axStr = resValue.substr(8, 4);
- let ayStr = resValue.substr(12, 4);
- let azStr = resValue.substr(16, 4);
- // console.log("accStr:" + axStr+","+ayStr+","+azStr);
- // console.log("hex2int:" + hexToSignedInt(axStr)+","+hexToSignedInt(ayStr)+","+hexToSignedInt(azStr));
- //一个字节最大只能表示265 2个字节可以表示65536 然后你这边做一下转换 例如00 3E 3*16+14=62 ----->0.03 g
- //(真实值= AD值 /32768 * 16)
- //0.003 = 62 / 2768 * 16
- let ax = hexToSignedInt(axStr) / 32768 * 16;
- let ay = hexToSignedInt(ayStr) / 32768 * 16;
- let az = hexToSignedInt(azStr) / 32768 * 16;
- let gxStr = resValue.substr(20, 4);
- let gyStr = resValue.substr(24, 4);
- let gzStr = resValue.substr(28, 4);
- //角速度(AD值/32768 * 2000) 角速度单位是 °/s 范围是 正负2000
- let gx = hexToSignedInt(gxStr) / 32768 * 2000;
- let gy = hexToSignedInt(gyStr) / 32768 * 2000;
- let gz = hexToSignedInt(gzStr) / 32768 * 2000;
- //毫秒
- let ms = hex2int(resValue.substr(2, 4));
- //分
- let min = hex2int(resValue.substr(32, 2));
- //秒
- let s = hex2int(resValue.substr(34, 2));
- box["handle"] = hexToString(handle);
- box["acc"] = {
- ax,
- ay,
- az
- };
- box["gyro"] = {
- gx,
- gy,
- gz
- };
- box["min"] = min;
- box["s"] = s;
- box["ms"] = ms;
- // console.log("box:" + JSON.stringify(box));
- // if (typeof obj !== 'object' && obj) {
- // // console.log("连接错误")
- // //-1为错误
- // uni.$emit("callbackBLEState", {
- // state: -1,
- // msg: "设备数据错误"
- // });
- // return;
- // }
- // if (obj.hasOwnProperty("H")) {
- // console.log("HHHH:", obj.H);
- // }
- //更新数据给webview,在game-play-web||game-play-sub绑定
- //后面更新数据都用此接口
- uni.$emit('updateBLEDeviceData', box);
- }
- });
- }
- // ArrayBuffer转16进制字符串示例
- function ab2hext(buffer) {
- var hexArr = Array.prototype.map.call(
- new Uint8Array(buffer),
- function(bit) {
- return ('00' + bit.toString(16)).slice(-2)
- }
- )
- return hexArr.join('');
- }
- // 字符串转为ArrayBuffer对象,参数为字符串
- function str2ab(str) {
- var buf = new ArrayBuffer(str.length * 2); // 每个字符占用2个字节
- var bufView = new Uint16Array(buf);
- for (var i = 0, strLen = str.length; i < strLen; i++) {
- bufView[i] = str.charCodeAt(i);
- }
- return buf;
- }
- //16进制的字符串 转换为整数
- function hex2int(hex) {
- var len = hex.length,
- a = new Array(len),
- code;
- for (var i = 0; i < len; i++) {
- code = hex.charCodeAt(i);
- if (48 <= code && code < 58) {
- code -= 48;
- } else {
- code = (code & 0xdf) - 65 + 10;
- }
- a[i] = code;
- }
- return a.reduce(function(acc, c) {
- acc = 16 * acc + c;
- return acc;
- }, 0);
- }
- //16进制转有符号的整数
- function hexToSignedInt(hex) {
- let two = parseInt(hex, 16).toString(2);
- let bitNum = hex.length * 4;
- if (two.length < bitNum) {
- while (two.length < bitNum) {
- two = "0" + two;
- }
- }
- if (two.substring(0, 1) == "0") {
- two = parseInt(two, 2);
- return two;
- } else {
- let two_unsign = "";
- two = parseInt(two, 2) - 1;
- two = two.toString(2);
- two_unsign = two.substring(1, bitNum);
- two_unsign = two_unsign.replace(/0/g, "z");
- two_unsign = two_unsign.replace(/1/g, "0");
- two_unsign = two_unsign.replace(/z/g, "1");
- two = parseInt(-two_unsign, 2);
- return two;
- }
- }
- //十六进制转ASCII码
- function hexCharCodeToStr(hexCharCodeStr) {
- var trimedStr = hexCharCodeStr.trim();
- var rawStr = trimedStr.substr(0, 2).toLowerCase() === "0x" ? trimedStr.substr(2) : trimedStr;
- var len = rawStr.length;
- if (len % 2 !== 0) {
- alert("存在非法字符!");
- return "";
- }
- var curCharCode;
- var resultStr = [];
- for (var i = 0; i < len; i = i + 2) {
- curCharCode = parseInt(rawStr.substr(i, 2), 16);
- resultStr.push(String.fromCharCode(curCharCode));
- }
- return resultStr.join("");
- }
- //ASCII码转16进制
- function strToHexCharCode(str) {
- if (str === "") {
- return "";
- } else {
- var hexCharCode = [];
- hexCharCode.push("0x");
- for (var i = 0; i < str.length; i++) {
- hexCharCode.push((str.charCodeAt(i)).toString(16));
- }
- return hexCharCode.join("");
- }
- }
- //16进制转字符串
- function hexToString(str) {
- var trimedStr = str.trim();
- var rawStr =
- trimedStr.substr(0, 2).toLowerCase() === "0x" ?
- trimedStr.substr(2) :
- trimedStr;
- var len = rawStr.length;
- if (len % 2 !== 0) {
- // alert("Illegal Format ASCII Code!");
- return "";
- }
- var curCharCode;
- var resultStr = [];
- for (var i = 0; i < len; i = i + 2) {
- curCharCode = parseInt(rawStr.substr(i, 2), 16); // ASCII Code Value
- resultStr.push(String.fromCharCode(curCharCode));
- }
- return resultStr.join("");
- }
- /**
- * 断开蓝牙模块连接
- */
- function closeBluetoothAdapter() {
- //#ifdef H5
- console.warn('h5不加载蓝牙模块');
- return;
- //#endif
- uni.closeBluetoothAdapter({
- success: res => {
- console.log('断开蓝牙模块成功');
- uni.showToast({
- icon: "none",
- title: "蓝牙已经断开!",
- mask: false,
- duration: 3000
- });
- }
- });
- }
- //向低功耗蓝牙设备特征值中写入二进制数据。注意:必须设备的特征值支持 write 才可以成功调用。
- function writeBLECharacteristicValue(value, retryCount, success, getFail) {
- var self = this;
- if (!value && value === '') {
- uni.showToast({
- title: "指令为空"
- })
- return;
- }
- //记录一下指令
- self.currentInstruction = value;
- //V 获取版本,M 获取mac 地址
- if (value == "V")
- self.showToast = true;
- if (value == "M") {
- self.showToast = true;
- self.bListenerMac = true;
- }
- if (value == "4") {
- self.bListenerUpdate = false;
- }
- if (value == "3") {
- if (self.bListenerUpdate) {
- uni.showToast({
- title: "原始数据已开启"
- })
- return;
- }
- self.bListenerUpdate = true;
- }
- if (value == "6") {
- self.bListenerJson = false;
- }
- if (value == "5") {
- if (self.bListenerJson) {
- uni.showToast({
- title: "步数数据已开启"
- })
- return;
- }
- self.bListenerJson = true;
- }
- console.log("currentInstruction:", self.currentInstruction, value, self.bListenerUpdate, self.bListenerMac);
- console.log("self.deviceId:", self.deviceId, self.serviceId, self.writeCharacteristicId);
- uni.writeBLECharacteristicValue({
- deviceId: self.deviceId,
- serviceId: self.serviceId,
- // 这里的 characteristicId 需要在 getBLEDeviceCharacteristics 接口中获取
- characteristicId: self.writeCharacteristicId,
- // 这里的value是ArrayBuffer类型
- value: str2ab(value),
- success:(res)=> {
- console.log('writeBLECharacteristicValue success', res.errMsg, value,retryCount);
- if (success) {
- success(res);
- }
- },
- fail: (fail) => {
- console.log(fail)
- //重新写入
- // uni.showModal({
- // title:"提示",
- // content:"蓝牙通信失败,是否重新执行此操作。",
- // success: (resValue) => {
- // if(resValue.confirm){
- // self.writeBLECharacteristicValue(value, success);
- // }
- // }
- // })
- if(retryCount>0){
- console.log("writeBLECharacteristicValue Rewrite ===================>"+value+" == "+retryCount);
- self.writeBLECharacteristicValue(value,retryCount,success,getFail);
- retryCount--;
- }
- if(getFail){
- getFail(fail);
- }
- },
- complete: (completeRes) => {
-
- console.log(completeRes)
- }
- })
-
- // uni.readBLECharacteristicValue({
- // deviceId:self.deviceId,
- // serviceId:self.serviceId,
- // characteristicId:self.notifyCharacteristicId,
- // success: (resValue) => {
- // console.log('read success!');
- // }
- // })
- }
- /**
- * 断开蓝牙连接
- */
- function closeBLEConnection(deviceId, success) {
- uni.closeBLEConnection({
- deviceId,
- success: res => {
- if (success)
- success();
- },
- fail: (fail) => {
- console.log("关闭蓝牙失败",fail);
- }
- });
- }
- function getRSSITransDistance(rssi) {
- return Math.pow(Math.E, (Math.abs(rssi) - 66.78) / 16.56);
- }
- /**
- * 获取在蓝牙模块生效期间所有已发现的蓝牙设备。包括已经和本机处于连接状态的设备。
- */
- function getBluetoothDevices() {
- uni.getBluetoothDevices({
- success(res) {
- console.log("getBluetoothDevices:", res)
- }
- })
- }
- export default {
- deviceId,
- serviceId,
- //蓝牙模块
- openBluetoothAdapter,
- closeBluetoothAdapter,
- onBLEConnectionStateChange,
- getBLEDeviceCharacteristics,
- notifyBLECharacteristicValueChange,
- onBLECharacteristicValueChange,
- //建立连接模块
- createBLEConnection,
- closeBLEConnection,
- getBLEDeviceServices,
- getRSSITransDistance,
- BLEDIS,
- //写入模块数据
- writeBLECharacteristicValue,
- //获取已经匹配的蓝牙
- getBluetoothDevices,
- //初始化this变量
- initData
- }
|