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,
|
||||
}
|
@@ -0,0 +1,83 @@
|
||||
"use strict";
|
||||
|
||||
function UpdateCRC16(crcIn, byte) {
|
||||
let crc = crcIn;
|
||||
let inNum = byte | 0x100;
|
||||
do {
|
||||
crc <<= 1;
|
||||
crc = crc & 0xFFFFFFFF;
|
||||
inNum <<= 1;
|
||||
inNum = inNum & 0xFFFFFFFF;
|
||||
|
||||
if (inNum & 0x100) {
|
||||
++crc;
|
||||
}
|
||||
|
||||
if (crc & 0x10000) {
|
||||
crc ^= 0x1021;
|
||||
crc = crc & 0xFFFFFFFF;
|
||||
}
|
||||
|
||||
} while (!(inNum & 0x10000));
|
||||
|
||||
return crc & 0xffff;
|
||||
}
|
||||
|
||||
function crc16(data, size) {
|
||||
let crc = 0;
|
||||
|
||||
for (let i = 0; i < size; i++) {
|
||||
crc = UpdateCRC16(crc, data[i])
|
||||
}
|
||||
crc = UpdateCRC16(crc, 0);
|
||||
crc = UpdateCRC16(crc, 0);
|
||||
|
||||
return crc & 0xffff;
|
||||
}
|
||||
|
||||
|
||||
function crc16_backup(buf, len) {
|
||||
// let crc = 0x0000;
|
||||
let crc = 0xFFFF;
|
||||
|
||||
for (let pos = 0; pos < len; pos++) {
|
||||
// XOR byte into least sig. byte of crc
|
||||
crc ^= buf[pos];
|
||||
crc = crc & 0xFFFF;
|
||||
for (let i = 8; i != 0; i--) { // Loop over each bit
|
||||
if ((crc & 0x0001) != 0) { // If the LSB is set
|
||||
crc >>= 1; // Shift right and XOR 0xA001
|
||||
crc ^= 0xA001;
|
||||
crc = crc & 0xFFFF;
|
||||
}
|
||||
else {// Else LSB is not set
|
||||
crc >>= 1; // Just shift right
|
||||
crc = crc & 0xFFFF;
|
||||
}
|
||||
}
|
||||
}
|
||||
return crc;
|
||||
}
|
||||
/*
|
||||
int calcrc(char *ptr, int count)
|
||||
{
|
||||
int crc;
|
||||
char i;
|
||||
crc = 0;
|
||||
while (--count >= 0)
|
||||
{
|
||||
crc = crc ^ (int) *ptr++ << 8;
|
||||
i = 8;
|
||||
do
|
||||
{
|
||||
if (crc & 0x8000)
|
||||
crc = crc << 1 ^ 0x1021;
|
||||
else
|
||||
crc = crc << 1;
|
||||
} while(--i);
|
||||
}
|
||||
return (crc);
|
||||
}
|
||||
*/
|
||||
|
||||
module.exports = crc16;
|
109
tools/Mini_Program/iap/miniprogram/utils/hardware/ble/packet.js
Normal file
109
tools/Mini_Program/iap/miniprogram/utils/hardware/ble/packet.js
Normal file
@@ -0,0 +1,109 @@
|
||||
|
||||
let crc16 = require('./crc16.js')
|
||||
|
||||
const SOH = 0x01 /* start of 128-byte data packet */
|
||||
const STX = 0x02 /* start of 1024-byte data packet */
|
||||
const EOT = 0x04 /* end of transmission */
|
||||
const ACK = 0x06 /* acknowledge */
|
||||
const NAK = 0x15 /* negative acknowledge */
|
||||
const CA = 0x18 /* two of these in succession aborts transfer */
|
||||
const CRC16 = 0x43 /* 'C' == 0x43, request 16-bit CRC */
|
||||
const NEGATIVE_BYTE = 0xFF
|
||||
|
||||
const ABORT1 = 0x41 /* 'A' == 0x41, abort by user */
|
||||
const ABORT2 = 0x61 /* 'a' == 0x61, abort by user */
|
||||
|
||||
const NAK_TIMEOUT = 10000
|
||||
const DOWNLOAD_TIMEOUT = 1000 /* One second retry delay */
|
||||
const MAX_ERRORS = 10
|
||||
|
||||
const NORMAL_LEN = 128;
|
||||
const LONG_LEN = 1024;
|
||||
const DATA_INDEX = 3;
|
||||
|
||||
function getNormalPacket(id, contentBuf) {
|
||||
let buf = new Uint8Array(NORMAL_LEN + 3 + 2); //NORMAL_LEN
|
||||
let i = 0;
|
||||
buf[i++] = SOH;
|
||||
|
||||
buf[i++] = id;
|
||||
buf[i++] = 0xFF - id;
|
||||
|
||||
if (contentBuf.length > NORMAL_LEN) {
|
||||
throw new Error("Over normal packet size limit");
|
||||
}
|
||||
|
||||
for (let j = 0; j < contentBuf.length; j++) {
|
||||
buf[i++] = contentBuf[j];
|
||||
}
|
||||
|
||||
while (i < NORMAL_LEN + 3) {
|
||||
buf[i++] = 0x1A;
|
||||
}
|
||||
let bufcrc = buf.slice(3, 3 + NORMAL_LEN)
|
||||
let crc = crc16(bufcrc, NORMAL_LEN);
|
||||
|
||||
buf[i++] = (crc >> 8) & 0xFF;
|
||||
buf[i++] = crc & 0xFF;
|
||||
|
||||
// console.log("packet forming End i = ", i);
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
function getLongPacket (id, contentBuf) {
|
||||
let buf = new Uint8Array(LONG_LEN + 3 + 2);
|
||||
let i = 0;
|
||||
buf[i++] = STX;
|
||||
|
||||
buf[i++] = id;
|
||||
buf[i++] = 0xFF - id;
|
||||
|
||||
if (contentBuf.length > LONG_LEN) {
|
||||
throw new Error("Over long packet size limit");
|
||||
}
|
||||
|
||||
for (let j = 0; j < contentBuf.length; j++) {
|
||||
buf[i++] = contentBuf[j];
|
||||
}
|
||||
|
||||
while (i < LONG_LEN + 3) {
|
||||
buf[i++] = 0x1A;
|
||||
}
|
||||
let bufcrc = buf.slice(3, LONG_LEN + 3)
|
||||
let crc = crc16(bufcrc, LONG_LEN);
|
||||
|
||||
buf[i++] = (crc >> 8) & 0xFF;
|
||||
buf[i++] = crc & 0xFF;
|
||||
|
||||
// console.log("packet forming End i = ", i);
|
||||
|
||||
return buf;
|
||||
}
|
||||
function getZeroContent (fileSymbol, fileLen) {
|
||||
|
||||
let buf = new Uint8Array(128);
|
||||
|
||||
// let fileLenBuf = Uint8Array.from(fileLen + '')
|
||||
// let symbolBuf = Uint8Array.from(fileSymbol)
|
||||
let fileLenStr = fileLen.toString()
|
||||
let i = 0, j = 0;
|
||||
for (j = 0; j < fileSymbol.length; j++) {
|
||||
buf[i++] = fileSymbol.charCodeAt(j)
|
||||
}
|
||||
buf[i++] = 0;
|
||||
for (j = 0; j < fileLenStr.length; j++) {
|
||||
buf[i++] = fileLenStr.charCodeAt(j)
|
||||
}
|
||||
// buf[i++] = 32;
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
let packet = {
|
||||
getZeroContent: getZeroContent,
|
||||
getNormalPacket: getNormalPacket,
|
||||
getLongPacket: getLongPacket
|
||||
};
|
||||
|
||||
module.exports = packet;
|
97
tools/Mini_Program/iap/miniprogram/utils/util.js
Normal file
97
tools/Mini_Program/iap/miniprogram/utils/util.js
Normal file
@@ -0,0 +1,97 @@
|
||||
const formatTime = function(date) {
|
||||
if (!date) {
|
||||
date = new Date()
|
||||
}
|
||||
const year = date.getFullYear()
|
||||
const month = date.getMonth() + 1
|
||||
const day = date.getDate()
|
||||
const hour = date.getHours()
|
||||
const minute = date.getMinutes()
|
||||
const second = date.getSeconds()
|
||||
|
||||
return [year, month, day].map(formatNumber).join('-') + ' ' + [hour, minute, second].map(formatNumber).join(':')
|
||||
}
|
||||
|
||||
const formatNumber = n => {
|
||||
n = n.toString()
|
||||
return n[1] ? n : '0' + n
|
||||
}
|
||||
|
||||
// await util.delayMs(1000)
|
||||
const delayMs = (ms) => {
|
||||
return new Promise(resolve => {
|
||||
setTimeout(resolve, ms);
|
||||
});
|
||||
}
|
||||
|
||||
// ArrayBuffer转16进制字符串
|
||||
// ArrayBuffer => hex string
|
||||
function ab2strHex(ab) {
|
||||
let hexArr = Array.prototype.map.call(
|
||||
new Uint8Array(ab),
|
||||
function(bit) {
|
||||
return ('00' + bit.toString(16)).slice(-2)
|
||||
}
|
||||
)
|
||||
return hexArr.join('');
|
||||
}
|
||||
|
||||
// string => ArrayBuffer Uint8
|
||||
function str2abUint8(str) {
|
||||
var buf = new ArrayBuffer(str.length); // 2 bytes for each char
|
||||
var bufView = new Uint8Array(buf);
|
||||
for (var i = 0, strLen = str.length; i < strLen; i++) {
|
||||
bufView[i] = str.charCodeAt(i);
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
|
||||
// string => ArrayBuffer Uint16
|
||||
function str2abUint16(str) {
|
||||
var buf = new ArrayBuffer(str.length * 2); // 2 bytes for each char
|
||||
var bufView = new Uint16Array(buf);
|
||||
for (var i = 0, strLen = str.length; i < strLen; i++) {
|
||||
bufView[i] = str.charCodeAt(i);
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
|
||||
function ArrayBuffer2str(buf) {
|
||||
return String.fromCharCode.apply(null, new Uint8Array(buf));
|
||||
}
|
||||
|
||||
function Uint8Array2str(arr) {
|
||||
return String.fromCharCode.apply(null, arr);
|
||||
}
|
||||
|
||||
// let retryPromise = util.autoRetry(promise, 1);
|
||||
// refer to: https://blog.csdn.net/github_38589282/article/details/77414358
|
||||
function autoRetry(func, retryMax) {
|
||||
let retryNum = retryMax;
|
||||
return async function funcR() {
|
||||
let params = arguments
|
||||
while (retryNum--) {
|
||||
try {
|
||||
await func(...params)
|
||||
} catch (e) {
|
||||
if (retryNum > 0) {
|
||||
console.error(`retry ${retryMax - retryNum} time. error:`, e);
|
||||
continue
|
||||
} else {
|
||||
throw e
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
// autoRetry: autoRetry,
|
||||
formatTime: formatTime,
|
||||
delayMs: delayMs,
|
||||
ab2strHex: ab2strHex,
|
||||
str2abUint8: str2abUint8,
|
||||
str2abUint16: str2abUint16,
|
||||
ArrayBuffer2str: ArrayBuffer2str,
|
||||
Uint8Array2str: Uint8Array2str,
|
||||
}
|
Reference in New Issue
Block a user