@jiabaida/tools 1.1.1 → 1.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var commonfun=require("./commonfun.js"),TelinkApi=require("./TelinkApi.js"),Transfer=require("./Transfer.js");const max=Transfer.BLE.PACKAGE_MAX_LENGTH,delayDefault=Transfer.BLE.WRITE_DELAY,{isIOS:isIOS,isAndroid:isAndroid}=commonfun.getOS();class OTAUpgrade{constructor({deviceId:deviceId,filePath:filePath,otaInfo:otaInfo,otaStart:otaStart,otaReStart:otaReStart,macAddr:macAddr,onProgress:onProgress,onSuccess:onSuccess,onError:onError,delay:delay,platform:platform="APP"}){this.deviceId=deviceId,this.filePath=filePath,this.otaInfo=otaInfo,this.otaStart=otaStart,this.otaReStart=otaReStart,this.macAddr=macAddr,this.platform=platform,this.isTeLink=!!TelinkApi.TelinkApi.isTeLink&&TelinkApi.TelinkApi.isTeLink({macAddr:macAddr}),this.onProgress=onProgress,this.onSuccess=onSuccess,this.onError=onError,this.delay=delay||delayDefault,this.fileHexArray=[],this.totalTimes=1,this.finishedTimes=0,this.succeed=!1,this.ready=!0,this.timer=null,this.s_progress=0,this.otaStarting=!1,this.progressType="download"}async start(){this.progressType="download";try{await this.download()}catch(e){this.fail("下载失败: "+e.message)}}async download(){const that=this;return new Promise((resolve,reject)=>{const downloadTask=uni.downloadFile({url:that.filePath,success:({tempFilePath:tempFilePath})=>{this.addBLECharValueChangeListener(),that.resolve(tempFilePath).then(resolve).catch(reject)},fail:res=>{that.fail("固件下载失败"),reject(res)}});downloadTask.onProgressUpdate&&downloadTask.onProgressUpdate(({progress:progress})=>{that.onProgress&&that.onProgress({type:"download",percent:progress})})})}async resolve(tempFilePath){const that=this;return new Promise((resolve,reject)=>{uni.saveFile({tempFilePath:tempFilePath,success:({savedFilePath:savedFilePath})=>{if("APP"===this.platform)plus.io.resolveLocalFileSystemURL(savedFilePath,entry=>{entry.file(file=>{var fileReader=new plus.io.FileReader;fileReader.readAsDataURL(file),fileReader.onloadend=e=>{let base64=e.target.result.split(",")[1];const hexArray=Transfer.Transfer.base64ToHexArray(base64),times=Math.ceil(hexArray.length/(that.isTeLink?16:max));that.fileHexArray=hexArray,that.totalTimes=times,that.finishedTimes=0,that.progressType="upgrade",that.isTeLink?that.telinkUpgrade():that.normalUpgrade(),resolve()},fileReader.onerror=e=>{that.fail("固件解析失败"),reject(e)}})},err=>{that.fail("固件保存失败"),reject(err)});else if("MP"===this.platform){wx.getFileSystemManager().readFile({filePath:savedFilePath,encoding:"base64",success:res=>{let base64=res.data;const hexArray=Transfer.Transfer.base64ToHexArray(base64),times=Math.ceil(hexArray.length/(that.isTeLink?16:max));that.fileHexArray=hexArray,that.totalTimes=times,that.finishedTimes=0,that.progressType="upgrade",that.isTeLink?that.telinkUpgrade():that.normalUpgrade(),resolve()},fail:err=>{console.error("[OTA] resolve failed:",JSON.stringify(err)),that.failed("文件解析失败")}})}},fail:res=>{that.fail("固件保存失败"),reject(res)}})})}normalUpgrade(){setTimeout(()=>{Transfer.BLE.writeATCmd(this.otaInfo,this.deviceId,this.fail.bind(this))},2600)}telinkUpgrade(){this.write(["0x00","0xff"],0)}write(pkg,type){const value=function(hexArr){const buffer=new ArrayBuffer(hexArr.length),dataView=new DataView(buffer);return hexArr.forEach((hex,i)=>dataView.setUint8(i,hex)),buffer}(pkg.map(o=>parseInt(o,16))),opt={deviceId:this.deviceId,serviceId:"00010203-0405-0607-0809-0a0b0c0d1912",characteristicId:"00010203-0405-0607-0809-0a0b0c0d2b12",value:value,success:()=>this.onSucceed(type),fail:async()=>{await this.sleep(2*this.delay),uni.writeBLECharacteristicValue({...opt,fail:async()=>{await this.sleep(2*this.delay),uni.writeBLECharacteristicValue({...opt,fail:()=>{console.error("写入失败: ",pkg),this.fail("写入失败")}})}})}};uni.writeBLECharacteristicValue(opt),isIOS&&setTimeout(()=>this.onSucceed(type),5)}onSucceed(type){0==type?this.write(["0x01","0xff"],1):1==type?this.sendNextOtaPacketCommand():2==type?(this.finishedTimes++,this.sendNextOtaPacketCommand()):3==type?this.sendNextOtaPacketCommand():4==type?this.sendOtaEndCommand():5==type&&(this.finishedTimes++,this.succeed=!0,this.onSuccess&&this.onSuccess()),this.onProgress&&this.onProgress({type:"upgrade",percent:Math.floor(100*this.finishedTimes/this.totalTimes)})}async sendNextOtaPacketCommand(){const i=this.finishedTimes,index=TelinkApi.TelinkApi.getIndexHexArr(i);let pkgValue=this.fileHexArray.slice(16*i,16*(i+1));pkgValue.length<16&&(pkgValue=pkgValue.concat([...Array(16-pkgValue.length)].map(()=>"0xFF")));const crc=TelinkApi.TelinkApi.genCheck([...index,...pkgValue]),pkg=[...index,...pkgValue,...crc],type=i>=this.totalTimes-1?4:2;await this.sleep(this.delay),this.write(pkg,type)}sendOtaEndCommand(){const pkgValue=function(i,c=65282){return[255&c,c>>8&255,255&i,i>>8&255,255&~i,~i>>8&255].map(o=>`0x${`00${o.toString(16)}`.slice(-2)}`.toUpperCase())}(this.totalTimes-1),crc=TelinkApi.TelinkApi.genCheck([...pkgValue]),pkg=[...pkgValue,...crc];this.write(pkg,5)}addBLECharValueChangeListener(){console.log("添加蓝牙特征值变化监听");const that=this;uni.notifyBLECharacteristicValueChange({deviceId:that.deviceId,serviceId:Transfer.BLE.serviceId,characteristicId:Transfer.BLE.readUUID,state:!0,success:()=>{},fail:()=>{}}),that.ready=!0,that.readValue=[],that.receiveLength=null,uni.onBLECharacteristicValueChange(({deviceId:deviceId,serviceId:serviceId,characteristicId:characteristicId,value:value})=>{if(that.ready&&deviceId==that.deviceId&&serviceId==Transfer.BLE.serviceId){const intArr=Array.prototype.map.call(new Uint8Array(value),x=>x);intArr.length>0&&(null==that.receiveLength&&255==intArr[0]&&170==intArr[1]&&(that.receiveLength=intArr[3]+5),that.receiveLength?(that.readValue=that.readValue.concat(intArr),that.readValue.length==that.receiveLength&&(that.doWithResponse([...that.readValue]),that.readValue=[],that.receiveLength=null)):(that.readValue=[],that.receiveLength=null))}})}async doWithResponse(intArr){if(console.log("收到设备响应: ",intArr[2]),128==intArr[2]){let str=String.fromCharCode(...intArr.slice(4,-1));if(console.log("doWithResponse otaStart1",str),str.indexOf(this.otaInfo)>-1&&(this.finishedTimes=0,this.transferFirmwareFile()),str.indexOf(this.otaStart)>-1||this.otaStarting){if(str.indexOf(this.otaStart)>-1&&(this.otaStarting=!0),console.log("doWithResponse otaStart2",str),str.toUpperCase().includes("ERROR"))return void this.fail(str);str.toUpperCase().indexOf("S100")>-1&&(this.succeed=!0,this.onSuccess&&this.onSuccess())}}80==intArr[2]&&(0==intArr[4]?(this.finishedTimes++,this.transferFirmwareFile()):this.transferFirmwareFile()),81==intArr[2]&&(0==intArr[4]?this.startOTA():this.fail("升级失败"))}async transferFirmwareFile(){
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var commonfun=require("./commonfun.js"),TelinkApi=require("./TelinkApi.js"),Transfer=require("./Transfer.js");const max=Transfer.BLE.PACKAGE_MAX_LENGTH,delayDefault=Transfer.BLE.WRITE_DELAY,{isIOS:isIOS,isAndroid:isAndroid}=commonfun.getOS();class OTAUpgrade{constructor({deviceId:deviceId,filePath:filePath,otaInfo:otaInfo,otaStart:otaStart,otaReStart:otaReStart,macAddr:macAddr,onProgress:onProgress,onSuccess:onSuccess,onError:onError,delay:delay,platform:platform="APP"}){this.deviceId=deviceId,this.filePath=filePath,this.otaInfo=otaInfo,this.otaStart=otaStart,this.otaReStart=otaReStart,this.macAddr=macAddr,this.platform=platform,this.isTeLink=!!TelinkApi.TelinkApi.isTeLink&&TelinkApi.TelinkApi.isTeLink({macAddr:macAddr}),this.onProgress=onProgress,this.onSuccess=onSuccess,this.onError=onError,this.delay=delay||delayDefault,this.fileHexArray=[],this.totalTimes=1,this.finishedTimes=0,this.succeed=!1,this.ready=!0,this.timer=null,this.s_progress=0,this.otaStarting=!1,this.progressType="download"}async start(){this.progressType="download";try{await this.download()}catch(e){this.fail("下载失败: "+e.message)}}async download(){const that=this;return new Promise((resolve,reject)=>{const downloadTask=uni.downloadFile({url:that.filePath,success:({tempFilePath:tempFilePath})=>{this.addBLECharValueChangeListener(),that.resolve(tempFilePath).then(resolve).catch(reject)},fail:res=>{that.fail("固件下载失败"),reject(res)}});downloadTask.onProgressUpdate&&downloadTask.onProgressUpdate(({progress:progress})=>{that.onProgress&&that.onProgress({type:"download",percent:progress})})})}async resolve(tempFilePath){const that=this;return new Promise((resolve,reject)=>{uni.saveFile({tempFilePath:tempFilePath,success:({savedFilePath:savedFilePath})=>{if("APP"===this.platform)plus.io.resolveLocalFileSystemURL(savedFilePath,entry=>{entry.file(file=>{var fileReader=new plus.io.FileReader;fileReader.readAsDataURL(file),fileReader.onloadend=e=>{let base64=e.target.result.split(",")[1];const hexArray=Transfer.Transfer.base64ToHexArray(base64),times=Math.ceil(hexArray.length/(that.isTeLink?16:max));that.fileHexArray=hexArray,that.totalTimes=times,that.finishedTimes=0,that.progressType="upgrade",that.isTeLink?that.telinkUpgrade():that.normalUpgrade(),resolve()},fileReader.onerror=e=>{that.fail("固件解析失败"),reject(e)}})},err=>{that.fail("固件保存失败"),reject(err)});else if("MP"===this.platform){wx.getFileSystemManager().readFile({filePath:savedFilePath,encoding:"base64",success:res=>{let base64=res.data;const hexArray=Transfer.Transfer.base64ToHexArray(base64),times=Math.ceil(hexArray.length/(that.isTeLink?16:max));that.fileHexArray=hexArray,that.totalTimes=times,that.finishedTimes=0,that.progressType="upgrade",that.isTeLink?that.telinkUpgrade():that.normalUpgrade(),resolve()},fail:err=>{console.error("[OTA] resolve failed:",JSON.stringify(err)),that.failed("文件解析失败")}})}},fail:res=>{that.fail("固件保存失败"),reject(res)}})})}normalUpgrade(){setTimeout(()=>{Transfer.BLE.writeATCmd(this.otaInfo,this.deviceId,this.fail.bind(this))},2600)}telinkUpgrade(){this.write(["0x00","0xff"],0)}write(pkg,type){const value=function(hexArr){const buffer=new ArrayBuffer(hexArr.length),dataView=new DataView(buffer);return hexArr.forEach((hex,i)=>dataView.setUint8(i,hex)),buffer}(pkg.map(o=>parseInt(o,16))),opt={deviceId:this.deviceId,serviceId:"00010203-0405-0607-0809-0a0b0c0d1912",characteristicId:"00010203-0405-0607-0809-0a0b0c0d2b12",value:value,success:()=>this.onSucceed(type),fail:async()=>{await this.sleep(2*this.delay),uni.writeBLECharacteristicValue({...opt,fail:async()=>{await this.sleep(2*this.delay),uni.writeBLECharacteristicValue({...opt,fail:()=>{console.error("写入失败: ",pkg),this.fail("写入失败")}})}})}};uni.writeBLECharacteristicValue(opt),isIOS&&setTimeout(()=>this.onSucceed(type),5)}onSucceed(type){0==type?this.write(["0x01","0xff"],1):1==type?this.sendNextOtaPacketCommand():2==type?(this.finishedTimes++,this.sendNextOtaPacketCommand()):3==type?this.sendNextOtaPacketCommand():4==type?this.sendOtaEndCommand():5==type&&(this.finishedTimes++,this.succeed=!0,this.onSuccess&&this.onSuccess()),this.onProgress&&this.onProgress({type:"upgrade",percent:Math.floor(100*this.finishedTimes/this.totalTimes)})}async sendNextOtaPacketCommand(){const i=this.finishedTimes,index=TelinkApi.TelinkApi.getIndexHexArr(i);let pkgValue=this.fileHexArray.slice(16*i,16*(i+1));pkgValue.length<16&&(pkgValue=pkgValue.concat([...Array(16-pkgValue.length)].map(()=>"0xFF")));const crc=TelinkApi.TelinkApi.genCheck([...index,...pkgValue]),pkg=[...index,...pkgValue,...crc],type=i>=this.totalTimes-1?4:2;await this.sleep(this.delay),this.write(pkg,type)}sendOtaEndCommand(){const pkgValue=function(i,c=65282){return[255&c,c>>8&255,255&i,i>>8&255,255&~i,~i>>8&255].map(o=>`0x${`00${o.toString(16)}`.slice(-2)}`.toUpperCase())}(this.totalTimes-1),crc=TelinkApi.TelinkApi.genCheck([...pkgValue]),pkg=[...pkgValue,...crc];this.write(pkg,5)}addBLECharValueChangeListener(){console.log("添加蓝牙特征值变化监听");const that=this;uni.notifyBLECharacteristicValueChange({deviceId:that.deviceId,serviceId:Transfer.BLE.serviceId,characteristicId:Transfer.BLE.readUUID,state:!0,success:()=>{},fail:()=>{}}),that.ready=!0,that.readValue=[],that.receiveLength=null,uni.onBLECharacteristicValueChange(({deviceId:deviceId,serviceId:serviceId,characteristicId:characteristicId,value:value})=>{if(that.ready&&deviceId==that.deviceId&&serviceId==Transfer.BLE.serviceId){const intArr=Array.prototype.map.call(new Uint8Array(value),x=>x);intArr.length>0&&(null==that.receiveLength&&255==intArr[0]&&170==intArr[1]&&(that.receiveLength=intArr[3]+5),that.receiveLength?(that.readValue=that.readValue.concat(intArr),that.readValue.length==that.receiveLength&&(that.doWithResponse([...that.readValue]),that.readValue=[],that.receiveLength=null)):(that.readValue=[],that.receiveLength=null))}})}async doWithResponse(intArr){if(console.log("收到设备响应: ",intArr[2]),128==intArr[2]){let str=String.fromCharCode(...intArr.slice(4,-1));if(console.log("doWithResponse otaStart1",str),str.indexOf(this.otaInfo)>-1&&(this.finishedTimes=0,this.transferFirmwareFile()),str.indexOf(this.otaStart)>-1||this.otaStarting){if(str.indexOf(this.otaStart)>-1&&(this.otaStarting=!0),console.log("doWithResponse otaStart2",str),str.toUpperCase().includes("ERROR"))return void this.fail(str);str.toUpperCase().indexOf("S100")>-1&&(this.succeed=!0,this.onSuccess&&this.onSuccess())}}80==intArr[2]&&(0==intArr[4]?(this.finishedTimes++,this.transferFirmwareFile()):this.transferFirmwareFile()),81==intArr[2]&&(0==intArr[4]?this.startOTA():this.fail("升级失败"))}async transferFirmwareFile(){if(this.finishedTimes+1>this.totalTimes+1){const pkg=[0];await Transfer.BLE.sendDelay(this.delay),Transfer.BLE.transferFirmwareFileCmd(this.deviceId,pkg,!0,this.fail.bind(this)),console.log("[OTA]","=== Send 51 ===",this.finishedTimes,this.totalTimes,pkg)}else if(0===this.finishedTimes){const emptyPkg=[0,0];console.log("[OTA]","=== Send empty package first ==="),await Transfer.BLE.sendDelay(this.delay),Transfer.BLE.transferFirmwareFileCmd(this.deviceId,emptyPkg,!1,this.fail.bind(this))}else{const dataIndex=this.finishedTimes-1,pkg=this.fileHexArray.slice(dataIndex*max,(dataIndex+1)*max),index=Transfer.Transfer.decimalToTwoByteHexArray(this.finishedTimes);console.log("[OTA]",`S50-${this.finishedTimes}/${this.totalTimes}`),await Transfer.BLE.sendDelay(this.delay),Transfer.BLE.transferFirmwareFileCmd(this.deviceId,index.concat(pkg),!1,this.fail.bind(this))}this.onProgress&&this.onProgress({type:"upgrade",percent:Math.floor(100*this.finishedTimes/this.totalTimes)})}async startOTA(){Transfer.BLE.writeATCmd(this.otaStart,this.deviceId,this.fail.bind(this))}fail(msg){this.succeed=!1,this.onError&&this.onError(msg)}sleep(n=50){return new Promise(r=>setTimeout(()=>r(!0),n))}}exports.OTAUpgrade=OTAUpgrade,exports.default=OTAUpgrade;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{getOS}from"./commonfun.js";import{TelinkApi}from"./TelinkApi.js";import{BLE,Transfer}from"./Transfer.js";const max=BLE.PACKAGE_MAX_LENGTH,delayDefault=BLE.WRITE_DELAY,{isIOS:isIOS,isAndroid:isAndroid}=getOS();class OTAUpgrade{constructor({deviceId:deviceId,filePath:filePath,otaInfo:otaInfo,otaStart:otaStart,otaReStart:otaReStart,macAddr:macAddr,onProgress:onProgress,onSuccess:onSuccess,onError:onError,delay:delay,platform:platform="APP"}){this.deviceId=deviceId,this.filePath=filePath,this.otaInfo=otaInfo,this.otaStart=otaStart,this.otaReStart=otaReStart,this.macAddr=macAddr,this.platform=platform,this.isTeLink=!!TelinkApi.isTeLink&&TelinkApi.isTeLink({macAddr:macAddr}),this.onProgress=onProgress,this.onSuccess=onSuccess,this.onError=onError,this.delay=delay||delayDefault,this.fileHexArray=[],this.totalTimes=1,this.finishedTimes=0,this.succeed=!1,this.ready=!0,this.timer=null,this.s_progress=0,this.otaStarting=!1,this.progressType="download"}async start(){this.progressType="download";try{await this.download()}catch(e){this.fail("下载失败: "+e.message)}}async download(){const that=this;return new Promise((resolve,reject)=>{const downloadTask=uni.downloadFile({url:that.filePath,success:({tempFilePath:tempFilePath})=>{this.addBLECharValueChangeListener(),that.resolve(tempFilePath).then(resolve).catch(reject)},fail:res=>{that.fail("固件下载失败"),reject(res)}});downloadTask.onProgressUpdate&&downloadTask.onProgressUpdate(({progress:progress})=>{that.onProgress&&that.onProgress({type:"download",percent:progress})})})}async resolve(tempFilePath){const that=this;return new Promise((resolve,reject)=>{uni.saveFile({tempFilePath:tempFilePath,success:({savedFilePath:savedFilePath})=>{if("APP"===this.platform)plus.io.resolveLocalFileSystemURL(savedFilePath,entry=>{entry.file(file=>{var fileReader=new plus.io.FileReader;fileReader.readAsDataURL(file),fileReader.onloadend=e=>{let base64=e.target.result.split(",")[1];const hexArray=Transfer.base64ToHexArray(base64),times=Math.ceil(hexArray.length/(that.isTeLink?16:max));that.fileHexArray=hexArray,that.totalTimes=times,that.finishedTimes=0,that.progressType="upgrade",that.isTeLink?that.telinkUpgrade():that.normalUpgrade(),resolve()},fileReader.onerror=e=>{that.fail("固件解析失败"),reject(e)}})},err=>{that.fail("固件保存失败"),reject(err)});else if("MP"===this.platform){wx.getFileSystemManager().readFile({filePath:savedFilePath,encoding:"base64",success:res=>{let base64=res.data;const hexArray=Transfer.base64ToHexArray(base64),times=Math.ceil(hexArray.length/(that.isTeLink?16:max));that.fileHexArray=hexArray,that.totalTimes=times,that.finishedTimes=0,that.progressType="upgrade",that.isTeLink?that.telinkUpgrade():that.normalUpgrade(),resolve()},fail:err=>{console.error("[OTA] resolve failed:",JSON.stringify(err)),that.failed("文件解析失败")}})}},fail:res=>{that.fail("固件保存失败"),reject(res)}})})}normalUpgrade(){setTimeout(()=>{BLE.writeATCmd(this.otaInfo,this.deviceId,this.fail.bind(this))},2600)}telinkUpgrade(){this.write(["0x00","0xff"],0)}write(pkg,type){const value=function(hexArr){const buffer=new ArrayBuffer(hexArr.length),dataView=new DataView(buffer);return hexArr.forEach((hex,i)=>dataView.setUint8(i,hex)),buffer}(pkg.map(o=>parseInt(o,16))),opt={deviceId:this.deviceId,serviceId:"00010203-0405-0607-0809-0a0b0c0d1912",characteristicId:"00010203-0405-0607-0809-0a0b0c0d2b12",value:value,success:()=>this.onSucceed(type),fail:async()=>{await this.sleep(2*this.delay),uni.writeBLECharacteristicValue({...opt,fail:async()=>{await this.sleep(2*this.delay),uni.writeBLECharacteristicValue({...opt,fail:()=>{console.error("写入失败: ",pkg),this.fail("写入失败")}})}})}};uni.writeBLECharacteristicValue(opt),isIOS&&setTimeout(()=>this.onSucceed(type),5)}onSucceed(type){0==type?this.write(["0x01","0xff"],1):1==type?this.sendNextOtaPacketCommand():2==type?(this.finishedTimes++,this.sendNextOtaPacketCommand()):3==type?this.sendNextOtaPacketCommand():4==type?this.sendOtaEndCommand():5==type&&(this.finishedTimes++,this.succeed=!0,this.onSuccess&&this.onSuccess()),this.onProgress&&this.onProgress({type:"upgrade",percent:Math.floor(100*this.finishedTimes/this.totalTimes)})}async sendNextOtaPacketCommand(){const i=this.finishedTimes,index=TelinkApi.getIndexHexArr(i);let pkgValue=this.fileHexArray.slice(16*i,16*(i+1));pkgValue.length<16&&(pkgValue=pkgValue.concat([...Array(16-pkgValue.length)].map(()=>"0xFF")));const crc=TelinkApi.genCheck([...index,...pkgValue]),pkg=[...index,...pkgValue,...crc],type=i>=this.totalTimes-1?4:2;await this.sleep(this.delay),this.write(pkg,type)}sendOtaEndCommand(){const pkgValue=function(i,c=65282){return[255&c,c>>8&255,255&i,i>>8&255,255&~i,~i>>8&255].map(o=>`0x${`00${o.toString(16)}`.slice(-2)}`.toUpperCase())}(this.totalTimes-1),crc=TelinkApi.genCheck([...pkgValue]),pkg=[...pkgValue,...crc];this.write(pkg,5)}addBLECharValueChangeListener(){console.log("添加蓝牙特征值变化监听");const that=this;uni.notifyBLECharacteristicValueChange({deviceId:that.deviceId,serviceId:BLE.serviceId,characteristicId:BLE.readUUID,state:!0,success:()=>{},fail:()=>{}}),that.ready=!0,that.readValue=[],that.receiveLength=null,uni.onBLECharacteristicValueChange(({deviceId:deviceId,serviceId:serviceId,characteristicId:characteristicId,value:value})=>{if(that.ready&&deviceId==that.deviceId&&serviceId==BLE.serviceId){const intArr=Array.prototype.map.call(new Uint8Array(value),x=>x);intArr.length>0&&(null==that.receiveLength&&255==intArr[0]&&170==intArr[1]&&(that.receiveLength=intArr[3]+5),that.receiveLength?(that.readValue=that.readValue.concat(intArr),that.readValue.length==that.receiveLength&&(that.doWithResponse([...that.readValue]),that.readValue=[],that.receiveLength=null)):(that.readValue=[],that.receiveLength=null))}})}async doWithResponse(intArr){if(console.log("收到设备响应: ",intArr[2]),128==intArr[2]){let str=String.fromCharCode(...intArr.slice(4,-1));if(console.log("doWithResponse otaStart1",str),str.indexOf(this.otaInfo)>-1&&(this.finishedTimes=0,this.transferFirmwareFile()),str.indexOf(this.otaStart)>-1||this.otaStarting){if(str.indexOf(this.otaStart)>-1&&(this.otaStarting=!0),console.log("doWithResponse otaStart2",str),str.toUpperCase().includes("ERROR"))return void this.fail(str);str.toUpperCase().indexOf("S100")>-1&&(this.succeed=!0,this.onSuccess&&this.onSuccess())}}80==intArr[2]&&(0==intArr[4]?(this.finishedTimes++,this.transferFirmwareFile()):this.transferFirmwareFile()),81==intArr[2]&&(0==intArr[4]?this.startOTA():this.fail("升级失败"))}async transferFirmwareFile(){
|
|
1
|
+
import{getOS}from"./commonfun.js";import{TelinkApi}from"./TelinkApi.js";import{BLE,Transfer}from"./Transfer.js";const max=BLE.PACKAGE_MAX_LENGTH,delayDefault=BLE.WRITE_DELAY,{isIOS:isIOS,isAndroid:isAndroid}=getOS();class OTAUpgrade{constructor({deviceId:deviceId,filePath:filePath,otaInfo:otaInfo,otaStart:otaStart,otaReStart:otaReStart,macAddr:macAddr,onProgress:onProgress,onSuccess:onSuccess,onError:onError,delay:delay,platform:platform="APP"}){this.deviceId=deviceId,this.filePath=filePath,this.otaInfo=otaInfo,this.otaStart=otaStart,this.otaReStart=otaReStart,this.macAddr=macAddr,this.platform=platform,this.isTeLink=!!TelinkApi.isTeLink&&TelinkApi.isTeLink({macAddr:macAddr}),this.onProgress=onProgress,this.onSuccess=onSuccess,this.onError=onError,this.delay=delay||delayDefault,this.fileHexArray=[],this.totalTimes=1,this.finishedTimes=0,this.succeed=!1,this.ready=!0,this.timer=null,this.s_progress=0,this.otaStarting=!1,this.progressType="download"}async start(){this.progressType="download";try{await this.download()}catch(e){this.fail("下载失败: "+e.message)}}async download(){const that=this;return new Promise((resolve,reject)=>{const downloadTask=uni.downloadFile({url:that.filePath,success:({tempFilePath:tempFilePath})=>{this.addBLECharValueChangeListener(),that.resolve(tempFilePath).then(resolve).catch(reject)},fail:res=>{that.fail("固件下载失败"),reject(res)}});downloadTask.onProgressUpdate&&downloadTask.onProgressUpdate(({progress:progress})=>{that.onProgress&&that.onProgress({type:"download",percent:progress})})})}async resolve(tempFilePath){const that=this;return new Promise((resolve,reject)=>{uni.saveFile({tempFilePath:tempFilePath,success:({savedFilePath:savedFilePath})=>{if("APP"===this.platform)plus.io.resolveLocalFileSystemURL(savedFilePath,entry=>{entry.file(file=>{var fileReader=new plus.io.FileReader;fileReader.readAsDataURL(file),fileReader.onloadend=e=>{let base64=e.target.result.split(",")[1];const hexArray=Transfer.base64ToHexArray(base64),times=Math.ceil(hexArray.length/(that.isTeLink?16:max));that.fileHexArray=hexArray,that.totalTimes=times,that.finishedTimes=0,that.progressType="upgrade",that.isTeLink?that.telinkUpgrade():that.normalUpgrade(),resolve()},fileReader.onerror=e=>{that.fail("固件解析失败"),reject(e)}})},err=>{that.fail("固件保存失败"),reject(err)});else if("MP"===this.platform){wx.getFileSystemManager().readFile({filePath:savedFilePath,encoding:"base64",success:res=>{let base64=res.data;const hexArray=Transfer.base64ToHexArray(base64),times=Math.ceil(hexArray.length/(that.isTeLink?16:max));that.fileHexArray=hexArray,that.totalTimes=times,that.finishedTimes=0,that.progressType="upgrade",that.isTeLink?that.telinkUpgrade():that.normalUpgrade(),resolve()},fail:err=>{console.error("[OTA] resolve failed:",JSON.stringify(err)),that.failed("文件解析失败")}})}},fail:res=>{that.fail("固件保存失败"),reject(res)}})})}normalUpgrade(){setTimeout(()=>{BLE.writeATCmd(this.otaInfo,this.deviceId,this.fail.bind(this))},2600)}telinkUpgrade(){this.write(["0x00","0xff"],0)}write(pkg,type){const value=function(hexArr){const buffer=new ArrayBuffer(hexArr.length),dataView=new DataView(buffer);return hexArr.forEach((hex,i)=>dataView.setUint8(i,hex)),buffer}(pkg.map(o=>parseInt(o,16))),opt={deviceId:this.deviceId,serviceId:"00010203-0405-0607-0809-0a0b0c0d1912",characteristicId:"00010203-0405-0607-0809-0a0b0c0d2b12",value:value,success:()=>this.onSucceed(type),fail:async()=>{await this.sleep(2*this.delay),uni.writeBLECharacteristicValue({...opt,fail:async()=>{await this.sleep(2*this.delay),uni.writeBLECharacteristicValue({...opt,fail:()=>{console.error("写入失败: ",pkg),this.fail("写入失败")}})}})}};uni.writeBLECharacteristicValue(opt),isIOS&&setTimeout(()=>this.onSucceed(type),5)}onSucceed(type){0==type?this.write(["0x01","0xff"],1):1==type?this.sendNextOtaPacketCommand():2==type?(this.finishedTimes++,this.sendNextOtaPacketCommand()):3==type?this.sendNextOtaPacketCommand():4==type?this.sendOtaEndCommand():5==type&&(this.finishedTimes++,this.succeed=!0,this.onSuccess&&this.onSuccess()),this.onProgress&&this.onProgress({type:"upgrade",percent:Math.floor(100*this.finishedTimes/this.totalTimes)})}async sendNextOtaPacketCommand(){const i=this.finishedTimes,index=TelinkApi.getIndexHexArr(i);let pkgValue=this.fileHexArray.slice(16*i,16*(i+1));pkgValue.length<16&&(pkgValue=pkgValue.concat([...Array(16-pkgValue.length)].map(()=>"0xFF")));const crc=TelinkApi.genCheck([...index,...pkgValue]),pkg=[...index,...pkgValue,...crc],type=i>=this.totalTimes-1?4:2;await this.sleep(this.delay),this.write(pkg,type)}sendOtaEndCommand(){const pkgValue=function(i,c=65282){return[255&c,c>>8&255,255&i,i>>8&255,255&~i,~i>>8&255].map(o=>`0x${`00${o.toString(16)}`.slice(-2)}`.toUpperCase())}(this.totalTimes-1),crc=TelinkApi.genCheck([...pkgValue]),pkg=[...pkgValue,...crc];this.write(pkg,5)}addBLECharValueChangeListener(){console.log("添加蓝牙特征值变化监听");const that=this;uni.notifyBLECharacteristicValueChange({deviceId:that.deviceId,serviceId:BLE.serviceId,characteristicId:BLE.readUUID,state:!0,success:()=>{},fail:()=>{}}),that.ready=!0,that.readValue=[],that.receiveLength=null,uni.onBLECharacteristicValueChange(({deviceId:deviceId,serviceId:serviceId,characteristicId:characteristicId,value:value})=>{if(that.ready&&deviceId==that.deviceId&&serviceId==BLE.serviceId){const intArr=Array.prototype.map.call(new Uint8Array(value),x=>x);intArr.length>0&&(null==that.receiveLength&&255==intArr[0]&&170==intArr[1]&&(that.receiveLength=intArr[3]+5),that.receiveLength?(that.readValue=that.readValue.concat(intArr),that.readValue.length==that.receiveLength&&(that.doWithResponse([...that.readValue]),that.readValue=[],that.receiveLength=null)):(that.readValue=[],that.receiveLength=null))}})}async doWithResponse(intArr){if(console.log("收到设备响应: ",intArr[2]),128==intArr[2]){let str=String.fromCharCode(...intArr.slice(4,-1));if(console.log("doWithResponse otaStart1",str),str.indexOf(this.otaInfo)>-1&&(this.finishedTimes=0,this.transferFirmwareFile()),str.indexOf(this.otaStart)>-1||this.otaStarting){if(str.indexOf(this.otaStart)>-1&&(this.otaStarting=!0),console.log("doWithResponse otaStart2",str),str.toUpperCase().includes("ERROR"))return void this.fail(str);str.toUpperCase().indexOf("S100")>-1&&(this.succeed=!0,this.onSuccess&&this.onSuccess())}}80==intArr[2]&&(0==intArr[4]?(this.finishedTimes++,this.transferFirmwareFile()):this.transferFirmwareFile()),81==intArr[2]&&(0==intArr[4]?this.startOTA():this.fail("升级失败"))}async transferFirmwareFile(){if(this.finishedTimes+1>this.totalTimes+1){const pkg=[0];await BLE.sendDelay(this.delay),BLE.transferFirmwareFileCmd(this.deviceId,pkg,!0,this.fail.bind(this)),console.log("[OTA]","=== Send 51 ===",this.finishedTimes,this.totalTimes,pkg)}else if(0===this.finishedTimes){const emptyPkg=[0,0];console.log("[OTA]","=== Send empty package first ==="),await BLE.sendDelay(this.delay),BLE.transferFirmwareFileCmd(this.deviceId,emptyPkg,!1,this.fail.bind(this))}else{const dataIndex=this.finishedTimes-1,pkg=this.fileHexArray.slice(dataIndex*max,(dataIndex+1)*max),index=Transfer.decimalToTwoByteHexArray(this.finishedTimes);console.log("[OTA]",`S50-${this.finishedTimes}/${this.totalTimes}`),await BLE.sendDelay(this.delay),BLE.transferFirmwareFileCmd(this.deviceId,index.concat(pkg),!1,this.fail.bind(this))}this.onProgress&&this.onProgress({type:"upgrade",percent:Math.floor(100*this.finishedTimes/this.totalTimes)})}async startOTA(){BLE.writeATCmd(this.otaStart,this.deviceId,this.fail.bind(this))}fail(msg){this.succeed=!1,this.onError&&this.onError(msg)}sleep(n=50){return new Promise(r=>setTimeout(()=>r(!0),n))}}export{OTAUpgrade,OTAUpgrade as default};
|
package/package.json
CHANGED
package/src/core/OtaUpgrade.js
CHANGED
|
@@ -323,18 +323,27 @@ export class OTAUpgrade {
|
|
|
323
323
|
|
|
324
324
|
async transferFirmwareFile() {
|
|
325
325
|
let nextTime = this.finishedTimes + 1;
|
|
326
|
-
const timeFor51 = nextTime > this.totalTimes;
|
|
326
|
+
const timeFor51 = nextTime > this.totalTimes + 1; // 51命令时机:当下一包序号大于总包数时,即所有包都已发送完毕,等待设备回复是否升级成功 此处+1是因为发了个无数据的0包,总次数需要加1出否则会丢包;
|
|
327
327
|
if (timeFor51) {
|
|
328
328
|
const pkg = [0x00];
|
|
329
329
|
await BLE.sendDelay(this.delay);
|
|
330
330
|
BLE.transferFirmwareFileCmd(this.deviceId, pkg, true, this.fail.bind(this));
|
|
331
331
|
console.log('[OTA]', '=== Send 51 ===', this.finishedTimes, this.totalTimes, pkg);
|
|
332
332
|
} else {
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
333
|
+
if (this.finishedTimes === 0) {
|
|
334
|
+
// 第一次时先发空包
|
|
335
|
+
const emptyPkg = [0x00, 0x00];
|
|
336
|
+
console.log('[OTA]', '=== Send empty package first ===');
|
|
337
|
+
await BLE.sendDelay(this.delay);
|
|
338
|
+
BLE.transferFirmwareFileCmd(this.deviceId, emptyPkg, false, this.fail.bind(this));
|
|
339
|
+
}else {
|
|
340
|
+
const dataIndex = this.finishedTimes - 1; // 因为第0次发的是空包,所以实际数据从finishedTimes-1开始
|
|
341
|
+
const pkg = this.fileHexArray.slice(dataIndex * max, (dataIndex + 1) * max);
|
|
342
|
+
const index = Transfer.decimalToTwoByteHexArray(this.finishedTimes);
|
|
343
|
+
console.log('[OTA]', `S50-${this.finishedTimes}/${this.totalTimes}`);
|
|
344
|
+
await BLE.sendDelay(this.delay);
|
|
345
|
+
BLE.transferFirmwareFileCmd(this.deviceId, index.concat(pkg), false, this.fail.bind(this));
|
|
346
|
+
}
|
|
338
347
|
}
|
|
339
348
|
this.onProgress && this.onProgress({ type: 'upgrade', percent: Math.floor((this.finishedTimes * 100) / this.totalTimes) });
|
|
340
349
|
}
|