@robdobsn/raftjs 1.1.1
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/.editorconfig +14 -0
- package/.gitattributes +11 -0
- package/.nvmrc +1 -0
- package/LICENSE +22 -0
- package/README.md +11 -0
- package/TODO.md +1 -0
- package/dist/RaftAttributeHandler.d.ts +12 -0
- package/dist/RaftAttributeHandler.js +241 -0
- package/dist/RaftAttributeHandler.js.map +1 -0
- package/dist/RaftChannel.d.ts +18 -0
- package/dist/RaftChannel.js +12 -0
- package/dist/RaftChannel.js.map +1 -0
- package/dist/RaftChannelWebBLE.d.ts +38 -0
- package/dist/RaftChannelWebBLE.js +274 -0
- package/dist/RaftChannelWebBLE.js.map +1 -0
- package/dist/RaftChannelWebSerial.d.ts +37 -0
- package/dist/RaftChannelWebSerial.js +319 -0
- package/dist/RaftChannelWebSerial.js.map +1 -0
- package/dist/RaftChannelWebSocket.d.ts +28 -0
- package/dist/RaftChannelWebSocket.js +197 -0
- package/dist/RaftChannelWebSocket.js.map +1 -0
- package/dist/RaftCommsStats.d.ts +39 -0
- package/dist/RaftCommsStats.js +128 -0
- package/dist/RaftCommsStats.js.map +1 -0
- package/dist/RaftConnEvents.d.ts +31 -0
- package/dist/RaftConnEvents.js +44 -0
- package/dist/RaftConnEvents.js.map +1 -0
- package/dist/RaftConnector.d.ts +242 -0
- package/dist/RaftConnector.js +613 -0
- package/dist/RaftConnector.js.map +1 -0
- package/dist/RaftCustomAttrHandler.d.ts +4 -0
- package/dist/RaftCustomAttrHandler.js +50 -0
- package/dist/RaftCustomAttrHandler.js.map +1 -0
- package/dist/RaftDeviceInfo.d.ts +64 -0
- package/dist/RaftDeviceInfo.js +36 -0
- package/dist/RaftDeviceInfo.js.map +1 -0
- package/dist/RaftDeviceManager.d.ts +37 -0
- package/dist/RaftDeviceManager.js +450 -0
- package/dist/RaftDeviceManager.js.map +1 -0
- package/dist/RaftDeviceMsg.d.ts +9 -0
- package/dist/RaftDeviceMsg.js +11 -0
- package/dist/RaftDeviceMsg.js.map +1 -0
- package/dist/RaftDeviceStates.d.ts +33 -0
- package/dist/RaftDeviceStates.js +60 -0
- package/dist/RaftDeviceStates.js.map +1 -0
- package/dist/RaftFileHandler.d.ts +52 -0
- package/dist/RaftFileHandler.js +502 -0
- package/dist/RaftFileHandler.js.map +1 -0
- package/dist/RaftLog.d.ts +22 -0
- package/dist/RaftLog.js +63 -0
- package/dist/RaftLog.js.map +1 -0
- package/dist/RaftMiniHDLC.d.ts +18 -0
- package/dist/RaftMiniHDLC.js +383 -0
- package/dist/RaftMiniHDLC.js.map +1 -0
- package/dist/RaftMsgHandler.d.ts +57 -0
- package/dist/RaftMsgHandler.js +480 -0
- package/dist/RaftMsgHandler.js.map +1 -0
- package/dist/RaftMsgTrackInfo.d.ts +17 -0
- package/dist/RaftMsgTrackInfo.js +42 -0
- package/dist/RaftMsgTrackInfo.js.map +1 -0
- package/dist/RaftProtocolDefs.d.ts +30 -0
- package/dist/RaftProtocolDefs.js +48 -0
- package/dist/RaftProtocolDefs.js.map +1 -0
- package/dist/RaftStreamHandler.d.ts +38 -0
- package/dist/RaftStreamHandler.js +257 -0
- package/dist/RaftStreamHandler.js.map +1 -0
- package/dist/RaftSystemType.d.ts +21 -0
- package/dist/RaftSystemType.js +3 -0
- package/dist/RaftSystemType.js.map +1 -0
- package/dist/RaftSystemUtils.d.ts +136 -0
- package/dist/RaftSystemUtils.js +410 -0
- package/dist/RaftSystemUtils.js.map +1 -0
- package/dist/RaftTypes.d.ts +184 -0
- package/dist/RaftTypes.js +157 -0
- package/dist/RaftTypes.js.map +1 -0
- package/dist/RaftUpdateEvents.d.ts +33 -0
- package/dist/RaftUpdateEvents.js +46 -0
- package/dist/RaftUpdateEvents.js.map +1 -0
- package/dist/RaftUpdateManager.d.ts +61 -0
- package/dist/RaftUpdateManager.js +618 -0
- package/dist/RaftUpdateManager.js.map +1 -0
- package/dist/RaftUtils.d.ts +125 -0
- package/dist/RaftUtils.js +454 -0
- package/dist/RaftUtils.js.map +1 -0
- package/dist/RaftWifiTypes.d.ts +23 -0
- package/dist/RaftWifiTypes.js +43 -0
- package/dist/RaftWifiTypes.js.map +1 -0
- package/dist/TestDataGen.d.ts +7 -0
- package/dist/TestDataGen.js +133 -0
- package/dist/TestDataGen.js.map +1 -0
- package/dist/main.d.ts +18 -0
- package/dist/main.js +42 -0
- package/dist/main.js.map +1 -0
- package/eslint.config.mjs +33 -0
- package/examples/dashboard/package.json +39 -0
- package/examples/dashboard/src/ConnManager.ts +86 -0
- package/examples/dashboard/src/Main.tsx +100 -0
- package/examples/dashboard/src/StatusScreen.tsx +72 -0
- package/examples/dashboard/src/SystemTypeCog/CogStateInfo.ts +144 -0
- package/examples/dashboard/src/SystemTypeCog/SystemTypeCog.ts +77 -0
- package/examples/dashboard/src/SystemTypeMarty/RICAddOn.ts +70 -0
- package/examples/dashboard/src/SystemTypeMarty/RICAddOnBase.ts +33 -0
- package/examples/dashboard/src/SystemTypeMarty/RICAddOnManager.ts +342 -0
- package/examples/dashboard/src/SystemTypeMarty/RICCommsStats.ts +170 -0
- package/examples/dashboard/src/SystemTypeMarty/RICHWElem.ts +123 -0
- package/examples/dashboard/src/SystemTypeMarty/RICLEDPatternChecker.ts +207 -0
- package/examples/dashboard/src/SystemTypeMarty/RICROSSerial.ts +464 -0
- package/examples/dashboard/src/SystemTypeMarty/RICServoFaultDetector.ts +146 -0
- package/examples/dashboard/src/SystemTypeMarty/RICStateInfo.ts +32 -0
- package/examples/dashboard/src/SystemTypeMarty/RICSystemUtils.ts +371 -0
- package/examples/dashboard/src/SystemTypeMarty/RICTypes.ts +20 -0
- package/examples/dashboard/src/SystemTypeMarty/SystemTypeMarty.ts +113 -0
- package/examples/dashboard/src/index.html +15 -0
- package/examples/dashboard/src/index.tsx +15 -0
- package/examples/dashboard/src/styles.css +122 -0
- package/examples/dashboard/tsconfig.json +18 -0
- package/jest.config.js +11 -0
- package/package.json +50 -0
- package/src/RaftAttributeHandler.ts +289 -0
- package/src/RaftChannel.ts +30 -0
- package/src/RaftChannelWebBLE.ts +342 -0
- package/src/RaftChannelWebSerial.ts +408 -0
- package/src/RaftChannelWebSocket.ts +245 -0
- package/src/RaftCommsStats.ts +142 -0
- package/src/RaftConnEvents.ts +46 -0
- package/src/RaftConnector.ts +745 -0
- package/src/RaftCustomAttrHandler.ts +54 -0
- package/src/RaftDeviceInfo.ts +104 -0
- package/src/RaftDeviceManager.ts +542 -0
- package/src/RaftDeviceMsg.ts +20 -0
- package/src/RaftDeviceStates.ts +89 -0
- package/src/RaftFileHandler.ts +668 -0
- package/src/RaftLog.ts +70 -0
- package/src/RaftMiniHDLC.ts +396 -0
- package/src/RaftMsgHandler.ts +778 -0
- package/src/RaftMsgTrackInfo.ts +51 -0
- package/src/RaftProtocolDefs.ts +46 -0
- package/src/RaftStreamHandler.ts +328 -0
- package/src/RaftSystemType.ts +25 -0
- package/src/RaftSystemUtils.ts +487 -0
- package/src/RaftTypes.ts +250 -0
- package/src/RaftUpdateEvents.ts +48 -0
- package/src/RaftUpdateManager.ts +778 -0
- package/src/RaftUtils.ts +484 -0
- package/src/RaftWifiTypes.ts +36 -0
- package/src/TestDataGen.ts +157 -0
- package/src/main.ts +28 -0
- package/testdata/TestDeviceTypeRecs.json +492 -0
- package/tsconfig.json +27 -0
|
@@ -0,0 +1,778 @@
|
|
|
1
|
+
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
2
|
+
//
|
|
3
|
+
// RaftUpdateManager
|
|
4
|
+
// Part of RaftJS
|
|
5
|
+
//
|
|
6
|
+
// Rob Dobson & Chris Greening 2020-2024
|
|
7
|
+
// (C) 2020-2024 All rights reserved
|
|
8
|
+
//
|
|
9
|
+
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
10
|
+
|
|
11
|
+
import axios from "axios";
|
|
12
|
+
import RaftChannel from "./RaftChannel";
|
|
13
|
+
import RaftFileHandler from "./RaftFileHandler";
|
|
14
|
+
import RaftLog from "./RaftLog";
|
|
15
|
+
import RaftMsgHandler from "./RaftMsgHandler";
|
|
16
|
+
import RaftSystemUtils from "./RaftSystemUtils";
|
|
17
|
+
import { RaftFWInfo, RaftFileDownloadFn, RaftFileSendType, RaftHWFWUpdRslt, RaftOKFail, RaftSystemInfo, RaftUpdateInfo } from "./RaftTypes";
|
|
18
|
+
import { RaftUpdateEvent, RaftUpdateEventFn } from "./RaftUpdateEvents";
|
|
19
|
+
import RaftUtils from "./RaftUtils";
|
|
20
|
+
import { RaftSystemType } from "./RaftSystemType";
|
|
21
|
+
|
|
22
|
+
export default class RICUpdateManager {
|
|
23
|
+
// Version info
|
|
24
|
+
private _latestVersionInfo: RaftUpdateInfo | null = null;
|
|
25
|
+
private _updateESPRequired = false;
|
|
26
|
+
private _updateElemsRequired = false;
|
|
27
|
+
|
|
28
|
+
// FW update
|
|
29
|
+
private readonly FW_UPDATE_CHECKS_BEFORE_ASSUME_FAILED = 10;
|
|
30
|
+
private readonly ELEM_FW_CHECK_LOOPS = 36;
|
|
31
|
+
|
|
32
|
+
// Progress levels
|
|
33
|
+
private _progressAfterDownload = 0.1;
|
|
34
|
+
private _progressDuringUpload = 0.8;
|
|
35
|
+
private _progressDuringRestart = 0.015;
|
|
36
|
+
|
|
37
|
+
// Raft info
|
|
38
|
+
private _idToConnectTo: string | null = null;
|
|
39
|
+
private _nameToConnectTo: string | null = null;
|
|
40
|
+
|
|
41
|
+
// TODO - decide what to do with RICHwRevNo
|
|
42
|
+
private _ricHwRevNo: number | null = null;
|
|
43
|
+
|
|
44
|
+
// TESTS - set to true for testing OTA updates ONLY
|
|
45
|
+
private readonly TEST_TRUNCATE_ESP_FILE = false;
|
|
46
|
+
private readonly TEST_PRETEND_ELEM_UPDATE_REQD = false;
|
|
47
|
+
public TEST_PRETEND_INITIAL_VERSIONS_DIFFER = false; // this is public so it can be set from the front-end to force an update
|
|
48
|
+
private readonly TEST_PRETEND_FINAL_VERSIONS_MATCH = false;
|
|
49
|
+
private readonly TEST_SKIP_FW_UPDATE = false;
|
|
50
|
+
|
|
51
|
+
constructor(
|
|
52
|
+
private _systemType: RaftSystemType | null,
|
|
53
|
+
private _msgHandler: RaftMsgHandler,
|
|
54
|
+
private _raftFileHandler: RaftFileHandler,
|
|
55
|
+
private _raftSystemUtils: RaftSystemUtils,
|
|
56
|
+
private _eventListener: RaftUpdateEventFn,
|
|
57
|
+
private _firmwareTypeStrForMainFw: string,
|
|
58
|
+
private _currentAppVersion: string,
|
|
59
|
+
private _fileDownloader: RaftFileDownloadFn,
|
|
60
|
+
private _firmwareUpdateURL: string,
|
|
61
|
+
private _firmwareBaseURL: string,
|
|
62
|
+
private _raftChannel: RaftChannel | null
|
|
63
|
+
) {}
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
async checkForUpdate(
|
|
67
|
+
systemInfo: RaftSystemInfo | null
|
|
68
|
+
): Promise<RaftUpdateEvent> {
|
|
69
|
+
if (systemInfo === null) {
|
|
70
|
+
return RaftUpdateEvent.UPDATE_NOT_AVAILABLE;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
this._latestVersionInfo = null;
|
|
74
|
+
try {
|
|
75
|
+
// handle url modifications
|
|
76
|
+
let updateURL = this._firmwareUpdateURL;
|
|
77
|
+
const raftSystemInfo = this._raftSystemUtils.getCachedSystemInfo();
|
|
78
|
+
|
|
79
|
+
// TODO - decide what to do with ricHWRevNo - several times below
|
|
80
|
+
|
|
81
|
+
if (!raftSystemInfo || !raftSystemInfo.RicHwRevNo){
|
|
82
|
+
RaftLog.debug("checkForUpdate failed to get Raft info, either no channel or no system info");
|
|
83
|
+
RaftLog.debug("raftSystemInfo:" + JSON.stringify(raftSystemInfo));
|
|
84
|
+
RaftLog.debug("ricHwRevNo:" + raftSystemInfo!.RicHwRevNo);
|
|
85
|
+
return RaftUpdateEvent.UPDATE_FAILED;
|
|
86
|
+
}
|
|
87
|
+
updateURL = updateURL.replace(
|
|
88
|
+
"{HWRevNo}",
|
|
89
|
+
raftSystemInfo.RicHwRevNo.toString()
|
|
90
|
+
);
|
|
91
|
+
|
|
92
|
+
// debug
|
|
93
|
+
RaftLog.debug(`Update URL: ${updateURL}`);
|
|
94
|
+
const response = await axios.get(updateURL);
|
|
95
|
+
this._latestVersionInfo = response.data;
|
|
96
|
+
} catch (error) {
|
|
97
|
+
RaftLog.debug(`Failed to get latest version from internet ${error}`);
|
|
98
|
+
}
|
|
99
|
+
if (this._latestVersionInfo === null) {
|
|
100
|
+
return RaftUpdateEvent.UPDATE_CANT_REACH_SERVER;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// Check the version and incomplete previous hw-elem update if needed
|
|
104
|
+
try {
|
|
105
|
+
const updateRequired = await this._isUpdateRequired(
|
|
106
|
+
this._latestVersionInfo,
|
|
107
|
+
systemInfo
|
|
108
|
+
);
|
|
109
|
+
RaftLog.debug(
|
|
110
|
+
`checkForUpdate systemVersion ${systemInfo?.SystemVersion} available online ${this._latestVersionInfo?.firmwareVersion} updateRequired ${updateRequired}`
|
|
111
|
+
);
|
|
112
|
+
if (updateRequired) {
|
|
113
|
+
if (
|
|
114
|
+
RaftUtils.isVersionGreater(
|
|
115
|
+
this._latestVersionInfo.minimumUpdaterVersion.ota,
|
|
116
|
+
this._currentAppVersion
|
|
117
|
+
)
|
|
118
|
+
) {
|
|
119
|
+
RaftLog.debug(
|
|
120
|
+
`App version ${this._currentAppVersion} but version ${this._latestVersionInfo.minimumUpdaterVersion.ota} required`
|
|
121
|
+
);
|
|
122
|
+
return RaftUpdateEvent.UPDATE_APP_UPDATE_REQUIRED;
|
|
123
|
+
} else {
|
|
124
|
+
return RaftUpdateEvent.UPDATE_IS_AVAILABLE;
|
|
125
|
+
}
|
|
126
|
+
} else {
|
|
127
|
+
return RaftUpdateEvent.UPDATE_NOT_AVAILABLE;
|
|
128
|
+
}
|
|
129
|
+
} catch (error) {
|
|
130
|
+
RaftLog.debug(`checkForUpdate failed ${error}`);
|
|
131
|
+
}
|
|
132
|
+
return RaftUpdateEvent.UPDATE_CANT_REACH_SERVER;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
async _isUpdateRequired(
|
|
136
|
+
latestVersion: RaftUpdateInfo,
|
|
137
|
+
systemInfo: RaftSystemInfo
|
|
138
|
+
): Promise<boolean> {
|
|
139
|
+
this._updateESPRequired = false;
|
|
140
|
+
this._updateElemsRequired = false;
|
|
141
|
+
|
|
142
|
+
// Perform the version check
|
|
143
|
+
this._updateESPRequired = RaftUtils.isVersionGreater(
|
|
144
|
+
latestVersion.firmwareVersion,
|
|
145
|
+
systemInfo.SystemVersion
|
|
146
|
+
);
|
|
147
|
+
|
|
148
|
+
// Test ONLY pretend an update is needed
|
|
149
|
+
if (this.TEST_PRETEND_INITIAL_VERSIONS_DIFFER) {
|
|
150
|
+
this._updateESPRequired = true;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
// TODO: check if elem updates are required using elemsUpdatesRequired()
|
|
154
|
+
|
|
155
|
+
// Check if a previous hw-elem update didn't complete - but no point if we would update anyway
|
|
156
|
+
if (!this._updateESPRequired) {
|
|
157
|
+
try {
|
|
158
|
+
const elUpdRslt =
|
|
159
|
+
await this._msgHandler.sendRICRESTURL<RaftHWFWUpdRslt>("hwfwupd");
|
|
160
|
+
|
|
161
|
+
// Check result
|
|
162
|
+
this._updateElemsRequired =
|
|
163
|
+
elUpdRslt.rslt === "ok" && elUpdRslt.st.i === 1;
|
|
164
|
+
|
|
165
|
+
// Debug
|
|
166
|
+
if (this._updateElemsRequired) {
|
|
167
|
+
RaftLog.debug("isUpdateRequired - prev incomplete");
|
|
168
|
+
} else {
|
|
169
|
+
RaftLog.debug("isUpdateRequired - prev complete");
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
// Test ONLY pretend an element update is needed
|
|
173
|
+
if (this.TEST_PRETEND_ELEM_UPDATE_REQD) {
|
|
174
|
+
this._updateElemsRequired = true;
|
|
175
|
+
}
|
|
176
|
+
} catch (error) {
|
|
177
|
+
RaftLog.debug(
|
|
178
|
+
`isUpdateRequired - failed to get hw-elem firmware update status ${error}`
|
|
179
|
+
);
|
|
180
|
+
}
|
|
181
|
+
} else {
|
|
182
|
+
this._updateElemsRequired = true;
|
|
183
|
+
}
|
|
184
|
+
return this._updateESPRequired || this._updateElemsRequired;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
|
|
188
|
+
// Mark: Firmware update ------------------------------------------------------------------------------------------------
|
|
189
|
+
elemUpdateRequired(expectedVersion: string, actualVersion: string, dtid: number, addr: number, elemType: string){
|
|
190
|
+
if (elemType != "SmartServo" && elemType != "RSAddOn") return false;
|
|
191
|
+
const outdated = RaftUtils.isVersionGreater(expectedVersion, actualVersion);
|
|
192
|
+
if (!outdated) return false;
|
|
193
|
+
// if stm32, we only want to update the base elems
|
|
194
|
+
const stm32_dtid_mask = 0xFFFFFF00
|
|
195
|
+
const stm32_dtid_id = 0x00000100
|
|
196
|
+
const stm32_base_elems = [0x10, 0x13, 0x16];
|
|
197
|
+
if ((dtid & stm32_dtid_mask) == stm32_dtid_id){
|
|
198
|
+
return stm32_base_elems.includes(addr);
|
|
199
|
+
}
|
|
200
|
+
return true;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
getExpectedVersion(firmwareVersions: any, dtid: number){
|
|
204
|
+
if (Object.prototype.hasOwnProperty.call(firmwareVersions["dtid"], dtid)){
|
|
205
|
+
return firmwareVersions["dtid"][dtid]["version"];
|
|
206
|
+
}
|
|
207
|
+
return null;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
async elemUpdatesRequired(): Promise<Array<any> | null> {
|
|
211
|
+
const elemsToUpdate = [];
|
|
212
|
+
|
|
213
|
+
const firmwareVersionsUrl = `${this._firmwareBaseURL}/firmware/firmwareVersions.json`;
|
|
214
|
+
|
|
215
|
+
// get elem firmware expected versions
|
|
216
|
+
const firmwareVersionResponse = await fetch(firmwareVersionsUrl);
|
|
217
|
+
if (!firmwareVersionResponse.ok) return null;
|
|
218
|
+
const firmwareVersionsJson = await firmwareVersionResponse.json();
|
|
219
|
+
RaftLog.debug(`firmwareVersions response ${JSON.stringify(firmwareVersionsJson)}`);
|
|
220
|
+
|
|
221
|
+
// get connected elements
|
|
222
|
+
const hwstatus: any = await this._msgHandler.sendRICRESTURL("hwstatus");
|
|
223
|
+
RaftLog.debug(`hwstatus response: ${JSON.stringify(hwstatus)}`);
|
|
224
|
+
const hwElems = hwstatus["hw"];
|
|
225
|
+
// TODO: check if hwstatus is reporting versions as "0.0.0", if so pause and retry as robot is probably still starting up
|
|
226
|
+
|
|
227
|
+
for (const elem in hwElems){
|
|
228
|
+
// TODO: use RaftHWElem type
|
|
229
|
+
const dtid = parseInt(hwElems[elem]["whoAmITypeCode"], 16);
|
|
230
|
+
const expectedVersion = this.getExpectedVersion(firmwareVersionsJson, dtid);
|
|
231
|
+
const actualVersion = hwElems[elem]["versionStr"];
|
|
232
|
+
const addr = parseInt(hwElems[elem]["addr"], 16);
|
|
233
|
+
const elemType = hwElems[elem]["type"];
|
|
234
|
+
const elemName = hwElems[elem]["name"];
|
|
235
|
+
RaftLog.debug(`hwElem ${elemName} dtid ${dtid} addr ${addr} type ${elemType} expectedVersion ${expectedVersion} actual version ${actualVersion}`);
|
|
236
|
+
if (expectedVersion){
|
|
237
|
+
hwElems[elem]["expectedVersion"] = expectedVersion;
|
|
238
|
+
if (this.elemUpdateRequired(expectedVersion, actualVersion, dtid, addr, elemType))
|
|
239
|
+
elemsToUpdate.push(hwElems[elem]);
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
return elemsToUpdate;
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
async firmwareUpdate(): Promise<RaftUpdateEvent> {
|
|
246
|
+
// Check valid
|
|
247
|
+
if (this._latestVersionInfo === null)
|
|
248
|
+
return RaftUpdateEvent.UPDATE_NOT_CONFIGURED;
|
|
249
|
+
|
|
250
|
+
// save Raft info for later restarts
|
|
251
|
+
const raftSystemInfo = this._raftSystemUtils.getCachedSystemInfo();
|
|
252
|
+
if (this._raftChannel && raftSystemInfo !== null) {
|
|
253
|
+
const deviceInfo: BluetoothDevice =
|
|
254
|
+
this._raftChannel.getConnectedLocator() as BluetoothDevice;
|
|
255
|
+
this._idToConnectTo = deviceInfo.id;
|
|
256
|
+
|
|
257
|
+
// TODO - decide what to do with this - used to say "Marty"
|
|
258
|
+
this._nameToConnectTo = deviceInfo.name || "Raft";
|
|
259
|
+
|
|
260
|
+
//Decide what to do with RICHwRevNo - should use HwRev if it exists
|
|
261
|
+
|
|
262
|
+
// Convert raftSystemInfo.RicHwRevNo to a number
|
|
263
|
+
const hwRev = raftSystemInfo.RicHwRevNo;
|
|
264
|
+
this._ricHwRevNo = hwRev === undefined ? 0 : (typeof hwRev === "string" ? parseInt(hwRev) : hwRev);
|
|
265
|
+
RaftLog.debug("iDToConnectTo " + this._idToConnectTo);
|
|
266
|
+
RaftLog.debug("nameToConnectTo " + this._nameToConnectTo);
|
|
267
|
+
RaftLog.debug("HW Rev " + this._ricHwRevNo.toString());
|
|
268
|
+
} else {
|
|
269
|
+
RaftLog.debug(
|
|
270
|
+
"firmwareUpdate failed to get Raft info, either no channel or no system info"
|
|
271
|
+
);
|
|
272
|
+
return RaftUpdateEvent.UPDATE_FAILED;
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
// Update started
|
|
276
|
+
this._eventListener(RaftUpdateEvent.UPDATE_STARTED);
|
|
277
|
+
this._eventListener(RaftUpdateEvent.UPDATE_PROGRESS, {
|
|
278
|
+
stage: "Downloading firmware",
|
|
279
|
+
progress: 0,
|
|
280
|
+
updatingFilesystem: false,
|
|
281
|
+
});
|
|
282
|
+
|
|
283
|
+
// parse version file to extract only "ota" files
|
|
284
|
+
const firmwareList: Array<RaftFWInfo> = [];
|
|
285
|
+
let mainFwInfo: RaftFWInfo | null = null;
|
|
286
|
+
this._latestVersionInfo.files.forEach((fileInfo) => {
|
|
287
|
+
if (fileInfo.updaters.indexOf("ota") != -1) {
|
|
288
|
+
fileInfo.downloadUrl = fileInfo.firmware || fileInfo.downloadUrl;
|
|
289
|
+
if (fileInfo.elemType === this._firmwareTypeStrForMainFw) {
|
|
290
|
+
mainFwInfo = fileInfo;
|
|
291
|
+
} else {
|
|
292
|
+
firmwareList.push(fileInfo);
|
|
293
|
+
}
|
|
294
|
+
RaftLog.debug(
|
|
295
|
+
`fwUpdate selected file ${fileInfo.destname} for download`
|
|
296
|
+
);
|
|
297
|
+
}
|
|
298
|
+
});
|
|
299
|
+
|
|
300
|
+
// Add the main firware if it is required
|
|
301
|
+
if (this._updateESPRequired && mainFwInfo != null) {
|
|
302
|
+
firmwareList.unshift(mainFwInfo); // add to front of array so it's downloaded first
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
// Binary data downloaded from the internet
|
|
306
|
+
const firmwareData = new Array<Uint8Array>();
|
|
307
|
+
|
|
308
|
+
// Iterate through the firmware entities
|
|
309
|
+
const numFw = firmwareList.length;
|
|
310
|
+
try {
|
|
311
|
+
for (let fwIdx = 0; fwIdx < firmwareList.length; fwIdx++) {
|
|
312
|
+
// Download the firmware
|
|
313
|
+
RaftLog.debug(
|
|
314
|
+
`fwUpdate downloading file URI ${firmwareList[fwIdx].downloadUrl}`
|
|
315
|
+
);
|
|
316
|
+
const downloadResult = await this._fileDownloader(
|
|
317
|
+
firmwareList[fwIdx].downloadUrl,
|
|
318
|
+
(received: number, total: number) => {
|
|
319
|
+
const currentProgress =
|
|
320
|
+
((fwIdx + received / total) / numFw) *
|
|
321
|
+
this._progressAfterDownload;
|
|
322
|
+
this._eventListener(RaftUpdateEvent.UPDATE_PROGRESS, {
|
|
323
|
+
stage: "Downloading firmware",
|
|
324
|
+
progress: currentProgress,
|
|
325
|
+
updatingFilesystem: false,
|
|
326
|
+
});
|
|
327
|
+
}
|
|
328
|
+
);
|
|
329
|
+
if (downloadResult.downloadedOk && downloadResult.fileData != null) {
|
|
330
|
+
firmwareData.push(downloadResult.fileData);
|
|
331
|
+
} else {
|
|
332
|
+
this._eventListener(RaftUpdateEvent.UPDATE_FAILED);
|
|
333
|
+
throw Error("file download res null");
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
} catch (error: unknown) {
|
|
337
|
+
RaftLog.debug(`fwUpdate error ${error}`);
|
|
338
|
+
this._eventListener(RaftUpdateEvent.UPDATE_FAILED);
|
|
339
|
+
return RaftUpdateEvent.UPDATE_FAILED;
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
// Test ONLY truncate the main firmware
|
|
343
|
+
if (
|
|
344
|
+
this._updateESPRequired &&
|
|
345
|
+
mainFwInfo != null &&
|
|
346
|
+
this.TEST_TRUNCATE_ESP_FILE
|
|
347
|
+
) {
|
|
348
|
+
firmwareData[0] = new Uint8Array(500);
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
// Calculate total length of data
|
|
352
|
+
let totalBytes = 0;
|
|
353
|
+
for (const fileData of firmwareData) {
|
|
354
|
+
totalBytes += fileData.length;
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
// Debug
|
|
358
|
+
RaftLog.debug(
|
|
359
|
+
`fwUpdate got ok ${firmwareData.length} files total ${totalBytes} bytes`
|
|
360
|
+
);
|
|
361
|
+
|
|
362
|
+
// Start uploading
|
|
363
|
+
this._eventListener(RaftUpdateEvent.UPDATE_PROGRESS, {
|
|
364
|
+
stage: "Starting firmware upload",
|
|
365
|
+
progress: this._progressAfterDownload,
|
|
366
|
+
updatingFilesystem: false,
|
|
367
|
+
});
|
|
368
|
+
|
|
369
|
+
// Upload each file
|
|
370
|
+
let updateStage =
|
|
371
|
+
"Uploading new firmware\nThis may take a while, please be patient";
|
|
372
|
+
let updatingFilesystem = false;
|
|
373
|
+
try {
|
|
374
|
+
let sentBytes = 0;
|
|
375
|
+
for (let fwIdx = 0; fwIdx < firmwareData.length; fwIdx++) {
|
|
376
|
+
RaftLog.debug(
|
|
377
|
+
`fwUpdate uploading file name ${firmwareList[fwIdx].destname} len ${firmwareData[fwIdx].length}`
|
|
378
|
+
);
|
|
379
|
+
let updatingItemType = RaftFileSendType.NORMAL_FILE;
|
|
380
|
+
if (firmwareList[fwIdx].elemType === this._firmwareTypeStrForMainFw) {
|
|
381
|
+
updatingItemType = RaftFileSendType.FIRMWARE_UPDATE;
|
|
382
|
+
}
|
|
383
|
+
let percComplete =
|
|
384
|
+
(sentBytes / totalBytes) * this._progressDuringUpload +
|
|
385
|
+
this._progressAfterDownload;
|
|
386
|
+
|
|
387
|
+
if (
|
|
388
|
+
!updatingFilesystem &&
|
|
389
|
+
updatingItemType == RaftFileSendType.NORMAL_FILE
|
|
390
|
+
) {
|
|
391
|
+
// start of filesystem updates
|
|
392
|
+
updateStage =
|
|
393
|
+
"Updating system files\nThis may take a while, please be patient\nUpdate cannot be cancelled during this stage\n";
|
|
394
|
+
updatingFilesystem = true;
|
|
395
|
+
// emit event so app can deactivate cancel button
|
|
396
|
+
this._eventListener(RaftUpdateEvent.UPDATE_PROGRESS, {
|
|
397
|
+
stage: updateStage,
|
|
398
|
+
progress: percComplete,
|
|
399
|
+
updatingFilesystem: updatingFilesystem,
|
|
400
|
+
});
|
|
401
|
+
|
|
402
|
+
// TODO - Decide how to handle this
|
|
403
|
+
if (this._ricHwRevNo == 1) {
|
|
404
|
+
// the spiffs filesystem used on rev 1 doesn't delete files properly and has issues being more than 75% full
|
|
405
|
+
// it must be formatted to prevent issues after multiple OTA updates
|
|
406
|
+
// Reformat filesystem. This will take a few seconds so set a long timeout for the response
|
|
407
|
+
RaftLog.debug(`Beginning file system update. Reformatting FS.`);
|
|
408
|
+
await this._msgHandler.sendRICRESTURL<RaftOKFail>(
|
|
409
|
+
"reformatfs",
|
|
410
|
+
undefined,
|
|
411
|
+
15000
|
|
412
|
+
);
|
|
413
|
+
// trigger and wait for reboot
|
|
414
|
+
RaftLog.debug(`Restarting RIC`);
|
|
415
|
+
try {
|
|
416
|
+
await this._msgHandler.sendRICRESTURL<RaftOKFail>("reset");
|
|
417
|
+
} catch (error) {
|
|
418
|
+
RaftLog.debug(`fwUpdate reset failed ${error}`);
|
|
419
|
+
}
|
|
420
|
+
if (!(await this.waitForRestart(percComplete))) {
|
|
421
|
+
this._eventListener(RaftUpdateEvent.UPDATE_FAILED);
|
|
422
|
+
return RaftUpdateEvent.UPDATE_FAILED;
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
if (
|
|
428
|
+
updatingItemType == RaftFileSendType.FIRMWARE_UPDATE &&
|
|
429
|
+
this.TEST_SKIP_FW_UPDATE
|
|
430
|
+
) {
|
|
431
|
+
RaftLog.debug("fwUpdate: Skipping FW update");
|
|
432
|
+
} else {
|
|
433
|
+
await this.fileSend(
|
|
434
|
+
firmwareList[fwIdx].destname,
|
|
435
|
+
updatingItemType,
|
|
436
|
+
firmwareData[fwIdx],
|
|
437
|
+
(_, __, progress) => {
|
|
438
|
+
let percComplete =
|
|
439
|
+
((sentBytes + progress * firmwareData[fwIdx].length) /
|
|
440
|
+
totalBytes) *
|
|
441
|
+
this._progressDuringUpload +
|
|
442
|
+
this._progressAfterDownload;
|
|
443
|
+
if (updatingItemType == RaftFileSendType.NORMAL_FILE)
|
|
444
|
+
percComplete += this._progressDuringRestart * 2;
|
|
445
|
+
if (percComplete > 1.0) percComplete = 1.0;
|
|
446
|
+
RaftLog.debug(
|
|
447
|
+
`fwUpdate progress ${progress.toFixed(
|
|
448
|
+
2
|
|
449
|
+
)} sent ${sentBytes} len ${
|
|
450
|
+
firmwareData[fwIdx].length
|
|
451
|
+
} total ${totalBytes} propComplete ${percComplete.toFixed(2)}`
|
|
452
|
+
);
|
|
453
|
+
this._eventListener(RaftUpdateEvent.UPDATE_PROGRESS, {
|
|
454
|
+
stage: updateStage,
|
|
455
|
+
progress: percComplete,
|
|
456
|
+
updatingFilesystem: updatingFilesystem,
|
|
457
|
+
});
|
|
458
|
+
}
|
|
459
|
+
);
|
|
460
|
+
}
|
|
461
|
+
sentBytes += firmwareData[fwIdx].length;
|
|
462
|
+
if (updatingItemType == RaftFileSendType.FIRMWARE_UPDATE) {
|
|
463
|
+
percComplete =
|
|
464
|
+
(sentBytes / totalBytes) * this._progressDuringUpload +
|
|
465
|
+
this._progressAfterDownload;
|
|
466
|
+
// if the element was firmware, Raft app will now restart automatically
|
|
467
|
+
if (
|
|
468
|
+
!(await this.waitForRestart(
|
|
469
|
+
percComplete,
|
|
470
|
+
this._latestVersionInfo?.firmwareVersion
|
|
471
|
+
))
|
|
472
|
+
) {
|
|
473
|
+
this._eventListener(RaftUpdateEvent.UPDATE_FAILED);
|
|
474
|
+
return RaftUpdateEvent.UPDATE_FAILED;
|
|
475
|
+
}
|
|
476
|
+
}
|
|
477
|
+
}
|
|
478
|
+
} catch (error) {
|
|
479
|
+
RaftLog.debug(`fwUpdate error ${error}`);
|
|
480
|
+
this._eventListener(RaftUpdateEvent.UPDATE_FAILED);
|
|
481
|
+
return RaftUpdateEvent.UPDATE_FAILED;
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
// TODO: check this is working
|
|
485
|
+
const allElemsUpdatedOk = await this.updateElems();
|
|
486
|
+
|
|
487
|
+
/*
|
|
488
|
+
// Issue requests for hw-elem firmware updates
|
|
489
|
+
let elemFwIdx = 0;
|
|
490
|
+
let allElemsUpdatedOk = true;
|
|
491
|
+
for (const elemFw of firmwareList) {
|
|
492
|
+
// Update progress
|
|
493
|
+
const percComplete =
|
|
494
|
+
this._progressAfterUpload +
|
|
495
|
+
((1 - this._progressAfterUpload) * elemFwIdx) / firmwareList.length;
|
|
496
|
+
this._eventListener(RaftUpdateEvent.UPDATE_PROGRESS, {
|
|
497
|
+
stage: "Updating elements",
|
|
498
|
+
progress: percComplete,
|
|
499
|
+
updatingFilesystem: true,
|
|
500
|
+
});
|
|
501
|
+
elemFwIdx++;
|
|
502
|
+
|
|
503
|
+
// Check element is not main
|
|
504
|
+
if (elemFw.elemType === this._firmwareTypeStrForMainFw) continue;
|
|
505
|
+
|
|
506
|
+
// Non-firmware elemTypes
|
|
507
|
+
if (this._nonFirmwareElemTypes.includes(elemFw.elemType)) continue;
|
|
508
|
+
|
|
509
|
+
await this.updateElem(elemFw);
|
|
510
|
+
}
|
|
511
|
+
*/
|
|
512
|
+
|
|
513
|
+
// Done update
|
|
514
|
+
this._eventListener(RaftUpdateEvent.UPDATE_PROGRESS, {
|
|
515
|
+
stage: "Finished",
|
|
516
|
+
progress: 1,
|
|
517
|
+
updatingFilesystem: false,
|
|
518
|
+
});
|
|
519
|
+
let updateResult = RaftUpdateEvent.UPDATE_SUCCESS_ALL;
|
|
520
|
+
if (allElemsUpdatedOk) {
|
|
521
|
+
this._eventListener(updateResult, this._raftSystemUtils.getCachedSystemInfo());
|
|
522
|
+
} else {
|
|
523
|
+
updateResult = RaftUpdateEvent.UPDATE_SUCCESS_MAIN_ONLY;
|
|
524
|
+
this._eventListener(updateResult, this._raftSystemUtils.getCachedSystemInfo());
|
|
525
|
+
}
|
|
526
|
+
return updateResult;
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
async updateElems(elemsToUpdate: Array<any> | null = null): Promise<boolean>{
|
|
530
|
+
let allElemsUpdatedOk = true;
|
|
531
|
+
if (elemsToUpdate === null)
|
|
532
|
+
elemsToUpdate = await this.elemUpdatesRequired();
|
|
533
|
+
if (elemsToUpdate === null) return false;
|
|
534
|
+
|
|
535
|
+
let progress = this._progressAfterDownload +
|
|
536
|
+
this._progressDuringUpload +
|
|
537
|
+
2 * this._progressDuringRestart;
|
|
538
|
+
const progressPerElem = (1 - progress) / elemsToUpdate.length;
|
|
539
|
+
|
|
540
|
+
const updatedDtids: Array<number> = [];
|
|
541
|
+
for (const elem in elemsToUpdate){
|
|
542
|
+
const dtid = parseInt(elemsToUpdate[elem]["whoAmITypeCode"], 16);
|
|
543
|
+
const expectedVersion = elemsToUpdate[elem]["expectedVersion"];
|
|
544
|
+
const actualVersion = elemsToUpdate[elem]["versionStr"];
|
|
545
|
+
const elemType = elemsToUpdate[elem]["type"];
|
|
546
|
+
const elemName = elemsToUpdate[elem]["name"];
|
|
547
|
+
RaftLog.debug(`hwElem ${elemsToUpdate[elem]["name"]} dtid ${dtid} type ${elemType} expectedVersion ${expectedVersion} actual version ${actualVersion}`);
|
|
548
|
+
if (expectedVersion){
|
|
549
|
+
// only need to send each firmware file once
|
|
550
|
+
const sendFile = updatedDtids.includes(dtid) ? false : true;
|
|
551
|
+
if (!await this.updateHWElem(elemName, dtid, elemType, expectedVersion, sendFile))
|
|
552
|
+
allElemsUpdatedOk = false;
|
|
553
|
+
updatedDtids.push(dtid);
|
|
554
|
+
|
|
555
|
+
progress += progressPerElem;
|
|
556
|
+
this._eventListener(RaftUpdateEvent.UPDATE_PROGRESS, {
|
|
557
|
+
stage: "Updating elements",
|
|
558
|
+
progress: progress,
|
|
559
|
+
updatingFilesystem: true,
|
|
560
|
+
});
|
|
561
|
+
}
|
|
562
|
+
}
|
|
563
|
+
|
|
564
|
+
return allElemsUpdatedOk;
|
|
565
|
+
}
|
|
566
|
+
|
|
567
|
+
async updateHWElem(elemName: string, dtid: number, elemType: string, expectedVersion: string, sendFile: boolean){
|
|
568
|
+
const dtidStr = dtid.toString(16).padStart(8, "0");
|
|
569
|
+
const destFwFilename = `fw${dtidStr}.rfw`;
|
|
570
|
+
if (sendFile){
|
|
571
|
+
const firmwareUrl = `${this._firmwareBaseURL}/firmware/${dtidStr}/fw${dtidStr}-${expectedVersion}.rfw`;
|
|
572
|
+
const firmware = await this._fileDownloader(firmwareUrl, (received, total)=>{RaftLog.debug(`download received ${received} of total ${total}`)});
|
|
573
|
+
if (!firmware.downloadedOk || !firmware.fileData) return false;
|
|
574
|
+
if (!await this.fileSend(destFwFilename, RaftFileSendType.NORMAL_FILE, firmware.fileData, (sent, total, progress)=>{console.log(`sent ${sent} total ${total} progress ${progress}`)}))
|
|
575
|
+
return false;
|
|
576
|
+
}
|
|
577
|
+
// double check file on Raft has the correct version
|
|
578
|
+
const fwResp = await this._msgHandler.sendRICRESTURL<RaftHWFWUpdRslt>(`hwfwupd//${destFwFilename}`);
|
|
579
|
+
if (fwResp.st.v != expectedVersion) return false;
|
|
580
|
+
|
|
581
|
+
const fwInfo: RaftFWInfo = {
|
|
582
|
+
elemType: elemType,
|
|
583
|
+
destname: destFwFilename,
|
|
584
|
+
version: "",
|
|
585
|
+
md5: "",
|
|
586
|
+
releaseNotes: "",
|
|
587
|
+
comments: "",
|
|
588
|
+
updaters: [],
|
|
589
|
+
downloadUrl: ""
|
|
590
|
+
};
|
|
591
|
+
return await this.updateElem(fwInfo, elemName);
|
|
592
|
+
}
|
|
593
|
+
|
|
594
|
+
async updateElem(elemFw: RaftFWInfo, elemNameOrAll = "all") {
|
|
595
|
+
// Start hw-elem update
|
|
596
|
+
const updateCmd = `hwfwupd/${elemFw.elemType}/${elemFw.destname}/${elemNameOrAll}`;
|
|
597
|
+
try {
|
|
598
|
+
await this._msgHandler.sendRICRESTURL<RaftOKFail>(updateCmd);
|
|
599
|
+
} catch (error) {
|
|
600
|
+
RaftLog.debug(
|
|
601
|
+
`fwUpdate failed to start hw-elem firmware update cmd ${updateCmd} error ${error}`
|
|
602
|
+
);
|
|
603
|
+
return false;
|
|
604
|
+
}
|
|
605
|
+
|
|
606
|
+
let allElemsUpdatedOk = false;
|
|
607
|
+
// Check the status
|
|
608
|
+
for (
|
|
609
|
+
let updateCheckLoop = 0;
|
|
610
|
+
updateCheckLoop < this.ELEM_FW_CHECK_LOOPS;
|
|
611
|
+
updateCheckLoop++
|
|
612
|
+
) {
|
|
613
|
+
try {
|
|
614
|
+
// Wait for process to start on ESP32
|
|
615
|
+
await new Promise((resolve) => setTimeout(resolve, 5000));
|
|
616
|
+
|
|
617
|
+
// Get result (or status)
|
|
618
|
+
const elUpdRslt =
|
|
619
|
+
await this._msgHandler.sendRICRESTURL<RaftHWFWUpdRslt>("hwfwupd");
|
|
620
|
+
|
|
621
|
+
// Check result
|
|
622
|
+
if (
|
|
623
|
+
elUpdRslt.rslt === "ok" &&
|
|
624
|
+
(elUpdRslt.st.s === "idle" || elUpdRslt.st.s === "done")
|
|
625
|
+
) {
|
|
626
|
+
RaftLog.debug(
|
|
627
|
+
`fwUpdate hw-elem firmware updated ok - status ${elUpdRslt.st.s} rsltmsg ${elUpdRslt.st.m}`
|
|
628
|
+
);
|
|
629
|
+
|
|
630
|
+
// Check if any update outstanding (incomplete === 0)
|
|
631
|
+
allElemsUpdatedOk = elUpdRslt.st.i === 0;
|
|
632
|
+
break;
|
|
633
|
+
}
|
|
634
|
+
} catch (error) {
|
|
635
|
+
RaftLog.debug(`failed to get hw-elem firmware update status ${error}`);
|
|
636
|
+
}
|
|
637
|
+
}
|
|
638
|
+
return allElemsUpdatedOk;
|
|
639
|
+
}
|
|
640
|
+
|
|
641
|
+
async manualReconnect() {
|
|
642
|
+
return this._raftChannel?.connect({
|
|
643
|
+
name: this._nameToConnectTo,
|
|
644
|
+
localName: this._nameToConnectTo,
|
|
645
|
+
id: this._idToConnectTo || "",
|
|
646
|
+
rssi: 0,
|
|
647
|
+
}, {});
|
|
648
|
+
}
|
|
649
|
+
|
|
650
|
+
async waitForRestart(
|
|
651
|
+
percComplete: number,
|
|
652
|
+
checkFwVersion: string | null = null
|
|
653
|
+
) {
|
|
654
|
+
RaftLog.debug(
|
|
655
|
+
`fwUpdate: Waiting for restart. percComplete ${percComplete}, checkFwVersion: ${checkFwVersion}`
|
|
656
|
+
);
|
|
657
|
+
// sending the appropriate disconnect event to the UI so it knows that the device is disconnected
|
|
658
|
+
this._eventListener(RaftUpdateEvent.UPDATE_DISCONNECTED);
|
|
659
|
+
|
|
660
|
+
// Wait for firmware update to complete, restart to occur
|
|
661
|
+
// and BLE reconnection to happen
|
|
662
|
+
const waitTime = 5000;
|
|
663
|
+
const iterations = 3;
|
|
664
|
+
for (let i = 0; i < iterations; i++) {
|
|
665
|
+
await new Promise((resolve) => setTimeout(resolve, waitTime));
|
|
666
|
+
this._eventListener(RaftUpdateEvent.UPDATE_PROGRESS, {
|
|
667
|
+
stage: "Restarting " + (this._systemType ? this._systemType.nameForDialogs : ""),
|
|
668
|
+
progress: percComplete + (this._progressDuringRestart * i) / 3,
|
|
669
|
+
updatingFilesystem: true,
|
|
670
|
+
});
|
|
671
|
+
RaftLog.debug(
|
|
672
|
+
"fwUpdate waiting for reset, seconds: " +
|
|
673
|
+
i * waitTime +
|
|
674
|
+
" / " +
|
|
675
|
+
iterations * waitTime
|
|
676
|
+
);
|
|
677
|
+
}
|
|
678
|
+
|
|
679
|
+
// Attempt to get status from main ESP32 update
|
|
680
|
+
// The ESP32 will power cycle at this point so we need to wait a while
|
|
681
|
+
let versionConfirmed = false;
|
|
682
|
+
for (
|
|
683
|
+
let fwUpdateCheckCount = 0;
|
|
684
|
+
fwUpdateCheckCount < this.FW_UPDATE_CHECKS_BEFORE_ASSUME_FAILED;
|
|
685
|
+
fwUpdateCheckCount++
|
|
686
|
+
) {
|
|
687
|
+
try {
|
|
688
|
+
// Get version
|
|
689
|
+
RaftLog.debug(
|
|
690
|
+
`fwUpdate attempting to get Raft version attempt ${fwUpdateCheckCount}`
|
|
691
|
+
);
|
|
692
|
+
const systemInfo = await this._raftSystemUtils.getSystemInfo(true);
|
|
693
|
+
RaftLog.debug(
|
|
694
|
+
`fwUpdate version rslt "${systemInfo.rslt}" System Version ${systemInfo.SystemVersion}`
|
|
695
|
+
);
|
|
696
|
+
|
|
697
|
+
if (systemInfo.rslt !== "ok") {
|
|
698
|
+
let shouldContiue = true; // if this is not the last attempt, or if the manual reconnect fails, we should continue the loop
|
|
699
|
+
if (fwUpdateCheckCount === this.FW_UPDATE_CHECKS_BEFORE_ASSUME_FAILED - 1) {
|
|
700
|
+
// we have failed to get the version after the last attempt, so we need to fallback to manually reconnecting
|
|
701
|
+
const didConnect = await this.manualReconnect();
|
|
702
|
+
if (didConnect) shouldContiue = false;
|
|
703
|
+
}
|
|
704
|
+
if (shouldContiue) continue;
|
|
705
|
+
}
|
|
706
|
+
|
|
707
|
+
// at this point we are connected to BLE again, so we can send to the UI the appropriate events
|
|
708
|
+
this._eventListener(RaftUpdateEvent.UPDATE_RECONNECTED);
|
|
709
|
+
|
|
710
|
+
if (checkFwVersion != null) {
|
|
711
|
+
// Check version
|
|
712
|
+
versionConfirmed = RaftUtils.isVersionEqual(
|
|
713
|
+
checkFwVersion,
|
|
714
|
+
systemInfo.SystemVersion
|
|
715
|
+
);
|
|
716
|
+
RaftLog.debug(`fwUpdate got version rslt ${versionConfirmed}`);
|
|
717
|
+
} else {
|
|
718
|
+
versionConfirmed = true;
|
|
719
|
+
}
|
|
720
|
+
|
|
721
|
+
// Test fiddle to say it worked!
|
|
722
|
+
if (this.TEST_PRETEND_FINAL_VERSIONS_MATCH) {
|
|
723
|
+
versionConfirmed = true;
|
|
724
|
+
}
|
|
725
|
+
break;
|
|
726
|
+
} catch (error) {
|
|
727
|
+
RaftLog.debug(
|
|
728
|
+
`fwUpdate failed to get version attempt', ${fwUpdateCheckCount} error ${error}`
|
|
729
|
+
);
|
|
730
|
+
}
|
|
731
|
+
}
|
|
732
|
+
|
|
733
|
+
return versionConfirmed;
|
|
734
|
+
}
|
|
735
|
+
|
|
736
|
+
async firmwareUpdateCancel() {
|
|
737
|
+
this._eventListener(RaftUpdateEvent.UPDATE_CANCELLING);
|
|
738
|
+
|
|
739
|
+
await this.fileSendCancel();
|
|
740
|
+
}
|
|
741
|
+
|
|
742
|
+
// Mark: File Transfer ------------------------------------------------------------------------------------
|
|
743
|
+
|
|
744
|
+
/**
|
|
745
|
+
*
|
|
746
|
+
* fileSend - start file transfer
|
|
747
|
+
* @param fileName name of file to send
|
|
748
|
+
* @param fileType normal file or firmware
|
|
749
|
+
* @param fileDest destination on the system (fs or fw generally)
|
|
750
|
+
* @param fileContents contenst of the file (binary object)
|
|
751
|
+
* @returns Promise<boolean>
|
|
752
|
+
*
|
|
753
|
+
*/
|
|
754
|
+
async fileSend(
|
|
755
|
+
fileName: string,
|
|
756
|
+
fileType: RaftFileSendType,
|
|
757
|
+
fileContents: Uint8Array,
|
|
758
|
+
progressCallback: (sent: number, total: number, progress: number) => void
|
|
759
|
+
): Promise<boolean> {
|
|
760
|
+
|
|
761
|
+
// Get the destination
|
|
762
|
+
let fileDest = this._systemType ? this._systemType.normalFileDestName : "fs";
|
|
763
|
+
if (fileType === RaftFileSendType.FIRMWARE_UPDATE) {
|
|
764
|
+
fileDest = this._systemType ? this._systemType.firmwareDestName : "fw";
|
|
765
|
+
}
|
|
766
|
+
return await this._raftFileHandler.fileSend(
|
|
767
|
+
fileName,
|
|
768
|
+
fileType,
|
|
769
|
+
fileDest,
|
|
770
|
+
fileContents,
|
|
771
|
+
progressCallback
|
|
772
|
+
);
|
|
773
|
+
}
|
|
774
|
+
|
|
775
|
+
fileSendCancel() {
|
|
776
|
+
return this._raftFileHandler.fileSendCancel();
|
|
777
|
+
}
|
|
778
|
+
}
|