miniprogram: add iap mp for ble OTA
This commit is contained in:
554
tools/Mini_Program/iap/miniprogram/utils/hardware/ble/ble-api.js
Normal file
554
tools/Mini_Program/iap/miniprogram/utils/hardware/ble/ble-api.js
Normal file
@@ -0,0 +1,554 @@
|
||||
/**
|
||||
* 初始化蓝牙模块
|
||||
*
|
||||
* @return {Object} 调用结果
|
||||
*/
|
||||
function openBluetoothAdapter() {
|
||||
return new Promise((resolve, reject) => {
|
||||
wx.openBluetoothAdapter({
|
||||
success(res) {
|
||||
resolve(res)
|
||||
},
|
||||
fail(res) {
|
||||
reject(res)
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 关闭蓝牙模块
|
||||
*
|
||||
* @return {Object} 调用结果
|
||||
*/
|
||||
function closeBluetoothAdapter() {
|
||||
return new Promise((resolve, reject) => {
|
||||
wx.closeBluetoothAdapter({
|
||||
complete(res) {
|
||||
resolve(res)
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 监听蓝牙状态
|
||||
*
|
||||
* @param {function} onBluetoothStateChange 函数对象,监听蓝牙状态变化的回调函数
|
||||
* @return void
|
||||
*/
|
||||
function onBluetoothAdapterStateChange(onBluetoothStateChange) {
|
||||
return new Promise((resolve) => {
|
||||
wx.onBluetoothAdapterStateChange(function(res) {
|
||||
// console.log('onBluetoothAdapterStateChange, now is', res)
|
||||
onBluetoothStateChange(res)
|
||||
})
|
||||
resolve()
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 启动搜索蓝牙设备功能
|
||||
*
|
||||
* @param {string} services 蓝牙服务
|
||||
* @return void
|
||||
*/
|
||||
function startBluetoothDevicesDiscovery(services) {
|
||||
return new Promise((resolve, reject) => {
|
||||
wx.startBluetoothDevicesDiscovery({
|
||||
services: services || [],
|
||||
allowDuplicatesKey: false,
|
||||
success(res) {
|
||||
console.log("wx.startBluetoothDevicesDiscovery success")
|
||||
resolve(res)
|
||||
},
|
||||
fail(res) {
|
||||
console.log("wx.startBluetoothDevicesDiscovery fail")
|
||||
reject(res)
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 关闭搜索蓝牙设备功能
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
function stopBluetoothDevicesDiscovery() {
|
||||
return new Promise((resolve, reject) => {
|
||||
wx.stopBluetoothDevicesDiscovery({
|
||||
complete(res) {
|
||||
console.log("wx.stopBluetoothDevicesDiscovery success")
|
||||
resolve()
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 断开与低功耗蓝牙设备的连接
|
||||
*
|
||||
* @param {string} deviceId 蓝牙设备ID
|
||||
* @return void
|
||||
*/
|
||||
function closeBLEConnection(deviceId) {
|
||||
return new Promise((resolve, reject) => {
|
||||
wx.closeBLEConnection({
|
||||
deviceId,
|
||||
success(res) {
|
||||
console.log(`closeBLEConnection ${deviceId} success`, res)
|
||||
},
|
||||
fail(res) {
|
||||
console.log(`closeBLEConnection ${deviceId} fail`, res)
|
||||
},
|
||||
complete(res) {
|
||||
resolve()
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 连接低功耗蓝牙设备
|
||||
*
|
||||
* @param {string} deviceId 蓝牙设备ID
|
||||
* @return {Object} 调用结果
|
||||
*/
|
||||
function createBLEConnection(deviceId) {
|
||||
return new Promise((resolve, reject) => {
|
||||
wx.createBLEConnection({
|
||||
deviceId: deviceId,
|
||||
timeout: 5000, // TO_CHECK: 设置连接蓝牙超时时间
|
||||
success: function(res) {
|
||||
console.log(`createBLEConnection ${deviceId} success`, res)
|
||||
resolve(res)
|
||||
},
|
||||
fail: function(res) {
|
||||
console.log(`createBLEConnection ${deviceId} fail`, res);
|
||||
reject(new Error(res.errMsg || 'wx.createBLEConnection fail'))
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 监听低功耗蓝牙连接状态的改变事件
|
||||
*
|
||||
* @param {function} onStateChange 函数对象,连接状态变化的回调函数
|
||||
* @return void
|
||||
*/
|
||||
function onBLEConnectionStateChange(onStateChange) {
|
||||
return new Promise((resolve) => {
|
||||
wx.onBLEConnectionStateChange(function(res) { // 该方法回调中可以用于处理连接意外断开等异常情况
|
||||
// console.log(`onBLEConnectionStateChange device ${res.deviceId} state has changed, connected: ${res.connected}`)
|
||||
onStateChange(res)
|
||||
})
|
||||
resolve()
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取蓝牙设备所有服务
|
||||
*
|
||||
* @param {string} deviceId 蓝牙设备ID
|
||||
* @return {Object} 调用结果
|
||||
*/
|
||||
function getBLEDeviceServices(deviceId) {
|
||||
return new Promise((resolve, reject) => {
|
||||
wx.getBLEDeviceServices({
|
||||
deviceId: deviceId,
|
||||
success: function(res) {
|
||||
console.log(`wx.getBLEDeviceServices ${deviceId} success:`, res.services)
|
||||
resolve(res.services)
|
||||
},
|
||||
fail(res) { // 获取蓝牙服务失败
|
||||
console.log(`wx.getBLEDeviceServices ${deviceId} fail:`, res)
|
||||
reject(res.errMsg || 'wx.getBLEDeviceServices fail')
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取蓝牙设备某个服务中所有特征值
|
||||
*
|
||||
* @param {string} deviceId 蓝牙设备ID
|
||||
* @param {string} serviceId 蓝牙服务ID
|
||||
* @return {Object} 调用结果
|
||||
*/
|
||||
function getBLEDeviceCharacteristics(deviceId, serviceId) {
|
||||
return new Promise((resolve, reject) => {
|
||||
wx.getBLEDeviceCharacteristics({
|
||||
deviceId: deviceId,
|
||||
serviceId: serviceId,
|
||||
success(res) {
|
||||
console.log(`wx.getBLEDeviceCharacteristics ${deviceId} ${serviceId} success:`, res.characteristics)
|
||||
resolve(res.characteristics)
|
||||
},
|
||||
fail(res) { // 读取蓝牙特征值失败
|
||||
console.log(`wx.getBLEDeviceCharacteristics ${deviceId} ${serviceId} fail`, res)
|
||||
reject(res.errMsg || 'wx.getBLEDeviceCharacteristics fail')
|
||||
},
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 启用低功耗蓝牙设备特征值变化时的 notify 功能,订阅特征值
|
||||
* 注:必须设备的特征值支持 notify 或者 indicate 才可以成功调用
|
||||
*
|
||||
* @param {string} deviceId 蓝牙设备ID
|
||||
* @param {string} serviceId 蓝牙服务ID
|
||||
* @param {string} notifyCharacteristicId 蓝牙特征值ID
|
||||
* @return {Object} 调用结果
|
||||
*/
|
||||
function notifyBLECharacteristicValueChanged(deviceId, serviceId, notifyCharacteristicId) {
|
||||
return new Promise((resolve, reject) => {
|
||||
wx.notifyBLECharacteristicValueChanged({
|
||||
deviceId: deviceId,
|
||||
serviceId: serviceId,
|
||||
characteristicId: notifyCharacteristicId,
|
||||
state: true,
|
||||
success(res) {
|
||||
console.log(`wx.notifyBLECharacteristicValueChanged ${deviceId} ${serviceId} ${notifyCharacteristicId} success`);
|
||||
resolve(true)
|
||||
},
|
||||
fail(err) {
|
||||
console.log(`wx.notifyBLECharacteristicValueChanged ${deviceId} ${serviceId} ${notifyCharacteristicId} fail`, err);
|
||||
reject("启用蓝牙特征值notify功能失败")
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 监听低功耗蓝牙设备的特征值变化事件
|
||||
* 注:必须先启用 notifyBLECharacteristicValueChange 接口才能接收到设备推送的 notification
|
||||
*
|
||||
* @param {function} onMessage 函数对象,读数据的回调函数
|
||||
* @return void
|
||||
*/
|
||||
function onBLECharacteristicValueChange(onMessage) {
|
||||
var receivedData = null
|
||||
return new Promise((resolve, reject) => {
|
||||
wx.onBLECharacteristicValueChange(function(res) {
|
||||
//{value: ArrayBuffer, deviceId: "D8:00:D2:4F:24:17", serviceId: "ba11f08c-5f14-0b0d-1080-007cbe238851-0x600000460240", characteristicId: "0000cd04-0000-1000-8000-00805f9b34fb-0x60800069fb80"}
|
||||
onMessage(res.value)
|
||||
})
|
||||
resolve()
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 向低功耗蓝牙设备特征值中写入二进制数据
|
||||
* 注:必须设备的特征值支持 write 才可以成功调用
|
||||
*
|
||||
* @param {string} deviceId 蓝牙设备ID
|
||||
* @param {string} serviceId 蓝牙服务ID
|
||||
* @param {string} writeCharacteristicId 蓝牙特征值ID
|
||||
* @param {string} payload 数据,必须是ArrayBuffer类型
|
||||
* @return {Object} 调用结果
|
||||
*/
|
||||
function writeBLECharacteristicValue(deviceId, serviceId, writeCharacteristicId, payload) {
|
||||
return new Promise((resolve, reject) => {
|
||||
wx.writeBLECharacteristicValue({
|
||||
deviceId: deviceId,
|
||||
serviceId: serviceId,
|
||||
characteristicId: writeCharacteristicId,
|
||||
value: payload, // parameter.value should be ArrayBuffer
|
||||
fail(res) {
|
||||
console.log(`writeBLECharacteristicValue fail: ${deviceId} ${serviceId} ${writeCharacteristicId}`, res)
|
||||
reject(res)
|
||||
},
|
||||
success(res) {
|
||||
resolve(res)
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 读取低功耗蓝牙设备的特征值的二进制数据值。
|
||||
* 注:必须设备的特征值支持 read 才可以成功调用; 接口读取到的信息需要在 onBLECharacteristicValueChange 方法注册的回调中获取
|
||||
*
|
||||
* @param {string} deviceId 蓝牙设备ID
|
||||
* @param {string} serviceId 蓝牙服务ID
|
||||
* @param {string} readCharacteristicId 蓝牙特征值ID
|
||||
* @return {Object} 调用结果
|
||||
*/
|
||||
function readBLECharacteristicValue(deviceId, serviceId, readCharacteristicId) {
|
||||
return new Promise((resolve, reject) => {
|
||||
wx.readBLECharacteristicValue({
|
||||
deviceId: deviceId,
|
||||
serviceId: serviceId,
|
||||
characteristicId: readCharacteristicId,
|
||||
fail(res) {
|
||||
console.log(`readBLECharacteristicValue fail: ${deviceId} ${serviceId} ${readCharacteristicId}`, res)
|
||||
reject(res)
|
||||
},
|
||||
success(res) {
|
||||
resolve(res)
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 连接设备
|
||||
*
|
||||
* @param {string} deviceId 蓝牙设备ID
|
||||
* @return {Object} 设备连接信息
|
||||
*/
|
||||
function connectDevice(deviceId) {
|
||||
return closeBLEConnection(deviceId).then(() => {
|
||||
// 断开重连需要间隔1s,否则会出现假连接成功
|
||||
// 还有一种方式是 getConnectedBluetoothDevices,对比已连接的蓝牙,如果已连接直接跳到设备页面
|
||||
return createBLEConnection(deviceId)
|
||||
}).then(() => {
|
||||
// 读取 BLE services
|
||||
return getBLEDeviceServices(deviceId)
|
||||
}).then(([deviceId, services]) => {
|
||||
// 读取 BLE Characteristics
|
||||
for (let i = 0; i < services.length; i++) {
|
||||
if (services[i].isPrimary) { // 确定对应服务。这里使用第一个primary服务
|
||||
let serviceId = services[i].uuid
|
||||
return getBLEDeviceCharacteristics(deviceId, serviceId)
|
||||
}
|
||||
}
|
||||
return Promise.reject(new Error('未找到蓝牙主服务'))
|
||||
}).then(
|
||||
// 必须先启用 notifyBLECharacteristicValueChange 才能监听到设备 onBLECharacteristicValueChange 事件
|
||||
([deviceId, serviceId, characteristics]) => {
|
||||
let notifyCharacteristicId = null
|
||||
let writeCharacteristicId = null
|
||||
let readCharacteristicId = null
|
||||
characteristics.forEach(function(item, index) {
|
||||
if (item.properties.notify == true) {
|
||||
notifyCharacteristicId = item.uuid
|
||||
notifyBLECharacteristicValueChanged(deviceId, serviceId, item.uuid)
|
||||
}
|
||||
if (item.properties.write == true) {
|
||||
writeCharacteristicId = item.uuid
|
||||
}
|
||||
if (item.properties.read == true) {
|
||||
readCharacteristicId = item.uuid
|
||||
}
|
||||
})
|
||||
let device = {
|
||||
connected: true,
|
||||
deviceId: deviceId,
|
||||
serviceId: serviceId,
|
||||
notifyCharacteristicId: notifyCharacteristicId,
|
||||
writeCharacteristicId: writeCharacteristicId,
|
||||
readCharacteristicId: readCharacteristicId,
|
||||
}
|
||||
return Promise.resolve(device)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据名称搜索设备
|
||||
*
|
||||
* @param {string} name 蓝牙设备名称
|
||||
* @param {string} timeout 搜索超时时间,单位ms
|
||||
* @param {array} services 蓝牙设备的服务ID
|
||||
* @return {string} deviceId 蓝牙设备ID
|
||||
*/
|
||||
function searchDeviceName(name, timeout, services = ["6E400001-B5A3-F393-E0A9-E50E24DCCA9E"]) {
|
||||
console.log("search begin", name)
|
||||
let timer = null
|
||||
let searchTimeout = new Promise((resolve, reject) => {
|
||||
timer = setTimeout(function() {
|
||||
console.log("searchDeviceName timeout", name)
|
||||
stopBluetoothDevicesDiscovery()
|
||||
reject(null)
|
||||
}, timeout);
|
||||
})
|
||||
|
||||
let search = Promise.resolve()
|
||||
.then(() => {
|
||||
return closeBluetoothAdapter()
|
||||
})
|
||||
.then(() => {
|
||||
return openBluetoothAdapter()
|
||||
})
|
||||
.then(() => {
|
||||
return startBluetoothDevicesDiscovery(services)
|
||||
})
|
||||
.then(() => {
|
||||
return new Promise((resolve) => {
|
||||
console.log("wx.onBluetoothDeviceFound start")
|
||||
wx.onBluetoothDeviceFound(function(res) {
|
||||
let foundName = res.devices[0].localName // TODO: localName or name?
|
||||
if (foundName && foundName == name) {
|
||||
console.log("searchDeviceName found:", name, res);
|
||||
wx.offBluetoothDeviceFound(this)
|
||||
clearTimeout(timer)
|
||||
stopBluetoothDevicesDiscovery()
|
||||
resolve(res.devices[0].deviceId)
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
return Promise.race([search, searchTimeout])
|
||||
}
|
||||
|
||||
async function searchDevices(name, timeout, services = ["6E400001-B5A3-F393-E0A9-E50E24DCCA9E"]) {
|
||||
console.log("searchDevices", name)
|
||||
let timer = null
|
||||
let searchTimeout = new Promise((resolve, reject) => {
|
||||
timer = setTimeout(function() {
|
||||
console.log("searchDevices timeout", name)
|
||||
stopBluetoothDevicesDiscovery()
|
||||
reject(null)
|
||||
}, timeout);
|
||||
})
|
||||
|
||||
let search = Promise.resolve()
|
||||
.then(() => {
|
||||
return closeBluetoothAdapter()
|
||||
})
|
||||
.then(() => {
|
||||
return openBluetoothAdapter()
|
||||
})
|
||||
.then(() => {
|
||||
return startBluetoothDevicesDiscovery(services)
|
||||
})
|
||||
.then(() => {
|
||||
return new Promise((resolve) => {
|
||||
console.log("wx.onBluetoothDeviceFound start")
|
||||
wx.onBluetoothDeviceFound(function(res) {
|
||||
let foundName = res.devices[0].localName // TODO: localName or name?
|
||||
if (foundName && foundName == name) {
|
||||
console.log("searchDeviceName found:", name, res);
|
||||
wx.offBluetoothDeviceFound(this)
|
||||
clearTimeout(timer)
|
||||
stopBluetoothDevicesDiscovery()
|
||||
resolve(res.devices[0].deviceId)
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
return Promise.race([search, searchTimeout])
|
||||
}
|
||||
|
||||
// function searchAndConnect(name, timeout, services = ["6E400001-B5A3-F393-E0A9-E50E24DCCA9E"]) {
|
||||
function searchAndConnect(name, timeout, services = []) {
|
||||
return searchDeviceName(name, timeout, services).then(res => {
|
||||
let devicesList = res
|
||||
if (devicesList.length == 0) {
|
||||
return Promise.reject(false)
|
||||
}
|
||||
let deviceId = devicesList[0].deviceId
|
||||
return connectDevice(deviceId)
|
||||
})
|
||||
}
|
||||
|
||||
// 扫描设备
|
||||
function scanDevicesForSometime(services, ms) {
|
||||
startBluetoothDevicesDiscovery(services).then(res => {
|
||||
console.log("wx.startBluetoothDevicesDiscovery success", res)
|
||||
})
|
||||
setTimeout(function() {
|
||||
wx.stopBluetoothDevicesDiscovery({
|
||||
success(res) {
|
||||
console.log("wx.stopBluetoothDevicesDiscovery success", res)
|
||||
},
|
||||
fail(e) {
|
||||
console.log("wx.stopBluetoothDevicesDiscovery fail", res)
|
||||
}
|
||||
})
|
||||
}, ms);
|
||||
}
|
||||
|
||||
// 扫描设备
|
||||
function connectFailAnalysis(deviceId) {
|
||||
console.log("scanDevices ...")
|
||||
let that = this
|
||||
let found = false
|
||||
let discovery = Promise.resolve().then(
|
||||
() => {
|
||||
return openBluetoothAdapter()
|
||||
}
|
||||
).then(
|
||||
() => {
|
||||
return startBluetoothDevicesDiscovery([])
|
||||
// return startBluetoothDevicesDiscovery(["6E400001-B5A3-F393-E0A9-E50E24DCCA9E"])
|
||||
}
|
||||
).then(
|
||||
() => {
|
||||
let devicesList = []
|
||||
return new Promise((resolve) => {
|
||||
wx.onBluetoothDeviceFound(function(res) {
|
||||
let name = res.devices[0].name
|
||||
if (name != "") {
|
||||
console.log("onBluetoothDeviceFound:", name, res);
|
||||
devicesList.push(res.devices[0])
|
||||
let foundDeviceId = res.devices[0].deviceId
|
||||
console.log("found", foundDeviceId, deviceId)
|
||||
// 尝试连接,读取等
|
||||
if (foundDeviceId = deviceId) {
|
||||
found = true
|
||||
}
|
||||
}
|
||||
})
|
||||
resolve()
|
||||
})
|
||||
}
|
||||
)
|
||||
|
||||
let discoveryTimeout = new Promise(resolve => {
|
||||
setTimeout(resolve, 10000);
|
||||
}).then(res => {
|
||||
console.log("discoveryTimeout")
|
||||
return stopBluetoothDevicesDiscovery()
|
||||
}).then(res => {
|
||||
return new Promise(res => {
|
||||
console.log("xxxx", found)
|
||||
if (found) {
|
||||
console.log("found", deviceId)
|
||||
resolve(true)
|
||||
} else {
|
||||
console.log("not found", deviceId)
|
||||
reject(false)
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
return Promise.race([discovery, discoveryTimeout])
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
// 蓝牙适配器
|
||||
closeBluetoothAdapter: closeBluetoothAdapter,
|
||||
openBluetoothAdapter: openBluetoothAdapter,
|
||||
onBluetoothAdapterStateChange: onBluetoothAdapterStateChange,
|
||||
startBluetoothDevicesDiscovery: startBluetoothDevicesDiscovery,
|
||||
stopBluetoothDevicesDiscovery: stopBluetoothDevicesDiscovery,
|
||||
|
||||
// BLE连接
|
||||
closeBLEConnection: closeBLEConnection,
|
||||
createBLEConnection: createBLEConnection,
|
||||
onBLEConnectionStateChange: onBLEConnectionStateChange,
|
||||
|
||||
// BLE服务和特征值
|
||||
getBLEDeviceServices: getBLEDeviceServices,
|
||||
getBLEDeviceCharacteristics: getBLEDeviceCharacteristics,
|
||||
notifyBLECharacteristicValueChanged: notifyBLECharacteristicValueChanged,
|
||||
onBLECharacteristicValueChange: onBLECharacteristicValueChange,
|
||||
|
||||
// BLE读写
|
||||
writeBLECharacteristicValue: writeBLECharacteristicValue,
|
||||
readBLECharacteristicValue: readBLECharacteristicValue,
|
||||
|
||||
// wrapper
|
||||
scanDevicesForSometime: scanDevicesForSometime,
|
||||
searchDeviceName: searchDeviceName,
|
||||
connectDevice: connectDevice,
|
||||
searchAndConnect: searchAndConnect,
|
||||
connectFailAnalysis: connectFailAnalysis,
|
||||
}
|
Reference in New Issue
Block a user