
小程序连接低功耗蓝牙硬件的方案记录
来源:
浏览:119
时间:2023-08-06
前段时间搞了几天 小程序连接硬件蓝牙 实现读取数据 写入数据的功能。
之前没搞过还是遇到了一些问题。这次记录一下方案。
看下效果
- 根据小程序官方说明 大概就是
- 获取蓝牙设备列表
- 连接指定蓝牙设备
- 获取蓝牙设备的服务
- 连接指定蓝牙设备的 指定服务
- 根据服务获取 该服务的 特征 拿到 可读特征,可写特征,可通知特征
- 根据设备ID 服务ID 服务通知特征创建一个 数据监听 用来接收蓝牙响应数据
- 根据设备ID 服务ID 可写特征uuid 来写入数据
不说这么多 自己封装了一个函数js 文件 贴在这里 有需要的老铁可以自己领取
// 低功耗蓝牙链接 模块函数封装
// 寻找数组索引
export const inArray = (arr, key, val) => {
for (let i = 0; i < arr.length; i++) {
if (arr[i][key] === val) {
return i;
}
}
return -1;
}
// ArrayBuffer转16进度字符串示例
export const ab2hex = (buffer) => {
var hexArr = Array.prototype.map.call(
new Uint8Array(buffer),
function (bit) {
return ('00' + bit.toString(16)).slice(-2)
}
)
return hexArr.join('');
}
export const readFloat16 = (bytes, offset, littleEndian) => {
let sign = (bytes[offset + 1] & 0x80) ? -1 : 1;
let exponent = ((bytes[offset + 1] & 0x7f) << 1) | (bytes[offset] >> 7);
let fraction = ((bytes[offset] & 0x7f) << 8) | bytes[offset + 1];
if (exponent === 0 && fraction === 0) {
return 0;
} else if (exponent === 0) {
return sign * Math.pow(2, -14) * (fraction / Math.pow(2, 10));
} else if (exponent === 0x1f) {
return fraction !== 0 ? NaN : sign * Infinity;
}
return sign * Math.pow(2, exponent - 15) * (1 + fraction / Math.pow(2, 10));
}
// A 链接蓝牙关闭蓝牙扫描
export const stopBluetoothDevicesDiscovery = () =>{
wx.stopBluetoothDevicesDiscovery() // 关闭蓝牙扫描
}
// 01 获取蓝牙列表 新设备 会连续查找
export const getBluetList = (callout = null) => {
// 初始化蓝牙模块
wx.openBluetoothAdapter({
success: function (res) {
// 开始搜索设备
wx.startBluetoothDevicesDiscovery({
success: function (res) {
// 找到设备后停止搜索
wx.onBluetoothDeviceFound(function (devices) {
callout && callout(devices.devices)
})
},
fail: function (err) {
console.log('01 搜索设备失败:', err)
}
})
},
fail: function (err) {
console.log('01 初始化蓝牙失败:', err)
}
})
}
// 02 链接蓝牙
export const createBLEConnection = (deviceId, callout = null) => {
wx.createBLEConnection({
deviceId,
success: (res) => {
callout && callout(deviceId)
},
fail(e) {
console.log('02 链接蓝牙失败:', e)
}
})
this.stopBluetoothDevicesDiscovery()
}
// 03 获取指定蓝牙服务
export const getBLEDeviceServices = (deviceId, callout = null) =>{
wx.getBLEDeviceServices({
deviceId: deviceId,
success: function (res) {
console.log('03 获取蓝牙服务成功:', res.services)
callout && callout(res.services)
},
fail(e) {
console.log('03 获取蓝牙服务失败:', e)
}
})
}
// 04 获取低功耗蓝牙 某个指定服务得特征
export const getBLEDeviceCharacteristics = (deviceId, serviceId, callout = null) => {
wx.getBLEDeviceCharacteristics({
deviceId,
serviceId,
success: (res) => {
console.log('04 获取蓝牙某个服务特征成功', res.characteristics)
const query = {
deviceId: deviceId,
serviceId: serviceId,
characteristicId: '',
writeCharacteristicId: '',
readCharacteristicId: '',
}
res.characteristics.forEach(item => {
// 获取可读特征 读取蓝牙低功耗设备特征值的二进制数据 注意:必须设备的特征支持 read 才可以成功调用
if (item.properties.read) {
wx.readBLECharacteristicValue({
deviceId,
serviceId,
characteristicId: item.uuid,
})
query.characteristicId = item.uuid
} else if (item.properties.write) {
// 蓝牙可写特征
query.writeCharacteristicId = item.uuid
} else if (item.properties.notify) {
// 蓝牙可通知特征
query.readCharacteristicId = item.uuid
}
});
callout && callout(query)
},
fail(res) {
console.error('04 获取低功耗蓝牙 某个指定服务得特征 error: ', res)
}
})
}
// 05 启用蓝牙低功耗设备特征值变化时的 notify 功能,订阅特征。注意:必须设备的特征支持 notify 或者 indicate 才可以成功调用。
export const notifyBLECharacteristicValueChange = (deviceId, services_UUID, characteristic_UUID, callout = null) => {
wx.notifyBLECharacteristicValueChange({
deviceId: deviceId,
serviceId: services_UUID,
characteristicId: characteristic_UUID,
state: true,
type: 'notification',
success(res) {
console.log('启用低功耗蓝牙设备特征值变化时的 notify 功能,订阅特征值: 成功---', characteristic_UUID);
wx.onBLECharacteristicValueChange((res) => {
callout && callout(res.value)
})
},
fail(res) {
console.log('05 监听失败: ', res)
},
});
}
// 06 蓝牙写入函数
export const writeBufferToBLE = (deviceId, serviceId, writeCharacteristicId, sendBuffer, callout = null) => {
wx.writeBLECharacteristicValue({
deviceId: deviceId,
serviceId: serviceId, // 在这里替换成你的设备服务ID
characteristicId:writeCharacteristicId, // 在这里替换成你的设备特征ID
value: sendBuffer,
success: function (res) {
console.log('写入 writeBLECharacteristicValue success', res)
callout && callout(res)
}
})
}
// B 通用连续调用方式 整合方法 ---------------------------------------------
const bluetConfig = {
list: [],
deviceId: '',
services: [],
serviceId: null, // 指定服务的UUID
characteristicId: '',
writeCharacteristicId: '',
readCharacteristicId: '',
}
export const bluetFuns = () => {
// 获取蓝牙 列表
getBluetList((res) => {
bluetConfig.list = [...bluetConfig.list, ...res]
})
bluetConfig.deviceId = bluetConfig.list[0]['id']
// 连接蓝牙 - 并且 监听数据 - 并模拟写入数据
createBLEConnection(bluetConfig.deviceId, (res) => {
// 获取蓝牙所有的服务
getBLEDeviceServices(res, (res) => {
bluetConfig.services = res
// 获取指定服务的特征 xxxx 代表自己想要的 指定的服务的uuid 或 其中的某一段唯一标识
res.forEach(box => {
if(box.uuid.indexOf('xxxx') != -1) {
bluetConfig.serviceId = box.uuid
// 获取这个服务的所有特征
getBLEDeviceCharacteristics(bluetConfig.deviceId, bluetConfig.serviceId, (res) => {
bluetConfig.characteristicId = res.characteristicId
bluetConfig.writeCharacteristicId = res.writeCharacteristicId
bluetConfig.readCharacteristicId = res.readCharacteristicId
// 服务特征变化监听
notifyBLECharacteristicValueChange(bluetConfig.deviceId, bluetConfig.serviceId, bluetConfig.readCharacteristicId, (res) => {
// 注意这里 是 实时响应的 在这里处理 响应数据把
console.log('监听数据:', res)
})
// 这里模拟一个写入方法
let sendBuffer = new ArrayBuffer(2)
let dataView = new DataView(sendBuffer)
dataView.setUint8(0, 0x00)
writeBufferToBLE(bluetConfig.deviceId, bluetConfig.serviceId, bluetConfig.writeCharacteristicId, sendBuffer, (res)=>{
console.log('蓝牙写入回调:', res)
})
})
}
})
})
})
}


