@jiabaida/tools 1.0.7 → 1.0.10
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.
- package/dist/cjs/core/BleApiManager.js +1 -1
- package/dist/cjs/core/BleCmdAnalysis/BaseParamProtocol.js +1 -1
- package/dist/cjs/core/BleCmdAnalysis/BleCmdAnalysis.js +1 -1
- package/dist/cjs/core/BleCmdAnalysis/BleCmdDD.js +1 -1
- package/dist/cjs/core/BleCmdAnalysis/BleCmdDDA4.js +1 -1
- package/dist/cjs/core/BleCmdAnalysis/BleCmdFFAA.js +1 -1
- package/dist/cjs/core/BleCmdAnalysis/readAndSetParam.js +1 -1
- package/dist/cjs/core/BleDataProcess.js +1 -1
- package/dist/cjs/core/OtaUpgrade.js +1 -1
- package/dist/cjs/core/Queue.js +1 -0
- package/dist/cjs/core/mqttServer.js +1 -1
- package/dist/cjs/core/tcpServer.js +1 -0
- package/dist/cjs/index.js +1 -1
- package/dist/esm/core/BleApiManager.js +1 -1
- package/dist/esm/core/BleCmdAnalysis/BaseParamProtocol.js +1 -1
- package/dist/esm/core/BleCmdAnalysis/BleCmdAnalysis.js +1 -1
- package/dist/esm/core/BleCmdAnalysis/BleCmdDD.js +1 -1
- package/dist/esm/core/BleCmdAnalysis/BleCmdDDA4.js +1 -1
- package/dist/esm/core/BleCmdAnalysis/BleCmdFFAA.js +1 -1
- package/dist/esm/core/BleCmdAnalysis/BleCmdHVES.js +1 -1
- package/dist/esm/core/BleCmdAnalysis/readAndSetParam.js +1 -1
- package/dist/esm/core/BleDataProcess.js +1 -1
- package/dist/esm/core/OtaUpgrade.js +1 -1
- package/dist/esm/core/Queue.js +1 -0
- package/dist/esm/core/mqttServer.js +1 -1
- package/dist/esm/core/tcpServer.js +1 -0
- package/dist/esm/index.js +1 -1
- package/package.json +1 -1
- package/src/core/BleApiManager.js +33 -15
- package/src/core/BleCmdAnalysis/BaseParamProtocol.js +116 -32
- package/src/core/BleCmdAnalysis/BleCmdAnalysis.js +58 -2
- package/src/core/BleCmdAnalysis/BleCmdDD.js +88 -19
- package/src/core/BleCmdAnalysis/BleCmdDDA4.js +154 -227
- package/src/core/BleCmdAnalysis/BleCmdFFAA.js +1 -0
- package/src/core/BleCmdAnalysis/readAndSetParam.js +133 -16
- package/src/core/BleDataProcess.js +15 -11
- package/src/core/OtaUpgrade.js +356 -350
- package/src/core/Queue.js +34 -0
- package/src/core/mqttServer.js +75 -5
- package/src/core/tcpServer.js +341 -0
- package/src/index.js +1 -0
package/src/core/OtaUpgrade.js
CHANGED
|
@@ -1,350 +1,356 @@
|
|
|
1
|
-
import { getOS } from './commonfun';
|
|
2
|
-
import { TelinkApi } from './TelinkApi';
|
|
3
|
-
import Transfer, { BLE } from './Transfer';
|
|
4
|
-
|
|
5
|
-
const max = BLE.PACKAGE_MAX_LENGTH;
|
|
6
|
-
const delayDefault = BLE.WRITE_DELAY;
|
|
7
|
-
const { isIOS, isAndroid } = getOS();
|
|
8
|
-
|
|
9
|
-
function getBuffer(hexArr) {
|
|
10
|
-
const buffer = new ArrayBuffer(hexArr.length);
|
|
11
|
-
const dataView = new DataView(buffer);
|
|
12
|
-
hexArr.forEach((hex, i) => dataView.setUint8(i, hex));
|
|
13
|
-
return buffer;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* const ota = new OTAUpgrade({
|
|
18
|
-
* deviceId,
|
|
19
|
-
* macAddr,
|
|
20
|
-
* filePath,
|
|
21
|
-
* otaInfo,
|
|
22
|
-
* otaStart,
|
|
23
|
-
* otaReStart,
|
|
24
|
-
* isTeLink, // 是否 Telink 升级
|
|
25
|
-
* onProgress, // 升级进度回调
|
|
26
|
-
* onSuccess, // 升级成功回调
|
|
27
|
-
* onError, // 升级失败回调
|
|
28
|
-
* delay, // 写入延时,默认20ms,iOS可适当调大一些
|
|
29
|
-
* });
|
|
30
|
-
* ota.start();
|
|
31
|
-
**/
|
|
32
|
-
|
|
33
|
-
export class OTAUpgrade {
|
|
34
|
-
constructor({ deviceId, filePath, otaInfo, otaStart, otaReStart, macAddr, onProgress, onSuccess, onError, delay, platform = 'APP' }) {
|
|
35
|
-
this.deviceId = deviceId;
|
|
36
|
-
this.filePath = filePath;
|
|
37
|
-
this.otaInfo = otaInfo;
|
|
38
|
-
this.otaStart = otaStart;
|
|
39
|
-
this.otaReStart = otaReStart;
|
|
40
|
-
this.macAddr = macAddr;
|
|
41
|
-
this.platform = platform; // 'APP' | 'MP' | 'H5'
|
|
42
|
-
// 自动判断是否Telink,入参为macAddr
|
|
43
|
-
this.isTeLink = TelinkApi.isTeLink ? TelinkApi.isTeLink({
|
|
44
|
-
macAddr
|
|
45
|
-
}) : false;
|
|
46
|
-
this.onProgress = onProgress;
|
|
47
|
-
this.onSuccess = onSuccess;
|
|
48
|
-
this.onError = onError;
|
|
49
|
-
this.delay = delay || delayDefault;
|
|
50
|
-
this.fileHexArray = [];
|
|
51
|
-
this.totalTimes = 1;
|
|
52
|
-
this.finishedTimes = 0;
|
|
53
|
-
this.succeed = false;
|
|
54
|
-
this.ready = true;
|
|
55
|
-
this.timer = null;
|
|
56
|
-
this.s_progress = 0;
|
|
57
|
-
this.otaStarting = false;
|
|
58
|
-
this.progressType = 'download'; // 当前进度类型: 'download' | 'upgrade'
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
async start() {
|
|
62
|
-
this.progressType = 'download';
|
|
63
|
-
try {
|
|
64
|
-
await this.download();
|
|
65
|
-
} catch (e) {
|
|
66
|
-
this.fail('下载失败: ' + e.message);
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
async download() {
|
|
71
|
-
const that = this;
|
|
72
|
-
return new Promise((resolve, reject) => {
|
|
73
|
-
const downloadTask = uni.downloadFile({
|
|
74
|
-
url: that.filePath,
|
|
75
|
-
success: ({ tempFilePath }) => {
|
|
76
|
-
this.addBLECharValueChangeListener();
|
|
77
|
-
that.resolve(tempFilePath).then(resolve).catch(reject);
|
|
78
|
-
},
|
|
79
|
-
fail: (res) => {
|
|
80
|
-
that.fail('固件下载失败');
|
|
81
|
-
reject(res);
|
|
82
|
-
},
|
|
83
|
-
});
|
|
84
|
-
downloadTask.onProgressUpdate &&
|
|
85
|
-
downloadTask.onProgressUpdate(({ progress }) => {
|
|
86
|
-
that.onProgress && that.onProgress({ type: 'download', percent: progress });
|
|
87
|
-
});
|
|
88
|
-
});
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
async resolve(tempFilePath) {
|
|
92
|
-
const that = this;
|
|
93
|
-
return new Promise((resolve, reject) => {
|
|
94
|
-
uni.saveFile({
|
|
95
|
-
tempFilePath,
|
|
96
|
-
success: ({ savedFilePath }) => {
|
|
97
|
-
if (this.platform === 'APP') {
|
|
98
|
-
plus.io.resolveLocalFileSystemURL(
|
|
99
|
-
savedFilePath,
|
|
100
|
-
(entry) => {
|
|
101
|
-
entry.file((file) => {
|
|
102
|
-
var fileReader = new plus.io.FileReader();
|
|
103
|
-
fileReader.readAsDataURL(file);
|
|
104
|
-
fileReader.onloadend = (e) => {
|
|
105
|
-
let base64 = e.target.result.split(',')[1];
|
|
106
|
-
const hexArray = Transfer.base64ToHexArray(base64);
|
|
107
|
-
const times = Math.ceil(hexArray.length / (that.isTeLink ? 16 : max));
|
|
108
|
-
that.fileHexArray = hexArray;
|
|
109
|
-
that.totalTimes = times;
|
|
110
|
-
that.finishedTimes = 0;
|
|
111
|
-
// 切换进度类型为升级
|
|
112
|
-
that.progressType = 'upgrade';
|
|
113
|
-
that.isTeLink ? that.telinkUpgrade() : that.normalUpgrade();
|
|
114
|
-
resolve();
|
|
115
|
-
};
|
|
116
|
-
fileReader.onerror = (e) => {
|
|
117
|
-
that.fail('固件解析失败');
|
|
118
|
-
reject(e);
|
|
119
|
-
};
|
|
120
|
-
});
|
|
121
|
-
},
|
|
122
|
-
(err) => {
|
|
123
|
-
that.fail('固件保存失败');
|
|
124
|
-
reject(err);
|
|
125
|
-
}
|
|
126
|
-
);
|
|
127
|
-
} else if (this.platform === 'MP') {
|
|
128
|
-
// 微信小程序读取本地文件为base64
|
|
129
|
-
const fs = wx.getFileSystemManager();
|
|
130
|
-
fs.readFile({
|
|
131
|
-
filePath: savedFilePath,
|
|
132
|
-
encoding: 'base64',
|
|
133
|
-
success: (res) => {
|
|
134
|
-
// res.data 为 base64 字符串
|
|
135
|
-
let base64 = res.data;
|
|
136
|
-
const hexArray = Transfer.base64ToHexArray(base64);
|
|
137
|
-
const times = Math.ceil(hexArray.length / (that.isTeLink ? 16 : max));
|
|
138
|
-
that.fileHexArray = hexArray;
|
|
139
|
-
that.totalTimes = times;
|
|
140
|
-
that.finishedTimes = 0;
|
|
141
|
-
// 切换进度类型为升级
|
|
142
|
-
that.progressType = 'upgrade';
|
|
143
|
-
that.isTeLink ? that.telinkUpgrade() : that.normalUpgrade();
|
|
144
|
-
resolve();
|
|
145
|
-
},
|
|
146
|
-
fail: (err) => {
|
|
147
|
-
console.error('[OTA] resolve failed:', JSON.stringify(err));
|
|
148
|
-
that.failed('文件解析失败');
|
|
149
|
-
},
|
|
150
|
-
});
|
|
151
|
-
}
|
|
152
|
-
},
|
|
153
|
-
fail: (res) => {
|
|
154
|
-
that.fail('固件保存失败');
|
|
155
|
-
reject(res);
|
|
156
|
-
},
|
|
157
|
-
});
|
|
158
|
-
});
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
// 普通升级流程
|
|
162
|
-
normalUpgrade() {
|
|
163
|
-
setTimeout(() => {
|
|
164
|
-
BLE.writeATCmd(this.otaInfo, this.deviceId, this.fail.bind(this));
|
|
165
|
-
}, 2600);
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
// Telink 升级流程
|
|
169
|
-
telinkUpgrade() {
|
|
170
|
-
this.write(['0x00', '0xff'], 0);
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
write(pkg, type) {
|
|
174
|
-
const value = getBuffer(pkg.map((o) => parseInt(o, 16)));
|
|
175
|
-
const opt = {
|
|
176
|
-
deviceId: this.deviceId,
|
|
177
|
-
serviceId: '00010203-0405-0607-0809-0a0b0c0d1912',
|
|
178
|
-
characteristicId: '00010203-0405-0607-0809-0a0b0c0d2b12',
|
|
179
|
-
value,
|
|
180
|
-
success: () => this.onSucceed(type),
|
|
181
|
-
fail: async () => {
|
|
182
|
-
await this.sleep(this.delay * 2);
|
|
183
|
-
uni.writeBLECharacteristicValue({
|
|
184
|
-
...opt,
|
|
185
|
-
fail: async () => {
|
|
186
|
-
await this.sleep(this.delay * 2);
|
|
187
|
-
uni.writeBLECharacteristicValue({
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
if (
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
this.
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
this.
|
|
208
|
-
} else if (type ==
|
|
209
|
-
this.
|
|
210
|
-
|
|
211
|
-
this.
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
if (str.indexOf(this.
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
if (str.
|
|
294
|
-
this.
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
if (str.toUpperCase().
|
|
298
|
-
this.
|
|
299
|
-
|
|
300
|
-
}
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
const pkg =
|
|
329
|
-
|
|
330
|
-
BLE.transferFirmwareFileCmd(this.deviceId,
|
|
331
|
-
console.log('[OTA]',
|
|
332
|
-
}
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
1
|
+
import { getOS } from './commonfun';
|
|
2
|
+
import { TelinkApi } from './TelinkApi';
|
|
3
|
+
import Transfer, { BLE } from './Transfer';
|
|
4
|
+
|
|
5
|
+
const max = BLE.PACKAGE_MAX_LENGTH;
|
|
6
|
+
const delayDefault = BLE.WRITE_DELAY;
|
|
7
|
+
const { isIOS, isAndroid } = getOS();
|
|
8
|
+
|
|
9
|
+
function getBuffer(hexArr) {
|
|
10
|
+
const buffer = new ArrayBuffer(hexArr.length);
|
|
11
|
+
const dataView = new DataView(buffer);
|
|
12
|
+
hexArr.forEach((hex, i) => dataView.setUint8(i, hex));
|
|
13
|
+
return buffer;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* const ota = new OTAUpgrade({
|
|
18
|
+
* deviceId,
|
|
19
|
+
* macAddr,
|
|
20
|
+
* filePath,
|
|
21
|
+
* otaInfo,
|
|
22
|
+
* otaStart,
|
|
23
|
+
* otaReStart,
|
|
24
|
+
* isTeLink, // 是否 Telink 升级
|
|
25
|
+
* onProgress, // 升级进度回调
|
|
26
|
+
* onSuccess, // 升级成功回调
|
|
27
|
+
* onError, // 升级失败回调
|
|
28
|
+
* delay, // 写入延时,默认20ms,iOS可适当调大一些
|
|
29
|
+
* });
|
|
30
|
+
* ota.start();
|
|
31
|
+
**/
|
|
32
|
+
|
|
33
|
+
export class OTAUpgrade {
|
|
34
|
+
constructor({ deviceId, filePath, otaInfo, otaStart, otaReStart, macAddr, onProgress, onSuccess, onError, delay, platform = 'APP' }) {
|
|
35
|
+
this.deviceId = deviceId;
|
|
36
|
+
this.filePath = filePath;
|
|
37
|
+
this.otaInfo = otaInfo;
|
|
38
|
+
this.otaStart = otaStart;
|
|
39
|
+
this.otaReStart = otaReStart;
|
|
40
|
+
this.macAddr = macAddr;
|
|
41
|
+
this.platform = platform; // 'APP' | 'MP' | 'H5'
|
|
42
|
+
// 自动判断是否Telink,入参为macAddr
|
|
43
|
+
this.isTeLink = TelinkApi.isTeLink ? TelinkApi.isTeLink({
|
|
44
|
+
macAddr
|
|
45
|
+
}) : false;
|
|
46
|
+
this.onProgress = onProgress;
|
|
47
|
+
this.onSuccess = onSuccess;
|
|
48
|
+
this.onError = onError;
|
|
49
|
+
this.delay = delay || delayDefault;
|
|
50
|
+
this.fileHexArray = [];
|
|
51
|
+
this.totalTimes = 1;
|
|
52
|
+
this.finishedTimes = 0;
|
|
53
|
+
this.succeed = false;
|
|
54
|
+
this.ready = true;
|
|
55
|
+
this.timer = null;
|
|
56
|
+
this.s_progress = 0;
|
|
57
|
+
this.otaStarting = false;
|
|
58
|
+
this.progressType = 'download'; // 当前进度类型: 'download' | 'upgrade'
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
async start() {
|
|
62
|
+
this.progressType = 'download';
|
|
63
|
+
try {
|
|
64
|
+
await this.download();
|
|
65
|
+
} catch (e) {
|
|
66
|
+
this.fail('下载失败: ' + e.message);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
async download() {
|
|
71
|
+
const that = this;
|
|
72
|
+
return new Promise((resolve, reject) => {
|
|
73
|
+
const downloadTask = uni.downloadFile({
|
|
74
|
+
url: that.filePath,
|
|
75
|
+
success: ({ tempFilePath }) => {
|
|
76
|
+
this.addBLECharValueChangeListener();
|
|
77
|
+
that.resolve(tempFilePath).then(resolve).catch(reject);
|
|
78
|
+
},
|
|
79
|
+
fail: (res) => {
|
|
80
|
+
that.fail('固件下载失败');
|
|
81
|
+
reject(res);
|
|
82
|
+
},
|
|
83
|
+
});
|
|
84
|
+
downloadTask.onProgressUpdate &&
|
|
85
|
+
downloadTask.onProgressUpdate(({ progress }) => {
|
|
86
|
+
that.onProgress && that.onProgress({ type: 'download', percent: progress });
|
|
87
|
+
});
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
async resolve(tempFilePath) {
|
|
92
|
+
const that = this;
|
|
93
|
+
return new Promise((resolve, reject) => {
|
|
94
|
+
uni.saveFile({
|
|
95
|
+
tempFilePath,
|
|
96
|
+
success: ({ savedFilePath }) => {
|
|
97
|
+
if (this.platform === 'APP') {
|
|
98
|
+
plus.io.resolveLocalFileSystemURL(
|
|
99
|
+
savedFilePath,
|
|
100
|
+
(entry) => {
|
|
101
|
+
entry.file((file) => {
|
|
102
|
+
var fileReader = new plus.io.FileReader();
|
|
103
|
+
fileReader.readAsDataURL(file);
|
|
104
|
+
fileReader.onloadend = (e) => {
|
|
105
|
+
let base64 = e.target.result.split(',')[1];
|
|
106
|
+
const hexArray = Transfer.base64ToHexArray(base64);
|
|
107
|
+
const times = Math.ceil(hexArray.length / (that.isTeLink ? 16 : max));
|
|
108
|
+
that.fileHexArray = hexArray;
|
|
109
|
+
that.totalTimes = times;
|
|
110
|
+
that.finishedTimes = 0;
|
|
111
|
+
// 切换进度类型为升级
|
|
112
|
+
that.progressType = 'upgrade';
|
|
113
|
+
that.isTeLink ? that.telinkUpgrade() : that.normalUpgrade();
|
|
114
|
+
resolve();
|
|
115
|
+
};
|
|
116
|
+
fileReader.onerror = (e) => {
|
|
117
|
+
that.fail('固件解析失败');
|
|
118
|
+
reject(e);
|
|
119
|
+
};
|
|
120
|
+
});
|
|
121
|
+
},
|
|
122
|
+
(err) => {
|
|
123
|
+
that.fail('固件保存失败');
|
|
124
|
+
reject(err);
|
|
125
|
+
}
|
|
126
|
+
);
|
|
127
|
+
} else if (this.platform === 'MP') {
|
|
128
|
+
// 微信小程序读取本地文件为base64
|
|
129
|
+
const fs = wx.getFileSystemManager();
|
|
130
|
+
fs.readFile({
|
|
131
|
+
filePath: savedFilePath,
|
|
132
|
+
encoding: 'base64',
|
|
133
|
+
success: (res) => {
|
|
134
|
+
// res.data 为 base64 字符串
|
|
135
|
+
let base64 = res.data;
|
|
136
|
+
const hexArray = Transfer.base64ToHexArray(base64);
|
|
137
|
+
const times = Math.ceil(hexArray.length / (that.isTeLink ? 16 : max));
|
|
138
|
+
that.fileHexArray = hexArray;
|
|
139
|
+
that.totalTimes = times;
|
|
140
|
+
that.finishedTimes = 0;
|
|
141
|
+
// 切换进度类型为升级
|
|
142
|
+
that.progressType = 'upgrade';
|
|
143
|
+
that.isTeLink ? that.telinkUpgrade() : that.normalUpgrade();
|
|
144
|
+
resolve();
|
|
145
|
+
},
|
|
146
|
+
fail: (err) => {
|
|
147
|
+
console.error('[OTA] resolve failed:', JSON.stringify(err));
|
|
148
|
+
that.failed('文件解析失败');
|
|
149
|
+
},
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
},
|
|
153
|
+
fail: (res) => {
|
|
154
|
+
that.fail('固件保存失败');
|
|
155
|
+
reject(res);
|
|
156
|
+
},
|
|
157
|
+
});
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
// 普通升级流程
|
|
162
|
+
normalUpgrade() {
|
|
163
|
+
setTimeout(() => {
|
|
164
|
+
BLE.writeATCmd(this.otaInfo, this.deviceId, this.fail.bind(this));
|
|
165
|
+
}, 2600);
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
// Telink 升级流程
|
|
169
|
+
telinkUpgrade() {
|
|
170
|
+
this.write(['0x00', '0xff'], 0);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
write(pkg, type) {
|
|
174
|
+
const value = getBuffer(pkg.map((o) => parseInt(o, 16)));
|
|
175
|
+
const opt = {
|
|
176
|
+
deviceId: this.deviceId,
|
|
177
|
+
serviceId: '00010203-0405-0607-0809-0a0b0c0d1912',
|
|
178
|
+
characteristicId: '00010203-0405-0607-0809-0a0b0c0d2b12',
|
|
179
|
+
value,
|
|
180
|
+
success: () => this.onSucceed(type),
|
|
181
|
+
fail: async () => {
|
|
182
|
+
await this.sleep(this.delay * 2);
|
|
183
|
+
uni.writeBLECharacteristicValue({
|
|
184
|
+
...opt,
|
|
185
|
+
fail: async () => {
|
|
186
|
+
await this.sleep(this.delay * 2);
|
|
187
|
+
uni.writeBLECharacteristicValue({
|
|
188
|
+
...opt, fail: () => {
|
|
189
|
+
console.error('写入失败: ', pkg);
|
|
190
|
+
this.fail('写入失败');
|
|
191
|
+
} });
|
|
192
|
+
},
|
|
193
|
+
});
|
|
194
|
+
},
|
|
195
|
+
};
|
|
196
|
+
uni.writeBLECharacteristicValue(opt);
|
|
197
|
+
if (isIOS) setTimeout(() => this.onSucceed(type), 5);
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
onSucceed(type) {
|
|
201
|
+
if (type == 0) {
|
|
202
|
+
this.write(['0x01', '0xff'], 1);
|
|
203
|
+
} else if (type == 1) {
|
|
204
|
+
this.sendNextOtaPacketCommand();
|
|
205
|
+
} else if (type == 2) {
|
|
206
|
+
this.finishedTimes++;
|
|
207
|
+
this.sendNextOtaPacketCommand();
|
|
208
|
+
} else if (type == 3) {
|
|
209
|
+
this.sendNextOtaPacketCommand();
|
|
210
|
+
} else if (type == 4) {
|
|
211
|
+
this.sendOtaEndCommand();
|
|
212
|
+
} else if (type == 5) {
|
|
213
|
+
this.finishedTimes++;
|
|
214
|
+
this.succeed = true;
|
|
215
|
+
this.onSuccess && this.onSuccess();
|
|
216
|
+
}
|
|
217
|
+
this.onProgress && this.onProgress({ type: 'upgrade', percent: Math.floor((this.finishedTimes * 100) / this.totalTimes) });
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
async sendNextOtaPacketCommand() {
|
|
221
|
+
const i = this.finishedTimes;
|
|
222
|
+
const maxLen = 16;
|
|
223
|
+
const index = TelinkApi.getIndexHexArr(i);
|
|
224
|
+
let pkgValue = this.fileHexArray.slice(i * maxLen, (i + 1) * maxLen);
|
|
225
|
+
if (pkgValue.length < maxLen) {
|
|
226
|
+
pkgValue = pkgValue.concat([...Array(maxLen - pkgValue.length)].map(() => '0xFF'));
|
|
227
|
+
}
|
|
228
|
+
const crc = TelinkApi.genCheck([...index, ...pkgValue]);
|
|
229
|
+
const pkg = [...index, ...pkgValue, ...crc];
|
|
230
|
+
const type = i >= this.totalTimes - 1 ? 4 : 2;
|
|
231
|
+
await this.sleep(this.delay);
|
|
232
|
+
this.write(pkg, type);
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
sendOtaEndCommand() {
|
|
236
|
+
function genEnd(i, c = 0xff02) {
|
|
237
|
+
return [c & 0xff, (c >> 8) & 0xff, i & 0xff, (i >> 8) & 0xff, ~i & 0xff, (~i >> 8) & 0xff].map((o) => `0x${`00${o.toString(16)}`.slice(-2)}`.toUpperCase());
|
|
238
|
+
}
|
|
239
|
+
const pkgValue = genEnd(this.totalTimes - 1);
|
|
240
|
+
const crc = TelinkApi.genCheck([...pkgValue]);
|
|
241
|
+
const pkg = [...pkgValue, ...crc];
|
|
242
|
+
this.write(pkg, 5);
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
addBLECharValueChangeListener() {
|
|
246
|
+
console.log('添加蓝牙特征值变化监听');
|
|
247
|
+
const that = this;
|
|
248
|
+
uni.notifyBLECharacteristicValueChange({
|
|
249
|
+
deviceId: that.deviceId,
|
|
250
|
+
serviceId: BLE.serviceId,
|
|
251
|
+
characteristicId: BLE.readUUID,
|
|
252
|
+
state: true,
|
|
253
|
+
success: () => {},
|
|
254
|
+
fail: () => {},
|
|
255
|
+
});
|
|
256
|
+
that.ready = true;
|
|
257
|
+
that.readValue = [];
|
|
258
|
+
that.receiveLength = null;
|
|
259
|
+
uni.onBLECharacteristicValueChange(({ deviceId, serviceId, characteristicId, value }) => {
|
|
260
|
+
if (!that.ready) return;
|
|
261
|
+
if (deviceId == that.deviceId && serviceId == BLE.serviceId) {
|
|
262
|
+
const intArr = Array.prototype.map.call(new Uint8Array(value), (x) => x);
|
|
263
|
+
if (intArr.length > 0) {
|
|
264
|
+
if (that.receiveLength == null && intArr[0] == 0xff && intArr[1] == 0xaa) {
|
|
265
|
+
that.receiveLength = intArr[3] + 5;
|
|
266
|
+
}
|
|
267
|
+
if (that.receiveLength) {
|
|
268
|
+
that.readValue = that.readValue.concat(intArr);
|
|
269
|
+
if (that.readValue.length == that.receiveLength) {
|
|
270
|
+
that.doWithResponse([...that.readValue]);
|
|
271
|
+
that.readValue = [];
|
|
272
|
+
that.receiveLength = null;
|
|
273
|
+
}
|
|
274
|
+
} else {
|
|
275
|
+
that.readValue = [];
|
|
276
|
+
that.receiveLength = null;
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
});
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
async doWithResponse(intArr) {
|
|
284
|
+
console.log('收到设备响应: ', intArr[2]);
|
|
285
|
+
if (intArr[2] == 0x80) {
|
|
286
|
+
let str = String.fromCharCode(...intArr.slice(4, -1));
|
|
287
|
+
console.log('doWithResponse otaStart1', str);
|
|
288
|
+
if (str.indexOf(this.otaInfo) > -1) {
|
|
289
|
+
this.finishedTimes = 0;
|
|
290
|
+
this.transferFirmwareFile();
|
|
291
|
+
}
|
|
292
|
+
if (str.indexOf(this.otaStart) > -1 || this.otaStarting) {
|
|
293
|
+
if (str.indexOf(this.otaStart) > -1) {
|
|
294
|
+
this.otaStarting = true;
|
|
295
|
+
}
|
|
296
|
+
console.log('doWithResponse otaStart2', str);
|
|
297
|
+
if (str.toUpperCase().includes('ERROR')) {
|
|
298
|
+
this.fail(str);
|
|
299
|
+
return;
|
|
300
|
+
}
|
|
301
|
+
if (str.toUpperCase().indexOf('S100') > -1) {
|
|
302
|
+
this.succeed = true;
|
|
303
|
+
this.onSuccess && this.onSuccess();
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
if (intArr[2] == 0x50) {
|
|
308
|
+
if (intArr[4] == 0) {
|
|
309
|
+
this.finishedTimes++;
|
|
310
|
+
this.transferFirmwareFile();
|
|
311
|
+
} else {
|
|
312
|
+
this.transferFirmwareFile();
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
if (intArr[2] == 0x51) {
|
|
316
|
+
if (intArr[4] == 0) {
|
|
317
|
+
this.startOTA();
|
|
318
|
+
} else {
|
|
319
|
+
this.fail('升级失败');
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
async transferFirmwareFile() {
|
|
325
|
+
let nextTime = this.finishedTimes + 1;
|
|
326
|
+
const timeFor51 = nextTime > this.totalTimes;
|
|
327
|
+
if (timeFor51) {
|
|
328
|
+
const pkg = [0x00];
|
|
329
|
+
await BLE.sendDelay(this.delay);
|
|
330
|
+
BLE.transferFirmwareFileCmd(this.deviceId, pkg, true, this.fail.bind(this));
|
|
331
|
+
console.log('[OTA]', '=== Send 51 ===', this.finishedTimes, this.totalTimes, pkg);
|
|
332
|
+
} else {
|
|
333
|
+
const pkg = this.fileHexArray.slice(this.finishedTimes * max, nextTime * max);
|
|
334
|
+
const index = Transfer.decimalToTwoByteHexArray(this.finishedTimes);
|
|
335
|
+
await BLE.sendDelay(this.delay);
|
|
336
|
+
BLE.transferFirmwareFileCmd(this.deviceId, index.concat(pkg), false, this.fail.bind(this));
|
|
337
|
+
console.log('[OTA]', `S50-${this.finishedTimes}/${this.totalTimes}`);
|
|
338
|
+
}
|
|
339
|
+
this.onProgress && this.onProgress({ type: 'upgrade', percent: Math.floor((this.finishedTimes * 100) / this.totalTimes) });
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
async startOTA() {
|
|
343
|
+
BLE.writeATCmd(this.otaStart, this.deviceId, this.fail.bind(this));
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
fail(msg) {
|
|
347
|
+
this.succeed = false;
|
|
348
|
+
this.onError && this.onError(msg);
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
sleep(n = 50) {
|
|
352
|
+
return new Promise((r) => setTimeout(() => r(true), n));
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
export default OTAUpgrade;
|