|
@@ -9,6 +9,8 @@ const writeID = '000036F5-0000-1000-8000-00805F9B34FB';
|
|
|
const MTU = 115;
|
|
|
const app = getApp();
|
|
|
let subIndex = -1
|
|
|
+let commands = []; // 升级包指令数组,每个指令是一个 ArrayBuffer
|
|
|
+let currentCommandIndex = 1;
|
|
|
|
|
|
function acceptDevice(device) {
|
|
|
return device.btid ? true : false;
|
|
@@ -27,7 +29,7 @@ function haveBms() {
|
|
|
function isDevice(device, data) {
|
|
|
// console.log(device,data,'device111');
|
|
|
const advertisData = new Uint8Array(data.advertisData);
|
|
|
- console.log(advertisData,'判断返回第几个字段是正常模式还是升级模式');
|
|
|
+ // console.log(advertisData,'判断返回第几个字段是正常模式还是升级模式');
|
|
|
//打印返回广播 判断返回字段是正常模式还是升级模式
|
|
|
// console.log(advertisData.slice(4, 10).toString(),'device2222');
|
|
|
const mac = device.btid
|
|
@@ -49,16 +51,23 @@ function isDevice(device, data) {
|
|
|
function alterConnect(device, deviceId) {
|
|
|
//登录 crc[0x1F,0x0F,0x5A,0x58,0x32,0x32,0x30,0x32,0x32,0x32,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x08,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x67,0xAC,0x53,0xE7,0x08,0x00]
|
|
|
//登录 [[0x22,0x22,0x01,0x1F,0x0F,0x5A,0x58,0x32,0x32,0x30,0x32,0x32,0x32,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x08,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x67,0xAC,0x53,0xE7,0x08,0x00,crc_data,0xAA,0xAA]]
|
|
|
- //时间戳 0x67AC53E7 16:00:05
|
|
|
+ //时间戳 0x67AC53E7 0x65,0xB3,0xED,0x6F 16:00:05
|
|
|
//切换正常,工厂下发指令 [[0x22,0x22,0x54,0x01,0x01,0x12,0xAA,0xAA]]
|
|
|
//OTA 升级指令 [[0x22,0x22,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,n,0xCB,0xAA,0xAA]]
|
|
|
|
|
|
// const data = [0x1F, 0x0F, ,0x5A,0x58, 0x35, 0x32, 0x30, 0x32, 0x32, 0x32, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
|
|
|
- // 0x08, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x67, 0xAC, 0x53, 0xE7, 0x08, 0x00]
|
|
|
|
|
|
- const data=[ 0x1F, 0x0F,0x38, 0x36, 0x35, 0x34, 0x31, 0x36, 0x30, 0x33, 0x38, 0x30, 0x30, 0x32, 0x32, 0x30, 0x31]
|
|
|
- const crc_data = crc8Ieee8023(data)
|
|
|
- console.log(crc_data, 111);
|
|
|
+ const data=[ 0x1F, 0x0F,0x38, 0x36, 0x35, 0x34, 0x31, 0x36, 0x30, 0x33, 0x38, 0x30, 0x30, 0x32, 0x32, 0x30, 0x31,0x08, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x67, 0xAC, 0x53, 0xE7, 0x08, 0x00]
|
|
|
+ // console.log(data,'datatest');
|
|
|
+ const crc_data = crc8IEEE8023(data)
|
|
|
+ // console.log(crc_data, 111);
|
|
|
+ // 示例数据(16进制字符串转换为字节数组)
|
|
|
+ // const hexString = "1F0F38363534313630333830303232303108313233343536373867AC53E70800";
|
|
|
+ // const byteArray = hexString.match(/.{1,2}/g).map(byte => parseInt(byte, 16));
|
|
|
+ // console.log(byteArray,'byteArray');
|
|
|
+ // 计算 CRC-8 IEEE 802.3 校验值
|
|
|
+ // const crcResult = crc8IEEE8023(byteArray).toString(16).toUpperCase();
|
|
|
+ // console.log("CRC-8 IEEE 802.3 Checksum:", crcResult.toString(16).toUpperCase());
|
|
|
return [
|
|
|
[0x22, 0x22, 0x01, 0x1F, 0x0F, 0x38, 0x36, 0x35, 0x34, 0x31, 0x36, 0x30, 0x33, 0x38, 0x30, 0x30, 0x32, 0x32, 0x30, 0x31, 0x08, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x67, 0xAC, 0x53, 0xE7, 0x08, 0x00,
|
|
|
crc_data, 0xAA, 0xAA
|
|
@@ -67,56 +76,56 @@ function alterConnect(device, deviceId) {
|
|
|
//return [sendCommand(0x01, [0xAB, 0xCD, 0xAB, 0xCD])]
|
|
|
}
|
|
|
|
|
|
+function crc8IEEE8023(data) {
|
|
|
+ const poly = 0x07; // IEEE 802.3 polynomial x^8 + x^2 + x + 1
|
|
|
+ let crc = 0x00;
|
|
|
|
|
|
-function crc8Ieee8023(data) {
|
|
|
- let crc = 0x00; // 初始化CRC为0
|
|
|
- const polynomial = 0x07; // CRC-8 IEEE 802.3 多项式
|
|
|
- // 遍历数据数组中的每个字节
|
|
|
- for (let byte of data) {
|
|
|
- crc ^= byte; // 将当前字节与CRC寄存器进行异或操作
|
|
|
- // 对CRC寄存器的每一位进行8次迭代
|
|
|
- for (let i = 0; i < 8; i++) {
|
|
|
- if (crc & 0x80) { // 检查最高位是否为1
|
|
|
- crc = (crc << 1) ^ polynomial; // 左移一位并与多项式异或
|
|
|
- } else {
|
|
|
- crc <<= 1; // 仅左移一位
|
|
|
- }
|
|
|
- }
|
|
|
- // 截断CRC到8位(在JavaScript中这一步是多余的,因为位运算会自动处理溢出)
|
|
|
- crc &= 0xFF;
|
|
|
- }
|
|
|
-
|
|
|
- // 返回CRC校验码的最低8位,并转换为十六进制字符串
|
|
|
- return '0x' + crc.toString(16).toUpperCase().padStart(2, '0'); // 使用padStart确保结果始终是两位十六进制数
|
|
|
+ for (let i = 0; i < data.length; i++) {
|
|
|
+ crc ^= data[i];
|
|
|
+ for (let j = 0; j < 8; j++) {
|
|
|
+ if (crc & 0x80) {
|
|
|
+ crc = ((crc << 1) ^ poly) & 0xFF;
|
|
|
+ } else {
|
|
|
+ crc = (crc << 1) & 0xFF;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return crc;
|
|
|
}
|
|
|
|
|
|
-//connectDevice 打开连接 findDevice 查找设备
|
|
|
+
|
|
|
|
|
|
//收到硬件方向软件方发送的数据
|
|
|
function readData(device, value, data) {
|
|
|
// console.log(value, 'test1111');
|
|
|
var value = new Uint8Array(value);
|
|
|
- console.log(value, 'value**************************');
|
|
|
- switch (value[0]) {
|
|
|
- case 0:
|
|
|
- //登陆成功准备
|
|
|
- switchFactory(device)
|
|
|
- break;
|
|
|
- }
|
|
|
- // switch(value[2]){
|
|
|
- // case 0x66:
|
|
|
+
|
|
|
+ const normalArray = Array.from(value); // 或 [...uint8Array]
|
|
|
+ console.log(normalArray, 'value**************************');
|
|
|
+ // switch (value[0]) {
|
|
|
+ // case 0:
|
|
|
+ // //登陆成功准备
|
|
|
+ // switchFactory(device)
|
|
|
+ // break;
|
|
|
+ // }
|
|
|
+ switch(normalArray[3]){
|
|
|
+ case 0x00:
|
|
|
+ sendNextCommand(device.mac_id)
|
|
|
+ break;
|
|
|
|
|
|
- // break;
|
|
|
- // }
|
|
|
+ case 0x01:
|
|
|
+ test()
|
|
|
+ break;
|
|
|
+ }
|
|
|
|
|
|
return data;
|
|
|
}
|
|
|
-
|
|
|
-function parseOTAData(){
|
|
|
- //解析是否成功&&第几个包
|
|
|
- //如果是第一个包成功 发送第二个包的数据 //otaUpgrade
|
|
|
+function test(){
|
|
|
+ currentCommandIndex=1
|
|
|
+ console.log(commands[currentCommandIndex],'test');
|
|
|
}
|
|
|
|
|
|
+
|
|
|
function sendCommand(cmd, data = []) {
|
|
|
const startCmd = [0x02, 0x02]
|
|
|
const endCmd = [0xAA, 0xAA]
|
|
@@ -145,55 +154,166 @@ function switchFactory(device, deviceId) {
|
|
|
return [[0x22,0x22,0x54,0x01,0x01,0x12,0xAA,0xAA]]
|
|
|
// return [sendCommand([0x54, 0x01, 0x01, 0x12])];
|
|
|
}
|
|
|
+//升级按钮
|
|
|
+function otaUpgrade(device){
|
|
|
+
|
|
|
+ const data = readBinBinarayToCommand()
|
|
|
+ data.then(result=>{commands=result})
|
|
|
+
|
|
|
+ // console.log(data,'datatest111');
|
|
|
+ return data
|
|
|
+}
|
|
|
+async function readBinBinarayToCommand() {
|
|
|
+ let res =await uni.request({
|
|
|
+ url: 'https://opt.bms16.com/ota.BIN', // 文件的网络地址
|
|
|
+ method: 'GET',
|
|
|
+ responseType: 'arraybuffer', // 指定响应类型为 arraybuffer
|
|
|
+ });
|
|
|
+ const arrayBuffer=res[1].data
|
|
|
+ const uint8Array = new Uint8Array(arrayBuffer); // 转换为 Uint8Array
|
|
|
+ const test = splitArrayIntoChunks(uint8Array, 80); // 分割成长度为 80 的数组
|
|
|
+ const data =makeArr(test)
|
|
|
+ // const tests=data.slice(data.length-3)
|
|
|
+ // console.log(data.length,tests[0],'testtest数组');
|
|
|
+ // console.log(tests,'tests');
|
|
|
+ return data
|
|
|
+}
|
|
|
|
|
|
-//升级OTA
|
|
|
-async function otaUpgrade(device, deviceId) {
|
|
|
- //return [sendCommand([0x54,0x01,0x01,0x12])];
|
|
|
- //第一步先读取BIN文件的二进制流
|
|
|
- const subPackage = await readBinBinarayToCommand()
|
|
|
- // console.log(dataRecursion(subPackage,subIndex))
|
|
|
- return dataRecursion(subPackage)
|
|
|
- // //提取分包数据
|
|
|
- // var subPackage = []
|
|
|
- // for(var i=0;Math.ceil(fileCommandList.length/80) >i;i++){
|
|
|
- // //提取数组的分割数据
|
|
|
- // var subCmd = []
|
|
|
- // subCmd = [0x22,0x22,]
|
|
|
- // //[[0x01,0x02,0x23],[0x04,0x05,0x06]] subPackage
|
|
|
- // subPackage.push(subCmd) //提取80个数据 0-80 81-160
|
|
|
- // }
|
|
|
- // return [subPackage[2]]
|
|
|
+function sendNextCommand(mac_id) {
|
|
|
+ console.log(commands[currentCommandIndex],'command');
|
|
|
+ if (currentCommandIndex >= commands.length) {
|
|
|
+ console.log('所有指令发送完成');
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ const deviceId = Object.keys(app.globalData.connectionState).find((i) => app.globalData.connectionState[i].device.mac_id == mac_id);
|
|
|
+ if (deviceId == undefined) {
|
|
|
+ console.log('deviceId == undefined');
|
|
|
+ return ;
|
|
|
+ }
|
|
|
+ const command = [commands[currentCommandIndex]];
|
|
|
+
|
|
|
+ if(command.length==0){
|
|
|
+ return
|
|
|
+ }
|
|
|
+ // 将数据转换为ArrayBuffer类型
|
|
|
+ var buffer;
|
|
|
+ buffer = common.toArrayBuffer(command.shift());
|
|
|
+ // console.log(command,'command');
|
|
|
+ uni.writeBLECharacteristicValue({
|
|
|
+ deviceId: deviceId, // 替换为实际的设备 ID
|
|
|
+ serviceId: writeServiceID, // 替换为实际的服务 ID
|
|
|
+ characteristicId: writeID, // 替换为可写入的特征值 ID
|
|
|
+ value: buffer,
|
|
|
+ success() {
|
|
|
+ // console.log('指令发送成功,等待设备响应');
|
|
|
+ },
|
|
|
+ fail(err) {
|
|
|
+ console.error('指令发送失败', err);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ currentCommandIndex++;
|
|
|
}
|
|
|
|
|
|
+function splitArrayIntoChunks(array, chunkSize) {
|
|
|
+ const numChunks = Math.ceil(array.length / chunkSize);
|
|
|
+ return Array.from({ length: numChunks }, (_, i) => {
|
|
|
+ return array.slice(i * chunkSize, (i + 1) * chunkSize);
|
|
|
+ });
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+// 处理分割后的数组
|
|
|
+function makeArr(array) {
|
|
|
+ const result = [];
|
|
|
+ for (let i = 0; i < array.length; i ++) {
|
|
|
+
|
|
|
+ let endPackage = 0x00
|
|
|
+ if((i + 1) >= array.length){
|
|
|
+ //当前是最后一次循环
|
|
|
+ endPackage = 0x01
|
|
|
+ }
|
|
|
+ //协议号 30 包长度未固定array.length+8 转16进制 固件类型0x00 升级包大小(总包大小) 125396字节-》0x00,0x01,0xE9,0xD4
|
|
|
+ let startArray = []
|
|
|
+ const packageLen=parseInt((array[i].length+8).toString(16).toUpperCase(), 16)
|
|
|
+
|
|
|
+ // const totalPackageSize=[0x00,0x00,0x01,0xE9,0xD4]
|
|
|
+ const totalPackageSize=[0x00,0x00,0x01,0xE9,0xac]
|
|
|
+ startArray.push(packageLen,...totalPackageSize)
|
|
|
+ //软件包id
|
|
|
+ const ids=splitNumber(i) // 0x00,0x01
|
|
|
+ startArray.push(...ids)
|
|
|
+ //是否为最后一个包
|
|
|
+ startArray.push(endPackage)
|
|
|
+ //软件数据包
|
|
|
+ const formattedChunk = array[i].map(byte => `0x${byte.toString(16).padStart(2, '0')}`); // 转换为 0xXX 格式
|
|
|
+ startArray.push(...formattedChunk)
|
|
|
+ // if(i==2){
|
|
|
+ // console.log(startArray,'startArraystartArray');
|
|
|
+ // }
|
|
|
+
|
|
|
+ //crc检验
|
|
|
+ const crcStr='0x'+crc8IEEE8023(startArray).toString(16).toUpperCase()
|
|
|
+ const testCrc=parseInt(crcStr,16)
|
|
|
+ startArray.push(crcStr)
|
|
|
+ // if(i==2){
|
|
|
+ // console.log(startArray,crcStr,testCrc,'crcStr');
|
|
|
+ // }
|
|
|
+ startArray.push(0xAA,0xAA)
|
|
|
+ startArray.unshift(0x22,0x22,0x30)
|
|
|
+ result.push(startArray);
|
|
|
+ }
|
|
|
+ // result.push([0x22,0x22,0x30,0x58,0x00,0x00,0x00,0xE9,0xD4,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x2C,0xAA,0xAA])
|
|
|
+ return result;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+function splitNumber(num) {
|
|
|
+ // 将数字转换为字符串
|
|
|
+ const numStr = num.toString();
|
|
|
+
|
|
|
+ // 使用正则表达式分割字符串为两位一组
|
|
|
+ const parts = numStr.match(/.{1,2}/g) || [];
|
|
|
+
|
|
|
+ // 将字符串数组转换为数字数组
|
|
|
+ let result = parts.map(part => parseInt(part, 10));
|
|
|
+
|
|
|
+ // 如果数组长度为 1,前面补一个 0
|
|
|
+ if (result.length === 1) {
|
|
|
+ result = [0, ...result];
|
|
|
+ }
|
|
|
+
|
|
|
+ return result;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
function dataRecursion(subPackage){
|
|
|
subIndex += 1
|
|
|
let endPackage = 0x00
|
|
|
if(subPackage.groupedArray.length - 1 == subIndex){
|
|
|
endPackage = 0x01
|
|
|
}
|
|
|
- let startArray = [0x22,0x22,0x30,0x30,0x00,0x58,0x00]
|
|
|
+ // let startArray = [0x22,0x22,0x30, 0x30,0x00, 0x58,0x00]
|
|
|
+ let startArray = [0x00,0x58,0x00]
|
|
|
+ //包长度 固件类型到前一位 0x00,0x58 0x00
|
|
|
+ //crc 包长度到crc前一位
|
|
|
+ //升级包大小
|
|
|
startArray = startArray.concat(decimalToHexBytes(subPackage.size,4))
|
|
|
- console.log(222222)
|
|
|
+ //软件包id
|
|
|
startArray = startArray.concat(decimalToHexBytes(subIndex + 1,2))
|
|
|
+ //是否为最后一个包
|
|
|
startArray.push(endPackage)
|
|
|
+ //软件数据包
|
|
|
startArray = startArray.concat(subPackage.groupedArray[subIndex])
|
|
|
- startArray.push(0xCB)
|
|
|
- console.log(subPackage.groupedArray[subIndex])
|
|
|
+ //crc检验
|
|
|
+ const crcStr=crc8IEEE8023(startArray)
|
|
|
+ startArray.push(crcStr)
|
|
|
+ startArray.unshift(0x22,0x22,0x30)
|
|
|
startArray = startArray.concat([0xAA,0xAA])
|
|
|
-
|
|
|
- console.log(startArray)
|
|
|
- return startArray
|
|
|
+ // console.log(startArray)
|
|
|
+ return [startArray]
|
|
|
}
|
|
|
|
|
|
-async function readBinBinarayToCommand() {
|
|
|
- let res = await uni.request({
|
|
|
- url: 'https://opt.bms16.com/ota.BIN', // 文件的网络地址
|
|
|
- method: 'GET',
|
|
|
- responseType: 'arraybuffer', // 指定响应类型为 arraybuffer
|
|
|
- });
|
|
|
-
|
|
|
- return arrayBufferToHexWithPrefix(res[1].data)
|
|
|
-}
|
|
|
function arrayBufferToHexWithPrefix(buffer,groupSize = 80) {
|
|
|
const uint8Array = new Uint8Array(buffer);
|
|
|
const groupedArray = [];
|