@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,502 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
3
|
+
//
|
|
4
|
+
// RaftFileHandler
|
|
5
|
+
// Communications Library
|
|
6
|
+
//
|
|
7
|
+
// Rob Dobson & Chris Greening 2020-2022
|
|
8
|
+
// (C) 2020-2022
|
|
9
|
+
//
|
|
10
|
+
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
const tslib_1 = require("tslib");
|
|
13
|
+
const RaftLog_1 = tslib_1.__importDefault(require("./RaftLog"));
|
|
14
|
+
const RaftTypes_1 = require("./RaftTypes");
|
|
15
|
+
const RaftUtils_1 = tslib_1.__importDefault(require("./RaftUtils"));
|
|
16
|
+
const RaftMiniHDLC_1 = tslib_1.__importDefault(require("./RaftMiniHDLC"));
|
|
17
|
+
const RaftProtocolDefs_1 = require("./RaftProtocolDefs");
|
|
18
|
+
class FileBlockTrackInfo {
|
|
19
|
+
constructor(prom) {
|
|
20
|
+
this.isDone = false;
|
|
21
|
+
this.prom = prom;
|
|
22
|
+
this.prom.then(() => {
|
|
23
|
+
// RaftLog.debug('send complete');
|
|
24
|
+
this.isDone = true;
|
|
25
|
+
}, rej => {
|
|
26
|
+
RaftLog_1.default.debug(`FileBlockTrackInfo send rejected ${rej}`);
|
|
27
|
+
this.isDone = true;
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
isComplete() {
|
|
31
|
+
return this.isDone;
|
|
32
|
+
}
|
|
33
|
+
get() {
|
|
34
|
+
return this.prom;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
class RaftFileHandler {
|
|
38
|
+
constructor(msgHandler, commsStats) {
|
|
39
|
+
// Timeouts
|
|
40
|
+
this.BLOCK_ACK_TIMEOUT_MS = 30000;
|
|
41
|
+
// Contents of file to send
|
|
42
|
+
this._requestedFileBlockSize = 500;
|
|
43
|
+
this._fileBlockSize = 0;
|
|
44
|
+
this._requestedBatchAckSize = 10;
|
|
45
|
+
this._batchAckSize = 0;
|
|
46
|
+
// File sending flow control
|
|
47
|
+
this._sendWithoutBatchAcks = false;
|
|
48
|
+
this._ackedFilePos = 0;
|
|
49
|
+
this._batchAckReceived = false;
|
|
50
|
+
this._isTxCancelled = false;
|
|
51
|
+
// File receive info
|
|
52
|
+
this._isRxCancelled = false;
|
|
53
|
+
this._fileRxActive = false;
|
|
54
|
+
this._fileRxBatchMsgSize = 0;
|
|
55
|
+
this._fileRxBatchAckSize = 0;
|
|
56
|
+
this._fileRxStreamID = 0;
|
|
57
|
+
this._fileRxFileLen = 0;
|
|
58
|
+
this._fileRxCrc16 = 0;
|
|
59
|
+
this._fileRxBuffer = new Uint8Array(0);
|
|
60
|
+
this._fileRxLastAckTime = 0;
|
|
61
|
+
this._fileRxLastBlockTime = 0;
|
|
62
|
+
this._fileRxLastAckPos = 0;
|
|
63
|
+
this.OVERALL_FILE_TRANSFER_TIMEOUT_MS = 100000;
|
|
64
|
+
this.FILE_RX_ACK_RESEND_TIMEOUT_MS = 1000;
|
|
65
|
+
// Message await list
|
|
66
|
+
this._msgAwaitList = new Array();
|
|
67
|
+
this.MAX_OUTSTANDING_FILE_BLOCK_SEND_PROMISES = 1;
|
|
68
|
+
this._msgHandler = msgHandler;
|
|
69
|
+
this._commsStats = commsStats;
|
|
70
|
+
this._fileBlockSize = this._requestedFileBlockSize;
|
|
71
|
+
this.onOktoMsg = this.onOktoMsg.bind(this);
|
|
72
|
+
}
|
|
73
|
+
setRequestedFileBlockSize(blockSize) {
|
|
74
|
+
this._requestedFileBlockSize = blockSize;
|
|
75
|
+
}
|
|
76
|
+
setRequestedBatchAckSize(batchAckSize) {
|
|
77
|
+
this._requestedBatchAckSize = batchAckSize;
|
|
78
|
+
}
|
|
79
|
+
async fileSend(fileName, fileType, fileDest, fileContents, progressCallback) {
|
|
80
|
+
this._isTxCancelled = false;
|
|
81
|
+
// Send file start message
|
|
82
|
+
if (!await this._sendFileStartMsg(fileName, fileType, fileDest, fileContents))
|
|
83
|
+
return false;
|
|
84
|
+
// Send contents
|
|
85
|
+
if (!await this._sendFileContents(fileContents, progressCallback))
|
|
86
|
+
return false;
|
|
87
|
+
// Send file end
|
|
88
|
+
await this._sendFileEndMsg(fileName, fileType, fileDest, fileContents);
|
|
89
|
+
// Clean up
|
|
90
|
+
await this.awaitOutstandingMsgPromises(true);
|
|
91
|
+
// Complete
|
|
92
|
+
return true;
|
|
93
|
+
}
|
|
94
|
+
async fileSendCancel() {
|
|
95
|
+
// Await outstanding promises
|
|
96
|
+
await this.awaitOutstandingMsgPromises(true);
|
|
97
|
+
this._isTxCancelled = true;
|
|
98
|
+
}
|
|
99
|
+
// Send the start message
|
|
100
|
+
async _sendFileStartMsg(fileName, fileType, fileDest, fileContents) {
|
|
101
|
+
// File start command message
|
|
102
|
+
const reqStr = fileType == RaftTypes_1.RaftFileSendType.FIRMWARE_UPDATE
|
|
103
|
+
? 'espfwupdate'
|
|
104
|
+
: 'fileupload';
|
|
105
|
+
const fileLen = fileContents.length;
|
|
106
|
+
const cmdMsg = `{"cmdName":"ufStart","reqStr":"${reqStr}","fileType":"${fileDest}","fileName":"${fileName}","fileLen":${fileLen},"batchMsgSize":${this._requestedFileBlockSize},"batchAckSize":${this._requestedBatchAckSize}}`;
|
|
107
|
+
// Debug
|
|
108
|
+
RaftLog_1.default.debug(`sendFileStartMsg ${cmdMsg}`);
|
|
109
|
+
// Send
|
|
110
|
+
let fileStartResp = null;
|
|
111
|
+
try {
|
|
112
|
+
fileStartResp = await this._msgHandler.sendRICREST(cmdMsg, RaftProtocolDefs_1.RICRESTElemCode.RICREST_ELEM_CODE_COMMAND_FRAME);
|
|
113
|
+
}
|
|
114
|
+
catch (err) {
|
|
115
|
+
RaftLog_1.default.error(`sendFileStartMsg error ${err}`);
|
|
116
|
+
return false;
|
|
117
|
+
}
|
|
118
|
+
if (fileStartResp.rslt !== 'ok') {
|
|
119
|
+
RaftLog_1.default.error(`sendFileStartMsg error ${fileStartResp.rslt}`);
|
|
120
|
+
return false;
|
|
121
|
+
}
|
|
122
|
+
// Extract params
|
|
123
|
+
if (fileStartResp.batchMsgSize) {
|
|
124
|
+
this._fileBlockSize = fileStartResp.batchMsgSize;
|
|
125
|
+
}
|
|
126
|
+
else {
|
|
127
|
+
this._fileBlockSize = this._requestedFileBlockSize;
|
|
128
|
+
}
|
|
129
|
+
if (fileStartResp.batchAckSize) {
|
|
130
|
+
this._batchAckSize = fileStartResp.batchAckSize;
|
|
131
|
+
}
|
|
132
|
+
else {
|
|
133
|
+
this._batchAckSize = this._requestedBatchAckSize;
|
|
134
|
+
}
|
|
135
|
+
RaftLog_1.default.debug(`_fileSendStartMsg fileBlockSize req ${this._requestedFileBlockSize} resp ${fileStartResp.batchMsgSize} actual ${this._fileBlockSize}`);
|
|
136
|
+
RaftLog_1.default.debug(`_fileSendStartMsg batchAckSize req ${this._requestedBatchAckSize} resp ${fileStartResp.batchAckSize} actual ${this._batchAckSize}`);
|
|
137
|
+
return true;
|
|
138
|
+
}
|
|
139
|
+
async _sendFileEndMsg(fileName, fileType, fileDest, fileContents) {
|
|
140
|
+
// File end command message
|
|
141
|
+
const reqStr = fileType == RaftTypes_1.RaftFileSendType.FIRMWARE_UPDATE
|
|
142
|
+
? 'espfwupdate'
|
|
143
|
+
: 'fileupload';
|
|
144
|
+
const fileLen = fileContents.length;
|
|
145
|
+
const cmdMsg = `{"cmdName":"ufEnd","reqStr":"${reqStr}","fileType":"${fileDest}","fileName":"${fileName}","fileLen":${fileLen}}`;
|
|
146
|
+
// Await outstanding promises
|
|
147
|
+
try {
|
|
148
|
+
await this.awaitOutstandingMsgPromises(true);
|
|
149
|
+
}
|
|
150
|
+
catch (err) {
|
|
151
|
+
// Ignore
|
|
152
|
+
RaftLog_1.default.error(`sendFileEndMsg awaitOutstandingMsgPromises error ${err}`);
|
|
153
|
+
}
|
|
154
|
+
// Send
|
|
155
|
+
let fileEndResp = null;
|
|
156
|
+
try {
|
|
157
|
+
fileEndResp = await this._msgHandler.sendRICREST(cmdMsg, RaftProtocolDefs_1.RICRESTElemCode.RICREST_ELEM_CODE_COMMAND_FRAME);
|
|
158
|
+
}
|
|
159
|
+
catch (err) {
|
|
160
|
+
RaftLog_1.default.error(`sendFileEndMsg error ${err}`);
|
|
161
|
+
return false;
|
|
162
|
+
}
|
|
163
|
+
return fileEndResp.rslt === 'ok';
|
|
164
|
+
}
|
|
165
|
+
async _sendFileCancelMsg() {
|
|
166
|
+
// File cancel command message
|
|
167
|
+
const cmdMsg = `{"cmdName":"ufCancel"}`;
|
|
168
|
+
// Await outstanding promises
|
|
169
|
+
await this.awaitOutstandingMsgPromises(true);
|
|
170
|
+
// Send
|
|
171
|
+
try {
|
|
172
|
+
return await this._msgHandler.sendRICREST(cmdMsg, RaftProtocolDefs_1.RICRESTElemCode.RICREST_ELEM_CODE_COMMAND_FRAME);
|
|
173
|
+
}
|
|
174
|
+
catch (err) {
|
|
175
|
+
RaftLog_1.default.error(`sendFileCancelMsg error ${err}`);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
async _sendFileContents(fileContents, progressCallback) {
|
|
179
|
+
if (progressCallback) {
|
|
180
|
+
progressCallback(0, fileContents.length, 0);
|
|
181
|
+
}
|
|
182
|
+
this._batchAckReceived = false;
|
|
183
|
+
this._ackedFilePos = 0;
|
|
184
|
+
// Send file blocks
|
|
185
|
+
let progressUpdateCtr = 0;
|
|
186
|
+
while (this._ackedFilePos < fileContents.length) {
|
|
187
|
+
// Sending with or without batches
|
|
188
|
+
if (this._sendWithoutBatchAcks) {
|
|
189
|
+
// Debug
|
|
190
|
+
RaftLog_1.default.verbose(`_sendFileContents NO BATCH ACKS ${progressUpdateCtr} blocks total sent ${this._ackedFilePos} block len ${this._fileBlockSize}`);
|
|
191
|
+
if (!await this._sendFileBlock(fileContents, this._ackedFilePos))
|
|
192
|
+
return false;
|
|
193
|
+
this._ackedFilePos += this._fileBlockSize;
|
|
194
|
+
progressUpdateCtr++;
|
|
195
|
+
}
|
|
196
|
+
else {
|
|
197
|
+
// NOTE: first batch MUST be of size 1 (not _batchAckSize) because Raft performs a long-running
|
|
198
|
+
// blocking task immediately after receiving the first message in a firmware
|
|
199
|
+
// update - although this could be relaxed for non-firmware update file uploads
|
|
200
|
+
let sendFromPos = this._ackedFilePos;
|
|
201
|
+
const batchSize = sendFromPos == 0 ? 1 : this._batchAckSize;
|
|
202
|
+
for (let i = 0; i < batchSize && sendFromPos < fileContents.length; i++) {
|
|
203
|
+
// Clear old batch acks
|
|
204
|
+
if (i == batchSize - 1) {
|
|
205
|
+
this._batchAckReceived = false;
|
|
206
|
+
}
|
|
207
|
+
// Debug
|
|
208
|
+
RaftLog_1.default.debug(`_sendFileContents sendblock pos ${sendFromPos} len ${this._fileBlockSize} ackedTo ${this._ackedFilePos} fileLen ${fileContents.length}`);
|
|
209
|
+
if (!await this._sendFileBlock(fileContents, sendFromPos))
|
|
210
|
+
return false;
|
|
211
|
+
sendFromPos += this._fileBlockSize;
|
|
212
|
+
}
|
|
213
|
+
// Wait for response (there is a timeout at the ESP end to ensure a response is always returned
|
|
214
|
+
// even if blocks are dropped on reception at ESP) - the timeout here is for these responses
|
|
215
|
+
// being dropped
|
|
216
|
+
await this.batchAck(this.BLOCK_ACK_TIMEOUT_MS);
|
|
217
|
+
progressUpdateCtr += this._batchAckSize;
|
|
218
|
+
}
|
|
219
|
+
// Show progress
|
|
220
|
+
if ((progressUpdateCtr >= 20) && progressCallback) {
|
|
221
|
+
// Update UI
|
|
222
|
+
progressCallback(this._ackedFilePos, fileContents.length, this._ackedFilePos / fileContents.length);
|
|
223
|
+
// Debug
|
|
224
|
+
RaftLog_1.default.debug(`_sendFileContents ${progressUpdateCtr} blocks sent OkTo ${this._ackedFilePos} block len ${this._fileBlockSize}`);
|
|
225
|
+
// Continue
|
|
226
|
+
progressUpdateCtr = 0;
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
return true;
|
|
230
|
+
}
|
|
231
|
+
async batchAck(timeout) {
|
|
232
|
+
// Handle acknowledgement to a batch (OkTo message)
|
|
233
|
+
return new Promise((resolve, reject) => {
|
|
234
|
+
const startTime = Date.now();
|
|
235
|
+
const checkForAck = async () => {
|
|
236
|
+
if (this._isTxCancelled) {
|
|
237
|
+
RaftLog_1.default.debug('checkForAck - cancelling file upload');
|
|
238
|
+
this._isTxCancelled = false;
|
|
239
|
+
// Send cancel
|
|
240
|
+
await this._sendFileCancelMsg();
|
|
241
|
+
// abort the upload process
|
|
242
|
+
reject(new Error('Update Cancelled'));
|
|
243
|
+
return;
|
|
244
|
+
}
|
|
245
|
+
if (this._batchAckReceived) {
|
|
246
|
+
RaftLog_1.default.debug(`checkForAck - rx OkTo ${this._ackedFilePos}`);
|
|
247
|
+
this._batchAckReceived = false;
|
|
248
|
+
resolve();
|
|
249
|
+
return;
|
|
250
|
+
}
|
|
251
|
+
else {
|
|
252
|
+
const now = Date.now();
|
|
253
|
+
if (now - startTime > timeout) {
|
|
254
|
+
RaftLog_1.default.warn(`checkForAck - time-out no new ack received`);
|
|
255
|
+
reject(new Error('Update failed. Please try again.'));
|
|
256
|
+
return;
|
|
257
|
+
}
|
|
258
|
+
setTimeout(checkForAck, 100);
|
|
259
|
+
}
|
|
260
|
+
};
|
|
261
|
+
checkForAck();
|
|
262
|
+
});
|
|
263
|
+
}
|
|
264
|
+
async _sendFileBlock(fileContents, blockStart) {
|
|
265
|
+
// Calc block start and end
|
|
266
|
+
const blockEnd = Math.min(fileContents.length, blockStart + this._fileBlockSize);
|
|
267
|
+
// Check if we need to await a message send promise
|
|
268
|
+
await this.awaitOutstandingMsgPromises(false);
|
|
269
|
+
// Send
|
|
270
|
+
const promRslt = this._msgHandler.sendFileBlock(fileContents.subarray(blockStart, blockEnd), blockStart);
|
|
271
|
+
if (!promRslt) {
|
|
272
|
+
return false;
|
|
273
|
+
}
|
|
274
|
+
// Record
|
|
275
|
+
this._commsStats.recordFileBytes(blockEnd - blockStart);
|
|
276
|
+
// Add to list of pending messages
|
|
277
|
+
this._msgAwaitList.push(new FileBlockTrackInfo(promRslt));
|
|
278
|
+
// Debug
|
|
279
|
+
// RaftLog.debug(
|
|
280
|
+
// `sendFileBlock start ${blockStart} end ${blockEnd} len ${blockLen}`,
|
|
281
|
+
// );
|
|
282
|
+
return true;
|
|
283
|
+
}
|
|
284
|
+
onOktoMsg(fileOkTo) {
|
|
285
|
+
// Get how far we've progressed in file
|
|
286
|
+
this._ackedFilePos = fileOkTo;
|
|
287
|
+
this._batchAckReceived = true;
|
|
288
|
+
RaftLog_1.default.verbose(`onOktoMsg received file up to ${this._ackedFilePos}`);
|
|
289
|
+
}
|
|
290
|
+
async awaitOutstandingMsgPromises(all) {
|
|
291
|
+
// Check if all outstanding promises to be awaited
|
|
292
|
+
if (all) {
|
|
293
|
+
for (const promRslt of this._msgAwaitList) {
|
|
294
|
+
try {
|
|
295
|
+
await promRslt.get();
|
|
296
|
+
}
|
|
297
|
+
catch (error) {
|
|
298
|
+
RaftLog_1.default.warn(`awaitAll file part send failed ${error}`);
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
this._msgAwaitList = [];
|
|
302
|
+
}
|
|
303
|
+
else {
|
|
304
|
+
// RaftLog.debug('Await list len', this._msgAwaitList.length);
|
|
305
|
+
if (this._msgAwaitList.length >=
|
|
306
|
+
this.MAX_OUTSTANDING_FILE_BLOCK_SEND_PROMISES) {
|
|
307
|
+
const fileBlockTrackInfo = this._msgAwaitList.shift();
|
|
308
|
+
try {
|
|
309
|
+
if (fileBlockTrackInfo) {
|
|
310
|
+
await fileBlockTrackInfo.get();
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
catch (error) {
|
|
314
|
+
RaftLog_1.default.warn(`awaitSome file part send failed ${error}`);
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
async fileReceive(fileName, fileSource, progressCallback) {
|
|
320
|
+
this._isRxCancelled = false;
|
|
321
|
+
// Check for bridgeserial1..N as fileSource - in this case use the RICREST bridging protocol
|
|
322
|
+
// as attached devices using CommandSerial require bridging
|
|
323
|
+
let bridgeID = undefined;
|
|
324
|
+
const bridgeSerialPrefix = 'bridgeserial';
|
|
325
|
+
if (fileSource.startsWith(bridgeSerialPrefix)) {
|
|
326
|
+
// Establish a bridge
|
|
327
|
+
const bridgedDeviceSerialPort = "Serial" + fileSource.slice(bridgeSerialPrefix.length);
|
|
328
|
+
const cmdResp = await this._msgHandler.createCommsBridge(bridgedDeviceSerialPort, "fileSource");
|
|
329
|
+
if (cmdResp.rslt != "ok") {
|
|
330
|
+
RaftLog_1.default.error(`fileReceive - failed to setup bridge ${cmdResp.rslt}`);
|
|
331
|
+
return new RaftTypes_1.RaftFileDownloadResult();
|
|
332
|
+
}
|
|
333
|
+
bridgeID = cmdResp.bridgeID;
|
|
334
|
+
// Debug
|
|
335
|
+
RaftLog_1.default.info(`fileReceive - bridge setup ${bridgeID}`);
|
|
336
|
+
}
|
|
337
|
+
// Send file start message
|
|
338
|
+
if (!await this._receiveFileStart(fileName, bridgeID))
|
|
339
|
+
return new RaftTypes_1.RaftFileDownloadResult();
|
|
340
|
+
// Send contents
|
|
341
|
+
const fileContents = await this._receiveFileContents(progressCallback, bridgeID);
|
|
342
|
+
// Send file end
|
|
343
|
+
await this._receiveFileEnd(fileName, bridgeID);
|
|
344
|
+
// Clean up
|
|
345
|
+
await this.awaitOutstandingMsgPromises(true);
|
|
346
|
+
// Complete
|
|
347
|
+
return fileContents;
|
|
348
|
+
}
|
|
349
|
+
async fileReceiveCancel() {
|
|
350
|
+
this._isRxCancelled = true;
|
|
351
|
+
}
|
|
352
|
+
async _receiveFileStart(fileName, bridgeID) {
|
|
353
|
+
const blockMaxSizeRequested = 5000;
|
|
354
|
+
const batchAckSizeRequested = 10;
|
|
355
|
+
const fileSrc = "fs";
|
|
356
|
+
// Request file transfer
|
|
357
|
+
// Frames follow the approach used in the web interface start, block..., end
|
|
358
|
+
const cmdMsg = `{"cmdName":"dfStart","reqStr":"getFile","fileType":"${fileSrc}",` +
|
|
359
|
+
`"batchMsgSize":${blockMaxSizeRequested},` +
|
|
360
|
+
`"batchAckSize":${batchAckSizeRequested},` +
|
|
361
|
+
`"fileName":"${fileName}"}`;
|
|
362
|
+
// Send
|
|
363
|
+
let cmdResp = null;
|
|
364
|
+
try {
|
|
365
|
+
cmdResp = await this._msgHandler.sendRICREST(cmdMsg, RaftProtocolDefs_1.RICRESTElemCode.RICREST_ELEM_CODE_COMMAND_FRAME, bridgeID);
|
|
366
|
+
}
|
|
367
|
+
catch (err) {
|
|
368
|
+
RaftLog_1.default.error(`_receiveFileStartMsg error ${err}`);
|
|
369
|
+
return false;
|
|
370
|
+
}
|
|
371
|
+
RaftLog_1.default.info(`_receiveFileStartMsg rslt ${JSON.stringify(cmdResp)}`);
|
|
372
|
+
if (cmdResp.rslt === 'ok') {
|
|
373
|
+
this._fileRxBatchMsgSize = cmdResp.batchMsgSize;
|
|
374
|
+
this._fileRxBatchAckSize = cmdResp.batchAckSize;
|
|
375
|
+
this._fileRxStreamID = cmdResp.streamID;
|
|
376
|
+
this._fileRxFileLen = cmdResp.fileLen;
|
|
377
|
+
this._fileRxCrc16 = parseInt(cmdResp.crc16, 16);
|
|
378
|
+
this._fileRxBuffer = new Uint8Array(0);
|
|
379
|
+
this._fileRxLastAckTime = 0;
|
|
380
|
+
this._fileRxLastAckPos = 0;
|
|
381
|
+
this._fileRxLastBlockTime = Date.now();
|
|
382
|
+
this._fileRxActive = true;
|
|
383
|
+
}
|
|
384
|
+
return cmdResp.rslt === 'ok';
|
|
385
|
+
}
|
|
386
|
+
async _receiveFileContents(progressCallback, bridgeID) {
|
|
387
|
+
// Wait for file to be received
|
|
388
|
+
return new Promise((resolve, reject) => {
|
|
389
|
+
const startTime = Date.now();
|
|
390
|
+
const checkForComplete = async () => {
|
|
391
|
+
// Check if we've received the whole file
|
|
392
|
+
if (this._fileRxFileLen === this._fileRxBuffer.length) {
|
|
393
|
+
this._fileRxActive = false;
|
|
394
|
+
// Progress callback
|
|
395
|
+
if (progressCallback) {
|
|
396
|
+
progressCallback(this._fileRxBuffer.length, this._fileRxFileLen);
|
|
397
|
+
}
|
|
398
|
+
// Check CRC
|
|
399
|
+
const crc16 = RaftMiniHDLC_1.default.crc16(this._fileRxBuffer);
|
|
400
|
+
if (crc16 !== this._fileRxCrc16) {
|
|
401
|
+
RaftLog_1.default.error(`_receiveFileContents - CRC error ${crc16} ${this._fileRxCrc16}`);
|
|
402
|
+
reject(new Error('fileReceive CRC error'));
|
|
403
|
+
return;
|
|
404
|
+
}
|
|
405
|
+
else {
|
|
406
|
+
RaftLog_1.default.info(`_receiveFileContents - CRC OK ${crc16} ${this._fileRxCrc16}`);
|
|
407
|
+
}
|
|
408
|
+
resolve(new RaftTypes_1.RaftFileDownloadResult(this._fileRxBuffer));
|
|
409
|
+
return;
|
|
410
|
+
}
|
|
411
|
+
// Check if file transfer cancelled
|
|
412
|
+
if (this._isRxCancelled) {
|
|
413
|
+
RaftLog_1.default.info('_receiveFileContents - cancelling file upload');
|
|
414
|
+
this._isRxCancelled = false;
|
|
415
|
+
this._fileRxActive = false;
|
|
416
|
+
// Send cancel message
|
|
417
|
+
this._sendFileRxCancelMsg(bridgeID);
|
|
418
|
+
// abort the upload process
|
|
419
|
+
reject(new Error('fileReceive Cancelled'));
|
|
420
|
+
return;
|
|
421
|
+
}
|
|
422
|
+
// Check for timeouts
|
|
423
|
+
const now = Date.now();
|
|
424
|
+
// Check for overall timeouts
|
|
425
|
+
if ((now - startTime > this.OVERALL_FILE_TRANSFER_TIMEOUT_MS) ||
|
|
426
|
+
(now - this._fileRxLastBlockTime > this.BLOCK_ACK_TIMEOUT_MS)) {
|
|
427
|
+
RaftLog_1.default.warn(`_receiveFileContents - time-out no new data received`);
|
|
428
|
+
this._fileRxActive = false;
|
|
429
|
+
reject(new Error('fileReceive failed'));
|
|
430
|
+
return;
|
|
431
|
+
}
|
|
432
|
+
// Check if time to send ack
|
|
433
|
+
let ackRequired = false;
|
|
434
|
+
if (Date.now() - this._fileRxLastAckTime > this.FILE_RX_ACK_RESEND_TIMEOUT_MS) {
|
|
435
|
+
ackRequired = true;
|
|
436
|
+
}
|
|
437
|
+
// Check if position to send ack
|
|
438
|
+
if (this._fileRxBuffer.length - this._fileRxLastAckPos >= this._fileRxBatchAckSize * this._fileRxBatchMsgSize) {
|
|
439
|
+
ackRequired = true;
|
|
440
|
+
}
|
|
441
|
+
// RaftLog.info(`_receiveFileContents ${ackRequired ? "ACK_REQUIRED" : "ACK_NOTREQUIRED"} ${this._fileRxBuffer.length} ${this._fileRxLastAckPos} ${this._fileRxBatchAckSize} ${this._fileRxBatchMsgSize}`);
|
|
442
|
+
// Check if ack required
|
|
443
|
+
if (ackRequired) {
|
|
444
|
+
// Ack timing
|
|
445
|
+
this._fileRxLastAckTime = Date.now();
|
|
446
|
+
this._fileRxLastAckPos = this._fileRxBuffer.length;
|
|
447
|
+
// Okto message
|
|
448
|
+
const cmdMsg = `{"cmdName":"dfAck","okto":${this._fileRxBuffer.length},` +
|
|
449
|
+
`"streamID":${this._fileRxStreamID},"rslt":"ok"}`;
|
|
450
|
+
// Send without waiting for response
|
|
451
|
+
this._msgHandler.sendRICRESTNoResp(cmdMsg, RaftProtocolDefs_1.RICRESTElemCode.RICREST_ELEM_CODE_COMMAND_FRAME, bridgeID);
|
|
452
|
+
// Debug
|
|
453
|
+
RaftLog_1.default.verbose(`_receiveFileContents ack generated at ${this._fileRxBuffer.length} msg ${cmdMsg}`);
|
|
454
|
+
}
|
|
455
|
+
// Progress callback
|
|
456
|
+
if (progressCallback) {
|
|
457
|
+
progressCallback(this._fileRxBuffer.length, this._fileRxFileLen);
|
|
458
|
+
}
|
|
459
|
+
// Set timeout for next check
|
|
460
|
+
setTimeout(checkForComplete, 50);
|
|
461
|
+
};
|
|
462
|
+
checkForComplete();
|
|
463
|
+
});
|
|
464
|
+
}
|
|
465
|
+
async _receiveFileEnd(fileName, bridgeID) {
|
|
466
|
+
// Send file end message
|
|
467
|
+
const cmdMsg = `{"cmdName":"dfAck","reqStr":"getFile","okto":${this._fileRxBuffer.length},` +
|
|
468
|
+
`"fileName":"${fileName}","streamID":${this._fileRxStreamID},"rslt":"ok"}`;
|
|
469
|
+
this._msgHandler.sendRICRESTNoResp(cmdMsg, RaftProtocolDefs_1.RICRESTElemCode.RICREST_ELEM_CODE_COMMAND_FRAME, bridgeID);
|
|
470
|
+
// No longer active
|
|
471
|
+
this._fileRxActive = false;
|
|
472
|
+
return false;
|
|
473
|
+
}
|
|
474
|
+
async _sendFileRxCancelMsg(bridgeID) {
|
|
475
|
+
// Send file end message
|
|
476
|
+
const cmdMsg = `{"cmdName":"dfCancel","reqStr":"getFile","streamID":${this._fileRxStreamID}}`;
|
|
477
|
+
this._msgHandler.sendRICRESTNoResp(cmdMsg, RaftProtocolDefs_1.RICRESTElemCode.RICREST_ELEM_CODE_COMMAND_FRAME, bridgeID);
|
|
478
|
+
}
|
|
479
|
+
onFileBlock(filePos, fileBlockData) {
|
|
480
|
+
// RaftLog.info(`onFileBlock filePos ${filePos} fileBlockData ${RaftUtils.bufferToHex(fileBlockData)}`);
|
|
481
|
+
// Check if this is the next block we are expecting
|
|
482
|
+
if (filePos === this._fileRxBuffer.length) {
|
|
483
|
+
// Add to buffer
|
|
484
|
+
const tmpArray = new Uint8Array(this._fileRxBuffer.length + fileBlockData.length);
|
|
485
|
+
tmpArray.set(this._fileRxBuffer, 0);
|
|
486
|
+
tmpArray.set(fileBlockData, this._fileRxBuffer.length);
|
|
487
|
+
this._fileRxBuffer = tmpArray;
|
|
488
|
+
// Update last block time
|
|
489
|
+
this._fileRxLastBlockTime = Date.now();
|
|
490
|
+
// Debug
|
|
491
|
+
// RaftLog.info(`onFileBlock filePos ${filePos} fileBlockData ${RaftUtils.bufferToHex(fileBlockData)} added to buffer`);
|
|
492
|
+
}
|
|
493
|
+
else {
|
|
494
|
+
RaftLog_1.default.warn(`onFileBlock expected streamID ${this._fileRxStreamID} filePos ${filePos} fileBlockData ${RaftUtils_1.default.bufferToHex(fileBlockData)} out of sequence`);
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
isFileRxActive() {
|
|
498
|
+
return this._fileRxActive;
|
|
499
|
+
}
|
|
500
|
+
}
|
|
501
|
+
exports.default = RaftFileHandler;
|
|
502
|
+
//# sourceMappingURL=RaftFileHandler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RaftFileHandler.js","sourceRoot":"","sources":["../src/RaftFileHandler.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export declare enum RaftLogLevel {
|
|
2
|
+
NONE = 0,
|
|
3
|
+
ERROR = 1,
|
|
4
|
+
WARN = 2,
|
|
5
|
+
INFO = 3,
|
|
6
|
+
DEBUG = 4,
|
|
7
|
+
VERBOSE = 5
|
|
8
|
+
}
|
|
9
|
+
export type RaftLogFn = (logLevel: RaftLogLevel, msg: string) => void;
|
|
10
|
+
export default class RaftLog {
|
|
11
|
+
static _logListener: RaftLogFn | null;
|
|
12
|
+
static _logLevel: RaftLogLevel;
|
|
13
|
+
static format(msg: string): string;
|
|
14
|
+
static debug(msg: string): void;
|
|
15
|
+
static info(msg: string): void;
|
|
16
|
+
static warn(msg: string): void;
|
|
17
|
+
static error(msg: string): void;
|
|
18
|
+
static verbose(msg: string): void;
|
|
19
|
+
static setLogListener(listener: RaftLogFn | null): void;
|
|
20
|
+
static setLogLevel(logLevel: RaftLogLevel): void;
|
|
21
|
+
static doLogging(logLevel: RaftLogLevel, msg: string): boolean;
|
|
22
|
+
}
|
package/dist/RaftLog.js
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
3
|
+
//
|
|
4
|
+
// RaftLog
|
|
5
|
+
// Communications Library
|
|
6
|
+
//
|
|
7
|
+
// Rob Dobson & Chris Greening 2020-2022
|
|
8
|
+
// (C) 2020-2022
|
|
9
|
+
//
|
|
10
|
+
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.RaftLogLevel = void 0;
|
|
13
|
+
var RaftLogLevel;
|
|
14
|
+
(function (RaftLogLevel) {
|
|
15
|
+
RaftLogLevel[RaftLogLevel["NONE"] = 0] = "NONE";
|
|
16
|
+
RaftLogLevel[RaftLogLevel["ERROR"] = 1] = "ERROR";
|
|
17
|
+
RaftLogLevel[RaftLogLevel["WARN"] = 2] = "WARN";
|
|
18
|
+
RaftLogLevel[RaftLogLevel["INFO"] = 3] = "INFO";
|
|
19
|
+
RaftLogLevel[RaftLogLevel["DEBUG"] = 4] = "DEBUG";
|
|
20
|
+
RaftLogLevel[RaftLogLevel["VERBOSE"] = 5] = "VERBOSE";
|
|
21
|
+
})(RaftLogLevel || (exports.RaftLogLevel = RaftLogLevel = {}));
|
|
22
|
+
class RaftLog {
|
|
23
|
+
static format(msg) {
|
|
24
|
+
return (Date.now() / 1000).toFixed(3).toString() + " " + msg;
|
|
25
|
+
}
|
|
26
|
+
static debug(msg) {
|
|
27
|
+
if (!this.doLogging(RaftLogLevel.DEBUG, msg))
|
|
28
|
+
console.debug(RaftLog.format(msg));
|
|
29
|
+
}
|
|
30
|
+
static info(msg) {
|
|
31
|
+
if (!this.doLogging(RaftLogLevel.INFO, msg))
|
|
32
|
+
console.info(RaftLog.format(msg));
|
|
33
|
+
}
|
|
34
|
+
static warn(msg) {
|
|
35
|
+
if (!this.doLogging(RaftLogLevel.WARN, msg))
|
|
36
|
+
console.warn(RaftLog.format(msg));
|
|
37
|
+
}
|
|
38
|
+
static error(msg) {
|
|
39
|
+
if (!this.doLogging(RaftLogLevel.ERROR, msg))
|
|
40
|
+
console.error(RaftLog.format(msg));
|
|
41
|
+
}
|
|
42
|
+
static verbose(msg) {
|
|
43
|
+
if (!this.doLogging(RaftLogLevel.VERBOSE, msg))
|
|
44
|
+
console.debug(RaftLog.format(msg));
|
|
45
|
+
}
|
|
46
|
+
static setLogListener(listener) {
|
|
47
|
+
this._logListener = listener;
|
|
48
|
+
}
|
|
49
|
+
static setLogLevel(logLevel) {
|
|
50
|
+
this._logLevel = logLevel;
|
|
51
|
+
}
|
|
52
|
+
static doLogging(logLevel, msg) {
|
|
53
|
+
if (this._logListener) {
|
|
54
|
+
this._logListener(logLevel, msg);
|
|
55
|
+
return true;
|
|
56
|
+
}
|
|
57
|
+
return this._logLevel < logLevel;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
RaftLog._logListener = null;
|
|
61
|
+
RaftLog._logLevel = RaftLogLevel.DEBUG;
|
|
62
|
+
exports.default = RaftLog;
|
|
63
|
+
//# sourceMappingURL=RaftLog.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RaftLog.js","sourceRoot":"","sources":["../src/RaftLog.ts"],"names":[],"mappings":";AAAA,iHAAiH;AACjH,EAAE;AACF,UAAU;AACV,yBAAyB;AACzB,EAAE;AACF,wCAAwC;AACxC,gBAAgB;AAChB,EAAE;AACF,iHAAiH;;;AAEjH,IAAY,YAOX;AAPD,WAAY,YAAY;IACtB,+CAAI,CAAA;IACJ,iDAAK,CAAA;IACL,+CAAI,CAAA;IACJ,+CAAI,CAAA;IACJ,iDAAK,CAAA;IACL,qDAAO,CAAA;AACT,CAAC,EAPW,YAAY,4BAAZ,YAAY,QAOvB;AAID,MAAqB,OAAO;IAI1B,MAAM,CAAC,MAAM,CAAC,GAAW;QACvB,OAAO,CAAC,IAAI,CAAC,GAAG,EAAE,GAAC,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE,GAAG,GAAG,GAAG,GAAG,CAAC;IAC7D,CAAC;IAED,MAAM,CAAC,KAAK,CAAC,GAAW;QACtB,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,YAAY,CAAC,KAAK,EAAE,GAAG,CAAC;YAC1C,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;IACvC,CAAC;IAED,MAAM,CAAC,IAAI,CAAC,GAAW;QACrB,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,YAAY,CAAC,IAAI,EAAE,GAAG,CAAC;YACzC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;IACtC,CAAC;IAED,MAAM,CAAC,IAAI,CAAC,GAAW;QACrB,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,YAAY,CAAC,IAAI,EAAE,GAAG,CAAC;YACzC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;IACtC,CAAC;IAED,MAAM,CAAC,KAAK,CAAC,GAAW;QACtB,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,YAAY,CAAC,KAAK,EAAE,GAAG,CAAC;YAC1C,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;IACvC,CAAC;IAED,MAAM,CAAC,OAAO,CAAC,GAAW;QACxB,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,YAAY,CAAC,OAAO,EAAE,GAAG,CAAC;YAC5C,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;IACvC,CAAC;IAED,MAAM,CAAC,cAAc,CAAC,QAA0B;QAC9C,IAAI,CAAC,YAAY,GAAG,QAAQ,CAAC;IAC/B,CAAC;IAED,MAAM,CAAC,WAAW,CAAC,QAAsB;QACvC,IAAI,CAAC,SAAS,GAAG,QAAQ,CAAC;IAC5B,CAAC;IAED,MAAM,CAAC,SAAS,CAAC,QAAsB,EAAE,GAAW;QAClD,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC;YACtB,IAAI,CAAC,YAAY,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAA;YAChC,OAAO,IAAI,CAAC;QACd,CAAC;QACD,OAAO,IAAI,CAAC,SAAS,GAAG,QAAQ,CAAC;IACnC,CAAC;;AA9CM,oBAAY,GAAqB,IAAI,CAAC;AACtC,iBAAS,GAAG,YAAY,CAAC,KAAK,CAAC;kBAFnB,OAAO"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export default class RaftMiniHDLC {
|
|
2
|
+
private rxState;
|
|
3
|
+
private rxBuffer;
|
|
4
|
+
private onRxFrame;
|
|
5
|
+
private frameCRC;
|
|
6
|
+
private readonly FRAME_BOUNDARY_OCTET;
|
|
7
|
+
private readonly CONTROL_ESCAPE_OCTET;
|
|
8
|
+
private readonly INVERT_OCTET;
|
|
9
|
+
private frameStartTimeMs;
|
|
10
|
+
constructor();
|
|
11
|
+
setOnRxFrame(onRxFrame: (rxFrame: Uint8Array, frameTimeMs: number) => void): void;
|
|
12
|
+
addRxByte(rxByte: number): void;
|
|
13
|
+
addRxBytes(rxBytes: Uint8Array): void;
|
|
14
|
+
_checkCRC(): boolean;
|
|
15
|
+
static crc16(buf: Array<number> | Uint8Array): number;
|
|
16
|
+
encode(content: Uint8Array): Uint8Array;
|
|
17
|
+
_setData(destBuf: Uint8Array, dataVal: number, pos: number): number;
|
|
18
|
+
}
|