619 lines
16 KiB
JavaScript
619 lines
16 KiB
JavaScript
let BLEList = []
|
|
let getServiceCount = 0; //获取服务的次数
|
|
// 蓝牙模块
|
|
// 注意: 小程序端不支持蓝牙4.0以下的版本
|
|
// 1. 初始化(搜索蓝牙列表)
|
|
function inArray(arr, key, val) {
|
|
for (let i = 0; i < arr.length; i++) {
|
|
if (arr[i][key] === val) {
|
|
return i
|
|
}
|
|
}
|
|
return -1
|
|
}
|
|
export function getBlooth() {
|
|
BLEList = []
|
|
return new Promise((resolve, reject) => {
|
|
uni.openBluetoothAdapter({
|
|
success(res) {
|
|
searchBlooth().then(res => {
|
|
console.log(res, 'searchBlooth')
|
|
uni.onBluetoothDeviceFound(function(devices) {
|
|
console.log(devices, '搜索到蓝牙设备')
|
|
// let result = BLEList.find(devices.devices[0])
|
|
// console.log(result, 'res')
|
|
console.log(devices.devices[0])
|
|
let idx = inArray(BLEList, 'deviceId', devices.devices[0]
|
|
.deviceId)
|
|
console.log(idx, 'idx')
|
|
if (idx == '-1') {
|
|
if (devices.devices[0].localName && (!(devices.devices[0]
|
|
.name) || devices.devices[0].name == '未知设备')) {
|
|
devices.devices[0].name = devices.devices[0].localName
|
|
BLEList.push(devices.devices[0])
|
|
} else if (devices.devices[0].name && devices.devices[0]
|
|
.name != '未知设备') {
|
|
BLEList.push(devices.devices[0])
|
|
}
|
|
}
|
|
|
|
// BLEList.push(devices.devices[0])
|
|
// 5秒后停止搜索
|
|
})
|
|
setTimeout(() => {
|
|
DeviceFound().then(res => {
|
|
console.log(res, 'DeviceFound')
|
|
console.log(BLEList, 'BLEList')
|
|
//同时监听蓝牙连接状态
|
|
onBLEConnectionStateChange()
|
|
resolve(res)
|
|
}).catch(err => {
|
|
console.log(err, 'searchBlooth1')
|
|
reject(err)
|
|
})
|
|
}, 5000)
|
|
}).catch(err => {
|
|
console.log(err, 'DeviceFound1')
|
|
reject(err)
|
|
})
|
|
},
|
|
fail(err) {
|
|
console.log(err, 'openBluetoothAdapter err')
|
|
reject(err)
|
|
}
|
|
})
|
|
|
|
})
|
|
}
|
|
// 2. 检查手机蓝牙开启状态
|
|
function searchBlooth() {
|
|
return new Promise((resolve, reject) => {
|
|
uni.startBluetoothDevicesDiscovery({
|
|
success(res) {
|
|
console.log(res, 'startBluetoothDevicesDiscovery')
|
|
// DeviceFound()
|
|
resolve(res)
|
|
},
|
|
fail(err) {
|
|
reject(err)
|
|
}
|
|
})
|
|
})
|
|
}
|
|
|
|
// 3. 搜索蓝牙列表
|
|
export function DeviceFound() {
|
|
|
|
// uni.onBluetoothDeviceFound(function (devices) {
|
|
// console.log(devices, '搜索到蓝牙设备')
|
|
// // 5秒后停止搜索
|
|
// })
|
|
// setTimeout(() => {
|
|
stopBlueth()
|
|
|
|
// 搜索到的设备列表
|
|
return new Promise((resolve, reject) => {
|
|
uni.getBluetoothDevices({
|
|
success(res) {
|
|
console.log(res, '蓝牙列表')
|
|
console.log(BLEList, 'BLEListBLEList')
|
|
resolve({
|
|
devices: BLEList
|
|
})
|
|
},
|
|
fail(err) {
|
|
console.log(err, '错误的')
|
|
|
|
reject(err)
|
|
}
|
|
})
|
|
})
|
|
|
|
// }, 5000);
|
|
|
|
|
|
|
|
}
|
|
// 4.停止搜索蓝牙
|
|
function stopBlueth() {
|
|
uni.stopBluetoothDevicesDiscovery({
|
|
success(res) {
|
|
console.log(res, '蓝牙停止')
|
|
}
|
|
})
|
|
}
|
|
|
|
// 5. 断开蓝牙连接
|
|
export function closeBle(deviceId2, uuid) {
|
|
console.log('closeBle')
|
|
return new Promise((resolve, reject) => {
|
|
let deviceId = uni.getStorageSync('BLECONNID')
|
|
console.log(deviceId, 'closeBle')
|
|
if (deviceId) {
|
|
uni.closeBLEConnection({
|
|
deviceId: deviceId,
|
|
success(res) {
|
|
console.log('断开蓝牙连接', res)
|
|
// 记得打开
|
|
uni.removeStorageSync('RESCODE')
|
|
uni.removeStorageSync('BLECONNID')
|
|
}
|
|
})
|
|
// 断开蓝牙模块
|
|
uni.closeBluetoothAdapter({
|
|
success(res) {
|
|
console.log('断开蓝牙模块', res)
|
|
if (deviceId2) {
|
|
uni.openBluetoothAdapter({
|
|
success(res) {
|
|
console.log('打开蓝牙模块')
|
|
createBLE({
|
|
deviceId: deviceId2
|
|
}, uuid)
|
|
},
|
|
fail(err) {
|
|
console.log(err, 'openBluetoothAdapter err')
|
|
reject(err)
|
|
}
|
|
})
|
|
}
|
|
resolve(res)
|
|
},
|
|
fail(err) {
|
|
console.log(err)
|
|
reject(err)
|
|
}
|
|
})
|
|
}
|
|
})
|
|
}
|
|
// 6.连接蓝牙(连接之前应该把之前连接的蓝牙设备断开)
|
|
/*
|
|
item,要连接的蓝牙
|
|
uuid
|
|
*/
|
|
export function createBLE(item, uuid) {
|
|
console.log('开始连接')
|
|
return new Promise((resolve, reject) => {
|
|
uni.createBLEConnection({
|
|
// 这里的 deviceId 需要已经通过 createBLEConnection 与对应设备建立链接
|
|
deviceId: item.deviceId,
|
|
success(res) {
|
|
console.log(res, 'createBLE success')
|
|
getServiceCount = 0
|
|
setTimeout(() => {
|
|
getAllService(item.deviceId, uuid).then(res2 => {
|
|
console.log(res2, 'createBLE getAllService')
|
|
getCharacteristics(item.deviceId, res2.uuid).then(res3 => {
|
|
console.log('createBLE getCharacteristics', res3)
|
|
resolve(res3)
|
|
}).catch(err => {
|
|
uni.hideLoading()
|
|
reject(err)
|
|
})
|
|
}).catch(err => {
|
|
uni.hideLoading()
|
|
reject(err)
|
|
})
|
|
}, 2000)
|
|
|
|
console.log('create end')
|
|
},
|
|
fail(err) {
|
|
uni.hideLoading()
|
|
// console.log('111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111')
|
|
reject(err)
|
|
}
|
|
})
|
|
})
|
|
|
|
}
|
|
/**
|
|
* 监听低功耗蓝牙连接状态的改变事件。包括开发者主动连接或断开连接,设备丢失,连接异常断开等等
|
|
*/
|
|
function onBLEConnectionStateChange() {
|
|
console.log('onBLEConnectionStateChange')
|
|
uni.onBLEConnectionStateChange(function(res) {
|
|
// 该方法回调中可以用于处理连接意外断开等异常情况
|
|
console.log(`device ${res.deviceId} state has changed, connected: ${res.connected}`)
|
|
if (res.deviceId && res.connected) {
|
|
// 连接成功将本次连接的设备deviceId和name保存本地
|
|
uni.setStorageSync('BLECONNID', res.deviceId)
|
|
uni.setStorageSync('deviceName', name)
|
|
}
|
|
});
|
|
}
|
|
// 8.获取所有服务
|
|
|
|
function getAllService(deviceId, uuid) {
|
|
console.log(uuid)
|
|
return new Promise((resolve, reject) => {
|
|
uni.getBLEDeviceServices({
|
|
// 这里的 deviceId 需要已经通过 createBLEConnection 与对应设备建立链接
|
|
deviceId,
|
|
success: (res) => {
|
|
console.log('uni.getBLEDeviceServices')
|
|
console.log(res, getServiceCount)
|
|
if (res.services.length == 0) {
|
|
getServiceCount++
|
|
if (getServiceCount > 3) {
|
|
|
|
closeBle(deviceId, uuid)
|
|
// setTimeout(()=>{
|
|
// uni.closeBLEConnection({
|
|
// deviceId: deviceId,
|
|
// success(res) {
|
|
// console.log('断开连接')
|
|
|
|
// // setTimeout(()=>{
|
|
// // // uni.hideLoading()
|
|
// // createBLE({deviceId:deviceId},uuid)
|
|
// // },500)
|
|
|
|
// }
|
|
// })
|
|
// },500)
|
|
|
|
} else {
|
|
getAllService(deviceId, uuid)
|
|
}
|
|
|
|
} else {
|
|
res.services.forEach((item, index) => {
|
|
console.log(item, 'deviceid')
|
|
// 这里的uuid'0000FFE0-0000-1000-8000-00805F9B34FB'
|
|
if (item.isPrimary && item.uuid === uuid) {
|
|
uni.setStorageSync("deviceId", deviceId)
|
|
uni.setStorageSync("serviceId", item.uuid)
|
|
resolve(item)
|
|
}
|
|
// else if (index == (res.services).length-1) {
|
|
// console.log(index, item, 'getBLEDeviceServices')
|
|
// reject(res)
|
|
// } else {
|
|
// console.log(index, item, 'getBLEDeviceServices')
|
|
// reject(res)
|
|
// }
|
|
})
|
|
}
|
|
|
|
|
|
// getCharacteristics(deviceId, res.services[0].uuid)
|
|
},
|
|
fail: (err) => {
|
|
// console.log(err)
|
|
uni.hideLoading()
|
|
reject(err)
|
|
}
|
|
})
|
|
})
|
|
|
|
}
|
|
// 9. 获取某个服务的特征值
|
|
function getCharacteristics(deviceId, serviceId) {
|
|
return new Promise((resolve, reject) => {
|
|
uni.getBLEDeviceCharacteristics({
|
|
// 这里的 deviceId 需要已经通过 createBLEConnection 与对应设备建立链接
|
|
deviceId,
|
|
// 这里的 serviceId 需要在 getBLEDeviceServices 接口中获取
|
|
serviceId,
|
|
success(res) {
|
|
console.log(res, 'getCharacteristics')
|
|
// console.log('device getBLEDeviceCharacteristics:', res.characteristics)
|
|
// uni.showLoading({
|
|
// title: "检测中...",
|
|
// icon: "loading",
|
|
// mask: true
|
|
// })
|
|
res.characteristics.forEach((item, index) => {
|
|
if (!item.properties.notify && !item.properties.read && item.properties
|
|
.write) {
|
|
uni.setStorageSync("characteristicId", item.uuid)
|
|
console.log('characteristicId1', item.uuid)
|
|
}
|
|
if (item.properties.notify && !item.properties.read && !item.properties
|
|
.write) {
|
|
// 启用 notify 功能(成功 监听 失败 进行读取操作)
|
|
console.log('characteristicId2', item.uuid)
|
|
// console.log(1)
|
|
// setTimeout(function() {
|
|
// uni.hideLoading()
|
|
// }, 500);
|
|
// console.log(deviceId, serviceId, item.uuid, 'res.deviceId, res.serviceId, item.uuid')
|
|
notify(deviceId, serviceId, item.uuid).then(res => {
|
|
// console.log(res, 'notify')
|
|
resolve(res)
|
|
})
|
|
watchNotify()
|
|
|
|
} else if (index == (res.characteristics).length - 1 && !item.properties
|
|
.write) {
|
|
// console.log(index, item, 'fsakdfjslfj')
|
|
setTimeout(function() {
|
|
// uni.hideLoading()
|
|
uni.showToast({
|
|
title: "该设备不支持读和写",
|
|
icon: "none"
|
|
})
|
|
}, 500);
|
|
reject(res)
|
|
} else {
|
|
notify(deviceId, serviceId, item.uuid).then(res => {
|
|
// console.log(res, 'notify')
|
|
resolve(res)
|
|
})
|
|
watchNotify()
|
|
}
|
|
})
|
|
},
|
|
fail(err) {
|
|
reject(err)
|
|
}
|
|
})
|
|
})
|
|
|
|
}
|
|
// 10. 启用 notify 功能
|
|
export function notify(deviceId, serviceId, characteristicId) {
|
|
uni.setStorageSync("characteristicId", characteristicId)
|
|
return new Promise((resolve, reject) => {
|
|
uni.notifyBLECharacteristicValueChange({
|
|
state: true, // 启用 notify 功能
|
|
// 这里的 deviceId 需要已经通过 createBLEConnection 与对应设备建立链接
|
|
deviceId,
|
|
// 这里的 serviceId 需要在 getBLEDeviceServices 接口中获取
|
|
serviceId,
|
|
// 这里的 characteristicId 需要在 getBLEDeviceCharacteristics 接口中获取
|
|
characteristicId,
|
|
success(res) {
|
|
// console.log('notifyBLECharacteristicValueChange success', res.errMsg)
|
|
resolve(res)
|
|
},
|
|
fail(err) {
|
|
// console.log(err, 'notifuerr')
|
|
// readBLE(deviceId, serviceId, characteristicId)
|
|
reject(err)
|
|
}
|
|
})
|
|
})
|
|
|
|
}
|
|
/**
|
|
* 字符串转换为数组,个数为n,s为字符串
|
|
|
|
*/
|
|
function strToArr(s, g) {
|
|
// var s = "051102003"
|
|
var re = new RegExp(".{" + g + "}", "g")
|
|
var a = []
|
|
var n
|
|
while ((n = re.exec(s)) != null) {
|
|
a[a.length] = n[0]
|
|
}
|
|
return a
|
|
}
|
|
|
|
// 11 监听notify功能
|
|
var packData = '' // 分包操作
|
|
var first = '' // 开始部分
|
|
var center = '' // 中间拼接部分
|
|
var last = '' // 结尾部分
|
|
var len = 0 // 包的长度
|
|
// var flag = true // flag判断是否进行了分包操作 如果分包需要清空开始部分 中间部分 结尾部分
|
|
export function watchNotify(isHeart) {
|
|
console.log('开始监听。。。')
|
|
// ArrayBuffer转16进度字符串示例
|
|
function ab2hex(buffer) {
|
|
const hexArr = Array.prototype.map.call(
|
|
new Uint8Array(buffer),
|
|
function(bit) {
|
|
return ('00' + bit.toString(16)).slice(-2)
|
|
}
|
|
)
|
|
return hexArr.join('')
|
|
}
|
|
|
|
return new Promise((resolve, reject) => {
|
|
uni.onBLECharacteristicValueChange(function(res) {
|
|
console.log(res)
|
|
// 监听帧头帧尾
|
|
var resCode1 = ab2hex(res.value)
|
|
var resCode = resCode1.toUpperCase()
|
|
console.log(resCode, '收到的')
|
|
let a = hexCharCodeToStr(resCode)
|
|
// let arr = a.split('"')
|
|
uni.$emit('recvEvent', a)
|
|
})
|
|
})
|
|
|
|
}
|
|
// 16进制转字符串
|
|
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("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("");
|
|
}
|
|
// 12.读取功能
|
|
export function readBLE(deviceId, serviceId, characteristicId) {
|
|
uni.readBLECharacteristicValue({
|
|
// 这里的 deviceId 需要已经通过 createBLEConnection 与对应设备建立链接
|
|
deviceId,
|
|
// 这里的 serviceId 需要在 getBLEDeviceServices 接口中获取
|
|
serviceId,
|
|
// 这里的 characteristicId 需要在 getBLEDeviceCharacteristics 接口中获取
|
|
characteristicId,
|
|
success(res) {
|
|
// console.log('readBLECharacteristicValue:', res.errCode)
|
|
},
|
|
fail(err) {
|
|
// console.log('readBLEerr:', err)
|
|
}
|
|
})
|
|
}
|
|
|
|
function str2Bytes(str) {
|
|
var pos = 0;
|
|
str = str.replace(/\s*/g, "");
|
|
var len = str.length;
|
|
if (len % 2 != 0) {
|
|
return null;
|
|
}
|
|
len /= 2;
|
|
var hexA = new Array();
|
|
for (var i = 0; i < len; i++) {
|
|
var s = str.substr(pos, 2);
|
|
var v = parseInt(s, 16);
|
|
hexA.push(v);
|
|
pos += 2;
|
|
}
|
|
return hexA;
|
|
}
|
|
// 字符串和16进制的互相转换
|
|
function strToHexCharCode(str) {
|
|
if (str === "")
|
|
return "";
|
|
var hexCharCode = [];
|
|
hexCharCode.push("0x");
|
|
for (var i = 0; i < str.length; i++) {
|
|
let a = (str.charCodeAt(i)).toString(16)
|
|
if (a.length == 1) {
|
|
a = '0' + a
|
|
}
|
|
hexCharCode.push(a);
|
|
}
|
|
var hex = hexCharCode.splice(1, hexCharCode.length);
|
|
console.log('16-----', hex.join(""))
|
|
var b = str2Bytes(hex.join(""))
|
|
|
|
return b;
|
|
}
|
|
// 14.写入功能.
|
|
export function writeBLE(strData) {
|
|
console.log('writeBLE before', strData)
|
|
// var e = strToHexCharCode(strData)
|
|
var e = str2Bytes(strData)
|
|
console.log(e)
|
|
console.log('writeBLE after')
|
|
|
|
var deviceId = uni.getStorageSync("deviceId")
|
|
var serviceId = uni.getStorageSync("serviceId")
|
|
var characteristicId = uni.getStorageSync("characteristicId")
|
|
console.log(deviceId, serviceId, characteristicId)
|
|
// 向蓝牙设备发送一个0x00的16进制数据
|
|
return new Promise((resolve, reject) => {
|
|
for (var i = 0; i < e.length; i += 20) {
|
|
var endLength = 0
|
|
// console.log(i)
|
|
if (i + 20 < e.length) {
|
|
var senddata = e
|
|
let buffer = new ArrayBuffer(20)
|
|
|
|
let dataView = new DataView(buffer)
|
|
for (var j = i; j < i + 20; j++) {
|
|
dataView.setUint8(j - i, senddata[j])
|
|
}
|
|
// let dataSend = []
|
|
// for (var j = i; j < i + 20; j++) {
|
|
// dataView.setUint8(j - i, senddata[j])
|
|
|
|
// dataSend.push(dataView.getUint8(j-i))
|
|
// }
|
|
// console.log('多包发送的包数据:'+dataView.buffer)
|
|
uni.writeBLECharacteristicValue({
|
|
// 这里的 deviceId 需要在 getBluetoothDevices 或 onBluetoothDeviceFound 接口中获取
|
|
deviceId: deviceId,
|
|
// 这里的 serviceId 需要在 getBLEDeviceServices 接口中获取
|
|
serviceId: serviceId,
|
|
// 这里的 characteristicId 需要在 getBLEDeviceCharacteristics 接口中获取
|
|
characteristicId: characteristicId,
|
|
// 这里的value是ArrayBuffer类型
|
|
value: dataView.buffer,
|
|
// value: buffer,
|
|
success(res) {
|
|
resolve(res)
|
|
},
|
|
fail(err) {
|
|
// console.log(err)
|
|
reject(err)
|
|
}
|
|
})
|
|
// 等待
|
|
sleep(0.02)
|
|
} else {
|
|
var senddata = e
|
|
// console.log(senddata)
|
|
|
|
if (20 < e.length) {
|
|
|
|
endLength = senddata.length - i
|
|
// console.log(endLength, 'endLength')
|
|
|
|
} else {
|
|
|
|
endLength = senddata.length
|
|
// console.log('endLength2', endLength)
|
|
|
|
}
|
|
|
|
let buffer = new ArrayBuffer(endLength)
|
|
|
|
// var dataSend = []
|
|
// console.log(senddata.length)
|
|
let dataViewLast = new DataView(buffer)
|
|
for (var k = i; k < senddata.length; k++) {
|
|
// console.log(k)
|
|
// console.log(i)
|
|
// console.log(senddata[k])
|
|
dataViewLast.setUint8(k - i, senddata[k])
|
|
// console.log(dataViewLast.getUint8(k-i))
|
|
// dataSend.push(dataViewLast.getUint8(k-i))
|
|
|
|
}
|
|
|
|
console.log('最后一包或第一数据:')
|
|
console.log(dataViewLast.buffer)
|
|
uni.writeBLECharacteristicValue({
|
|
// 这里的 deviceId 需要在 getBluetoothDevices 或 onBluetoothDeviceFound 接口中获取
|
|
deviceId: deviceId,
|
|
// 这里的 serviceId 需要在 getBLEDeviceServices 接口中获取
|
|
serviceId: serviceId,
|
|
// 这里的 characteristicId 需要在 getBLEDeviceCharacteristics 接口中获取
|
|
characteristicId: characteristicId,
|
|
// 这里的value是ArrayBuffer类型
|
|
value: dataViewLast.buffer,
|
|
// value: buffer,
|
|
success(res) {
|
|
resolve(res)
|
|
},
|
|
fail(err) {
|
|
// console.log(err)
|
|
reject(err)
|
|
}
|
|
})
|
|
sleep(0.02)
|
|
}
|
|
}
|
|
})
|
|
}
|
|
|
|
function sleep(delay) {
|
|
var start = (new Date()).getTime();
|
|
while ((new Date()).getTime() - start < delay) {
|
|
continue;
|
|
}
|
|
}
|