@v5x/serial 0.5.5 → 0.5.7
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/README.md +44 -13
- package/dist/Vex.d.ts +3 -1
- package/dist/VexCRC.d.ts +0 -11
- package/dist/VexConnection.d.ts +77 -10
- package/dist/VexDevice.d.ts +32 -2
- package/dist/VexDeviceState.d.ts +39 -17
- package/dist/VexError.d.ts +5 -1
- package/dist/VexEvent.d.ts +14 -10
- package/dist/VexFirmware.d.ts +5 -2
- package/dist/VexFirmwareVersion.d.ts +4 -43
- package/dist/VexIniConfig.d.ts +0 -1
- package/dist/VexPacketBase.d.ts +5 -2
- package/dist/VexPacketCore.d.ts +5 -0
- package/dist/VexPacketEncoder.d.ts +13 -30
- package/dist/VexPacketModels.d.ts +1 -12
- package/dist/VexPacketRegistry.d.ts +3 -0
- package/dist/VexPacketView.d.ts +2 -0
- package/dist/VexScreenCapture.d.ts +2 -0
- package/dist/VexTransfers.d.ts +1 -0
- package/dist/index.cjs +1291 -1818
- package/dist/index.cjs.map +19 -19
- package/dist/index.js +1392 -1872
- package/dist/index.js.map +19 -19
- package/dist/packet-core.cjs +383 -0
- package/dist/packet-core.cjs.map +14 -0
- package/dist/packet-core.js +341 -0
- package/dist/packet-core.js.map +14 -0
- package/package.json +11 -4
package/dist/index.cjs
CHANGED
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
var __create = Object.create;
|
|
2
|
-
var __getProtoOf = Object.getPrototypeOf;
|
|
3
1
|
var __defProp = Object.defineProperty;
|
|
4
2
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
3
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
@@ -7,28 +5,6 @@ var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
|
7
5
|
function __accessProp(key) {
|
|
8
6
|
return this[key];
|
|
9
7
|
}
|
|
10
|
-
var __toESMCache_node;
|
|
11
|
-
var __toESMCache_esm;
|
|
12
|
-
var __toESM = (mod, isNodeMode, target) => {
|
|
13
|
-
var canCache = mod != null && typeof mod === "object";
|
|
14
|
-
if (canCache) {
|
|
15
|
-
var cache = isNodeMode ? __toESMCache_node ??= new WeakMap : __toESMCache_esm ??= new WeakMap;
|
|
16
|
-
var cached = cache.get(mod);
|
|
17
|
-
if (cached)
|
|
18
|
-
return cached;
|
|
19
|
-
}
|
|
20
|
-
target = mod != null ? __create(__getProtoOf(mod)) : {};
|
|
21
|
-
const to = isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target;
|
|
22
|
-
for (let key of __getOwnPropNames(mod))
|
|
23
|
-
if (!__hasOwnProp.call(to, key))
|
|
24
|
-
__defProp(to, key, {
|
|
25
|
-
get: __accessProp.bind(mod, key),
|
|
26
|
-
enumerable: true
|
|
27
|
-
});
|
|
28
|
-
if (canCache)
|
|
29
|
-
cache.set(mod, to);
|
|
30
|
-
return to;
|
|
31
|
-
};
|
|
32
8
|
var __toCommonJS = (from) => {
|
|
33
9
|
var entry = (__moduleCache ??= new WeakMap).get(from), desc;
|
|
34
10
|
if (entry)
|
|
@@ -46,7 +22,6 @@ var __toCommonJS = (from) => {
|
|
|
46
22
|
return entry;
|
|
47
23
|
};
|
|
48
24
|
var __moduleCache;
|
|
49
|
-
var __commonJS = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports, mod), mod.exports);
|
|
50
25
|
var __returnValue = (v) => v;
|
|
51
26
|
function __exportSetter(name, newValue) {
|
|
52
27
|
this[name] = __returnValue.bind(null, newValue);
|
|
@@ -61,483 +36,6 @@ var __export = (target, all) => {
|
|
|
61
36
|
});
|
|
62
37
|
};
|
|
63
38
|
|
|
64
|
-
// ../../node_modules/.bun/neverthrow@8.2.0/node_modules/neverthrow/dist/index.cjs.js
|
|
65
|
-
var require_index_cjs = __commonJS((exports2) => {
|
|
66
|
-
var defaultErrorConfig = {
|
|
67
|
-
withStackTrace: false
|
|
68
|
-
};
|
|
69
|
-
var createNeverThrowError = (message, result, config = defaultErrorConfig) => {
|
|
70
|
-
const data = result.isOk() ? { type: "Ok", value: result.value } : { type: "Err", value: result.error };
|
|
71
|
-
const maybeStack = config.withStackTrace ? new Error().stack : undefined;
|
|
72
|
-
return {
|
|
73
|
-
data,
|
|
74
|
-
message,
|
|
75
|
-
stack: maybeStack
|
|
76
|
-
};
|
|
77
|
-
};
|
|
78
|
-
function __awaiter(thisArg, _arguments, P, generator) {
|
|
79
|
-
function adopt(value) {
|
|
80
|
-
return value instanceof P ? value : new P(function(resolve) {
|
|
81
|
-
resolve(value);
|
|
82
|
-
});
|
|
83
|
-
}
|
|
84
|
-
return new (P || (P = Promise))(function(resolve, reject) {
|
|
85
|
-
function fulfilled(value) {
|
|
86
|
-
try {
|
|
87
|
-
step(generator.next(value));
|
|
88
|
-
} catch (e) {
|
|
89
|
-
reject(e);
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
function rejected(value) {
|
|
93
|
-
try {
|
|
94
|
-
step(generator["throw"](value));
|
|
95
|
-
} catch (e) {
|
|
96
|
-
reject(e);
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
function step(result) {
|
|
100
|
-
result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected);
|
|
101
|
-
}
|
|
102
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
103
|
-
});
|
|
104
|
-
}
|
|
105
|
-
function __values(o) {
|
|
106
|
-
var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
|
|
107
|
-
if (m)
|
|
108
|
-
return m.call(o);
|
|
109
|
-
if (o && typeof o.length === "number")
|
|
110
|
-
return {
|
|
111
|
-
next: function() {
|
|
112
|
-
if (o && i >= o.length)
|
|
113
|
-
o = undefined;
|
|
114
|
-
return { value: o && o[i++], done: !o };
|
|
115
|
-
}
|
|
116
|
-
};
|
|
117
|
-
throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
|
|
118
|
-
}
|
|
119
|
-
function __await(v) {
|
|
120
|
-
return this instanceof __await ? (this.v = v, this) : new __await(v);
|
|
121
|
-
}
|
|
122
|
-
function __asyncGenerator(thisArg, _arguments, generator) {
|
|
123
|
-
if (!Symbol.asyncIterator)
|
|
124
|
-
throw new TypeError("Symbol.asyncIterator is not defined.");
|
|
125
|
-
var g = generator.apply(thisArg, _arguments || []), i, q = [];
|
|
126
|
-
return i = Object.create((typeof AsyncIterator === "function" ? AsyncIterator : Object).prototype), verb("next"), verb("throw"), verb("return", awaitReturn), i[Symbol.asyncIterator] = function() {
|
|
127
|
-
return this;
|
|
128
|
-
}, i;
|
|
129
|
-
function awaitReturn(f) {
|
|
130
|
-
return function(v) {
|
|
131
|
-
return Promise.resolve(v).then(f, reject);
|
|
132
|
-
};
|
|
133
|
-
}
|
|
134
|
-
function verb(n, f) {
|
|
135
|
-
if (g[n]) {
|
|
136
|
-
i[n] = function(v) {
|
|
137
|
-
return new Promise(function(a, b) {
|
|
138
|
-
q.push([n, v, a, b]) > 1 || resume(n, v);
|
|
139
|
-
});
|
|
140
|
-
};
|
|
141
|
-
if (f)
|
|
142
|
-
i[n] = f(i[n]);
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
function resume(n, v) {
|
|
146
|
-
try {
|
|
147
|
-
step(g[n](v));
|
|
148
|
-
} catch (e) {
|
|
149
|
-
settle(q[0][3], e);
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
function step(r) {
|
|
153
|
-
r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r);
|
|
154
|
-
}
|
|
155
|
-
function fulfill(value) {
|
|
156
|
-
resume("next", value);
|
|
157
|
-
}
|
|
158
|
-
function reject(value) {
|
|
159
|
-
resume("throw", value);
|
|
160
|
-
}
|
|
161
|
-
function settle(f, v) {
|
|
162
|
-
if (f(v), q.shift(), q.length)
|
|
163
|
-
resume(q[0][0], q[0][1]);
|
|
164
|
-
}
|
|
165
|
-
}
|
|
166
|
-
function __asyncDelegator(o) {
|
|
167
|
-
var i, p;
|
|
168
|
-
return i = {}, verb("next"), verb("throw", function(e) {
|
|
169
|
-
throw e;
|
|
170
|
-
}), verb("return"), i[Symbol.iterator] = function() {
|
|
171
|
-
return this;
|
|
172
|
-
}, i;
|
|
173
|
-
function verb(n, f) {
|
|
174
|
-
i[n] = o[n] ? function(v) {
|
|
175
|
-
return (p = !p) ? { value: __await(o[n](v)), done: false } : f ? f(v) : v;
|
|
176
|
-
} : f;
|
|
177
|
-
}
|
|
178
|
-
}
|
|
179
|
-
function __asyncValues(o) {
|
|
180
|
-
if (!Symbol.asyncIterator)
|
|
181
|
-
throw new TypeError("Symbol.asyncIterator is not defined.");
|
|
182
|
-
var m = o[Symbol.asyncIterator], i;
|
|
183
|
-
return m ? m.call(o) : (o = typeof __values === "function" ? __values(o) : o[Symbol.iterator](), i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function() {
|
|
184
|
-
return this;
|
|
185
|
-
}, i);
|
|
186
|
-
function verb(n) {
|
|
187
|
-
i[n] = o[n] && function(v) {
|
|
188
|
-
return new Promise(function(resolve, reject) {
|
|
189
|
-
v = o[n](v), settle(resolve, reject, v.done, v.value);
|
|
190
|
-
});
|
|
191
|
-
};
|
|
192
|
-
}
|
|
193
|
-
function settle(resolve, reject, d, v) {
|
|
194
|
-
Promise.resolve(v).then(function(v2) {
|
|
195
|
-
resolve({ value: v2, done: d });
|
|
196
|
-
}, reject);
|
|
197
|
-
}
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
class ResultAsync {
|
|
201
|
-
constructor(res) {
|
|
202
|
-
this._promise = res;
|
|
203
|
-
}
|
|
204
|
-
static fromSafePromise(promise) {
|
|
205
|
-
const newPromise = promise.then((value) => new Ok(value));
|
|
206
|
-
return new ResultAsync(newPromise);
|
|
207
|
-
}
|
|
208
|
-
static fromPromise(promise, errorFn) {
|
|
209
|
-
const newPromise = promise.then((value) => new Ok(value)).catch((e) => new Err(errorFn(e)));
|
|
210
|
-
return new ResultAsync(newPromise);
|
|
211
|
-
}
|
|
212
|
-
static fromThrowable(fn, errorFn) {
|
|
213
|
-
return (...args) => {
|
|
214
|
-
return new ResultAsync((() => __awaiter(this, undefined, undefined, function* () {
|
|
215
|
-
try {
|
|
216
|
-
return new Ok(yield fn(...args));
|
|
217
|
-
} catch (error) {
|
|
218
|
-
return new Err(errorFn ? errorFn(error) : error);
|
|
219
|
-
}
|
|
220
|
-
}))());
|
|
221
|
-
};
|
|
222
|
-
}
|
|
223
|
-
static combine(asyncResultList) {
|
|
224
|
-
return combineResultAsyncList(asyncResultList);
|
|
225
|
-
}
|
|
226
|
-
static combineWithAllErrors(asyncResultList) {
|
|
227
|
-
return combineResultAsyncListWithAllErrors(asyncResultList);
|
|
228
|
-
}
|
|
229
|
-
map(f) {
|
|
230
|
-
return new ResultAsync(this._promise.then((res) => __awaiter(this, undefined, undefined, function* () {
|
|
231
|
-
if (res.isErr()) {
|
|
232
|
-
return new Err(res.error);
|
|
233
|
-
}
|
|
234
|
-
return new Ok(yield f(res.value));
|
|
235
|
-
})));
|
|
236
|
-
}
|
|
237
|
-
andThrough(f) {
|
|
238
|
-
return new ResultAsync(this._promise.then((res) => __awaiter(this, undefined, undefined, function* () {
|
|
239
|
-
if (res.isErr()) {
|
|
240
|
-
return new Err(res.error);
|
|
241
|
-
}
|
|
242
|
-
const newRes = yield f(res.value);
|
|
243
|
-
if (newRes.isErr()) {
|
|
244
|
-
return new Err(newRes.error);
|
|
245
|
-
}
|
|
246
|
-
return new Ok(res.value);
|
|
247
|
-
})));
|
|
248
|
-
}
|
|
249
|
-
andTee(f) {
|
|
250
|
-
return new ResultAsync(this._promise.then((res) => __awaiter(this, undefined, undefined, function* () {
|
|
251
|
-
if (res.isErr()) {
|
|
252
|
-
return new Err(res.error);
|
|
253
|
-
}
|
|
254
|
-
try {
|
|
255
|
-
yield f(res.value);
|
|
256
|
-
} catch (e) {}
|
|
257
|
-
return new Ok(res.value);
|
|
258
|
-
})));
|
|
259
|
-
}
|
|
260
|
-
orTee(f) {
|
|
261
|
-
return new ResultAsync(this._promise.then((res) => __awaiter(this, undefined, undefined, function* () {
|
|
262
|
-
if (res.isOk()) {
|
|
263
|
-
return new Ok(res.value);
|
|
264
|
-
}
|
|
265
|
-
try {
|
|
266
|
-
yield f(res.error);
|
|
267
|
-
} catch (e) {}
|
|
268
|
-
return new Err(res.error);
|
|
269
|
-
})));
|
|
270
|
-
}
|
|
271
|
-
mapErr(f) {
|
|
272
|
-
return new ResultAsync(this._promise.then((res) => __awaiter(this, undefined, undefined, function* () {
|
|
273
|
-
if (res.isOk()) {
|
|
274
|
-
return new Ok(res.value);
|
|
275
|
-
}
|
|
276
|
-
return new Err(yield f(res.error));
|
|
277
|
-
})));
|
|
278
|
-
}
|
|
279
|
-
andThen(f) {
|
|
280
|
-
return new ResultAsync(this._promise.then((res) => {
|
|
281
|
-
if (res.isErr()) {
|
|
282
|
-
return new Err(res.error);
|
|
283
|
-
}
|
|
284
|
-
const newValue = f(res.value);
|
|
285
|
-
return newValue instanceof ResultAsync ? newValue._promise : newValue;
|
|
286
|
-
}));
|
|
287
|
-
}
|
|
288
|
-
orElse(f) {
|
|
289
|
-
return new ResultAsync(this._promise.then((res) => __awaiter(this, undefined, undefined, function* () {
|
|
290
|
-
if (res.isErr()) {
|
|
291
|
-
return f(res.error);
|
|
292
|
-
}
|
|
293
|
-
return new Ok(res.value);
|
|
294
|
-
})));
|
|
295
|
-
}
|
|
296
|
-
match(ok2, _err) {
|
|
297
|
-
return this._promise.then((res) => res.match(ok2, _err));
|
|
298
|
-
}
|
|
299
|
-
unwrapOr(t) {
|
|
300
|
-
return this._promise.then((res) => res.unwrapOr(t));
|
|
301
|
-
}
|
|
302
|
-
safeUnwrap() {
|
|
303
|
-
return __asyncGenerator(this, arguments, function* safeUnwrap_1() {
|
|
304
|
-
return yield __await(yield __await(yield* __asyncDelegator(__asyncValues(yield __await(this._promise.then((res) => res.safeUnwrap()))))));
|
|
305
|
-
});
|
|
306
|
-
}
|
|
307
|
-
then(successCallback, failureCallback) {
|
|
308
|
-
return this._promise.then(successCallback, failureCallback);
|
|
309
|
-
}
|
|
310
|
-
[Symbol.asyncIterator]() {
|
|
311
|
-
return __asyncGenerator(this, arguments, function* _a() {
|
|
312
|
-
const result = yield __await(this._promise);
|
|
313
|
-
if (result.isErr()) {
|
|
314
|
-
yield yield __await(errAsync(result.error));
|
|
315
|
-
}
|
|
316
|
-
return yield __await(result.value);
|
|
317
|
-
});
|
|
318
|
-
}
|
|
319
|
-
}
|
|
320
|
-
function okAsync(value) {
|
|
321
|
-
return new ResultAsync(Promise.resolve(new Ok(value)));
|
|
322
|
-
}
|
|
323
|
-
function errAsync(err2) {
|
|
324
|
-
return new ResultAsync(Promise.resolve(new Err(err2)));
|
|
325
|
-
}
|
|
326
|
-
var fromPromise = ResultAsync.fromPromise;
|
|
327
|
-
var fromSafePromise = ResultAsync.fromSafePromise;
|
|
328
|
-
var fromAsyncThrowable = ResultAsync.fromThrowable;
|
|
329
|
-
var combineResultList = (resultList) => {
|
|
330
|
-
let acc = ok([]);
|
|
331
|
-
for (const result of resultList) {
|
|
332
|
-
if (result.isErr()) {
|
|
333
|
-
acc = err(result.error);
|
|
334
|
-
break;
|
|
335
|
-
} else {
|
|
336
|
-
acc.map((list) => list.push(result.value));
|
|
337
|
-
}
|
|
338
|
-
}
|
|
339
|
-
return acc;
|
|
340
|
-
};
|
|
341
|
-
var combineResultAsyncList = (asyncResultList) => ResultAsync.fromSafePromise(Promise.all(asyncResultList)).andThen(combineResultList);
|
|
342
|
-
var combineResultListWithAllErrors = (resultList) => {
|
|
343
|
-
let acc = ok([]);
|
|
344
|
-
for (const result of resultList) {
|
|
345
|
-
if (result.isErr() && acc.isErr()) {
|
|
346
|
-
acc.error.push(result.error);
|
|
347
|
-
} else if (result.isErr() && acc.isOk()) {
|
|
348
|
-
acc = err([result.error]);
|
|
349
|
-
} else if (result.isOk() && acc.isOk()) {
|
|
350
|
-
acc.value.push(result.value);
|
|
351
|
-
}
|
|
352
|
-
}
|
|
353
|
-
return acc;
|
|
354
|
-
};
|
|
355
|
-
var combineResultAsyncListWithAllErrors = (asyncResultList) => ResultAsync.fromSafePromise(Promise.all(asyncResultList)).andThen(combineResultListWithAllErrors);
|
|
356
|
-
exports2.Result = undefined;
|
|
357
|
-
(function(Result) {
|
|
358
|
-
function fromThrowable2(fn, errorFn) {
|
|
359
|
-
return (...args) => {
|
|
360
|
-
try {
|
|
361
|
-
const result = fn(...args);
|
|
362
|
-
return ok(result);
|
|
363
|
-
} catch (e) {
|
|
364
|
-
return err(errorFn ? errorFn(e) : e);
|
|
365
|
-
}
|
|
366
|
-
};
|
|
367
|
-
}
|
|
368
|
-
Result.fromThrowable = fromThrowable2;
|
|
369
|
-
function combine(resultList) {
|
|
370
|
-
return combineResultList(resultList);
|
|
371
|
-
}
|
|
372
|
-
Result.combine = combine;
|
|
373
|
-
function combineWithAllErrors(resultList) {
|
|
374
|
-
return combineResultListWithAllErrors(resultList);
|
|
375
|
-
}
|
|
376
|
-
Result.combineWithAllErrors = combineWithAllErrors;
|
|
377
|
-
})(exports2.Result || (exports2.Result = {}));
|
|
378
|
-
function ok(value) {
|
|
379
|
-
return new Ok(value);
|
|
380
|
-
}
|
|
381
|
-
function err(err2) {
|
|
382
|
-
return new Err(err2);
|
|
383
|
-
}
|
|
384
|
-
function safeTry(body) {
|
|
385
|
-
const n = body().next();
|
|
386
|
-
if (n instanceof Promise) {
|
|
387
|
-
return new ResultAsync(n.then((r) => r.value));
|
|
388
|
-
}
|
|
389
|
-
return n.value;
|
|
390
|
-
}
|
|
391
|
-
|
|
392
|
-
class Ok {
|
|
393
|
-
constructor(value) {
|
|
394
|
-
this.value = value;
|
|
395
|
-
}
|
|
396
|
-
isOk() {
|
|
397
|
-
return true;
|
|
398
|
-
}
|
|
399
|
-
isErr() {
|
|
400
|
-
return !this.isOk();
|
|
401
|
-
}
|
|
402
|
-
map(f) {
|
|
403
|
-
return ok(f(this.value));
|
|
404
|
-
}
|
|
405
|
-
mapErr(_f) {
|
|
406
|
-
return ok(this.value);
|
|
407
|
-
}
|
|
408
|
-
andThen(f) {
|
|
409
|
-
return f(this.value);
|
|
410
|
-
}
|
|
411
|
-
andThrough(f) {
|
|
412
|
-
return f(this.value).map((_value) => this.value);
|
|
413
|
-
}
|
|
414
|
-
andTee(f) {
|
|
415
|
-
try {
|
|
416
|
-
f(this.value);
|
|
417
|
-
} catch (e) {}
|
|
418
|
-
return ok(this.value);
|
|
419
|
-
}
|
|
420
|
-
orTee(_f) {
|
|
421
|
-
return ok(this.value);
|
|
422
|
-
}
|
|
423
|
-
orElse(_f) {
|
|
424
|
-
return ok(this.value);
|
|
425
|
-
}
|
|
426
|
-
asyncAndThen(f) {
|
|
427
|
-
return f(this.value);
|
|
428
|
-
}
|
|
429
|
-
asyncAndThrough(f) {
|
|
430
|
-
return f(this.value).map(() => this.value);
|
|
431
|
-
}
|
|
432
|
-
asyncMap(f) {
|
|
433
|
-
return ResultAsync.fromSafePromise(f(this.value));
|
|
434
|
-
}
|
|
435
|
-
unwrapOr(_v) {
|
|
436
|
-
return this.value;
|
|
437
|
-
}
|
|
438
|
-
match(ok2, _err) {
|
|
439
|
-
return ok2(this.value);
|
|
440
|
-
}
|
|
441
|
-
safeUnwrap() {
|
|
442
|
-
const value = this.value;
|
|
443
|
-
return function* () {
|
|
444
|
-
return value;
|
|
445
|
-
}();
|
|
446
|
-
}
|
|
447
|
-
_unsafeUnwrap(_) {
|
|
448
|
-
return this.value;
|
|
449
|
-
}
|
|
450
|
-
_unsafeUnwrapErr(config) {
|
|
451
|
-
throw createNeverThrowError("Called `_unsafeUnwrapErr` on an Ok", this, config);
|
|
452
|
-
}
|
|
453
|
-
*[Symbol.iterator]() {
|
|
454
|
-
return this.value;
|
|
455
|
-
}
|
|
456
|
-
}
|
|
457
|
-
|
|
458
|
-
class Err {
|
|
459
|
-
constructor(error) {
|
|
460
|
-
this.error = error;
|
|
461
|
-
}
|
|
462
|
-
isOk() {
|
|
463
|
-
return false;
|
|
464
|
-
}
|
|
465
|
-
isErr() {
|
|
466
|
-
return !this.isOk();
|
|
467
|
-
}
|
|
468
|
-
map(_f) {
|
|
469
|
-
return err(this.error);
|
|
470
|
-
}
|
|
471
|
-
mapErr(f) {
|
|
472
|
-
return err(f(this.error));
|
|
473
|
-
}
|
|
474
|
-
andThrough(_f) {
|
|
475
|
-
return err(this.error);
|
|
476
|
-
}
|
|
477
|
-
andTee(_f) {
|
|
478
|
-
return err(this.error);
|
|
479
|
-
}
|
|
480
|
-
orTee(f) {
|
|
481
|
-
try {
|
|
482
|
-
f(this.error);
|
|
483
|
-
} catch (e) {}
|
|
484
|
-
return err(this.error);
|
|
485
|
-
}
|
|
486
|
-
andThen(_f) {
|
|
487
|
-
return err(this.error);
|
|
488
|
-
}
|
|
489
|
-
orElse(f) {
|
|
490
|
-
return f(this.error);
|
|
491
|
-
}
|
|
492
|
-
asyncAndThen(_f) {
|
|
493
|
-
return errAsync(this.error);
|
|
494
|
-
}
|
|
495
|
-
asyncAndThrough(_f) {
|
|
496
|
-
return errAsync(this.error);
|
|
497
|
-
}
|
|
498
|
-
asyncMap(_f) {
|
|
499
|
-
return errAsync(this.error);
|
|
500
|
-
}
|
|
501
|
-
unwrapOr(v) {
|
|
502
|
-
return v;
|
|
503
|
-
}
|
|
504
|
-
match(_ok, err2) {
|
|
505
|
-
return err2(this.error);
|
|
506
|
-
}
|
|
507
|
-
safeUnwrap() {
|
|
508
|
-
const error = this.error;
|
|
509
|
-
return function* () {
|
|
510
|
-
yield err(error);
|
|
511
|
-
throw new Error("Do not use this generator out of `safeTry`");
|
|
512
|
-
}();
|
|
513
|
-
}
|
|
514
|
-
_unsafeUnwrap(config) {
|
|
515
|
-
throw createNeverThrowError("Called `_unsafeUnwrap` on an Err", this, config);
|
|
516
|
-
}
|
|
517
|
-
_unsafeUnwrapErr(_) {
|
|
518
|
-
return this.error;
|
|
519
|
-
}
|
|
520
|
-
*[Symbol.iterator]() {
|
|
521
|
-
const self = this;
|
|
522
|
-
yield self;
|
|
523
|
-
return self;
|
|
524
|
-
}
|
|
525
|
-
}
|
|
526
|
-
var fromThrowable = exports2.Result.fromThrowable;
|
|
527
|
-
exports2.Err = Err;
|
|
528
|
-
exports2.Ok = Ok;
|
|
529
|
-
exports2.ResultAsync = ResultAsync;
|
|
530
|
-
exports2.err = err;
|
|
531
|
-
exports2.errAsync = errAsync;
|
|
532
|
-
exports2.fromAsyncThrowable = fromAsyncThrowable;
|
|
533
|
-
exports2.fromPromise = fromPromise;
|
|
534
|
-
exports2.fromSafePromise = fromSafePromise;
|
|
535
|
-
exports2.fromThrowable = fromThrowable;
|
|
536
|
-
exports2.ok = ok;
|
|
537
|
-
exports2.okAsync = okAsync;
|
|
538
|
-
exports2.safeTry = safeTry;
|
|
539
|
-
});
|
|
540
|
-
|
|
541
39
|
// src/index.ts
|
|
542
40
|
var exports_src = {};
|
|
543
41
|
__export(exports_src, {
|
|
@@ -755,6 +253,7 @@ var AckType;
|
|
|
755
253
|
AckType2[AckType2["CDC2_NACK_FILE_SYS_FULL"] = 220] = "CDC2_NACK_FILE_SYS_FULL";
|
|
756
254
|
AckType2[AckType2["TIMEOUT"] = 256] = "TIMEOUT";
|
|
757
255
|
AckType2[AckType2["WRITE_ERROR"] = 257] = "WRITE_ERROR";
|
|
256
|
+
AckType2[AckType2["NOT_CONNECTED"] = 258] = "NOT_CONNECTED";
|
|
758
257
|
})(AckType ||= {});
|
|
759
258
|
var SmartDeviceType;
|
|
760
259
|
((SmartDeviceType2) => {
|
|
@@ -850,6 +349,7 @@ var SelectDashScreen;
|
|
|
850
349
|
// src/VexError.ts
|
|
851
350
|
class VexSerialError extends Error {
|
|
852
351
|
kind;
|
|
352
|
+
ackType = undefined;
|
|
853
353
|
constructor(kind, message) {
|
|
854
354
|
super(message);
|
|
855
355
|
this.name = "VexSerialError";
|
|
@@ -872,9 +372,11 @@ class VexInvalidArgumentError extends VexSerialError {
|
|
|
872
372
|
}
|
|
873
373
|
|
|
874
374
|
class VexProtocolError extends VexSerialError {
|
|
875
|
-
|
|
375
|
+
ackType;
|
|
376
|
+
constructor(message, ackType) {
|
|
876
377
|
super("protocol", message);
|
|
877
378
|
this.name = "VexProtocolError";
|
|
379
|
+
this.ackType = ackType;
|
|
878
380
|
}
|
|
879
381
|
}
|
|
880
382
|
|
|
@@ -934,9 +436,26 @@ class VexEventEmitter {
|
|
|
934
436
|
this.handlerMap.set(eventName, listeners);
|
|
935
437
|
}
|
|
936
438
|
emit(eventName, data) {
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
439
|
+
const listeners = this.handlerMap.get(eventName);
|
|
440
|
+
if (listeners === undefined || listeners.length === 0)
|
|
441
|
+
return;
|
|
442
|
+
if (listeners.length === 1) {
|
|
443
|
+
listeners[0](data);
|
|
444
|
+
return;
|
|
445
|
+
}
|
|
446
|
+
const errors = [];
|
|
447
|
+
for (const callback of [...listeners]) {
|
|
448
|
+
try {
|
|
449
|
+
callback(data);
|
|
450
|
+
} catch (error) {
|
|
451
|
+
errors.push(error);
|
|
452
|
+
}
|
|
453
|
+
}
|
|
454
|
+
if (errors.length === 1)
|
|
455
|
+
throw errors[0];
|
|
456
|
+
if (errors.length > 1) {
|
|
457
|
+
throw new AggregateError(errors, `listeners for ${String(eventName)} failed`);
|
|
458
|
+
}
|
|
940
459
|
}
|
|
941
460
|
clearListeners() {
|
|
942
461
|
this.handlerMap.clear();
|
|
@@ -949,13 +468,13 @@ class VexEventTarget {
|
|
|
949
468
|
this.emitter = new VexEventEmitter;
|
|
950
469
|
}
|
|
951
470
|
emit(eventName, data) {
|
|
952
|
-
this.emitter.emit(
|
|
471
|
+
this.emitter.emit(eventName, data);
|
|
953
472
|
}
|
|
954
473
|
on(eventName, listener) {
|
|
955
|
-
this.emitter.on(
|
|
474
|
+
this.emitter.on(eventName, listener);
|
|
956
475
|
}
|
|
957
476
|
remove(eventName, listener) {
|
|
958
|
-
this.emitter.remove(
|
|
477
|
+
this.emitter.remove(eventName, listener);
|
|
959
478
|
}
|
|
960
479
|
clearListeners() {
|
|
961
480
|
this.emitter.clearListeners();
|
|
@@ -963,7 +482,7 @@ class VexEventTarget {
|
|
|
963
482
|
}
|
|
964
483
|
|
|
965
484
|
// src/VexConnection.ts
|
|
966
|
-
var import_neverthrow =
|
|
485
|
+
var import_neverthrow = require("neverthrow");
|
|
967
486
|
|
|
968
487
|
// src/VexPacketBase.ts
|
|
969
488
|
var MATCH_STATUS_ALT_ACK = 167;
|
|
@@ -977,42 +496,32 @@ class Packet {
|
|
|
977
496
|
}
|
|
978
497
|
|
|
979
498
|
class DeviceBoundPacket extends Packet {
|
|
499
|
+
static COMMAND_ID;
|
|
500
|
+
static COMMAND_EXTENDED_ID;
|
|
980
501
|
get commandId() {
|
|
981
502
|
return this.constructor.COMMAND_ID;
|
|
982
503
|
}
|
|
983
504
|
get commandExtendedId() {
|
|
984
505
|
return this.constructor.COMMAND_EXTENDED_ID;
|
|
985
506
|
}
|
|
986
|
-
static COMMAND_ID;
|
|
987
|
-
static COMMAND_EXTENDED_ID;
|
|
988
507
|
constructor(payload) {
|
|
989
|
-
|
|
990
|
-
const
|
|
991
|
-
|
|
992
|
-
if (payload === undefined) {
|
|
993
|
-
this.data = Packet.ENCODER.cdcCommand(me.COMMAND_ID);
|
|
994
|
-
} else {
|
|
995
|
-
this.data = Packet.ENCODER.cdcCommandWithData(me.COMMAND_ID, payload);
|
|
996
|
-
}
|
|
997
|
-
} else {
|
|
998
|
-
if (payload === undefined) {
|
|
999
|
-
this.data = Packet.ENCODER.cdc2Command(me.COMMAND_ID, me.COMMAND_EXTENDED_ID);
|
|
1000
|
-
} else {
|
|
1001
|
-
this.data = Packet.ENCODER.cdc2CommandWithData(me.COMMAND_ID, me.COMMAND_EXTENDED_ID, payload);
|
|
1002
|
-
}
|
|
1003
|
-
}
|
|
508
|
+
const { COMMAND_ID: cmd, COMMAND_EXTENDED_ID: ext } = new.target;
|
|
509
|
+
const encoder = Packet.ENCODER;
|
|
510
|
+
super(ext === undefined ? payload === undefined ? encoder.cdcCommand(cmd) : encoder.cdcCommandWithData(cmd, payload) : payload === undefined ? encoder.cdc2Command(cmd, ext) : encoder.cdc2CommandWithData(cmd, ext, payload));
|
|
1004
511
|
}
|
|
1005
512
|
}
|
|
1006
513
|
|
|
1007
514
|
class HostBoundPacket extends Packet {
|
|
1008
|
-
|
|
515
|
+
static COMMAND_ID;
|
|
516
|
+
static COMMAND_EXTENDED_ID;
|
|
517
|
+
ack;
|
|
1009
518
|
payloadSize;
|
|
1010
519
|
ackIndex;
|
|
1011
520
|
constructor(data) {
|
|
1012
521
|
super(data);
|
|
1013
522
|
this.payloadSize = Packet.ENCODER.getPayloadSize(this.data);
|
|
1014
|
-
|
|
1015
|
-
this.ack = this.data[this.ackIndex
|
|
523
|
+
this.ackIndex = Packet.ENCODER.getHostHeaderLength(this.data) + 1;
|
|
524
|
+
this.ack = this.data[this.ackIndex];
|
|
1016
525
|
}
|
|
1017
526
|
static isValidPacket(data, n) {
|
|
1018
527
|
const ack = data[n + 1];
|
|
@@ -1021,385 +530,162 @@ class HostBoundPacket extends Packet {
|
|
|
1021
530
|
}
|
|
1022
531
|
|
|
1023
532
|
// src/VexCRC.ts
|
|
1024
|
-
var
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
33560,
|
|
1051
|
-
45947,
|
|
1052
|
-
41818,
|
|
1053
|
-
54205,
|
|
1054
|
-
50076,
|
|
1055
|
-
62463,
|
|
1056
|
-
58334,
|
|
1057
|
-
9314,
|
|
1058
|
-
13379,
|
|
1059
|
-
1056,
|
|
1060
|
-
5121,
|
|
1061
|
-
25830,
|
|
1062
|
-
29895,
|
|
1063
|
-
17572,
|
|
1064
|
-
21637,
|
|
1065
|
-
42346,
|
|
1066
|
-
46411,
|
|
1067
|
-
34088,
|
|
1068
|
-
38153,
|
|
1069
|
-
58862,
|
|
1070
|
-
62927,
|
|
1071
|
-
50604,
|
|
1072
|
-
54669,
|
|
1073
|
-
13907,
|
|
1074
|
-
9842,
|
|
1075
|
-
5649,
|
|
1076
|
-
1584,
|
|
1077
|
-
30423,
|
|
1078
|
-
26358,
|
|
1079
|
-
22165,
|
|
1080
|
-
18100,
|
|
1081
|
-
46939,
|
|
1082
|
-
42874,
|
|
1083
|
-
38681,
|
|
1084
|
-
34616,
|
|
1085
|
-
63455,
|
|
1086
|
-
59390,
|
|
1087
|
-
55197,
|
|
1088
|
-
51132,
|
|
1089
|
-
18628,
|
|
1090
|
-
22757,
|
|
1091
|
-
26758,
|
|
1092
|
-
30887,
|
|
1093
|
-
2112,
|
|
1094
|
-
6241,
|
|
1095
|
-
10242,
|
|
1096
|
-
14371,
|
|
1097
|
-
51660,
|
|
1098
|
-
55789,
|
|
1099
|
-
59790,
|
|
1100
|
-
63919,
|
|
1101
|
-
35144,
|
|
1102
|
-
39273,
|
|
1103
|
-
43274,
|
|
1104
|
-
47403,
|
|
1105
|
-
23285,
|
|
1106
|
-
19156,
|
|
1107
|
-
31415,
|
|
1108
|
-
27286,
|
|
1109
|
-
6769,
|
|
1110
|
-
2640,
|
|
1111
|
-
14899,
|
|
1112
|
-
10770,
|
|
1113
|
-
56317,
|
|
1114
|
-
52188,
|
|
1115
|
-
64447,
|
|
1116
|
-
60318,
|
|
1117
|
-
39801,
|
|
1118
|
-
35672,
|
|
1119
|
-
47931,
|
|
1120
|
-
43802,
|
|
1121
|
-
27814,
|
|
1122
|
-
31879,
|
|
1123
|
-
19684,
|
|
1124
|
-
23749,
|
|
1125
|
-
11298,
|
|
1126
|
-
15363,
|
|
1127
|
-
3168,
|
|
1128
|
-
7233,
|
|
1129
|
-
60846,
|
|
1130
|
-
64911,
|
|
1131
|
-
52716,
|
|
1132
|
-
56781,
|
|
1133
|
-
44330,
|
|
1134
|
-
48395,
|
|
1135
|
-
36200,
|
|
1136
|
-
40265,
|
|
1137
|
-
32407,
|
|
1138
|
-
28342,
|
|
1139
|
-
24277,
|
|
1140
|
-
20212,
|
|
1141
|
-
15891,
|
|
1142
|
-
11826,
|
|
1143
|
-
7761,
|
|
1144
|
-
3696,
|
|
1145
|
-
65439,
|
|
1146
|
-
61374,
|
|
1147
|
-
57309,
|
|
1148
|
-
53244,
|
|
1149
|
-
48923,
|
|
1150
|
-
44858,
|
|
1151
|
-
40793,
|
|
1152
|
-
36728,
|
|
1153
|
-
37256,
|
|
1154
|
-
33193,
|
|
1155
|
-
45514,
|
|
1156
|
-
41451,
|
|
1157
|
-
53516,
|
|
1158
|
-
49453,
|
|
1159
|
-
61774,
|
|
1160
|
-
57711,
|
|
1161
|
-
4224,
|
|
1162
|
-
161,
|
|
1163
|
-
12482,
|
|
1164
|
-
8419,
|
|
1165
|
-
20484,
|
|
1166
|
-
16421,
|
|
1167
|
-
28742,
|
|
1168
|
-
24679,
|
|
1169
|
-
33721,
|
|
1170
|
-
37784,
|
|
1171
|
-
41979,
|
|
1172
|
-
46042,
|
|
1173
|
-
49981,
|
|
1174
|
-
54044,
|
|
1175
|
-
58239,
|
|
1176
|
-
62302,
|
|
1177
|
-
689,
|
|
1178
|
-
4752,
|
|
1179
|
-
8947,
|
|
1180
|
-
13010,
|
|
1181
|
-
16949,
|
|
1182
|
-
21012,
|
|
1183
|
-
25207,
|
|
1184
|
-
29270,
|
|
1185
|
-
46570,
|
|
1186
|
-
42443,
|
|
1187
|
-
38312,
|
|
1188
|
-
34185,
|
|
1189
|
-
62830,
|
|
1190
|
-
58703,
|
|
1191
|
-
54572,
|
|
1192
|
-
50445,
|
|
1193
|
-
13538,
|
|
1194
|
-
9411,
|
|
1195
|
-
5280,
|
|
1196
|
-
1153,
|
|
1197
|
-
29798,
|
|
1198
|
-
25671,
|
|
1199
|
-
21540,
|
|
1200
|
-
17413,
|
|
1201
|
-
42971,
|
|
1202
|
-
47098,
|
|
1203
|
-
34713,
|
|
1204
|
-
38840,
|
|
1205
|
-
59231,
|
|
1206
|
-
63358,
|
|
1207
|
-
50973,
|
|
1208
|
-
55100,
|
|
1209
|
-
9939,
|
|
1210
|
-
14066,
|
|
1211
|
-
1681,
|
|
1212
|
-
5808,
|
|
1213
|
-
26199,
|
|
1214
|
-
30326,
|
|
1215
|
-
17941,
|
|
1216
|
-
22068,
|
|
1217
|
-
55628,
|
|
1218
|
-
51565,
|
|
1219
|
-
63758,
|
|
1220
|
-
59695,
|
|
1221
|
-
39368,
|
|
1222
|
-
35305,
|
|
1223
|
-
47498,
|
|
1224
|
-
43435,
|
|
1225
|
-
22596,
|
|
1226
|
-
18533,
|
|
1227
|
-
30726,
|
|
1228
|
-
26663,
|
|
1229
|
-
6336,
|
|
1230
|
-
2273,
|
|
1231
|
-
14466,
|
|
1232
|
-
10403,
|
|
1233
|
-
52093,
|
|
1234
|
-
56156,
|
|
1235
|
-
60223,
|
|
1236
|
-
64286,
|
|
1237
|
-
35833,
|
|
1238
|
-
39896,
|
|
1239
|
-
43963,
|
|
1240
|
-
48026,
|
|
1241
|
-
19061,
|
|
1242
|
-
23124,
|
|
1243
|
-
27191,
|
|
1244
|
-
31254,
|
|
1245
|
-
2801,
|
|
1246
|
-
6864,
|
|
1247
|
-
10931,
|
|
1248
|
-
14994,
|
|
1249
|
-
64814,
|
|
1250
|
-
60687,
|
|
1251
|
-
56684,
|
|
1252
|
-
52557,
|
|
1253
|
-
48554,
|
|
1254
|
-
44427,
|
|
1255
|
-
40424,
|
|
1256
|
-
36297,
|
|
1257
|
-
31782,
|
|
1258
|
-
27655,
|
|
1259
|
-
23652,
|
|
1260
|
-
19525,
|
|
1261
|
-
15522,
|
|
1262
|
-
11395,
|
|
1263
|
-
7392,
|
|
1264
|
-
3265,
|
|
1265
|
-
61215,
|
|
1266
|
-
65342,
|
|
1267
|
-
53085,
|
|
1268
|
-
57212,
|
|
1269
|
-
44955,
|
|
1270
|
-
49082,
|
|
1271
|
-
36825,
|
|
1272
|
-
40952,
|
|
1273
|
-
28183,
|
|
1274
|
-
32310,
|
|
1275
|
-
20053,
|
|
1276
|
-
24180,
|
|
1277
|
-
11923,
|
|
1278
|
-
16050,
|
|
1279
|
-
3793,
|
|
1280
|
-
7920
|
|
1281
|
-
];
|
|
533
|
+
var POLYNOMIAL_CRC32 = 79764919;
|
|
534
|
+
var POLYNOMIAL_CRC16 = 4129;
|
|
535
|
+
function genTable16() {
|
|
536
|
+
const table = new Uint16Array(256);
|
|
537
|
+
for (let i = 0;i < 256; i++) {
|
|
538
|
+
let acc = i << 8;
|
|
539
|
+
for (let j = 0;j < 8; j++) {
|
|
540
|
+
acc = (acc & 32768) !== 0 ? acc << 1 ^ POLYNOMIAL_CRC16 : acc << 1;
|
|
541
|
+
}
|
|
542
|
+
table[i] = acc & 65535;
|
|
543
|
+
}
|
|
544
|
+
return table;
|
|
545
|
+
}
|
|
546
|
+
function genTable32() {
|
|
547
|
+
const table = new Uint32Array(256);
|
|
548
|
+
for (let i = 0;i < 256; i++) {
|
|
549
|
+
let acc = i << 24;
|
|
550
|
+
for (let j = 0;j < 8; j++) {
|
|
551
|
+
acc = (acc & 2147483648) !== 0 ? acc << 1 ^ POLYNOMIAL_CRC32 : acc << 1;
|
|
552
|
+
}
|
|
553
|
+
table[i] = acc;
|
|
554
|
+
}
|
|
555
|
+
return table;
|
|
556
|
+
}
|
|
557
|
+
var CRC16_TABLE = genTable16();
|
|
558
|
+
var CRC32_TABLE = genTable32();
|
|
1282
559
|
|
|
1283
560
|
class CrcGenerator {
|
|
1284
|
-
crc32Table;
|
|
1285
|
-
static POLYNOMIAL_CRC32 =
|
|
1286
|
-
static POLYNOMIAL_CRC16 =
|
|
1287
|
-
constructor() {
|
|
1288
|
-
this.crc32Table = new Uint32Array(256);
|
|
1289
|
-
this.crc32GenTable();
|
|
1290
|
-
}
|
|
561
|
+
crc32Table = CRC32_TABLE;
|
|
562
|
+
static POLYNOMIAL_CRC32 = POLYNOMIAL_CRC32;
|
|
563
|
+
static POLYNOMIAL_CRC16 = POLYNOMIAL_CRC16;
|
|
1291
564
|
crc16(buf, initValue) {
|
|
1292
|
-
|
|
1293
|
-
let
|
|
1294
|
-
|
|
1295
|
-
let j;
|
|
1296
|
-
for (j = 0;j < numberOfBytes; j++) {
|
|
1297
|
-
i = (accumulator >>> 8 ^ buf[j]) & 255;
|
|
1298
|
-
accumulator = (accumulator << 8 ^ CRC16TABLE[i]) >>> 0;
|
|
1299
|
-
}
|
|
1300
|
-
return (accumulator & 65535) >>> 0;
|
|
1301
|
-
}
|
|
1302
|
-
crc32GenTable() {
|
|
1303
|
-
let i;
|
|
1304
|
-
let j;
|
|
1305
|
-
let crcAccumulator;
|
|
1306
|
-
for (i = 0;i < 256; i++) {
|
|
1307
|
-
crcAccumulator = i << 24;
|
|
1308
|
-
for (j = 0;j < 8; j++) {
|
|
1309
|
-
if ((crcAccumulator & 2147483648) !== 0)
|
|
1310
|
-
crcAccumulator = crcAccumulator << 1 ^ CrcGenerator.POLYNOMIAL_CRC32;
|
|
1311
|
-
else
|
|
1312
|
-
crcAccumulator = crcAccumulator << 1;
|
|
1313
|
-
}
|
|
1314
|
-
this.crc32Table[i] = crcAccumulator;
|
|
565
|
+
let acc = initValue;
|
|
566
|
+
for (let j = 0;j < buf.length; j++) {
|
|
567
|
+
acc = (acc << 8 ^ CRC16_TABLE[(acc >>> 8 ^ buf[j]) & 255]) >>> 0;
|
|
1315
568
|
}
|
|
569
|
+
return acc & 65535;
|
|
1316
570
|
}
|
|
1317
571
|
crc32(buf, initValue) {
|
|
1318
|
-
|
|
1319
|
-
let
|
|
1320
|
-
|
|
1321
|
-
let j;
|
|
1322
|
-
for (j = 0;j < numberOfBytes; j++) {
|
|
1323
|
-
i = (crcAccumulator >>> 24 ^ buf[j]) & 255;
|
|
1324
|
-
crcAccumulator = (crcAccumulator << 8 ^ this.crc32Table[i]) >>> 0;
|
|
572
|
+
let acc = initValue;
|
|
573
|
+
for (let j = 0;j < buf.length; j++) {
|
|
574
|
+
acc = (acc << 8 ^ CRC32_TABLE[(acc >>> 24 ^ buf[j]) & 255]) >>> 0;
|
|
1325
575
|
}
|
|
1326
|
-
return
|
|
576
|
+
return acc >>> 0;
|
|
1327
577
|
}
|
|
1328
578
|
}
|
|
1329
579
|
|
|
1330
|
-
// src/
|
|
1331
|
-
var
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
}
|
|
580
|
+
// src/VexPacketEncoder.ts
|
|
581
|
+
var textEncoder = new TextEncoder;
|
|
582
|
+
var HEADER_TO_DEVICE = Uint8Array.of(201, 54, 184, 71);
|
|
583
|
+
function encodeFixedText(value, field, maxBytes) {
|
|
584
|
+
const encoded = textEncoder.encode(value);
|
|
585
|
+
if (encoded.byteLength > maxBytes) {
|
|
586
|
+
throw new RangeError(`${field} must be at most ${maxBytes} UTF-8 bytes`);
|
|
587
|
+
}
|
|
588
|
+
return encoded;
|
|
589
|
+
}
|
|
590
|
+
|
|
591
|
+
class PacketEncoder {
|
|
592
|
+
static HEADERS_LENGTH = 4;
|
|
593
|
+
static HEADER_TO_DEVICE = [201, 54, 184, 71];
|
|
594
|
+
static HEADER_TO_HOST = [170, 85];
|
|
595
|
+
static J2000_EPOCH = 946684800;
|
|
596
|
+
vexVersion = 0;
|
|
597
|
+
crcgen = new CrcGenerator;
|
|
598
|
+
allPacketsTable = new Map;
|
|
599
|
+
static getInstance() {
|
|
600
|
+
Packet.ENCODER ??= new PacketEncoder;
|
|
601
|
+
return Packet.ENCODER;
|
|
602
|
+
}
|
|
603
|
+
constructor() {}
|
|
604
|
+
registerPacketTypes(types) {
|
|
605
|
+
for (const type of types) {
|
|
606
|
+
let byExtendedId = this.allPacketsTable.get(type.COMMAND_ID);
|
|
607
|
+
if (byExtendedId === undefined) {
|
|
608
|
+
byExtendedId = new Map;
|
|
609
|
+
this.allPacketsTable.set(type.COMMAND_ID, byExtendedId);
|
|
610
|
+
}
|
|
611
|
+
byExtendedId.set(type.COMMAND_EXTENDED_ID, type);
|
|
612
|
+
}
|
|
613
|
+
}
|
|
614
|
+
getPacketType(commandId, commandExtendedId) {
|
|
615
|
+
if (commandId === undefined)
|
|
616
|
+
return;
|
|
617
|
+
return this.allPacketsTable.get(commandId)?.get(commandExtendedId);
|
|
618
|
+
}
|
|
619
|
+
createHeader(buf) {
|
|
620
|
+
if (buf === undefined || buf.byteLength < PacketEncoder.HEADERS_LENGTH) {
|
|
621
|
+
buf = new ArrayBuffer(PacketEncoder.HEADERS_LENGTH);
|
|
622
|
+
}
|
|
623
|
+
const h = new Uint8Array(buf);
|
|
624
|
+
h.set(HEADER_TO_DEVICE);
|
|
625
|
+
return h;
|
|
626
|
+
}
|
|
627
|
+
cdcCommand(cmd) {
|
|
628
|
+
const h = new Uint8Array(5);
|
|
629
|
+
h.set(HEADER_TO_DEVICE);
|
|
630
|
+
h[4] = cmd;
|
|
631
|
+
return h;
|
|
632
|
+
}
|
|
633
|
+
cdcCommandWithData(cmd, data) {
|
|
634
|
+
const h = new Uint8Array(6 + data.length);
|
|
635
|
+
h.set(HEADER_TO_DEVICE);
|
|
636
|
+
h[4] = cmd;
|
|
637
|
+
h[5] = data.length;
|
|
638
|
+
h.set(data, 6);
|
|
639
|
+
return h;
|
|
640
|
+
}
|
|
641
|
+
cdc2Command(cmd, ext) {
|
|
642
|
+
const h = new Uint8Array(9);
|
|
643
|
+
h.set(HEADER_TO_DEVICE);
|
|
644
|
+
h[4] = cmd;
|
|
645
|
+
h[5] = ext;
|
|
646
|
+
h[6] = 0;
|
|
647
|
+
this.appendCrc16(h);
|
|
648
|
+
return h;
|
|
649
|
+
}
|
|
650
|
+
cdc2CommandBufferLength(data) {
|
|
651
|
+
return PacketEncoder.HEADERS_LENGTH + data.length + 5 + (data.length > 127 ? 1 : 0);
|
|
652
|
+
}
|
|
653
|
+
cdc2CommandWithData(cmd, ext, data) {
|
|
654
|
+
const h = new Uint8Array(this.cdc2CommandBufferLength(data));
|
|
655
|
+
h.set(HEADER_TO_DEVICE);
|
|
656
|
+
h[4] = cmd;
|
|
657
|
+
h[5] = ext;
|
|
658
|
+
if (data.length < 128) {
|
|
659
|
+
h[6] = data.length;
|
|
660
|
+
h.set(data, 7);
|
|
661
|
+
} else {
|
|
662
|
+
h[6] = data.length >>> 8 | 128;
|
|
663
|
+
h[7] = data.length & 255;
|
|
664
|
+
h.set(data, 8);
|
|
665
|
+
}
|
|
666
|
+
this.appendCrc16(h);
|
|
667
|
+
return h;
|
|
668
|
+
}
|
|
669
|
+
appendCrc16(h) {
|
|
670
|
+
const crc = this.crcgen.crc16(h.subarray(0, h.length - 2), 0);
|
|
671
|
+
h[h.length - 2] = crc >>> 8;
|
|
672
|
+
h[h.length - 1] = crc & 255;
|
|
673
|
+
}
|
|
674
|
+
validateHeader(data) {
|
|
675
|
+
return data[0] === PacketEncoder.HEADER_TO_HOST[0] && data[1] === PacketEncoder.HEADER_TO_HOST[1];
|
|
676
|
+
}
|
|
677
|
+
validateMessageCdc(data) {
|
|
678
|
+
const crc = (data[data.byteLength - 2] << 8) + data[data.byteLength - 1];
|
|
679
|
+
return this.crcgen.crc16(data.subarray(0, data.byteLength - 2), 0) === crc;
|
|
680
|
+
}
|
|
681
|
+
getPayloadSize(data) {
|
|
682
|
+
const a = data[3];
|
|
683
|
+
return (a & 128) === 0 ? a : ((a & 127) << 8) + data[4];
|
|
684
|
+
}
|
|
685
|
+
getHostHeaderLength(data) {
|
|
686
|
+
return (data[3] & 128) === 0 ? 4 : 5;
|
|
687
|
+
}
|
|
688
|
+
}
|
|
1403
689
|
|
|
1404
690
|
// src/VexFirmwareVersion.ts
|
|
1405
691
|
class VexFirmwareVersion {
|
|
@@ -1415,9 +701,8 @@ class VexFirmwareVersion {
|
|
|
1415
701
|
}
|
|
1416
702
|
static fromString(version) {
|
|
1417
703
|
const parts = version.toLowerCase().replace(/b/g, "").split(".").map((x) => parseInt(x, 10));
|
|
1418
|
-
while (parts.length < 4)
|
|
704
|
+
while (parts.length < 4)
|
|
1419
705
|
parts.push(0);
|
|
1420
|
-
}
|
|
1421
706
|
return new VexFirmwareVersion(parts[0], parts[1], parts[2], parts[3]);
|
|
1422
707
|
}
|
|
1423
708
|
static fromUint8Array(data, offset = 0, reverse = false) {
|
|
@@ -1447,24 +732,23 @@ class VexFirmwareVersion {
|
|
|
1447
732
|
return `${this.toUserString()}.b${this.beta}`;
|
|
1448
733
|
}
|
|
1449
734
|
compare(that) {
|
|
1450
|
-
const
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
return buildComp;
|
|
1460
|
-
} else if (betaComp !== 0) {
|
|
1461
|
-
return betaComp;
|
|
735
|
+
for (const [a, b] of [
|
|
736
|
+
[this.major, that.major],
|
|
737
|
+
[this.minor, that.minor],
|
|
738
|
+
[this.build, that.build],
|
|
739
|
+
[this.beta, that.beta]
|
|
740
|
+
]) {
|
|
741
|
+
const delta = a - b;
|
|
742
|
+
if (delta !== 0)
|
|
743
|
+
return delta;
|
|
1462
744
|
}
|
|
1463
745
|
return 0;
|
|
1464
746
|
}
|
|
1465
747
|
}
|
|
1466
748
|
|
|
1467
749
|
// src/VexPacketView.ts
|
|
750
|
+
var textDecoder = new TextDecoder("UTF-8");
|
|
751
|
+
|
|
1468
752
|
class PacketView extends DataView {
|
|
1469
753
|
position = 0;
|
|
1470
754
|
littleEndianDefault = true;
|
|
@@ -1472,19 +756,15 @@ class PacketView extends DataView {
|
|
|
1472
756
|
super(buffer, offset, length);
|
|
1473
757
|
}
|
|
1474
758
|
static fromPacket(packet) {
|
|
1475
|
-
const view = new PacketView(packet.data.buffer, packet.data.byteOffset);
|
|
759
|
+
const view = new PacketView(packet.data.buffer, packet.data.byteOffset, packet.data.byteLength);
|
|
1476
760
|
view.position = packet.ackIndex + 1;
|
|
1477
761
|
return view;
|
|
1478
762
|
}
|
|
1479
763
|
nextInt8() {
|
|
1480
|
-
|
|
1481
|
-
this.position += 1;
|
|
1482
|
-
return result;
|
|
764
|
+
return this.getInt8(this.position++);
|
|
1483
765
|
}
|
|
1484
766
|
nextUint8() {
|
|
1485
|
-
|
|
1486
|
-
this.position += 1;
|
|
1487
|
-
return result;
|
|
767
|
+
return this.getUint8(this.position++);
|
|
1488
768
|
}
|
|
1489
769
|
nextInt16(littleEndian = this.littleEndianDefault) {
|
|
1490
770
|
const result = this.getInt16(this.position, littleEndian);
|
|
@@ -1507,37 +787,28 @@ class PacketView extends DataView {
|
|
|
1507
787
|
return result;
|
|
1508
788
|
}
|
|
1509
789
|
nextString(length) {
|
|
1510
|
-
|
|
1511
|
-
|
|
1512
|
-
result += String.fromCharCode(this.nextUint8());
|
|
1513
|
-
}
|
|
790
|
+
const result = textDecoder.decode(new Uint8Array(this.buffer, this.byteOffset + this.position, length));
|
|
791
|
+
this.position += length;
|
|
1514
792
|
return result;
|
|
1515
793
|
}
|
|
1516
794
|
nextNTBS(length) {
|
|
1517
|
-
|
|
1518
|
-
const
|
|
1519
|
-
|
|
1520
|
-
if (this.byteLength <= this.position)
|
|
1521
|
-
break;
|
|
1522
|
-
const g = this.nextUint8();
|
|
1523
|
-
if (g === 0)
|
|
1524
|
-
break;
|
|
1525
|
-
result += String.fromCharCode(g);
|
|
1526
|
-
}
|
|
1527
|
-
this.position = lastPosition + length;
|
|
795
|
+
const start = this.position;
|
|
796
|
+
const result = this.nextVarNTBS(length);
|
|
797
|
+
this.position = start + length;
|
|
1528
798
|
return result;
|
|
1529
799
|
}
|
|
1530
800
|
nextVarNTBS(length) {
|
|
1531
|
-
|
|
801
|
+
const start = this.position;
|
|
802
|
+
let byteLength = 0;
|
|
1532
803
|
for (let i = 0;i < length; i++) {
|
|
1533
804
|
if (this.byteLength <= this.position)
|
|
1534
805
|
break;
|
|
1535
806
|
const g = this.nextUint8();
|
|
1536
807
|
if (g === 0)
|
|
1537
808
|
break;
|
|
1538
|
-
|
|
809
|
+
byteLength++;
|
|
1539
810
|
}
|
|
1540
|
-
return
|
|
811
|
+
return textDecoder.decode(new Uint8Array(this.buffer, this.byteOffset + start, byteLength));
|
|
1541
812
|
}
|
|
1542
813
|
nextVersion(reverse = false) {
|
|
1543
814
|
const result = VexFirmwareVersion.fromUint8Array(new Uint8Array(this.buffer, this.byteOffset, this.byteLength), this.position, reverse);
|
|
@@ -1547,43 +818,34 @@ class PacketView extends DataView {
|
|
|
1547
818
|
}
|
|
1548
819
|
|
|
1549
820
|
// src/VexPacketModels.ts
|
|
1550
|
-
var
|
|
821
|
+
var textEncoder2 = new TextEncoder;
|
|
822
|
+
function filePayload(a, b, fileName) {
|
|
823
|
+
const payload = new Uint8Array(26);
|
|
824
|
+
payload[0] = a;
|
|
825
|
+
payload[1] = b;
|
|
826
|
+
payload.set(encodeFixedText(fileName, "Filename", 24), 2);
|
|
827
|
+
return payload;
|
|
828
|
+
}
|
|
829
|
+
var clamp100 = (value) => value !== undefined && value > 100 ? 100 : value;
|
|
1551
830
|
|
|
1552
831
|
class Query1H2DPacket extends DeviceBoundPacket {
|
|
1553
832
|
static COMMAND_ID = 33;
|
|
1554
833
|
static COMMAND_EXTENDED_ID = undefined;
|
|
1555
|
-
constructor() {
|
|
1556
|
-
super(undefined);
|
|
1557
|
-
}
|
|
1558
834
|
}
|
|
1559
835
|
|
|
1560
836
|
class SystemVersionH2DPacket extends DeviceBoundPacket {
|
|
1561
837
|
static COMMAND_ID = 164;
|
|
1562
838
|
static COMMAND_EXTENDED_ID = undefined;
|
|
1563
|
-
constructor() {
|
|
1564
|
-
super(undefined);
|
|
1565
|
-
}
|
|
1566
839
|
}
|
|
1567
840
|
|
|
1568
841
|
class UpdateMatchModeH2DPacket extends DeviceBoundPacket {
|
|
1569
842
|
static COMMAND_ID = 88;
|
|
1570
843
|
static COMMAND_EXTENDED_ID = 193;
|
|
1571
844
|
constructor(mode, matchClock) {
|
|
1572
|
-
|
|
1573
|
-
switch (mode) {
|
|
1574
|
-
case "autonomous":
|
|
1575
|
-
bit1 = 10;
|
|
1576
|
-
break;
|
|
1577
|
-
case "driver":
|
|
1578
|
-
bit1 = 8;
|
|
1579
|
-
break;
|
|
1580
|
-
case "disabled":
|
|
1581
|
-
bit1 = 11;
|
|
1582
|
-
}
|
|
845
|
+
const bit1 = mode === "autonomous" ? 10 : mode === "driver" ? 8 : 11;
|
|
1583
846
|
const payload = new Uint8Array(5);
|
|
1584
|
-
|
|
1585
|
-
|
|
1586
|
-
view.setUint32(1, matchClock, true);
|
|
847
|
+
payload[0] = bit1 & 15;
|
|
848
|
+
new DataView(payload.buffer).setUint32(1, matchClock, true);
|
|
1587
849
|
super(payload);
|
|
1588
850
|
}
|
|
1589
851
|
}
|
|
@@ -1591,18 +853,13 @@ class UpdateMatchModeH2DPacket extends DeviceBoundPacket {
|
|
|
1591
853
|
class GetMatchStatusH2DPacket extends DeviceBoundPacket {
|
|
1592
854
|
static COMMAND_ID = 88;
|
|
1593
855
|
static COMMAND_EXTENDED_ID = 194;
|
|
1594
|
-
constructor() {
|
|
1595
|
-
super(undefined);
|
|
1596
|
-
}
|
|
1597
856
|
}
|
|
1598
857
|
|
|
1599
858
|
class GetRadioModeH2DPacket extends DeviceBoundPacket {
|
|
1600
859
|
static COMMAND_ID = 88;
|
|
1601
860
|
static COMMAND_EXTENDED_ID = 65;
|
|
1602
861
|
constructor(mode) {
|
|
1603
|
-
|
|
1604
|
-
payload[0] = mode;
|
|
1605
|
-
super(payload);
|
|
862
|
+
super(Uint8Array.of(mode));
|
|
1606
863
|
}
|
|
1607
864
|
}
|
|
1608
865
|
|
|
@@ -1610,9 +867,7 @@ class FileControlH2DPacket extends DeviceBoundPacket {
|
|
|
1610
867
|
static COMMAND_ID = 86;
|
|
1611
868
|
static COMMAND_EXTENDED_ID = 16;
|
|
1612
869
|
constructor(a, b) {
|
|
1613
|
-
|
|
1614
|
-
payload.set([a, b], 0);
|
|
1615
|
-
super(payload);
|
|
870
|
+
super(Uint8Array.of(a, b));
|
|
1616
871
|
}
|
|
1617
872
|
}
|
|
1618
873
|
|
|
@@ -1622,25 +877,21 @@ class InitFileTransferH2DPacket extends DeviceBoundPacket {
|
|
|
1622
877
|
constructor(operation, target, vendor, options, binary, addr, name, type, version = new VexFirmwareVersion(1, 0, 0, 0)) {
|
|
1623
878
|
const payload = new Uint8Array(52);
|
|
1624
879
|
const view = new DataView(payload.buffer);
|
|
1625
|
-
|
|
1626
|
-
|
|
1627
|
-
|
|
1628
|
-
|
|
880
|
+
payload[0] = operation;
|
|
881
|
+
payload[1] = target;
|
|
882
|
+
payload[2] = vendor;
|
|
883
|
+
payload[3] = options;
|
|
1629
884
|
view.setUint32(4, binary.length, true);
|
|
1630
885
|
view.setUint32(8, addr, true);
|
|
1631
886
|
view.setUint32(12, operation === 1 /* WRITE */ ? Packet.ENCODER.crcgen.crc32(binary, 0) : 0, true);
|
|
1632
|
-
|
|
1633
|
-
|
|
1634
|
-
|
|
1635
|
-
ext ??= "";
|
|
1636
|
-
ext = ext === "gz" ? "bin" : ext;
|
|
887
|
+
let ext = /(?:\.([^.]+))?$/.exec(name)?.[1] ?? "";
|
|
888
|
+
if (ext === "gz")
|
|
889
|
+
ext = "bin";
|
|
1637
890
|
payload.set(encodeFixedText(type ?? ext, "File type", 4), 16);
|
|
1638
891
|
const timestamp = (Date.now() / 1000 >>> 0) - PacketEncoder.J2000_EPOCH;
|
|
1639
892
|
view.setUint32(20, timestamp, true);
|
|
1640
893
|
payload.set(version.toUint8Array(), 24);
|
|
1641
|
-
|
|
1642
|
-
payload.set(nameEncoded, 28);
|
|
1643
|
-
view.setUint8(51, 0);
|
|
894
|
+
payload.set(encodeFixedText(name, "Filename", 24), 28);
|
|
1644
895
|
super(payload);
|
|
1645
896
|
}
|
|
1646
897
|
}
|
|
@@ -1649,9 +900,7 @@ class ExitFileTransferH2DPacket extends DeviceBoundPacket {
|
|
|
1649
900
|
static COMMAND_ID = 86;
|
|
1650
901
|
static COMMAND_EXTENDED_ID = 18;
|
|
1651
902
|
constructor(action) {
|
|
1652
|
-
|
|
1653
|
-
payload[0] = action;
|
|
1654
|
-
super(payload);
|
|
903
|
+
super(Uint8Array.of(action));
|
|
1655
904
|
}
|
|
1656
905
|
}
|
|
1657
906
|
|
|
@@ -1660,8 +909,7 @@ class WriteFileH2DPacket extends DeviceBoundPacket {
|
|
|
1660
909
|
static COMMAND_EXTENDED_ID = 19;
|
|
1661
910
|
constructor(addr, buf) {
|
|
1662
911
|
const payload = new Uint8Array(4 + buf.length);
|
|
1663
|
-
|
|
1664
|
-
view.setUint32(0, addr, true);
|
|
912
|
+
new DataView(payload.buffer).setUint32(0, addr, true);
|
|
1665
913
|
payload.set(buf, 4);
|
|
1666
914
|
super(payload);
|
|
1667
915
|
}
|
|
@@ -1683,11 +931,7 @@ class LinkFileH2DPacket extends DeviceBoundPacket {
|
|
|
1683
931
|
static COMMAND_ID = 86;
|
|
1684
932
|
static COMMAND_EXTENDED_ID = 21;
|
|
1685
933
|
constructor(vendor, fileName, options) {
|
|
1686
|
-
|
|
1687
|
-
const payload = new Uint8Array(26);
|
|
1688
|
-
payload.set([vendor, options], 0);
|
|
1689
|
-
payload.set(str, 2);
|
|
1690
|
-
super(payload);
|
|
934
|
+
super(filePayload(vendor, options, fileName));
|
|
1691
935
|
}
|
|
1692
936
|
}
|
|
1693
937
|
|
|
@@ -1695,9 +939,7 @@ class GetDirectoryFileCountH2DPacket extends DeviceBoundPacket {
|
|
|
1695
939
|
static COMMAND_ID = 86;
|
|
1696
940
|
static COMMAND_EXTENDED_ID = 22;
|
|
1697
941
|
constructor(vendor) {
|
|
1698
|
-
|
|
1699
|
-
payload.set([vendor, 0], 0);
|
|
1700
|
-
super(payload);
|
|
942
|
+
super(Uint8Array.of(vendor, 0));
|
|
1701
943
|
}
|
|
1702
944
|
}
|
|
1703
945
|
|
|
@@ -1705,9 +947,7 @@ class GetDirectoryEntryH2DPacket extends DeviceBoundPacket {
|
|
|
1705
947
|
static COMMAND_ID = 86;
|
|
1706
948
|
static COMMAND_EXTENDED_ID = 23;
|
|
1707
949
|
constructor(index) {
|
|
1708
|
-
|
|
1709
|
-
payload.set([index, 0], 0);
|
|
1710
|
-
super(payload);
|
|
950
|
+
super(Uint8Array.of(index, 0));
|
|
1711
951
|
}
|
|
1712
952
|
}
|
|
1713
953
|
|
|
@@ -1715,17 +955,8 @@ class LoadFileActionH2DPacket extends DeviceBoundPacket {
|
|
|
1715
955
|
static COMMAND_ID = 86;
|
|
1716
956
|
static COMMAND_EXTENDED_ID = 24;
|
|
1717
957
|
constructor(vendor, actionId, fileNameOrSlotNumber) {
|
|
1718
|
-
|
|
1719
|
-
|
|
1720
|
-
fileName = fileNameOrSlotNumber;
|
|
1721
|
-
} else {
|
|
1722
|
-
fileName = "___s_" + (fileNameOrSlotNumber - 1) + ".bin";
|
|
1723
|
-
}
|
|
1724
|
-
const encodedName = encodeFixedText(fileName, "Filename", 23);
|
|
1725
|
-
const payload = new Uint8Array(26);
|
|
1726
|
-
payload.set([vendor, actionId], 0);
|
|
1727
|
-
payload.set(encodedName, 2);
|
|
1728
|
-
super(payload);
|
|
958
|
+
const fileName = typeof fileNameOrSlotNumber === "string" ? fileNameOrSlotNumber : `___s_${fileNameOrSlotNumber - 1}.bin`;
|
|
959
|
+
super(filePayload(vendor, actionId, fileName));
|
|
1729
960
|
}
|
|
1730
961
|
}
|
|
1731
962
|
|
|
@@ -1733,11 +964,7 @@ class GetFileMetadataH2DPacket extends DeviceBoundPacket {
|
|
|
1733
964
|
static COMMAND_ID = 86;
|
|
1734
965
|
static COMMAND_EXTENDED_ID = 25;
|
|
1735
966
|
constructor(vendor, fileName, options) {
|
|
1736
|
-
|
|
1737
|
-
const payload = new Uint8Array(26);
|
|
1738
|
-
payload.set([vendor, options], 0);
|
|
1739
|
-
payload.set(encodedName, 2);
|
|
1740
|
-
super(payload);
|
|
967
|
+
super(filePayload(vendor, options, fileName));
|
|
1741
968
|
}
|
|
1742
969
|
}
|
|
1743
970
|
|
|
@@ -1745,11 +972,7 @@ class EraseFileH2DPacket extends DeviceBoundPacket {
|
|
|
1745
972
|
static COMMAND_ID = 86;
|
|
1746
973
|
static COMMAND_EXTENDED_ID = 27;
|
|
1747
974
|
constructor(vendor, fileName) {
|
|
1748
|
-
|
|
1749
|
-
const payload = new Uint8Array(26);
|
|
1750
|
-
payload.set([vendor, 128], 0);
|
|
1751
|
-
payload.set(encodedName, 2);
|
|
1752
|
-
super(payload);
|
|
975
|
+
super(filePayload(vendor, 128, fileName));
|
|
1753
976
|
}
|
|
1754
977
|
}
|
|
1755
978
|
|
|
@@ -1757,11 +980,7 @@ class GetProgramSlotInfoH2DPacket extends DeviceBoundPacket {
|
|
|
1757
980
|
static COMMAND_ID = 86;
|
|
1758
981
|
static COMMAND_EXTENDED_ID = 28;
|
|
1759
982
|
constructor(vendor, fileName) {
|
|
1760
|
-
|
|
1761
|
-
const payload = new Uint8Array(26);
|
|
1762
|
-
payload.set([vendor, 0], 0);
|
|
1763
|
-
payload.set(encodedName, 2);
|
|
1764
|
-
super(payload);
|
|
983
|
+
super(filePayload(vendor, 0, fileName));
|
|
1765
984
|
}
|
|
1766
985
|
}
|
|
1767
986
|
|
|
@@ -1769,9 +988,7 @@ class FileClearUpH2DPacket extends DeviceBoundPacket {
|
|
|
1769
988
|
static COMMAND_ID = 86;
|
|
1770
989
|
static COMMAND_EXTENDED_ID = 30;
|
|
1771
990
|
constructor(vendor) {
|
|
1772
|
-
|
|
1773
|
-
payload.set([vendor, 0], 0);
|
|
1774
|
-
super(payload);
|
|
991
|
+
super(Uint8Array.of(vendor, 0));
|
|
1775
992
|
}
|
|
1776
993
|
}
|
|
1777
994
|
|
|
@@ -1779,9 +996,7 @@ class FileFormatH2DPacket extends DeviceBoundPacket {
|
|
|
1779
996
|
static COMMAND_ID = 86;
|
|
1780
997
|
static COMMAND_EXTENDED_ID = 31;
|
|
1781
998
|
constructor() {
|
|
1782
|
-
|
|
1783
|
-
payload.set([68, 67, 66, 65], 0);
|
|
1784
|
-
super(payload);
|
|
999
|
+
super(Uint8Array.of(68, 67, 66, 65));
|
|
1785
1000
|
}
|
|
1786
1001
|
}
|
|
1787
1002
|
|
|
@@ -1793,33 +1008,21 @@ class GetSystemFlagsH2DPacket extends DeviceBoundPacket {
|
|
|
1793
1008
|
class GetDeviceStatusH2DPacket extends DeviceBoundPacket {
|
|
1794
1009
|
static COMMAND_ID = 86;
|
|
1795
1010
|
static COMMAND_EXTENDED_ID = 33;
|
|
1796
|
-
constructor() {
|
|
1797
|
-
super(undefined);
|
|
1798
|
-
}
|
|
1799
1011
|
}
|
|
1800
1012
|
|
|
1801
1013
|
class GetSystemStatusH2DPacket extends DeviceBoundPacket {
|
|
1802
1014
|
static COMMAND_ID = 86;
|
|
1803
1015
|
static COMMAND_EXTENDED_ID = 34;
|
|
1804
|
-
constructor() {
|
|
1805
|
-
super(undefined);
|
|
1806
|
-
}
|
|
1807
1016
|
}
|
|
1808
1017
|
|
|
1809
1018
|
class GetFdtStatusH2DPacket extends DeviceBoundPacket {
|
|
1810
1019
|
static COMMAND_ID = 86;
|
|
1811
1020
|
static COMMAND_EXTENDED_ID = 35;
|
|
1812
|
-
constructor() {
|
|
1813
|
-
super(undefined);
|
|
1814
|
-
}
|
|
1815
1021
|
}
|
|
1816
1022
|
|
|
1817
1023
|
class GetLogCountH2DPacket extends DeviceBoundPacket {
|
|
1818
1024
|
static COMMAND_ID = 86;
|
|
1819
1025
|
static COMMAND_EXTENDED_ID = 36;
|
|
1820
|
-
constructor() {
|
|
1821
|
-
super(undefined);
|
|
1822
|
-
}
|
|
1823
1026
|
}
|
|
1824
1027
|
|
|
1825
1028
|
class ReadLogPageH2DPacket extends DeviceBoundPacket {
|
|
@@ -1837,18 +1040,13 @@ class ReadLogPageH2DPacket extends DeviceBoundPacket {
|
|
|
1837
1040
|
class GetRadioStatusH2DPacket extends DeviceBoundPacket {
|
|
1838
1041
|
static COMMAND_ID = 86;
|
|
1839
1042
|
static COMMAND_EXTENDED_ID = 38;
|
|
1840
|
-
constructor() {
|
|
1841
|
-
super(undefined);
|
|
1842
|
-
}
|
|
1843
1043
|
}
|
|
1844
1044
|
|
|
1845
1045
|
class ScreenCaptureH2DPacket extends DeviceBoundPacket {
|
|
1846
1046
|
static COMMAND_ID = 86;
|
|
1847
1047
|
static COMMAND_EXTENDED_ID = 40;
|
|
1848
1048
|
constructor(e) {
|
|
1849
|
-
|
|
1850
|
-
payload[0] = e;
|
|
1851
|
-
super(payload);
|
|
1049
|
+
super(Uint8Array.of(e));
|
|
1852
1050
|
}
|
|
1853
1051
|
}
|
|
1854
1052
|
|
|
@@ -1869,10 +1067,7 @@ class SelectDashH2DPacket extends DeviceBoundPacket {
|
|
|
1869
1067
|
static COMMAND_ID = 86;
|
|
1870
1068
|
static COMMAND_EXTENDED_ID = 43;
|
|
1871
1069
|
constructor(screen, port) {
|
|
1872
|
-
|
|
1873
|
-
payload[0] = screen;
|
|
1874
|
-
payload[1] = port;
|
|
1875
|
-
super(payload);
|
|
1070
|
+
super(Uint8Array.of(screen, port));
|
|
1876
1071
|
}
|
|
1877
1072
|
}
|
|
1878
1073
|
|
|
@@ -1880,9 +1075,8 @@ class ReadKeyValueH2DPacket extends DeviceBoundPacket {
|
|
|
1880
1075
|
static COMMAND_ID = 86;
|
|
1881
1076
|
static COMMAND_EXTENDED_ID = 46;
|
|
1882
1077
|
constructor(key) {
|
|
1883
|
-
const encodedKey = encodeFixedText(key, "Key", 31);
|
|
1884
1078
|
const payload = new Uint8Array(32);
|
|
1885
|
-
payload.set(
|
|
1079
|
+
payload.set(encodeFixedText(key, "Key", 31), 0);
|
|
1886
1080
|
super(payload);
|
|
1887
1081
|
}
|
|
1888
1082
|
}
|
|
@@ -1892,7 +1086,7 @@ class WriteKeyValueH2DPacket extends DeviceBoundPacket {
|
|
|
1892
1086
|
static COMMAND_EXTENDED_ID = 47;
|
|
1893
1087
|
constructor(key, value) {
|
|
1894
1088
|
const strk = encodeFixedText(key, "Key", 31);
|
|
1895
|
-
const strv =
|
|
1089
|
+
const strv = textEncoder2.encode(value);
|
|
1896
1090
|
if (strk.byteLength + strv.byteLength + 20 > 32767) {
|
|
1897
1091
|
throw new RangeError("Key and value are too large for a protocol packet");
|
|
1898
1092
|
}
|
|
@@ -1906,17 +1100,11 @@ class WriteKeyValueH2DPacket extends DeviceBoundPacket {
|
|
|
1906
1100
|
class GetSlot1to4InfoH2DPacket extends DeviceBoundPacket {
|
|
1907
1101
|
static COMMAND_ID = 86;
|
|
1908
1102
|
static COMMAND_EXTENDED_ID = 49;
|
|
1909
|
-
constructor() {
|
|
1910
|
-
super(undefined);
|
|
1911
|
-
}
|
|
1912
1103
|
}
|
|
1913
1104
|
|
|
1914
1105
|
class GetSlot5to8InfoH2DPacket extends DeviceBoundPacket {
|
|
1915
1106
|
static COMMAND_ID = 86;
|
|
1916
1107
|
static COMMAND_EXTENDED_ID = 50;
|
|
1917
|
-
constructor() {
|
|
1918
|
-
super(undefined);
|
|
1919
|
-
}
|
|
1920
1108
|
}
|
|
1921
1109
|
|
|
1922
1110
|
class FactoryStatusH2DPacket extends DeviceBoundPacket {
|
|
@@ -1928,9 +1116,7 @@ class FactoryEnableH2DPacket extends DeviceBoundPacket {
|
|
|
1928
1116
|
static COMMAND_ID = 86;
|
|
1929
1117
|
static COMMAND_EXTENDED_ID = 255;
|
|
1930
1118
|
constructor() {
|
|
1931
|
-
|
|
1932
|
-
payload.set([77, 76, 75, 74], 0);
|
|
1933
|
-
super(payload);
|
|
1119
|
+
super(Uint8Array.of(77, 76, 75, 74));
|
|
1934
1120
|
}
|
|
1935
1121
|
}
|
|
1936
1122
|
|
|
@@ -1972,8 +1158,7 @@ class MatchModeReplyD2HPacket extends HostBoundPacket {
|
|
|
1972
1158
|
modebit;
|
|
1973
1159
|
constructor(data) {
|
|
1974
1160
|
super(data);
|
|
1975
|
-
|
|
1976
|
-
this.modebit = dataView.nextUint8();
|
|
1161
|
+
this.modebit = PacketView.fromPacket(this).nextUint8();
|
|
1977
1162
|
}
|
|
1978
1163
|
}
|
|
1979
1164
|
|
|
@@ -1999,31 +1184,27 @@ class MatchStatusReplyD2HPacket extends HostBoundPacket {
|
|
|
1999
1184
|
rxSignalQuality;
|
|
2000
1185
|
constructor(data) {
|
|
2001
1186
|
super(data);
|
|
2002
|
-
const
|
|
1187
|
+
const view = PacketView.fromPacket(this);
|
|
2003
1188
|
const n = this.ackIndex;
|
|
2004
|
-
this.rssi =
|
|
2005
|
-
this.systemStatusBits =
|
|
2006
|
-
this.radioStatusBits =
|
|
2007
|
-
this.fieldStatusBits =
|
|
2008
|
-
this.matchClock =
|
|
2009
|
-
this.brainBatteryPercent =
|
|
2010
|
-
this.controllerBatteryPercent =
|
|
2011
|
-
this.partnerControllerBatteryPercent =
|
|
2012
|
-
this.pad =
|
|
2013
|
-
this.buttons =
|
|
2014
|
-
this.activeProgram =
|
|
2015
|
-
this.radioType =
|
|
2016
|
-
this.radioChannel =
|
|
2017
|
-
this.radioSlot =
|
|
2018
|
-
this.
|
|
2019
|
-
this.
|
|
2020
|
-
|
|
2021
|
-
|
|
2022
|
-
|
|
2023
|
-
if (endIdx > -1) {
|
|
2024
|
-
rawStr = rawStr.substr(0, endIdx);
|
|
2025
|
-
}
|
|
2026
|
-
this.robotName = rawStr;
|
|
1189
|
+
this.rssi = view.nextInt8();
|
|
1190
|
+
this.systemStatusBits = view.nextUint16();
|
|
1191
|
+
this.radioStatusBits = view.nextUint16();
|
|
1192
|
+
this.fieldStatusBits = view.nextUint8();
|
|
1193
|
+
this.matchClock = view.nextUint8();
|
|
1194
|
+
this.brainBatteryPercent = view.nextUint8();
|
|
1195
|
+
this.controllerBatteryPercent = view.nextUint8();
|
|
1196
|
+
this.partnerControllerBatteryPercent = view.nextUint8();
|
|
1197
|
+
this.pad = view.nextUint8();
|
|
1198
|
+
this.buttons = view.nextUint16();
|
|
1199
|
+
this.activeProgram = view.nextUint8();
|
|
1200
|
+
this.radioType = view.nextUint8();
|
|
1201
|
+
this.radioChannel = view.nextUint8();
|
|
1202
|
+
this.radioSlot = view.nextUint8();
|
|
1203
|
+
this.controllerFlags = view.getUint8(n + 28);
|
|
1204
|
+
this.rxSignalQuality = view.getUint8(n + 29);
|
|
1205
|
+
const raw = new TextDecoder("UTF-8").decode(this.data.slice(n + 18, n + this.payloadSize + 28));
|
|
1206
|
+
const end = raw.indexOf("\x00");
|
|
1207
|
+
this.robotName = end > -1 ? raw.slice(0, end) : raw;
|
|
2027
1208
|
}
|
|
2028
1209
|
}
|
|
2029
1210
|
|
|
@@ -2040,10 +1221,10 @@ class InitFileTransferReplyD2HPacket extends HostBoundPacket {
|
|
|
2040
1221
|
crc32;
|
|
2041
1222
|
constructor(data) {
|
|
2042
1223
|
super(data);
|
|
2043
|
-
const
|
|
2044
|
-
this.windowSize =
|
|
2045
|
-
this.fileSize =
|
|
2046
|
-
this.crc32 =
|
|
1224
|
+
const view = PacketView.fromPacket(this);
|
|
1225
|
+
this.windowSize = view.nextUint16();
|
|
1226
|
+
this.fileSize = view.nextUint32();
|
|
1227
|
+
this.crc32 = view.nextUint32();
|
|
2047
1228
|
}
|
|
2048
1229
|
}
|
|
2049
1230
|
|
|
@@ -2065,13 +1246,10 @@ class ReadFileReplyD2HPacket extends HostBoundPacket {
|
|
|
2065
1246
|
buf;
|
|
2066
1247
|
constructor(data) {
|
|
2067
1248
|
super(data);
|
|
2068
|
-
const
|
|
2069
|
-
this.addr =
|
|
1249
|
+
const view = PacketView.fromPacket(this);
|
|
1250
|
+
this.addr = view.nextUint32();
|
|
2070
1251
|
this.length = this.payloadSize - 8;
|
|
2071
|
-
this.buf = this.data.
|
|
2072
|
-
}
|
|
2073
|
-
static isValidPacket(data, n) {
|
|
2074
|
-
return super.isValidPacket(data, n);
|
|
1252
|
+
this.buf = this.data.subarray(view.position, view.position + this.length);
|
|
2075
1253
|
}
|
|
2076
1254
|
}
|
|
2077
1255
|
|
|
@@ -2086,8 +1264,7 @@ class GetDirectoryFileCountReplyD2HPacket extends HostBoundPacket {
|
|
|
2086
1264
|
count;
|
|
2087
1265
|
constructor(data) {
|
|
2088
1266
|
super(data);
|
|
2089
|
-
|
|
2090
|
-
this.count = dataView.nextUint16();
|
|
1267
|
+
this.count = PacketView.fromPacket(this).nextUint16();
|
|
2091
1268
|
}
|
|
2092
1269
|
}
|
|
2093
1270
|
|
|
@@ -2097,19 +1274,19 @@ class GetDirectoryEntryReplyD2HPacket extends HostBoundPacket {
|
|
|
2097
1274
|
file;
|
|
2098
1275
|
constructor(data) {
|
|
2099
1276
|
super(data);
|
|
2100
|
-
|
|
2101
|
-
|
|
2102
|
-
|
|
2103
|
-
|
|
2104
|
-
|
|
2105
|
-
|
|
2106
|
-
|
|
2107
|
-
|
|
2108
|
-
|
|
2109
|
-
|
|
2110
|
-
|
|
2111
|
-
|
|
2112
|
-
}
|
|
1277
|
+
if (this.payloadSize <= 4)
|
|
1278
|
+
return;
|
|
1279
|
+
const view = PacketView.fromPacket(this);
|
|
1280
|
+
this.file = {
|
|
1281
|
+
index: view.nextUint8(),
|
|
1282
|
+
size: view.nextUint32(),
|
|
1283
|
+
loadAddress: view.nextUint32(),
|
|
1284
|
+
crc32: view.nextUint32(),
|
|
1285
|
+
type: view.nextString(4),
|
|
1286
|
+
timestamp: view.nextUint32() + PacketEncoder.J2000_EPOCH,
|
|
1287
|
+
version: view.nextVersion(),
|
|
1288
|
+
filename: view.nextNTBS(32)
|
|
1289
|
+
};
|
|
2113
1290
|
}
|
|
2114
1291
|
}
|
|
2115
1292
|
|
|
@@ -2124,18 +1301,18 @@ class GetFileMetadataReplyD2HPacket extends HostBoundPacket {
|
|
|
2124
1301
|
file;
|
|
2125
1302
|
constructor(data) {
|
|
2126
1303
|
super(data);
|
|
2127
|
-
|
|
2128
|
-
|
|
2129
|
-
|
|
2130
|
-
|
|
2131
|
-
|
|
2132
|
-
|
|
2133
|
-
|
|
2134
|
-
|
|
2135
|
-
|
|
2136
|
-
|
|
2137
|
-
|
|
2138
|
-
}
|
|
1304
|
+
if (this.payloadSize <= 4)
|
|
1305
|
+
return;
|
|
1306
|
+
const view = PacketView.fromPacket(this);
|
|
1307
|
+
view.nextUint8();
|
|
1308
|
+
this.file = {
|
|
1309
|
+
size: view.nextUint32(),
|
|
1310
|
+
loadAddress: view.nextUint32(),
|
|
1311
|
+
crc32: view.nextUint32(),
|
|
1312
|
+
type: view.nextString(4),
|
|
1313
|
+
timestamp: view.nextUint32() + PacketEncoder.J2000_EPOCH,
|
|
1314
|
+
version: view.nextVersion()
|
|
1315
|
+
};
|
|
2139
1316
|
}
|
|
2140
1317
|
}
|
|
2141
1318
|
|
|
@@ -2151,9 +1328,9 @@ class GetProgramSlotInfoReplyD2HPacket extends HostBoundPacket {
|
|
|
2151
1328
|
slot;
|
|
2152
1329
|
constructor(data) {
|
|
2153
1330
|
super(data);
|
|
2154
|
-
const
|
|
2155
|
-
this.slot =
|
|
2156
|
-
this.requestedSlot =
|
|
1331
|
+
const view = PacketView.fromPacket(this);
|
|
1332
|
+
this.slot = view.nextUint8();
|
|
1333
|
+
this.requestedSlot = view.nextUint8();
|
|
2157
1334
|
}
|
|
2158
1335
|
}
|
|
2159
1336
|
|
|
@@ -2171,40 +1348,32 @@ class GetSystemFlagsReplyD2HPacket extends HostBoundPacket {
|
|
|
2171
1348
|
static COMMAND_ID = 86;
|
|
2172
1349
|
static COMMAND_EXTENDED_ID = 32;
|
|
2173
1350
|
flags;
|
|
2174
|
-
radioSearching;
|
|
1351
|
+
radioSearching = false;
|
|
2175
1352
|
radioQuality;
|
|
2176
1353
|
controllerBatteryPercent;
|
|
2177
1354
|
partnerControllerBatteryPercent;
|
|
2178
1355
|
battery;
|
|
2179
|
-
currentProgram;
|
|
1356
|
+
currentProgram = 0;
|
|
2180
1357
|
constructor(data) {
|
|
2181
1358
|
super(data);
|
|
2182
|
-
const
|
|
2183
|
-
this.
|
|
2184
|
-
this.currentProgram = 0;
|
|
2185
|
-
this.flags = dataView.nextUint32();
|
|
1359
|
+
const view = PacketView.fromPacket(this);
|
|
1360
|
+
this.flags = view.nextUint32();
|
|
2186
1361
|
const hasPartner = (8192 & this.flags) !== 0;
|
|
2187
1362
|
const hasRadio = (1536 & this.flags) === 1536;
|
|
2188
|
-
const byte1 =
|
|
2189
|
-
const byte2 =
|
|
1363
|
+
const byte1 = view.nextUint8();
|
|
1364
|
+
const byte2 = view.nextUint8();
|
|
2190
1365
|
if (this.payloadSize === 11) {
|
|
2191
|
-
this.battery = 8 * (byte1 & 15);
|
|
2192
|
-
if ((this.flags & 256) !== 0 || hasRadio)
|
|
2193
|
-
this.controllerBatteryPercent = 8 * (byte1 >> 4 & 15);
|
|
1366
|
+
this.battery = clamp100(8 * (byte1 & 15));
|
|
1367
|
+
if ((this.flags & 256) !== 0 || hasRadio) {
|
|
1368
|
+
this.controllerBatteryPercent = clamp100(8 * (byte1 >> 4 & 15));
|
|
1369
|
+
}
|
|
2194
1370
|
if (hasRadio)
|
|
2195
|
-
this.radioQuality = 8 * (byte2 & 15);
|
|
1371
|
+
this.radioQuality = clamp100(8 * (byte2 & 15));
|
|
2196
1372
|
this.radioSearching = (this.flags & 1536) === 512;
|
|
2197
|
-
if (hasPartner)
|
|
2198
|
-
this.partnerControllerBatteryPercent = 8 * (byte2 >> 4 & 15);
|
|
2199
|
-
|
|
2200
|
-
|
|
2201
|
-
this.battery = 100;
|
|
2202
|
-
if (this.controllerBatteryPercent != null && this.controllerBatteryPercent > 100)
|
|
2203
|
-
this.controllerBatteryPercent = 100;
|
|
2204
|
-
if (this.radioQuality != null && this.radioQuality > 100)
|
|
2205
|
-
this.radioQuality = 100;
|
|
2206
|
-
if (this.partnerControllerBatteryPercent != null && this.partnerControllerBatteryPercent > 100)
|
|
2207
|
-
this.partnerControllerBatteryPercent = 100;
|
|
1373
|
+
if (hasPartner) {
|
|
1374
|
+
this.partnerControllerBatteryPercent = clamp100(8 * (byte2 >> 4 & 15));
|
|
1375
|
+
}
|
|
1376
|
+
this.currentProgram = view.nextUint8();
|
|
2208
1377
|
}
|
|
2209
1378
|
}
|
|
2210
1379
|
}
|
|
@@ -2216,17 +1385,17 @@ class GetDeviceStatusReplyD2HPacket extends HostBoundPacket {
|
|
|
2216
1385
|
devices;
|
|
2217
1386
|
constructor(data) {
|
|
2218
1387
|
super(data);
|
|
2219
|
-
const
|
|
2220
|
-
this.count =
|
|
1388
|
+
const view = PacketView.fromPacket(this);
|
|
1389
|
+
this.count = view.nextUint8();
|
|
2221
1390
|
this.devices = [];
|
|
2222
1391
|
for (let i = 0;i < this.count; i++) {
|
|
2223
1392
|
this.devices.push({
|
|
2224
|
-
port:
|
|
2225
|
-
type:
|
|
2226
|
-
status:
|
|
2227
|
-
betaversion:
|
|
2228
|
-
version:
|
|
2229
|
-
bootversion:
|
|
1393
|
+
port: view.nextUint8(),
|
|
1394
|
+
type: view.nextUint8(),
|
|
1395
|
+
status: view.nextUint8(),
|
|
1396
|
+
betaversion: view.nextUint8(),
|
|
1397
|
+
version: view.nextUint16(),
|
|
1398
|
+
bootversion: view.nextUint16()
|
|
2230
1399
|
});
|
|
2231
1400
|
}
|
|
2232
1401
|
}
|
|
@@ -2238,48 +1407,42 @@ class GetSystemStatusReplyD2HPacket extends HostBoundPacket {
|
|
|
2238
1407
|
systemVersion;
|
|
2239
1408
|
cpu0Version;
|
|
2240
1409
|
cpu1Version;
|
|
2241
|
-
nxpVersion;
|
|
1410
|
+
nxpVersion = VexFirmwareVersion.allZero();
|
|
2242
1411
|
touchVersion;
|
|
2243
|
-
uniqueId;
|
|
2244
|
-
sysflags;
|
|
2245
|
-
eventBrain;
|
|
2246
|
-
romBootloaderActive;
|
|
2247
|
-
ramBootloaderActive;
|
|
2248
|
-
goldenVersion;
|
|
1412
|
+
uniqueId = 1234;
|
|
1413
|
+
sysflags = [0, 0, 0, 0, 0, 0, 0];
|
|
1414
|
+
eventBrain = false;
|
|
1415
|
+
romBootloaderActive = false;
|
|
1416
|
+
ramBootloaderActive = false;
|
|
1417
|
+
goldenVersion = VexFirmwareVersion.allZero();
|
|
2249
1418
|
constructor(data) {
|
|
2250
1419
|
super(data);
|
|
2251
|
-
const
|
|
2252
|
-
|
|
2253
|
-
this.systemVersion =
|
|
2254
|
-
this.cpu0Version =
|
|
2255
|
-
this.cpu1Version =
|
|
2256
|
-
this.touchVersion =
|
|
2257
|
-
this.uniqueId = 1234;
|
|
2258
|
-
this.sysflags = [0, 0, 0, 0, 0, 0, 0];
|
|
2259
|
-
this.goldenVersion = VexFirmwareVersion.allZero();
|
|
2260
|
-
this.nxpVersion = VexFirmwareVersion.allZero();
|
|
2261
|
-
this.eventBrain = false;
|
|
2262
|
-
this.romBootloaderActive = false;
|
|
2263
|
-
this.ramBootloaderActive = false;
|
|
1420
|
+
const view = PacketView.fromPacket(this);
|
|
1421
|
+
view.nextUint8();
|
|
1422
|
+
this.systemVersion = view.nextVersion();
|
|
1423
|
+
this.cpu0Version = view.nextVersion();
|
|
1424
|
+
this.cpu1Version = view.nextVersion();
|
|
1425
|
+
this.touchVersion = view.nextVersion(true);
|
|
2264
1426
|
if (this.payloadSize > 25) {
|
|
2265
|
-
this.uniqueId =
|
|
1427
|
+
this.uniqueId = view.nextUint32();
|
|
2266
1428
|
this.sysflags = [
|
|
2267
|
-
|
|
2268
|
-
|
|
2269
|
-
|
|
2270
|
-
|
|
2271
|
-
|
|
1429
|
+
view.nextUint8(),
|
|
1430
|
+
view.nextUint8(),
|
|
1431
|
+
view.nextUint8(),
|
|
1432
|
+
view.nextUint8(),
|
|
1433
|
+
view.nextUint8(),
|
|
2272
1434
|
0,
|
|
2273
|
-
|
|
1435
|
+
view.nextUint8()
|
|
2274
1436
|
];
|
|
2275
|
-
|
|
2276
|
-
this.
|
|
2277
|
-
this.
|
|
2278
|
-
|
|
2279
|
-
|
|
1437
|
+
const flags6 = this.sysflags[6];
|
|
1438
|
+
this.eventBrain = (1 & flags6) !== 0;
|
|
1439
|
+
this.romBootloaderActive = (2 & flags6) !== 0;
|
|
1440
|
+
this.ramBootloaderActive = (4 & flags6) !== 0;
|
|
1441
|
+
view.nextUint16();
|
|
1442
|
+
this.goldenVersion = view.nextVersion();
|
|
2280
1443
|
}
|
|
2281
1444
|
if (this.payloadSize > 37) {
|
|
2282
|
-
this.nxpVersion =
|
|
1445
|
+
this.nxpVersion = view.nextVersion();
|
|
2283
1446
|
}
|
|
2284
1447
|
}
|
|
2285
1448
|
}
|
|
@@ -2291,17 +1454,17 @@ class GetFdtStatusReplyD2HPacket extends HostBoundPacket {
|
|
|
2291
1454
|
status;
|
|
2292
1455
|
constructor(data) {
|
|
2293
1456
|
super(data);
|
|
2294
|
-
const
|
|
2295
|
-
this.count =
|
|
1457
|
+
const view = PacketView.fromPacket(this);
|
|
1458
|
+
this.count = view.nextUint8();
|
|
2296
1459
|
this.status = [];
|
|
2297
1460
|
for (let i = 0;i < this.count; i++) {
|
|
2298
1461
|
this.status.push({
|
|
2299
|
-
index:
|
|
2300
|
-
type:
|
|
2301
|
-
status:
|
|
2302
|
-
betaversion:
|
|
2303
|
-
version:
|
|
2304
|
-
bootversion:
|
|
1462
|
+
index: view.nextUint8(),
|
|
1463
|
+
type: view.nextUint8(),
|
|
1464
|
+
status: view.nextUint8(),
|
|
1465
|
+
betaversion: view.nextUint8(),
|
|
1466
|
+
version: view.nextUint16(),
|
|
1467
|
+
bootversion: view.nextUint16()
|
|
2305
1468
|
});
|
|
2306
1469
|
}
|
|
2307
1470
|
}
|
|
@@ -2313,9 +1476,9 @@ class GetLogCountReplyD2HPacket extends HostBoundPacket {
|
|
|
2313
1476
|
count;
|
|
2314
1477
|
constructor(data) {
|
|
2315
1478
|
super(data);
|
|
2316
|
-
const
|
|
2317
|
-
|
|
2318
|
-
this.count =
|
|
1479
|
+
const view = PacketView.fromPacket(this);
|
|
1480
|
+
view.nextUint8();
|
|
1481
|
+
this.count = view.nextUint32();
|
|
2319
1482
|
}
|
|
2320
1483
|
}
|
|
2321
1484
|
|
|
@@ -2327,20 +1490,19 @@ class ReadLogPageReplyD2HPacket extends HostBoundPacket {
|
|
|
2327
1490
|
entries;
|
|
2328
1491
|
constructor(data) {
|
|
2329
1492
|
super(data);
|
|
2330
|
-
const
|
|
2331
|
-
const
|
|
2332
|
-
|
|
2333
|
-
this.
|
|
2334
|
-
this.count = dataView.nextUint16();
|
|
1493
|
+
const view = PacketView.fromPacket(this);
|
|
1494
|
+
const size = view.nextUint8();
|
|
1495
|
+
this.offset = view.nextUint32();
|
|
1496
|
+
this.count = view.nextUint16();
|
|
2335
1497
|
this.entries = [];
|
|
2336
|
-
let j =
|
|
1498
|
+
let j = this.ackIndex + 8;
|
|
2337
1499
|
for (let i = 0;i < this.count; i++) {
|
|
2338
1500
|
this.entries.push({
|
|
2339
|
-
code:
|
|
2340
|
-
type:
|
|
2341
|
-
desc:
|
|
2342
|
-
spare:
|
|
2343
|
-
time:
|
|
1501
|
+
code: view.getUint8(j),
|
|
1502
|
+
type: view.getUint8(j + 1),
|
|
1503
|
+
desc: view.getUint8(j + 2),
|
|
1504
|
+
spare: view.getUint8(j + 3),
|
|
1505
|
+
time: view.getUint32(j + 4, true)
|
|
2344
1506
|
});
|
|
2345
1507
|
j += size;
|
|
2346
1508
|
}
|
|
@@ -2357,13 +1519,12 @@ class GetRadioStatusReplyD2HPacket extends HostBoundPacket {
|
|
|
2357
1519
|
timeslot;
|
|
2358
1520
|
constructor(data) {
|
|
2359
1521
|
super(data);
|
|
2360
|
-
const
|
|
2361
|
-
|
|
2362
|
-
this.
|
|
2363
|
-
this.
|
|
2364
|
-
this.
|
|
2365
|
-
this.
|
|
2366
|
-
this.timeslot = this.data[n + 7];
|
|
1522
|
+
const view = PacketView.fromPacket(this);
|
|
1523
|
+
this.device = view.nextUint8();
|
|
1524
|
+
this.quality = view.nextUint16();
|
|
1525
|
+
this.strength = view.nextInt16();
|
|
1526
|
+
this.channel = this.data[this.ackIndex + 6];
|
|
1527
|
+
this.timeslot = this.data[this.ackIndex + 7];
|
|
2367
1528
|
}
|
|
2368
1529
|
}
|
|
2369
1530
|
|
|
@@ -2388,8 +1549,7 @@ class ReadKeyValueReplyD2HPacket extends HostBoundPacket {
|
|
|
2388
1549
|
value;
|
|
2389
1550
|
constructor(data) {
|
|
2390
1551
|
super(data);
|
|
2391
|
-
|
|
2392
|
-
this.value = dataView.nextVarNTBS(255);
|
|
1552
|
+
this.value = PacketView.fromPacket(this).nextVarNTBS(255);
|
|
2393
1553
|
}
|
|
2394
1554
|
}
|
|
2395
1555
|
|
|
@@ -2405,20 +1565,18 @@ class GetSlot1to4InfoReplyD2HPacket extends HostBoundPacket {
|
|
|
2405
1565
|
slots;
|
|
2406
1566
|
constructor(data, start = 1) {
|
|
2407
1567
|
super(data);
|
|
2408
|
-
const
|
|
2409
|
-
this.slotFlags =
|
|
1568
|
+
const view = PacketView.fromPacket(this);
|
|
1569
|
+
this.slotFlags = view.nextUint8();
|
|
2410
1570
|
this.slots = [];
|
|
2411
1571
|
for (let i = 0;i < 4; i++) {
|
|
2412
|
-
|
|
2413
|
-
if (!hasData)
|
|
1572
|
+
if ((this.slotFlags & 1 << start - 1 + i) === 0)
|
|
2414
1573
|
continue;
|
|
2415
|
-
const
|
|
2416
|
-
const nameLen =
|
|
2417
|
-
const name = dataView.nextString(nameLen);
|
|
1574
|
+
const icon = view.nextUint16();
|
|
1575
|
+
const nameLen = view.nextUint8();
|
|
2418
1576
|
this.slots.push({
|
|
2419
1577
|
slot: start + i,
|
|
2420
|
-
icon
|
|
2421
|
-
name
|
|
1578
|
+
icon,
|
|
1579
|
+
name: view.nextString(nameLen)
|
|
2422
1580
|
});
|
|
2423
1581
|
}
|
|
2424
1582
|
}
|
|
@@ -2440,9 +1598,9 @@ class FactoryStatusReplyD2HPacket extends HostBoundPacket {
|
|
|
2440
1598
|
percent;
|
|
2441
1599
|
constructor(data) {
|
|
2442
1600
|
super(data);
|
|
2443
|
-
const
|
|
2444
|
-
this.status =
|
|
2445
|
-
this.percent =
|
|
1601
|
+
const view = PacketView.fromPacket(this);
|
|
1602
|
+
this.status = view.nextUint8();
|
|
1603
|
+
this.percent = view.nextUint8();
|
|
2446
1604
|
}
|
|
2447
1605
|
}
|
|
2448
1606
|
|
|
@@ -2451,120 +1609,35 @@ class FactoryEnableReplyD2HPacket extends HostBoundPacket {
|
|
|
2451
1609
|
static COMMAND_EXTENDED_ID = 255;
|
|
2452
1610
|
}
|
|
2453
1611
|
|
|
2454
|
-
// src/
|
|
2455
|
-
var
|
|
2456
|
-
|
|
2457
|
-
|
|
2458
|
-
|
|
2459
|
-
|
|
2460
|
-
|
|
2461
|
-
|
|
2462
|
-
|
|
2463
|
-
|
|
2464
|
-
class PacketEncoder {
|
|
2465
|
-
static HEADERS_LENGTH = 4;
|
|
2466
|
-
static HEADER_TO_DEVICE = [201, 54, 184, 71];
|
|
2467
|
-
static HEADER_TO_HOST = [170, 85];
|
|
2468
|
-
static J2000_EPOCH = 946684800;
|
|
2469
|
-
vexVersion;
|
|
2470
|
-
crcgen;
|
|
2471
|
-
allPacketsTable = {};
|
|
2472
|
-
static getInstance() {
|
|
2473
|
-
if (Packet.ENCODER === undefined) {
|
|
2474
|
-
Packet.ENCODER = new PacketEncoder;
|
|
2475
|
-
}
|
|
2476
|
-
return Packet.ENCODER;
|
|
2477
|
-
}
|
|
2478
|
-
constructor() {
|
|
2479
|
-
this.vexVersion = 0;
|
|
2480
|
-
this.crcgen = new CrcGenerator;
|
|
2481
|
-
Object.values(exports_VexPacketModels).forEach((packet) => {
|
|
2482
|
-
if (typeof packet === "function" && packet.prototype instanceof HostBoundPacket) {
|
|
2483
|
-
const packetType = packet;
|
|
2484
|
-
this.allPacketsTable[packetType.COMMAND_ID + " " + packetType.COMMAND_EXTENDED_ID] = packetType;
|
|
2485
|
-
}
|
|
2486
|
-
});
|
|
2487
|
-
}
|
|
2488
|
-
createHeader(buf) {
|
|
2489
|
-
if (buf === undefined || buf.byteLength < PacketEncoder.HEADERS_LENGTH) {
|
|
2490
|
-
buf = new ArrayBuffer(PacketEncoder.HEADERS_LENGTH);
|
|
2491
|
-
}
|
|
2492
|
-
const h = new Uint8Array(buf);
|
|
2493
|
-
h.set(PacketEncoder.HEADER_TO_DEVICE);
|
|
2494
|
-
return h;
|
|
2495
|
-
}
|
|
2496
|
-
cdcCommand(cmd) {
|
|
2497
|
-
const buf = new ArrayBuffer(PacketEncoder.HEADERS_LENGTH + 1);
|
|
2498
|
-
const h = this.createHeader(buf);
|
|
2499
|
-
h.set([cmd], PacketEncoder.HEADERS_LENGTH);
|
|
2500
|
-
return h;
|
|
2501
|
-
}
|
|
2502
|
-
cdcCommandWithData(cmd, data) {
|
|
2503
|
-
const buf = new ArrayBuffer(PacketEncoder.HEADERS_LENGTH + 2 + data.length);
|
|
2504
|
-
const h = this.createHeader(buf);
|
|
2505
|
-
h.set([cmd, data.length], PacketEncoder.HEADERS_LENGTH);
|
|
2506
|
-
h.set(data, PacketEncoder.HEADERS_LENGTH + 2);
|
|
2507
|
-
return h;
|
|
2508
|
-
}
|
|
2509
|
-
cdc2Command(cmd, ext) {
|
|
2510
|
-
const buf = new ArrayBuffer(PacketEncoder.HEADERS_LENGTH + 5);
|
|
2511
|
-
const h = this.createHeader(buf);
|
|
2512
|
-
h.set([cmd, ext, 0], PacketEncoder.HEADERS_LENGTH);
|
|
2513
|
-
const crc = this.crcgen.crc16(h.subarray(0, buf.byteLength - 2), 0) >>> 0;
|
|
2514
|
-
h.set([crc >>> 8, crc & 255], buf.byteLength - 2);
|
|
2515
|
-
return h;
|
|
2516
|
-
}
|
|
2517
|
-
cdc2CommandBufferLength(data) {
|
|
2518
|
-
let length = PacketEncoder.HEADERS_LENGTH + data.length + 3 + 2;
|
|
2519
|
-
if (data.length > 127)
|
|
2520
|
-
length += 1;
|
|
2521
|
-
return length;
|
|
2522
|
-
}
|
|
2523
|
-
cdc2CommandWithData(cmd, ext, data) {
|
|
2524
|
-
const buf = new ArrayBuffer(this.cdc2CommandBufferLength(data));
|
|
2525
|
-
const h = this.createHeader(buf);
|
|
2526
|
-
if (data.length < 128) {
|
|
2527
|
-
h.set([cmd, ext, data.length], PacketEncoder.HEADERS_LENGTH);
|
|
2528
|
-
h.set(data, PacketEncoder.HEADERS_LENGTH + 3);
|
|
2529
|
-
} else {
|
|
2530
|
-
const lengthMsb = (data.length >>> 8 | 128) >>> 0;
|
|
2531
|
-
const lengthLsb = (data.length & 255) >>> 0;
|
|
2532
|
-
h.set([cmd, ext, lengthMsb, lengthLsb], PacketEncoder.HEADERS_LENGTH);
|
|
2533
|
-
h.set(data, PacketEncoder.HEADERS_LENGTH + 4);
|
|
2534
|
-
}
|
|
2535
|
-
const crc = this.crcgen.crc16(h.subarray(0, buf.byteLength - 2), 0);
|
|
2536
|
-
h.set([crc >>> 8, crc & 255], buf.byteLength - 2);
|
|
2537
|
-
return h;
|
|
2538
|
-
}
|
|
2539
|
-
validateHeader(data) {
|
|
2540
|
-
return !(data[0] !== PacketEncoder.HEADER_TO_HOST[0] || data[1] !== PacketEncoder.HEADER_TO_HOST[1]);
|
|
2541
|
-
}
|
|
2542
|
-
validateMessageCdc(data) {
|
|
2543
|
-
const message = data.subarray(0, data.byteLength - 2);
|
|
2544
|
-
const lastTwoBytes = (data[data.byteLength - 2] << 8) + data[data.byteLength - 1];
|
|
2545
|
-
return this.crcgen.crc16(message, 0) === lastTwoBytes;
|
|
1612
|
+
// src/VexScreenCapture.ts
|
|
1613
|
+
var SCREEN_CAPTURE_HEIGHT = 272;
|
|
1614
|
+
var SCREEN_CAPTURE_WIDTH = 480;
|
|
1615
|
+
var SCREEN_CAPTURE_CHANNELS = 3;
|
|
1616
|
+
var SCREEN_CAPTURE_MESSAGE_WIDTH = 512;
|
|
1617
|
+
var SCREEN_CAPTURE_MESSAGE_CHANNELS = 4;
|
|
1618
|
+
var SCREEN_CAPTURE_FRAMEBUFFER_SIZE = SCREEN_CAPTURE_MESSAGE_WIDTH * SCREEN_CAPTURE_HEIGHT * SCREEN_CAPTURE_MESSAGE_CHANNELS;
|
|
1619
|
+
function convertScreenCapture(framebuffer) {
|
|
1620
|
+
if (framebuffer.length !== SCREEN_CAPTURE_FRAMEBUFFER_SIZE) {
|
|
1621
|
+
throw new Error(`bad screen capture framebuffer size: ${framebuffer.length}; expected ${SCREEN_CAPTURE_FRAMEBUFFER_SIZE}`);
|
|
2546
1622
|
}
|
|
2547
|
-
|
|
2548
|
-
|
|
2549
|
-
|
|
2550
|
-
|
|
2551
|
-
|
|
2552
|
-
|
|
1623
|
+
const pixels = new Uint8Array(SCREEN_CAPTURE_WIDTH * SCREEN_CAPTURE_HEIGHT * SCREEN_CAPTURE_CHANNELS);
|
|
1624
|
+
let source = 0;
|
|
1625
|
+
let target = 0;
|
|
1626
|
+
for (let row = 0;row < SCREEN_CAPTURE_HEIGHT; row++) {
|
|
1627
|
+
for (let column = 0;column < SCREEN_CAPTURE_WIDTH; column++) {
|
|
1628
|
+
pixels[target] = framebuffer[source + 2];
|
|
1629
|
+
pixels[target + 1] = framebuffer[source + 1];
|
|
1630
|
+
pixels[target + 2] = framebuffer[source];
|
|
1631
|
+
source += SCREEN_CAPTURE_MESSAGE_CHANNELS;
|
|
1632
|
+
target += SCREEN_CAPTURE_CHANNELS;
|
|
2553
1633
|
}
|
|
2554
|
-
|
|
2555
|
-
}
|
|
2556
|
-
getHostHeaderLength(data) {
|
|
2557
|
-
return (data[3] & 128) === 0 ? 4 : 5;
|
|
1634
|
+
source += (SCREEN_CAPTURE_MESSAGE_WIDTH - SCREEN_CAPTURE_WIDTH) * SCREEN_CAPTURE_MESSAGE_CHANNELS;
|
|
2558
1635
|
}
|
|
1636
|
+
return pixels;
|
|
2559
1637
|
}
|
|
2560
1638
|
|
|
2561
1639
|
// src/VexConnection.ts
|
|
2562
1640
|
var thePacketEncoder = PacketEncoder.getInstance();
|
|
2563
|
-
var SCREEN_CAPTURE_HEIGHT = 272;
|
|
2564
|
-
var SCREEN_CAPTURE_WIDTH = 480;
|
|
2565
|
-
var SCREEN_CAPTURE_CHANNELS = 3;
|
|
2566
|
-
var SCREEN_CAPTURE_MESSAGE_WIDTH = 512;
|
|
2567
|
-
var SCREEN_CAPTURE_MESSAGE_CHANNELS = 4;
|
|
2568
1641
|
|
|
2569
1642
|
class VexSerialConnection extends VexEventTarget {
|
|
2570
1643
|
filters = [{ usbVendorId: 10376 }];
|
|
@@ -2572,12 +1645,31 @@ class VexSerialConnection extends VexEventTarget {
|
|
|
2572
1645
|
reader;
|
|
2573
1646
|
port;
|
|
2574
1647
|
serial;
|
|
2575
|
-
|
|
1648
|
+
pendingCallbacks = new Map;
|
|
1649
|
+
rawCallbacks = {
|
|
1650
|
+
head: undefined,
|
|
1651
|
+
tail: undefined
|
|
1652
|
+
};
|
|
1653
|
+
pendingCommandTails = new Map;
|
|
2576
1654
|
_onPortDisconnect = null;
|
|
2577
1655
|
_closePromise = null;
|
|
1656
|
+
_openPromise = null;
|
|
1657
|
+
_isClosing = false;
|
|
2578
1658
|
_wasConnected = false;
|
|
2579
1659
|
fileTransferTail = Promise.resolve();
|
|
2580
1660
|
fileTransferDepth = 0;
|
|
1661
|
+
get callbacksQueue() {
|
|
1662
|
+
const callbacks = [];
|
|
1663
|
+
for (const queue of this.pendingCallbacks.values()) {
|
|
1664
|
+
for (let callback = queue.head;callback; callback = callback.next) {
|
|
1665
|
+
callbacks.push(callback);
|
|
1666
|
+
}
|
|
1667
|
+
}
|
|
1668
|
+
for (let callback = this.rawCallbacks.head;callback; callback = callback.next) {
|
|
1669
|
+
callbacks.push(callback);
|
|
1670
|
+
}
|
|
1671
|
+
return callbacks;
|
|
1672
|
+
}
|
|
2581
1673
|
get isConnected() {
|
|
2582
1674
|
return this.port !== undefined && this.reader !== undefined && this.writer !== undefined;
|
|
2583
1675
|
}
|
|
@@ -2588,25 +1680,46 @@ class VexSerialConnection extends VexEventTarget {
|
|
|
2588
1680
|
super();
|
|
2589
1681
|
this.serial = serial;
|
|
2590
1682
|
}
|
|
1683
|
+
reportWarning(message, details) {
|
|
1684
|
+
this.emitSafely("warning", {
|
|
1685
|
+
message,
|
|
1686
|
+
details
|
|
1687
|
+
});
|
|
1688
|
+
}
|
|
1689
|
+
emitSafely(eventName, data) {
|
|
1690
|
+
try {
|
|
1691
|
+
this.emit(eventName, data);
|
|
1692
|
+
} catch {}
|
|
1693
|
+
}
|
|
2591
1694
|
async close() {
|
|
2592
1695
|
if (this._closePromise)
|
|
2593
1696
|
return this._closePromise;
|
|
2594
|
-
|
|
2595
|
-
|
|
2596
|
-
this._closePromise =
|
|
1697
|
+
this._isClosing = true;
|
|
1698
|
+
const closing = this._closeAfterOpen();
|
|
1699
|
+
this._closePromise = closing;
|
|
2597
1700
|
try {
|
|
2598
|
-
await
|
|
1701
|
+
await closing;
|
|
2599
1702
|
} finally {
|
|
2600
|
-
this._closePromise
|
|
1703
|
+
if (this._closePromise === closing)
|
|
1704
|
+
this._closePromise = null;
|
|
1705
|
+
this._isClosing = false;
|
|
2601
1706
|
}
|
|
2602
1707
|
}
|
|
1708
|
+
async _closeAfterOpen() {
|
|
1709
|
+
const opening = this._openPromise;
|
|
1710
|
+
if (opening !== null)
|
|
1711
|
+
await opening;
|
|
1712
|
+
if (!this._hasOpenResources())
|
|
1713
|
+
return;
|
|
1714
|
+
await this._doClose();
|
|
1715
|
+
}
|
|
2603
1716
|
_hasOpenResources() {
|
|
2604
|
-
return this.port !== undefined || this.reader !== undefined || this.writer !== undefined || this._onPortDisconnect !== null || this.
|
|
1717
|
+
return this.port !== undefined || this.reader !== undefined || this.writer !== undefined || this._onPortDisconnect !== null || this.hasPendingCallbacks();
|
|
2605
1718
|
}
|
|
2606
1719
|
async _doClose() {
|
|
2607
|
-
for (const callback of this.
|
|
1720
|
+
for (const callback of this.drainPendingCallbacks()) {
|
|
2608
1721
|
clearTimeout(callback.timeout);
|
|
2609
|
-
callback.callback(
|
|
1722
|
+
callback.callback(258 /* NOT_CONNECTED */);
|
|
2610
1723
|
}
|
|
2611
1724
|
const onDisconnect = this._onPortDisconnect;
|
|
2612
1725
|
this._onPortDisconnect = null;
|
|
@@ -2650,38 +1763,48 @@ class VexSerialConnection extends VexEventTarget {
|
|
|
2650
1763
|
try {
|
|
2651
1764
|
await port.close();
|
|
2652
1765
|
} catch (e) {
|
|
2653
|
-
|
|
1766
|
+
this.reportWarning("failed to close the serial port", e);
|
|
2654
1767
|
}
|
|
2655
1768
|
}
|
|
2656
1769
|
if (this._wasConnected) {
|
|
2657
1770
|
this._wasConnected = false;
|
|
2658
|
-
this.
|
|
1771
|
+
this.emitSafely("disconnected", undefined);
|
|
2659
1772
|
}
|
|
2660
1773
|
}
|
|
2661
1774
|
open(use = 0, askUser = true) {
|
|
2662
|
-
if (this.
|
|
2663
|
-
return
|
|
2664
|
-
|
|
2665
|
-
|
|
1775
|
+
if (this._openPromise !== null)
|
|
1776
|
+
return new import_neverthrow.ResultAsync(this._openPromise);
|
|
1777
|
+
const opening = this._open(use, askUser);
|
|
1778
|
+
this._openPromise = opening;
|
|
1779
|
+
opening.then(() => {
|
|
1780
|
+
if (this._openPromise === opening)
|
|
1781
|
+
this._openPromise = null;
|
|
1782
|
+
}, () => {
|
|
1783
|
+
if (this._openPromise === opening)
|
|
1784
|
+
this._openPromise = null;
|
|
1785
|
+
});
|
|
1786
|
+
return new import_neverthrow.ResultAsync(opening);
|
|
2666
1787
|
}
|
|
2667
1788
|
async _open(use, askUser) {
|
|
2668
|
-
|
|
2669
|
-
|
|
2670
|
-
|
|
2671
|
-
|
|
2672
|
-
return this.filters.find((f) => (f.usbVendorId === undefined || f.usbVendorId === info.usbVendorId) && (f.usbProductId === undefined || f.usbProductId === info.usbProductId));
|
|
2673
|
-
}).filter((candidate) => candidate.readable === null);
|
|
2674
|
-
port = ports[use];
|
|
1789
|
+
if (this._closePromise !== null)
|
|
1790
|
+
await this._closePromise;
|
|
1791
|
+
if (this.port !== undefined) {
|
|
1792
|
+
return import_neverthrow.err(new VexIoError("Already connected."));
|
|
2675
1793
|
}
|
|
1794
|
+
const ports = (await this.serial.getPorts()).filter((p) => {
|
|
1795
|
+
const info = p.getInfo();
|
|
1796
|
+
return this.filters.find((f) => (f.usbVendorId === undefined || f.usbVendorId === info.usbVendorId) && (f.usbProductId === undefined || f.usbProductId === info.usbProductId));
|
|
1797
|
+
}).filter((candidate) => candidate.readable === null);
|
|
1798
|
+
let port = ports[use];
|
|
2676
1799
|
if (port == null && askUser) {
|
|
2677
1800
|
try {
|
|
2678
1801
|
port = await this.serial.requestPort({ filters: this.filters });
|
|
2679
1802
|
} catch {}
|
|
2680
1803
|
}
|
|
2681
1804
|
if (port == null)
|
|
2682
|
-
return import_neverthrow.ok(
|
|
1805
|
+
return import_neverthrow.ok("no-port");
|
|
2683
1806
|
if (port.readable != null)
|
|
2684
|
-
return import_neverthrow.ok(
|
|
1807
|
+
return import_neverthrow.ok("busy");
|
|
2685
1808
|
try {
|
|
2686
1809
|
this.port = port;
|
|
2687
1810
|
await port.open({ baudRate: 115200 });
|
|
@@ -2693,46 +1816,79 @@ class VexSerialConnection extends VexEventTarget {
|
|
|
2693
1816
|
this.reader = this.port.readable.getReader();
|
|
2694
1817
|
this.startReader();
|
|
2695
1818
|
this._wasConnected = true;
|
|
2696
|
-
this.
|
|
2697
|
-
return import_neverthrow.ok(
|
|
2698
|
-
} catch {
|
|
2699
|
-
await this.
|
|
2700
|
-
return import_neverthrow.
|
|
1819
|
+
this.emitSafely("connected", undefined);
|
|
1820
|
+
return import_neverthrow.ok("opened");
|
|
1821
|
+
} catch (e) {
|
|
1822
|
+
await this._doClose();
|
|
1823
|
+
return import_neverthrow.err(toVexSerialError(e, "io"));
|
|
1824
|
+
}
|
|
1825
|
+
}
|
|
1826
|
+
async writeDataAsync(rawData, timeout = 1000) {
|
|
1827
|
+
if (rawData instanceof DeviceBoundPacket) {
|
|
1828
|
+
return this.serializeCommand(rawData.commandId, rawData.commandExtendedId, () => this.writeDataAsyncUnserialized(rawData, timeout));
|
|
1829
|
+
}
|
|
1830
|
+
return this.writeDataAsyncUnserialized(rawData, timeout);
|
|
1831
|
+
}
|
|
1832
|
+
async serializeCommand(commandId, commandExtendedId, operation) {
|
|
1833
|
+
const key = `${commandId}:${commandExtendedId ?? ""}`;
|
|
1834
|
+
const previous = this.pendingCommandTails.get(key) ?? Promise.resolve();
|
|
1835
|
+
let release = () => {};
|
|
1836
|
+
const current = new Promise((resolve) => {
|
|
1837
|
+
release = resolve;
|
|
1838
|
+
});
|
|
1839
|
+
this.pendingCommandTails.set(key, current);
|
|
1840
|
+
await previous;
|
|
1841
|
+
try {
|
|
1842
|
+
return await operation();
|
|
1843
|
+
} finally {
|
|
1844
|
+
release();
|
|
1845
|
+
if (this.pendingCommandTails.get(key) === current) {
|
|
1846
|
+
this.pendingCommandTails.delete(key);
|
|
1847
|
+
}
|
|
2701
1848
|
}
|
|
2702
1849
|
}
|
|
2703
|
-
|
|
2704
|
-
this.writeDataAsync(rawData, timeout).then(resolve);
|
|
2705
|
-
}
|
|
2706
|
-
async writeDataAsync(rawData, timeout = 1000) {
|
|
1850
|
+
async writeDataAsyncUnserialized(rawData, timeout) {
|
|
2707
1851
|
return new Promise((resolve) => {
|
|
2708
|
-
if (this.writer === undefined) {
|
|
2709
|
-
resolve(
|
|
1852
|
+
if (this.writer === undefined || this._isClosing) {
|
|
1853
|
+
resolve(258 /* NOT_CONNECTED */);
|
|
2710
1854
|
return;
|
|
2711
1855
|
}
|
|
2712
1856
|
const data = rawData instanceof DeviceBoundPacket ? rawData.data : rawData;
|
|
1857
|
+
const queue = rawData instanceof DeviceBoundPacket ? this.getPendingQueue(rawData.commandId, rawData.commandExtendedId, true) : this.rawCallbacks;
|
|
2713
1858
|
const cb = {
|
|
1859
|
+
active: true,
|
|
2714
1860
|
callback: resolve,
|
|
2715
1861
|
timeout: setTimeout(() => {
|
|
2716
|
-
|
|
2717
|
-
if (index === -1)
|
|
1862
|
+
if (!this.removePendingCallback(cb))
|
|
2718
1863
|
return;
|
|
2719
|
-
this.callbacksQueue.splice(index, 1);
|
|
2720
1864
|
cb.callback(256 /* TIMEOUT */);
|
|
2721
1865
|
}, timeout),
|
|
1866
|
+
next: undefined,
|
|
1867
|
+
previous: undefined,
|
|
1868
|
+
queue,
|
|
2722
1869
|
wantedCommandId: rawData instanceof DeviceBoundPacket ? rawData.commandId : undefined,
|
|
2723
1870
|
wantedCommandExId: rawData instanceof DeviceBoundPacket ? rawData.commandExtendedId : undefined
|
|
2724
1871
|
};
|
|
2725
|
-
this.
|
|
1872
|
+
this.enqueuePendingCallback(cb);
|
|
2726
1873
|
this.writer.write(data).catch(() => {
|
|
2727
|
-
|
|
2728
|
-
if (index === -1)
|
|
1874
|
+
if (!this.removePendingCallback(cb))
|
|
2729
1875
|
return;
|
|
2730
|
-
this.callbacksQueue.splice(index, 1);
|
|
2731
1876
|
clearTimeout(cb.timeout);
|
|
2732
1877
|
resolve(257 /* WRITE_ERROR */);
|
|
2733
1878
|
});
|
|
2734
1879
|
});
|
|
2735
1880
|
}
|
|
1881
|
+
request(packet, ReplyType, timeout = 1000) {
|
|
1882
|
+
return new import_neverthrow.ResultAsync((async () => {
|
|
1883
|
+
const result = await this.writeDataAsync(packet, timeout);
|
|
1884
|
+
if (result instanceof ReplyType)
|
|
1885
|
+
return import_neverthrow.ok(result);
|
|
1886
|
+
if (result === 258 /* NOT_CONNECTED */) {
|
|
1887
|
+
return import_neverthrow.err(new VexNotConnectedError);
|
|
1888
|
+
}
|
|
1889
|
+
return import_neverthrow.err(new VexProtocolError(expectedReplyMessage(packet, ReplyType, result), typeof result === "number" ? result : undefined));
|
|
1890
|
+
})());
|
|
1891
|
+
}
|
|
2736
1892
|
async readData(cache, expectedSize) {
|
|
2737
1893
|
if (this.reader == null)
|
|
2738
1894
|
throw new Error("No reader");
|
|
@@ -2740,93 +1896,172 @@ class VexSerialConnection extends VexEventTarget {
|
|
|
2740
1896
|
const { value: readData, done: isDone } = await this.reader.read();
|
|
2741
1897
|
if (isDone)
|
|
2742
1898
|
throw new Error("No data");
|
|
2743
|
-
cache
|
|
1899
|
+
cache.append(readData);
|
|
2744
1900
|
}
|
|
2745
|
-
return cache;
|
|
2746
1901
|
}
|
|
2747
1902
|
async startReader() {
|
|
2748
|
-
|
|
1903
|
+
const cache = new ReceiveBuffer;
|
|
2749
1904
|
let sliceIdx = 0;
|
|
2750
1905
|
for (;; )
|
|
2751
1906
|
try {
|
|
2752
|
-
|
|
1907
|
+
await this.readData(cache, 5);
|
|
2753
1908
|
sliceIdx = 0;
|
|
2754
|
-
while (!thePacketEncoder.validateHeader(cache)) {
|
|
2755
|
-
const
|
|
1909
|
+
while (!thePacketEncoder.validateHeader(cache.bytes)) {
|
|
1910
|
+
const bytes = cache.bytes;
|
|
1911
|
+
const nextHeader = bytes.findIndex((byte, index) => index > 0 && byte === PacketEncoder.HEADER_TO_HOST[0] && bytes[index + 1] === PacketEncoder.HEADER_TO_HOST[1]);
|
|
2756
1912
|
if (nextHeader >= 0) {
|
|
2757
|
-
cache
|
|
1913
|
+
cache.discard(nextHeader);
|
|
2758
1914
|
} else {
|
|
2759
|
-
cache
|
|
1915
|
+
cache.discard(bytes.at(-1) === PacketEncoder.HEADER_TO_HOST[0] ? -1 : bytes.length);
|
|
2760
1916
|
}
|
|
2761
|
-
|
|
1917
|
+
await this.readData(cache, 5);
|
|
2762
1918
|
}
|
|
2763
|
-
const payloadExpectedSize = thePacketEncoder.getPayloadSize(cache);
|
|
2764
|
-
const n = thePacketEncoder.getHostHeaderLength(cache);
|
|
1919
|
+
const payloadExpectedSize = thePacketEncoder.getPayloadSize(cache.bytes);
|
|
1920
|
+
const n = thePacketEncoder.getHostHeaderLength(cache.bytes);
|
|
2765
1921
|
const totalSize = n + payloadExpectedSize;
|
|
2766
|
-
|
|
1922
|
+
await this.readData(cache, totalSize);
|
|
2767
1923
|
sliceIdx = totalSize;
|
|
2768
|
-
const
|
|
1924
|
+
const packet = cache.copy(totalSize);
|
|
1925
|
+
const cmdId = packet[2];
|
|
2769
1926
|
const hasExtId = cmdId === 88 || cmdId === 86;
|
|
2770
|
-
const cmdExId = hasExtId ?
|
|
2771
|
-
const ack =
|
|
1927
|
+
const cmdExId = hasExtId ? packet[n] : undefined;
|
|
1928
|
+
const ack = packet[n + 1];
|
|
2772
1929
|
if (hasExtId) {
|
|
2773
|
-
if (!thePacketEncoder.validateMessageCdc(
|
|
2774
|
-
|
|
2775
|
-
|
|
2776
|
-
|
|
2777
|
-
|
|
2778
|
-
|
|
2779
|
-
let tryIdx = 0;
|
|
2780
|
-
while ((callbackInfo = this.callbacksQueue[tryIdx++]) !== undefined) {
|
|
2781
|
-
wantedCmdId = callbackInfo?.wantedCommandId;
|
|
2782
|
-
wantedCmdExId = callbackInfo?.wantedCommandExId;
|
|
2783
|
-
if (wantedCmdId !== undefined && wantedCmdId !== cmdId || wantedCmdExId !== undefined && wantedCmdExId !== cmdExId) {
|
|
1930
|
+
if (!thePacketEncoder.validateMessageCdc(packet)) {
|
|
1931
|
+
this.reportWarning("discarding a reply with an invalid CDC CRC", {
|
|
1932
|
+
commandId: cmdId,
|
|
1933
|
+
commandExtendedId: cmdExId,
|
|
1934
|
+
ack
|
|
1935
|
+
});
|
|
2784
1936
|
continue;
|
|
2785
1937
|
}
|
|
2786
|
-
break;
|
|
2787
1938
|
}
|
|
1939
|
+
const callbackInfo = this.shiftPendingCallback(cmdId, cmdExId) ?? this.shiftRawCallback();
|
|
2788
1940
|
if (callbackInfo === undefined) {
|
|
2789
|
-
|
|
1941
|
+
this.reportWarning("received a reply with no matching request", {
|
|
1942
|
+
commandId: cmdId,
|
|
1943
|
+
commandExtendedId: cmdExId,
|
|
1944
|
+
ack
|
|
1945
|
+
});
|
|
2790
1946
|
continue;
|
|
2791
1947
|
}
|
|
2792
|
-
const
|
|
2793
|
-
const
|
|
2794
|
-
|
|
2795
|
-
|
|
1948
|
+
const wantedCmdId = callbackInfo.wantedCommandId;
|
|
1949
|
+
const wantedCmdExId = callbackInfo.wantedCommandExId;
|
|
1950
|
+
const PackageType = thePacketEncoder.getPacketType(wantedCmdId, wantedCmdExId);
|
|
1951
|
+
if (wantedCmdId === undefined || PackageType === undefined) {
|
|
1952
|
+
if (wantedCmdId !== undefined) {
|
|
1953
|
+
this.reportWarning("no packet class is registered for the wanted command", { commandId: wantedCmdId, commandExtendedId: wantedCmdExId });
|
|
1954
|
+
}
|
|
1955
|
+
callbackInfo.callback(packet.buffer);
|
|
2796
1956
|
} else {
|
|
2797
|
-
if (
|
|
2798
|
-
callbackInfo.callback(new PackageType(
|
|
1957
|
+
if (PackageType.isValidPacket(packet, n)) {
|
|
1958
|
+
callbackInfo.callback(new PackageType(packet));
|
|
2799
1959
|
} else {
|
|
2800
|
-
|
|
1960
|
+
this.reportWarning("reply failed packet validation; delivering its ack instead", { commandId: cmdId, commandExtendedId: cmdExId, ack });
|
|
2801
1961
|
callbackInfo.callback(ack);
|
|
2802
1962
|
}
|
|
2803
1963
|
}
|
|
2804
1964
|
clearTimeout(callbackInfo.timeout);
|
|
2805
|
-
this.callbacksQueue.splice(tryIdx - 1, 1);
|
|
2806
1965
|
} catch (e) {
|
|
2807
1966
|
if (!(e instanceof Error && e.message === "No data")) {
|
|
2808
|
-
|
|
1967
|
+
this.reportWarning("reader loop stopped by a read error", {
|
|
1968
|
+
error: e,
|
|
1969
|
+
pendingBytes: cache.bytes
|
|
1970
|
+
});
|
|
2809
1971
|
}
|
|
2810
1972
|
await this.close();
|
|
2811
1973
|
break;
|
|
2812
1974
|
} finally {
|
|
2813
|
-
cache
|
|
1975
|
+
cache.discard(sliceIdx);
|
|
1976
|
+
}
|
|
1977
|
+
}
|
|
1978
|
+
pendingKey(commandId, commandExtendedId) {
|
|
1979
|
+
return `${commandId}:${commandExtendedId ?? ""}`;
|
|
1980
|
+
}
|
|
1981
|
+
getPendingQueue(commandId, commandExtendedId, create) {
|
|
1982
|
+
const key = this.pendingKey(commandId, commandExtendedId);
|
|
1983
|
+
let queue = this.pendingCallbacks.get(key);
|
|
1984
|
+
if (queue === undefined && create) {
|
|
1985
|
+
const created = { head: undefined, tail: undefined };
|
|
1986
|
+
this.pendingCallbacks.set(key, created);
|
|
1987
|
+
queue = created;
|
|
1988
|
+
}
|
|
1989
|
+
return queue ?? { head: undefined, tail: undefined };
|
|
1990
|
+
}
|
|
1991
|
+
enqueuePendingCallback(callback) {
|
|
1992
|
+
const tail = callback.queue.tail;
|
|
1993
|
+
callback.previous = tail;
|
|
1994
|
+
if (tail === undefined)
|
|
1995
|
+
callback.queue.head = callback;
|
|
1996
|
+
else
|
|
1997
|
+
tail.next = callback;
|
|
1998
|
+
callback.queue.tail = callback;
|
|
1999
|
+
}
|
|
2000
|
+
removePendingCallback(callback) {
|
|
2001
|
+
if (!callback.active)
|
|
2002
|
+
return false;
|
|
2003
|
+
callback.active = false;
|
|
2004
|
+
const { queue, previous, next } = callback;
|
|
2005
|
+
if (previous === undefined)
|
|
2006
|
+
queue.head = next;
|
|
2007
|
+
else
|
|
2008
|
+
previous.next = next;
|
|
2009
|
+
if (next === undefined)
|
|
2010
|
+
queue.tail = previous;
|
|
2011
|
+
else
|
|
2012
|
+
next.previous = previous;
|
|
2013
|
+
callback.previous = undefined;
|
|
2014
|
+
callback.next = undefined;
|
|
2015
|
+
if (queue !== this.rawCallbacks && queue.head === undefined && callback.wantedCommandId !== undefined) {
|
|
2016
|
+
this.pendingCallbacks.delete(this.pendingKey(callback.wantedCommandId, callback.wantedCommandExId));
|
|
2017
|
+
}
|
|
2018
|
+
return true;
|
|
2019
|
+
}
|
|
2020
|
+
shiftPendingCallback(commandId, commandExtendedId) {
|
|
2021
|
+
const queue = this.getPendingQueue(commandId, commandExtendedId, false);
|
|
2022
|
+
const callback = queue.head;
|
|
2023
|
+
if (callback !== undefined)
|
|
2024
|
+
this.removePendingCallback(callback);
|
|
2025
|
+
return callback;
|
|
2026
|
+
}
|
|
2027
|
+
shiftRawCallback() {
|
|
2028
|
+
const callback = this.rawCallbacks.head;
|
|
2029
|
+
if (callback !== undefined)
|
|
2030
|
+
this.removePendingCallback(callback);
|
|
2031
|
+
return callback;
|
|
2032
|
+
}
|
|
2033
|
+
hasPendingCallbacks() {
|
|
2034
|
+
return this.pendingCallbacks.size > 0 || this.rawCallbacks.head !== undefined;
|
|
2035
|
+
}
|
|
2036
|
+
drainPendingCallbacks() {
|
|
2037
|
+
const callbacks = [];
|
|
2038
|
+
for (const queue of this.pendingCallbacks.values()) {
|
|
2039
|
+
for (let callback = queue.head;callback; ) {
|
|
2040
|
+
const next = callback.next;
|
|
2041
|
+
callback.active = false;
|
|
2042
|
+
callback.previous = undefined;
|
|
2043
|
+
callback.next = undefined;
|
|
2044
|
+
callbacks.push(callback);
|
|
2045
|
+
callback = next;
|
|
2814
2046
|
}
|
|
2047
|
+
}
|
|
2048
|
+
for (let callback = this.rawCallbacks.head;callback; ) {
|
|
2049
|
+
const next = callback.next;
|
|
2050
|
+
callback.active = false;
|
|
2051
|
+
callback.previous = undefined;
|
|
2052
|
+
callback.next = undefined;
|
|
2053
|
+
callbacks.push(callback);
|
|
2054
|
+
callback = next;
|
|
2055
|
+
}
|
|
2056
|
+
this.pendingCallbacks.clear();
|
|
2057
|
+
this.rawCallbacks = { head: undefined, tail: undefined };
|
|
2058
|
+
return callbacks;
|
|
2815
2059
|
}
|
|
2816
2060
|
query1() {
|
|
2817
|
-
return
|
|
2818
|
-
const result = await this.writeDataAsync(new Query1H2DPacket, 100);
|
|
2819
|
-
return result instanceof Query1ReplyD2HPacket ? import_neverthrow.ok(result) : import_neverthrow.err(new VexProtocolError("query1 was not acknowledged"));
|
|
2820
|
-
})());
|
|
2061
|
+
return this.request(new Query1H2DPacket, Query1ReplyD2HPacket, 100);
|
|
2821
2062
|
}
|
|
2822
2063
|
getSystemVersion() {
|
|
2823
|
-
return new
|
|
2824
|
-
const result = await this.writeDataAsync(new SystemVersionH2DPacket);
|
|
2825
|
-
if (result instanceof SystemVersionReplyD2HPacket) {
|
|
2826
|
-
return import_neverthrow.ok(result.version);
|
|
2827
|
-
}
|
|
2828
|
-
return import_neverthrow.err(new VexProtocolError("system version was not acknowledged"));
|
|
2829
|
-
})());
|
|
2064
|
+
return this.request(new SystemVersionH2DPacket, SystemVersionReplyD2HPacket).map((result) => result.version);
|
|
2830
2065
|
}
|
|
2831
2066
|
}
|
|
2832
2067
|
|
|
@@ -2853,34 +2088,19 @@ class V5SerialConnection extends VexSerialConnection {
|
|
|
2853
2088
|
}
|
|
2854
2089
|
}
|
|
2855
2090
|
getDeviceStatus() {
|
|
2856
|
-
return
|
|
2857
|
-
const result = await this.writeDataAsync(new GetDeviceStatusH2DPacket);
|
|
2858
|
-
return result instanceof GetDeviceStatusReplyD2HPacket ? import_neverthrow.ok(result) : import_neverthrow.err(new VexProtocolError("device status was not acknowledged"));
|
|
2859
|
-
})());
|
|
2091
|
+
return this.request(new GetDeviceStatusH2DPacket, GetDeviceStatusReplyD2HPacket);
|
|
2860
2092
|
}
|
|
2861
2093
|
getRadioStatus() {
|
|
2862
|
-
return
|
|
2863
|
-
const result = await this.writeDataAsync(new GetRadioStatusH2DPacket);
|
|
2864
|
-
return result instanceof GetRadioStatusReplyD2HPacket ? import_neverthrow.ok(result) : import_neverthrow.err(new VexProtocolError("radio status was not acknowledged"));
|
|
2865
|
-
})());
|
|
2094
|
+
return this.request(new GetRadioStatusH2DPacket, GetRadioStatusReplyD2HPacket);
|
|
2866
2095
|
}
|
|
2867
2096
|
getSystemFlags() {
|
|
2868
|
-
return
|
|
2869
|
-
const result = await this.writeDataAsync(new GetSystemFlagsH2DPacket);
|
|
2870
|
-
return result instanceof GetSystemFlagsReplyD2HPacket ? import_neverthrow.ok(result) : import_neverthrow.err(new VexProtocolError("system flags were not acknowledged"));
|
|
2871
|
-
})());
|
|
2097
|
+
return this.request(new GetSystemFlagsH2DPacket, GetSystemFlagsReplyD2HPacket);
|
|
2872
2098
|
}
|
|
2873
2099
|
getSystemStatus(timeout = 1000) {
|
|
2874
|
-
return
|
|
2875
|
-
const result = await this.writeDataAsync(new GetSystemStatusH2DPacket, timeout);
|
|
2876
|
-
return result instanceof GetSystemStatusReplyD2HPacket ? import_neverthrow.ok(result) : import_neverthrow.err(new VexProtocolError("system status was not acknowledged"));
|
|
2877
|
-
})());
|
|
2100
|
+
return this.request(new GetSystemStatusH2DPacket, GetSystemStatusReplyD2HPacket, timeout);
|
|
2878
2101
|
}
|
|
2879
2102
|
getMatchStatus() {
|
|
2880
|
-
return
|
|
2881
|
-
const result = await this.writeDataAsync(new GetMatchStatusH2DPacket);
|
|
2882
|
-
return result instanceof MatchStatusReplyD2HPacket ? import_neverthrow.ok(result) : import_neverthrow.err(new VexProtocolError("match status was not acknowledged"));
|
|
2883
|
-
})());
|
|
2103
|
+
return this.request(new GetMatchStatusH2DPacket, MatchStatusReplyD2HPacket);
|
|
2884
2104
|
}
|
|
2885
2105
|
uploadProgramToDevice(iniConfig, binFileBuf, coldFileBuf, progressCallback) {
|
|
2886
2106
|
return wrapTransfer(this, () => this._uploadProgramToDevice(iniConfig, binFileBuf, coldFileBuf, progressCallback));
|
|
@@ -2941,32 +2161,35 @@ class V5SerialConnection extends VexSerialConnection {
|
|
|
2941
2161
|
async _downloadFileToHostUnlocked(request, downloadTarget, progressCallback) {
|
|
2942
2162
|
const { filename, vendor, loadAddress, size } = request;
|
|
2943
2163
|
let nextAddress = loadAddress ?? USER_FLASH_USR_CODE_START;
|
|
2944
|
-
const
|
|
2945
|
-
if (
|
|
2946
|
-
return import_neverthrow.err(
|
|
2947
|
-
}
|
|
2164
|
+
const p1Result = await this.request(new InitFileTransferH2DPacket(2 /* READ */, downloadTarget, vendor, 0 /* NONE */, new Uint8Array, nextAddress, filename, ""), InitFileTransferReplyD2HPacket);
|
|
2165
|
+
if (p1Result.isErr())
|
|
2166
|
+
return import_neverthrow.err(p1Result.error);
|
|
2948
2167
|
let transferFailed = true;
|
|
2949
2168
|
let result = import_neverthrow.ok(new Uint8Array);
|
|
2950
2169
|
try {
|
|
2170
|
+
const p1 = p1Result.value;
|
|
2951
2171
|
const fileSize = size ?? p1.fileSize;
|
|
2952
2172
|
const bufferChunkSize = getTransferChunkSize(p1.windowSize);
|
|
2953
2173
|
let bufferOffset = 0;
|
|
2954
2174
|
const fileBuf = new Uint8Array(fileSize);
|
|
2955
2175
|
while (bufferOffset < fileSize) {
|
|
2956
|
-
const
|
|
2957
|
-
const
|
|
2958
|
-
|
|
2959
|
-
|
|
2960
|
-
|
|
2176
|
+
const remainingSize = fileSize - bufferOffset;
|
|
2177
|
+
const chunkSize = Math.min(bufferChunkSize, remainingSize);
|
|
2178
|
+
const requestedSize = chunkSize + 3 & ~3;
|
|
2179
|
+
const p2Result = await this.request(new ReadFileH2DPacket(nextAddress, requestedSize), ReadFileReplyD2HPacket, 3000);
|
|
2180
|
+
if (p2Result.isErr())
|
|
2181
|
+
throw p2Result.error;
|
|
2182
|
+
const p2 = p2Result.value;
|
|
2961
2183
|
if (p2.addr !== nextAddress) {
|
|
2962
2184
|
throw new VexTransferError(`ReadFileReplyD2HPacket returned address ${p2.addr}, expected ${nextAddress}`);
|
|
2963
2185
|
}
|
|
2964
2186
|
if (p2.length <= 0 || p2.length > requestedSize || p2.buf.byteLength !== p2.length) {
|
|
2965
2187
|
throw new VexTransferError(`ReadFileReplyD2HPacket returned invalid length ${p2.length}`);
|
|
2966
2188
|
}
|
|
2967
|
-
|
|
2968
|
-
|
|
2969
|
-
|
|
2189
|
+
const receivedSize = Math.min(p2.length, remainingSize);
|
|
2190
|
+
fileBuf.set(p2.buf.subarray(0, receivedSize), bufferOffset);
|
|
2191
|
+
bufferOffset += receivedSize;
|
|
2192
|
+
nextAddress += receivedSize;
|
|
2970
2193
|
progressCallback?.(bufferOffset, fileSize);
|
|
2971
2194
|
}
|
|
2972
2195
|
transferFailed = false;
|
|
@@ -2975,11 +2198,12 @@ class V5SerialConnection extends VexSerialConnection {
|
|
|
2975
2198
|
result = import_neverthrow.err(e instanceof VexSerialError ? e : toVexSerialError(e, "transfer"));
|
|
2976
2199
|
} finally {
|
|
2977
2200
|
try {
|
|
2978
|
-
await this.
|
|
2979
|
-
|
|
2980
|
-
|
|
2981
|
-
|
|
2982
|
-
|
|
2201
|
+
const exitResult = await this.request(new ExitFileTransferH2DPacket(3 /* EXIT_HALT */), ExitFileTransferReplyD2HPacket, 30000);
|
|
2202
|
+
if (!transferFailed && exitResult.isErr())
|
|
2203
|
+
result = import_neverthrow.err(exitResult.error);
|
|
2204
|
+
} catch (e) {
|
|
2205
|
+
if (!transferFailed)
|
|
2206
|
+
result = import_neverthrow.err(toVexSerialError(e, "io"));
|
|
2983
2207
|
}
|
|
2984
2208
|
}
|
|
2985
2209
|
return result;
|
|
@@ -3004,22 +2228,20 @@ class V5SerialConnection extends VexSerialConnection {
|
|
|
3004
2228
|
downloadTarget = downloadTarget ?? 1 /* FILE_TARGET_QSPI */;
|
|
3005
2229
|
vendor = vendor ?? 1 /* USER */;
|
|
3006
2230
|
let nextAddress = loadAddress ?? USER_FLASH_USR_CODE_START;
|
|
3007
|
-
const
|
|
3008
|
-
if (
|
|
3009
|
-
return import_neverthrow.err(
|
|
3010
|
-
|
|
2231
|
+
const p1Result = await this.request(new InitFileTransferH2DPacket(1 /* WRITE */, downloadTarget, vendor, 1 /* OVERWRITE */, buf, nextAddress, filename, exttype), InitFileTransferReplyD2HPacket);
|
|
2232
|
+
if (p1Result.isErr())
|
|
2233
|
+
return import_neverthrow.err(p1Result.error);
|
|
2234
|
+
const p1 = p1Result.value;
|
|
3011
2235
|
const bufferChunkSize = getTransferChunkSize(p1.windowSize);
|
|
3012
2236
|
let bufferOffset = 0;
|
|
3013
2237
|
let lastBlock = false;
|
|
3014
2238
|
let transferFailed = true;
|
|
3015
|
-
let exitReply;
|
|
3016
2239
|
let result = import_neverthrow.ok(false);
|
|
3017
2240
|
try {
|
|
3018
2241
|
if (linkedFile !== undefined) {
|
|
3019
|
-
const
|
|
3020
|
-
if (
|
|
3021
|
-
throw
|
|
3022
|
-
}
|
|
2242
|
+
const p3Result = await this.request(new LinkFileH2DPacket(linkedFile.vendor ?? 1 /* USER */, linkedFile.filename, 0), LinkFileReplyD2HPacket, 1e4);
|
|
2243
|
+
if (p3Result.isErr())
|
|
2244
|
+
throw p3Result.error;
|
|
3023
2245
|
}
|
|
3024
2246
|
while (!lastBlock) {
|
|
3025
2247
|
let tmpbuf;
|
|
@@ -3031,23 +2253,21 @@ class V5SerialConnection extends VexSerialConnection {
|
|
|
3031
2253
|
tmpbuf.set(buf.subarray(bufferOffset, buf.byteLength));
|
|
3032
2254
|
lastBlock = true;
|
|
3033
2255
|
}
|
|
3034
|
-
const
|
|
3035
|
-
if (
|
|
3036
|
-
throw
|
|
3037
|
-
if (progressCallback != null)
|
|
3038
|
-
progressCallback(bufferOffset, buf.byteLength);
|
|
2256
|
+
const p2Result = await this.request(new WriteFileH2DPacket(nextAddress, tmpbuf), WriteFileReplyD2HPacket, 3000);
|
|
2257
|
+
if (p2Result.isErr())
|
|
2258
|
+
throw p2Result.error;
|
|
3039
2259
|
bufferOffset += bufferChunkSize;
|
|
3040
2260
|
nextAddress += bufferChunkSize;
|
|
2261
|
+
progressCallback?.(Math.min(bufferOffset, buf.byteLength), buf.byteLength);
|
|
3041
2262
|
}
|
|
3042
|
-
progressCallback?.(buf.byteLength, buf.byteLength);
|
|
3043
2263
|
transferFailed = false;
|
|
3044
2264
|
} catch (e) {
|
|
3045
2265
|
result = import_neverthrow.err(e instanceof VexSerialError ? e : toVexSerialError(e, "transfer"));
|
|
3046
2266
|
} finally {
|
|
3047
2267
|
try {
|
|
3048
|
-
|
|
2268
|
+
const exitResult = await this.request(new ExitFileTransferH2DPacket(transferFailed ? 3 /* EXIT_HALT */ : autoRun ? 1 /* EXIT_RUN */ : 3 /* EXIT_HALT */), ExitFileTransferReplyD2HPacket, 30000);
|
|
3049
2269
|
if (!transferFailed) {
|
|
3050
|
-
result =
|
|
2270
|
+
result = exitResult.map(() => true);
|
|
3051
2271
|
}
|
|
3052
2272
|
} catch (cleanupError) {
|
|
3053
2273
|
if (!transferFailed) {
|
|
@@ -3069,14 +2289,20 @@ class V5SerialConnection extends VexSerialConnection {
|
|
|
3069
2289
|
}
|
|
3070
2290
|
let result;
|
|
3071
2291
|
try {
|
|
3072
|
-
const
|
|
3073
|
-
result =
|
|
2292
|
+
const eraseResult = await this.request(new EraseFileH2DPacket(vendor, filename), EraseFileReplyD2HPacket);
|
|
2293
|
+
result = eraseResult.map(() => {
|
|
2294
|
+
return;
|
|
2295
|
+
});
|
|
3074
2296
|
} catch (e) {
|
|
3075
2297
|
result = import_neverthrow.err(toVexSerialError(e, "io"));
|
|
3076
|
-
}
|
|
3077
|
-
|
|
3078
|
-
|
|
3079
|
-
|
|
2298
|
+
}
|
|
2299
|
+
try {
|
|
2300
|
+
const exitResult = await this.request(new ExitFileTransferH2DPacket(3 /* EXIT_HALT */), ExitFileTransferReplyD2HPacket, 30000);
|
|
2301
|
+
if (result.isOk() && exitResult.isErr())
|
|
2302
|
+
result = import_neverthrow.err(exitResult.error);
|
|
2303
|
+
} catch (e) {
|
|
2304
|
+
if (result.isOk())
|
|
2305
|
+
result = import_neverthrow.err(toVexSerialError(e, "io"));
|
|
3080
2306
|
}
|
|
3081
2307
|
return result;
|
|
3082
2308
|
}));
|
|
@@ -3085,23 +2311,26 @@ class V5SerialConnection extends VexSerialConnection {
|
|
|
3085
2311
|
return new import_neverthrow.ResultAsync(this.withFileTransfer(async () => {
|
|
3086
2312
|
let result;
|
|
3087
2313
|
try {
|
|
3088
|
-
const
|
|
3089
|
-
result =
|
|
2314
|
+
const clearResult = await this.request(new FileClearUpH2DPacket(1 /* USER */), FileClearUpReplyD2HPacket, 30000);
|
|
2315
|
+
result = clearResult.map(() => {
|
|
2316
|
+
return;
|
|
2317
|
+
});
|
|
3090
2318
|
} catch (e) {
|
|
3091
2319
|
result = import_neverthrow.err(toVexSerialError(e, "io"));
|
|
3092
|
-
}
|
|
3093
|
-
|
|
3094
|
-
|
|
3095
|
-
|
|
2320
|
+
}
|
|
2321
|
+
try {
|
|
2322
|
+
const exitResult = await this.request(new ExitFileTransferH2DPacket(3 /* EXIT_HALT */), ExitFileTransferReplyD2HPacket, 30000);
|
|
2323
|
+
if (result.isOk() && exitResult.isErr())
|
|
2324
|
+
result = import_neverthrow.err(exitResult.error);
|
|
2325
|
+
} catch (e) {
|
|
2326
|
+
if (result.isOk())
|
|
2327
|
+
result = import_neverthrow.err(toVexSerialError(e, "io"));
|
|
3096
2328
|
}
|
|
3097
2329
|
return result;
|
|
3098
2330
|
}));
|
|
3099
2331
|
}
|
|
3100
2332
|
captureScreenSetup() {
|
|
3101
|
-
return
|
|
3102
|
-
const result = await this.writeDataAsync(new ScreenCaptureH2DPacket(0));
|
|
3103
|
-
return result instanceof ScreenCaptureReplyD2HPacket ? import_neverthrow.ok(result) : import_neverthrow.err(new VexProtocolError("screen capture was rejected"));
|
|
3104
|
-
})());
|
|
2333
|
+
return this.request(new ScreenCaptureH2DPacket(0), ScreenCaptureReplyD2HPacket);
|
|
3105
2334
|
}
|
|
3106
2335
|
captureScreen(progressCallback) {
|
|
3107
2336
|
return wrapTransfer(this, () => this._captureScreen(progressCallback));
|
|
@@ -3115,74 +2344,85 @@ class V5SerialConnection extends VexSerialConnection {
|
|
|
3115
2344
|
filename: "screen",
|
|
3116
2345
|
vendor: 15 /* SYS */,
|
|
3117
2346
|
loadAddress: 0,
|
|
3118
|
-
size:
|
|
2347
|
+
size: SCREEN_CAPTURE_FRAMEBUFFER_SIZE
|
|
3119
2348
|
}, 2 /* FILE_TARGET_CBUF */, progressCallback);
|
|
3120
2349
|
if (framebuffer.isErr())
|
|
3121
2350
|
return import_neverthrow.err(framebuffer.error);
|
|
3122
2351
|
return import_neverthrow.ok(convertScreenCapture(framebuffer.value));
|
|
3123
2352
|
}
|
|
3124
2353
|
setMatchMode(mode) {
|
|
3125
|
-
return new
|
|
3126
|
-
const result = await this.writeDataAsync(new UpdateMatchModeH2DPacket(mode, 0));
|
|
3127
|
-
return result instanceof MatchModeReplyD2HPacket ? import_neverthrow.ok(result) : import_neverthrow.err(new VexProtocolError("setMatchMode was not acknowledged"));
|
|
3128
|
-
})());
|
|
2354
|
+
return this.request(new UpdateMatchModeH2DPacket(mode, 0), MatchModeReplyD2HPacket);
|
|
3129
2355
|
}
|
|
3130
2356
|
runProgram(value) {
|
|
3131
2357
|
return this.loadProgram(value);
|
|
3132
2358
|
}
|
|
3133
2359
|
loadProgram(value) {
|
|
3134
|
-
return new
|
|
3135
|
-
const result = await this.writeDataAsync(new LoadFileActionH2DPacket(1 /* USER */, 0 /* RUN */, value));
|
|
3136
|
-
return result instanceof LoadFileActionReplyD2HPacket ? import_neverthrow.ok(result) : import_neverthrow.err(new VexProtocolError("loadProgram was not acknowledged"));
|
|
3137
|
-
})());
|
|
2360
|
+
return this.request(new LoadFileActionH2DPacket(1 /* USER */, 0 /* RUN */, value), LoadFileActionReplyD2HPacket);
|
|
3138
2361
|
}
|
|
3139
2362
|
stopProgram() {
|
|
3140
|
-
return new
|
|
3141
|
-
const result = await this.writeDataAsync(new LoadFileActionH2DPacket(1 /* USER */, 128 /* STOP */, ""));
|
|
3142
|
-
return result instanceof LoadFileActionReplyD2HPacket ? import_neverthrow.ok(result) : import_neverthrow.err(new VexProtocolError("stopProgram was not acknowledged"));
|
|
3143
|
-
})());
|
|
2363
|
+
return this.request(new LoadFileActionH2DPacket(1 /* USER */, 128 /* STOP */, ""), LoadFileActionReplyD2HPacket);
|
|
3144
2364
|
}
|
|
3145
2365
|
mockTouch(x, y, press) {
|
|
3146
|
-
return new
|
|
3147
|
-
const result = await this.writeDataAsync(new SendDashTouchH2DPacket(x, y, press));
|
|
3148
|
-
return result instanceof SendDashTouchReplyD2HPacket ? import_neverthrow.ok(result) : import_neverthrow.err(new VexProtocolError("mockTouch was not acknowledged"));
|
|
3149
|
-
})());
|
|
2366
|
+
return this.request(new SendDashTouchH2DPacket(x, y, press), SendDashTouchReplyD2HPacket);
|
|
3150
2367
|
}
|
|
3151
2368
|
openScreen(screen, port) {
|
|
3152
|
-
return new
|
|
3153
|
-
|
|
3154
|
-
|
|
3155
|
-
|
|
2369
|
+
return this.request(new SelectDashH2DPacket(screen, port), SelectDashReplyD2HPacket);
|
|
2370
|
+
}
|
|
2371
|
+
}
|
|
2372
|
+
|
|
2373
|
+
class ReceiveBuffer {
|
|
2374
|
+
storage = new Uint8Array(0);
|
|
2375
|
+
start = 0;
|
|
2376
|
+
end = 0;
|
|
2377
|
+
get byteLength() {
|
|
2378
|
+
return this.end - this.start;
|
|
2379
|
+
}
|
|
2380
|
+
get bytes() {
|
|
2381
|
+
return this.storage.subarray(this.start, this.end);
|
|
2382
|
+
}
|
|
2383
|
+
append(chunk) {
|
|
2384
|
+
this.reserve(chunk.byteLength);
|
|
2385
|
+
this.storage.set(chunk, this.end);
|
|
2386
|
+
this.end += chunk.byteLength;
|
|
2387
|
+
}
|
|
2388
|
+
copy(length) {
|
|
2389
|
+
return this.bytes.slice(0, length);
|
|
2390
|
+
}
|
|
2391
|
+
discard(length) {
|
|
2392
|
+
this.start += length < 0 ? this.byteLength + length : length;
|
|
2393
|
+
if (this.start < 0)
|
|
2394
|
+
this.start = 0;
|
|
2395
|
+
if (this.start > this.end)
|
|
2396
|
+
this.start = this.end;
|
|
2397
|
+
if (this.start === this.end) {
|
|
2398
|
+
this.start = 0;
|
|
2399
|
+
this.end = 0;
|
|
2400
|
+
} else if (this.start >= 4096 && this.start * 2 >= this.storage.length) {
|
|
2401
|
+
this.storage.copyWithin(0, this.start, this.end);
|
|
2402
|
+
this.end -= this.start;
|
|
2403
|
+
this.start = 0;
|
|
2404
|
+
}
|
|
2405
|
+
}
|
|
2406
|
+
reserve(additional) {
|
|
2407
|
+
const required = this.byteLength + additional;
|
|
2408
|
+
if (this.storage.length - this.end >= additional)
|
|
2409
|
+
return;
|
|
2410
|
+
if (this.storage.length >= required) {
|
|
2411
|
+
this.storage.copyWithin(0, this.start, this.end);
|
|
2412
|
+
this.end = this.byteLength;
|
|
2413
|
+
this.start = 0;
|
|
2414
|
+
return;
|
|
2415
|
+
}
|
|
2416
|
+
const storage = new Uint8Array(Math.max(required, Math.max(64, this.storage.length * 2)));
|
|
2417
|
+
storage.set(this.bytes);
|
|
2418
|
+
this.end = this.byteLength;
|
|
2419
|
+
this.start = 0;
|
|
2420
|
+
this.storage = storage;
|
|
3156
2421
|
}
|
|
3157
2422
|
}
|
|
3158
|
-
function binaryArrayJoin(left, right) {
|
|
3159
|
-
const leftSize = left != null ? left.byteLength : 0;
|
|
3160
|
-
const rightSize = right != null ? right.byteLength : 0;
|
|
3161
|
-
const all = new Uint8Array(leftSize + rightSize);
|
|
3162
|
-
if (all.length === 0)
|
|
3163
|
-
return new Uint8Array;
|
|
3164
|
-
if (left != null)
|
|
3165
|
-
all.set(new Uint8Array(left), 0);
|
|
3166
|
-
if (right != null)
|
|
3167
|
-
all.set(new Uint8Array(right), leftSize);
|
|
3168
|
-
return all;
|
|
3169
|
-
}
|
|
3170
2423
|
function getTransferChunkSize(windowSize) {
|
|
3171
2424
|
return windowSize > 0 && windowSize <= USER_PROG_CHUNK_SIZE ? windowSize : USER_PROG_CHUNK_SIZE;
|
|
3172
2425
|
}
|
|
3173
|
-
function convertScreenCapture(framebuffer) {
|
|
3174
|
-
const pixels = new Uint8Array(SCREEN_CAPTURE_WIDTH * SCREEN_CAPTURE_HEIGHT * SCREEN_CAPTURE_CHANNELS);
|
|
3175
|
-
for (let row = 0;row < SCREEN_CAPTURE_HEIGHT; row++) {
|
|
3176
|
-
for (let column = 0;column < SCREEN_CAPTURE_WIDTH; column++) {
|
|
3177
|
-
const source = (row * SCREEN_CAPTURE_MESSAGE_WIDTH + column) * SCREEN_CAPTURE_MESSAGE_CHANNELS;
|
|
3178
|
-
const target = (row * SCREEN_CAPTURE_WIDTH + column) * SCREEN_CAPTURE_CHANNELS;
|
|
3179
|
-
pixels[target] = framebuffer[source + 2] ?? 0;
|
|
3180
|
-
pixels[target + 1] = framebuffer[source + 1] ?? 0;
|
|
3181
|
-
pixels[target + 2] = framebuffer[source] ?? 0;
|
|
3182
|
-
}
|
|
3183
|
-
}
|
|
3184
|
-
return pixels;
|
|
3185
|
-
}
|
|
3186
2426
|
function wrapTransfer(conn, operation) {
|
|
3187
2427
|
return new import_neverthrow.ResultAsync(conn.withFileTransfer(async () => {
|
|
3188
2428
|
try {
|
|
@@ -3194,21 +2434,26 @@ function wrapTransfer(conn, operation) {
|
|
|
3194
2434
|
}
|
|
3195
2435
|
}));
|
|
3196
2436
|
}
|
|
3197
|
-
function
|
|
3198
|
-
|
|
2437
|
+
function expectedReplyMessage(packet, ReplyType, reply) {
|
|
2438
|
+
const expected = `expected ${ReplyType.name} for ${packet.constructor.name}`;
|
|
2439
|
+
if (typeof reply === "number")
|
|
2440
|
+
return `${expected}; received ${ackTypeName(reply)}`;
|
|
2441
|
+
if (reply instanceof ArrayBuffer)
|
|
2442
|
+
return `${expected}; received raw ArrayBuffer`;
|
|
2443
|
+
return `${expected}; received ${reply.constructor.name}`;
|
|
2444
|
+
}
|
|
2445
|
+
function ackTypeName(ackType) {
|
|
2446
|
+
return `AckType.${AckType[ackType] ?? "UNKNOWN"} (${ackType})`;
|
|
3199
2447
|
}
|
|
3200
2448
|
// src/VexDeviceState.ts
|
|
3201
|
-
var import_neverthrow4 =
|
|
2449
|
+
var import_neverthrow4 = require("neverthrow");
|
|
3202
2450
|
|
|
3203
2451
|
// src/VexFirmware.ts
|
|
3204
|
-
var import_neverthrow2 =
|
|
2452
|
+
var import_neverthrow2 = require("neverthrow");
|
|
3205
2453
|
var MAX_CATALOG_BYTES = 4 * 1024;
|
|
3206
2454
|
var MAX_VEXOS_BYTES = 64 * 1024 * 1024;
|
|
3207
2455
|
var MAX_FIRMWARE_IMAGE_BYTES = 32 * 1024 * 1024;
|
|
3208
2456
|
var MAX_AGGREGATE_IMAGE_BYTES = 48 * 1024 * 1024;
|
|
3209
|
-
function fromAsyncFn(fn) {
|
|
3210
|
-
return new import_neverthrow2.ResultAsync(fn());
|
|
3211
|
-
}
|
|
3212
2457
|
function downloadFileFromInternet(link, options = {}) {
|
|
3213
2458
|
const { maxBytes = Number.POSITIVE_INFINITY, timeout = 30000 } = options;
|
|
3214
2459
|
if (maxBytes <= 0) {
|
|
@@ -3217,7 +2462,7 @@ function downloadFileFromInternet(link, options = {}) {
|
|
|
3217
2462
|
if (timeout < 0) {
|
|
3218
2463
|
return import_neverthrow2.errAsync(new VexInvalidArgumentError("timeout must be non-negative"));
|
|
3219
2464
|
}
|
|
3220
|
-
return
|
|
2465
|
+
return new import_neverthrow2.ResultAsync(runDownload(link, maxBytes, timeout));
|
|
3221
2466
|
}
|
|
3222
2467
|
async function runDownload(link, maxBytes, timeout) {
|
|
3223
2468
|
const controller = new AbortController;
|
|
@@ -3284,7 +2529,7 @@ function sleepUntilAsync(f, timeout, interval = 20) {
|
|
|
3284
2529
|
if (interval <= 0) {
|
|
3285
2530
|
return import_neverthrow2.errAsync(new VexInvalidArgumentError("interval must be positive"));
|
|
3286
2531
|
}
|
|
3287
|
-
return
|
|
2532
|
+
return new import_neverthrow2.ResultAsync(runSleepUntilAsync(f, timeout, interval));
|
|
3288
2533
|
}
|
|
3289
2534
|
async function runSleepUntilAsync(f, timeout, interval) {
|
|
3290
2535
|
const deadline = Date.now() + timeout;
|
|
@@ -3309,7 +2554,7 @@ function sleepUntil(f, timeout, interval = 20) {
|
|
|
3309
2554
|
if (interval <= 0) {
|
|
3310
2555
|
return import_neverthrow2.errAsync(new VexInvalidArgumentError("interval must be positive"));
|
|
3311
2556
|
}
|
|
3312
|
-
return
|
|
2557
|
+
return new import_neverthrow2.ResultAsync(runSleepUntil(f, timeout, interval));
|
|
3313
2558
|
}
|
|
3314
2559
|
async function runSleepUntil(f, timeout, interval) {
|
|
3315
2560
|
const deadline = Date.now() + timeout;
|
|
@@ -3336,6 +2581,59 @@ function sleep(ms) {
|
|
|
3336
2581
|
async function sleepInner(ms) {
|
|
3337
2582
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
3338
2583
|
}
|
|
2584
|
+
async function flashFactoryImage(conn, options, pcb) {
|
|
2585
|
+
const { image, label, downloadTarget } = options;
|
|
2586
|
+
pcb(`FACTORY ENB ${label}`, 0, 0);
|
|
2587
|
+
const enableReply = await conn.request(new FactoryEnableH2DPacket, FactoryEnableReplyD2HPacket);
|
|
2588
|
+
if (enableReply.isErr())
|
|
2589
|
+
return import_neverthrow2.err(enableReply.error);
|
|
2590
|
+
const writeRequest = {
|
|
2591
|
+
filename: "null.bin",
|
|
2592
|
+
vendor: 1 /* USER */,
|
|
2593
|
+
loadAddress: USER_FLASH_USR_CODE_START,
|
|
2594
|
+
buf: image.buf,
|
|
2595
|
+
downloadTarget,
|
|
2596
|
+
exttype: "bin",
|
|
2597
|
+
autoRun: true,
|
|
2598
|
+
linkedFile: undefined
|
|
2599
|
+
};
|
|
2600
|
+
const upload = await conn.uploadFileToDeviceUnlocked(writeRequest, (c, t) => {
|
|
2601
|
+
pcb(`UPLOAD ${label}`, c, t);
|
|
2602
|
+
});
|
|
2603
|
+
if (upload.isErr())
|
|
2604
|
+
return import_neverthrow2.err(upload.error);
|
|
2605
|
+
if (!upload.value) {
|
|
2606
|
+
return import_neverthrow2.err(new VexFirmwareError(`${label} upload was rejected by device`));
|
|
2607
|
+
}
|
|
2608
|
+
const deadline = Date.now() + 120000;
|
|
2609
|
+
while (Date.now() < deadline) {
|
|
2610
|
+
const statusReply = await conn.request(new FactoryStatusH2DPacket, FactoryStatusReplyD2HPacket, 1e4);
|
|
2611
|
+
if (statusReply.isErr())
|
|
2612
|
+
return import_neverthrow2.err(statusReply.error);
|
|
2613
|
+
reportFactoryStatus(label, statusReply.value, pcb);
|
|
2614
|
+
if (statusReply.value.status === 0 && statusReply.value.percent === 100) {
|
|
2615
|
+
return import_neverthrow2.ok(undefined);
|
|
2616
|
+
}
|
|
2617
|
+
await sleepInner(500);
|
|
2618
|
+
}
|
|
2619
|
+
return import_neverthrow2.err(new VexFirmwareError(`${label} factory status timed out`));
|
|
2620
|
+
}
|
|
2621
|
+
function reportFactoryStatus(label, reply, pcb) {
|
|
2622
|
+
switch (reply.status) {
|
|
2623
|
+
case 2:
|
|
2624
|
+
pcb(`ERASE ${label}`, reply.percent, 100);
|
|
2625
|
+
break;
|
|
2626
|
+
case 3:
|
|
2627
|
+
pcb(`WRITE ${label}`, reply.percent, 100);
|
|
2628
|
+
break;
|
|
2629
|
+
case 4:
|
|
2630
|
+
pcb(`VERIFY ${label}`, reply.percent, 100);
|
|
2631
|
+
break;
|
|
2632
|
+
case 8:
|
|
2633
|
+
pcb(`FINISHING ${label}`, reply.percent, 100);
|
|
2634
|
+
break;
|
|
2635
|
+
}
|
|
2636
|
+
}
|
|
3339
2637
|
async function extractFirmwareImages(usingVersion, vexos) {
|
|
3340
2638
|
const { unzip } = await import("unzipit");
|
|
3341
2639
|
const { entries } = await unzip(vexos);
|
|
@@ -3383,7 +2681,7 @@ async function extractFirmwareImages(usingVersion, vexos) {
|
|
|
3383
2681
|
return ordered;
|
|
3384
2682
|
}
|
|
3385
2683
|
function uploadFirmware(state, publicUrl = "https://content.vexrobotics.com/vexos/public/V5/", usingVersion, progressCallback) {
|
|
3386
|
-
return
|
|
2684
|
+
return new import_neverthrow2.ResultAsync(runUploadFirmware(state, publicUrl, usingVersion, progressCallback));
|
|
3387
2685
|
}
|
|
3388
2686
|
async function runUploadFirmware(state, publicUrl, usingVersion, progressCallback) {
|
|
3389
2687
|
const device = state._instance;
|
|
@@ -3425,133 +2723,48 @@ async function runUploadFirmware(state, publicUrl, usingVersion, progressCallbac
|
|
|
3425
2723
|
return import_neverthrow2.err(toVexSerialError(e, "firmware"));
|
|
3426
2724
|
}
|
|
3427
2725
|
pcb("UNZIP VEXOS", 1, 1);
|
|
3428
|
-
return state.
|
|
3429
|
-
|
|
3430
|
-
|
|
3431
|
-
|
|
3432
|
-
|
|
3433
|
-
|
|
3434
|
-
const boot = images.find((image) => image.name.endsWith("BOOT.bin"));
|
|
3435
|
-
if (boot === undefined) {
|
|
3436
|
-
return import_neverthrow2.err(new VexFirmwareError("VEXos archive is missing BOOT.bin"));
|
|
3437
|
-
}
|
|
3438
|
-
const assertImage = images.find((image) => image.name.endsWith("assets.bin"));
|
|
3439
|
-
if (assertImage === undefined) {
|
|
3440
|
-
return import_neverthrow2.err(new VexFirmwareError("VEXos archive is missing assets.bin"));
|
|
3441
|
-
}
|
|
3442
|
-
const bootWriteRequest = {
|
|
3443
|
-
filename: "null.bin",
|
|
3444
|
-
vendor: 1 /* USER */,
|
|
3445
|
-
loadAddress: USER_FLASH_USR_CODE_START,
|
|
3446
|
-
buf: boot.buf,
|
|
3447
|
-
downloadTarget: 14 /* FILE_TARGET_B1 */,
|
|
3448
|
-
exttype: "bin",
|
|
3449
|
-
autoRun: true,
|
|
3450
|
-
linkedFile: undefined
|
|
3451
|
-
};
|
|
3452
|
-
const bootUpload = await conn.uploadFileToDevice(bootWriteRequest, (c, t) => {
|
|
3453
|
-
pcb("UPLOAD BOOT", c, t);
|
|
3454
|
-
});
|
|
3455
|
-
if (bootUpload.isErr())
|
|
3456
|
-
return import_neverthrow2.err(bootUpload.error);
|
|
3457
|
-
if (!bootUpload.value)
|
|
3458
|
-
return import_neverthrow2.ok(false);
|
|
3459
|
-
const bootDeadline = Date.now() + 120000;
|
|
3460
|
-
let bootComplete = false;
|
|
3461
|
-
while (Date.now() < bootDeadline) {
|
|
3462
|
-
const result3 = await conn.writeDataAsync(new FactoryStatusH2DPacket, 1e4);
|
|
3463
|
-
if (result3 instanceof FactoryStatusReplyD2HPacket) {
|
|
3464
|
-
switch (result3.status) {
|
|
3465
|
-
case 2:
|
|
3466
|
-
pcb("ERASE BOOT", result3.percent, 100);
|
|
3467
|
-
break;
|
|
3468
|
-
case 3:
|
|
3469
|
-
pcb("WRITE BOOT", result3.percent, 100);
|
|
3470
|
-
break;
|
|
3471
|
-
case 4:
|
|
3472
|
-
pcb("VERIFY BOOT", result3.percent, 100);
|
|
3473
|
-
break;
|
|
3474
|
-
case 8:
|
|
3475
|
-
pcb("FINISHING BOOT", result3.percent, 100);
|
|
3476
|
-
break;
|
|
3477
|
-
}
|
|
3478
|
-
if (result3.status === 0 && result3.percent === 100) {
|
|
3479
|
-
bootComplete = true;
|
|
3480
|
-
break;
|
|
3481
|
-
}
|
|
3482
|
-
} else {
|
|
3483
|
-
return import_neverthrow2.ok(false);
|
|
3484
|
-
}
|
|
3485
|
-
await sleepInner(500);
|
|
3486
|
-
}
|
|
3487
|
-
if (!bootComplete)
|
|
3488
|
-
return import_neverthrow2.ok(false);
|
|
3489
|
-
pcb("FACTORY ENB ASSERT", 0, 0);
|
|
3490
|
-
const result5 = await conn.writeDataAsync(new FactoryEnableH2DPacket);
|
|
3491
|
-
if (!(result5 instanceof FactoryEnableReplyD2HPacket)) {
|
|
3492
|
-
return import_neverthrow2.err(new VexProtocolError("FactoryEnableH2DPacket failed"));
|
|
3493
|
-
}
|
|
3494
|
-
const assertWriteRequest = {
|
|
3495
|
-
filename: "null.bin",
|
|
3496
|
-
vendor: 1 /* USER */,
|
|
3497
|
-
loadAddress: USER_FLASH_USR_CODE_START,
|
|
3498
|
-
buf: assertImage.buf,
|
|
3499
|
-
downloadTarget: 13 /* FILE_TARGET_A1 */,
|
|
3500
|
-
exttype: "bin",
|
|
3501
|
-
autoRun: true,
|
|
3502
|
-
linkedFile: undefined
|
|
3503
|
-
};
|
|
3504
|
-
const assertUpload = await conn.uploadFileToDevice(assertWriteRequest, (c, t) => {
|
|
3505
|
-
pcb("UPLOAD ASSERT", c, t);
|
|
3506
|
-
});
|
|
3507
|
-
if (assertUpload.isErr())
|
|
3508
|
-
return import_neverthrow2.err(assertUpload.error);
|
|
3509
|
-
if (!assertUpload.value)
|
|
3510
|
-
return import_neverthrow2.ok(false);
|
|
3511
|
-
const assertDeadline = Date.now() + 120000;
|
|
3512
|
-
let assertComplete = false;
|
|
3513
|
-
while (Date.now() < assertDeadline) {
|
|
3514
|
-
const result7 = await conn.writeDataAsync(new FactoryStatusH2DPacket, 1e4);
|
|
3515
|
-
if (result7 instanceof FactoryStatusReplyD2HPacket) {
|
|
3516
|
-
switch (result7.status) {
|
|
3517
|
-
case 2:
|
|
3518
|
-
pcb("ERASE ASSERT", result7.percent, 100);
|
|
3519
|
-
break;
|
|
3520
|
-
case 3:
|
|
3521
|
-
pcb("WRITE ASSERT", result7.percent, 100);
|
|
3522
|
-
break;
|
|
3523
|
-
case 4:
|
|
3524
|
-
pcb("VERIFY ASSERT", result7.percent, 100);
|
|
3525
|
-
break;
|
|
3526
|
-
case 8:
|
|
3527
|
-
pcb("FINISHING ASSERT", result7.percent, 100);
|
|
3528
|
-
break;
|
|
2726
|
+
return state.withRefreshPaused(async () => {
|
|
2727
|
+
try {
|
|
2728
|
+
return await conn.withFileTransfer(async () => {
|
|
2729
|
+
const boot = images.find((image) => image.name.endsWith("BOOT.bin"));
|
|
2730
|
+
if (boot === undefined) {
|
|
2731
|
+
return import_neverthrow2.err(new VexFirmwareError("VEXos archive is missing BOOT.bin"));
|
|
3529
2732
|
}
|
|
3530
|
-
|
|
3531
|
-
|
|
3532
|
-
|
|
2733
|
+
const assertImage = images.find((image) => image.name.endsWith("assets.bin"));
|
|
2734
|
+
if (assertImage === undefined) {
|
|
2735
|
+
return import_neverthrow2.err(new VexFirmwareError("VEXos archive is missing assets.bin"));
|
|
3533
2736
|
}
|
|
3534
|
-
|
|
3535
|
-
|
|
3536
|
-
|
|
3537
|
-
|
|
2737
|
+
const bootFlash = await flashFactoryImage(conn, {
|
|
2738
|
+
image: boot,
|
|
2739
|
+
label: "BOOT",
|
|
2740
|
+
downloadTarget: 14 /* FILE_TARGET_B1 */
|
|
2741
|
+
}, pcb);
|
|
2742
|
+
if (bootFlash.isErr())
|
|
2743
|
+
return import_neverthrow2.err(bootFlash.error);
|
|
2744
|
+
const assetsFlash = await flashFactoryImage(conn, {
|
|
2745
|
+
image: assertImage,
|
|
2746
|
+
label: "ASSETS",
|
|
2747
|
+
downloadTarget: 13 /* FILE_TARGET_A1 */
|
|
2748
|
+
}, pcb);
|
|
2749
|
+
if (assetsFlash.isErr())
|
|
2750
|
+
return import_neverthrow2.err(assetsFlash.error);
|
|
2751
|
+
return import_neverthrow2.ok(true);
|
|
2752
|
+
});
|
|
2753
|
+
} catch (e) {
|
|
2754
|
+
return import_neverthrow2.err(toVexSerialError(e, "firmware"));
|
|
3538
2755
|
}
|
|
3539
|
-
if (!assertComplete)
|
|
3540
|
-
return import_neverthrow2.ok(false);
|
|
3541
|
-
return import_neverthrow2.ok(true);
|
|
3542
2756
|
});
|
|
3543
2757
|
}
|
|
3544
2758
|
|
|
3545
2759
|
// src/VexTransfers.ts
|
|
3546
|
-
var import_neverthrow3 =
|
|
2760
|
+
var import_neverthrow3 = require("neverthrow");
|
|
3547
2761
|
function getValue(state, key) {
|
|
3548
2762
|
return new import_neverthrow3.ResultAsync((async () => {
|
|
3549
2763
|
const conn = state._instance.connection;
|
|
3550
2764
|
if (conn == null || !conn.isConnected) {
|
|
3551
2765
|
return import_neverthrow3.err(new VexNotConnectedError);
|
|
3552
2766
|
}
|
|
3553
|
-
|
|
3554
|
-
return result instanceof ReadKeyValueReplyD2HPacket ? import_neverthrow3.ok(result.value) : import_neverthrow3.err(new VexProtocolError("getValue was not acknowledged"));
|
|
2767
|
+
return conn.request(new ReadKeyValueH2DPacket(key), ReadKeyValueReplyD2HPacket).map((result) => result.value);
|
|
3555
2768
|
})());
|
|
3556
2769
|
}
|
|
3557
2770
|
function setValue(state, key, value) {
|
|
@@ -3560,8 +2773,9 @@ function setValue(state, key, value) {
|
|
|
3560
2773
|
if (conn == null || !conn.isConnected) {
|
|
3561
2774
|
return import_neverthrow3.err(new VexNotConnectedError);
|
|
3562
2775
|
}
|
|
3563
|
-
|
|
3564
|
-
|
|
2776
|
+
return conn.request(new WriteKeyValueH2DPacket(key, value), WriteKeyValueReplyD2HPacket).map(() => {
|
|
2777
|
+
return;
|
|
2778
|
+
});
|
|
3565
2779
|
})());
|
|
3566
2780
|
}
|
|
3567
2781
|
function listFiles(state, vendor = 1 /* USER */) {
|
|
@@ -3570,26 +2784,24 @@ function listFiles(state, vendor = 1 /* USER */) {
|
|
|
3570
2784
|
if (conn == null || !conn.isConnected) {
|
|
3571
2785
|
return import_neverthrow3.err(new VexNotConnectedError);
|
|
3572
2786
|
}
|
|
3573
|
-
const
|
|
3574
|
-
if (
|
|
3575
|
-
return import_neverthrow3.err(
|
|
3576
|
-
}
|
|
2787
|
+
const countResult = await conn.request(new GetDirectoryFileCountH2DPacket(vendor), GetDirectoryFileCountReplyD2HPacket);
|
|
2788
|
+
if (countResult.isErr())
|
|
2789
|
+
return import_neverthrow3.err(countResult.error);
|
|
3577
2790
|
const files = [];
|
|
3578
|
-
for (let i = 0;i <
|
|
3579
|
-
const
|
|
3580
|
-
if (
|
|
3581
|
-
return import_neverthrow3.err(
|
|
3582
|
-
|
|
3583
|
-
if (result2.file != null) {
|
|
2791
|
+
for (let i = 0;i < countResult.value.count; i++) {
|
|
2792
|
+
const entryResult = await conn.request(new GetDirectoryEntryH2DPacket(i), GetDirectoryEntryReplyD2HPacket);
|
|
2793
|
+
if (entryResult.isErr())
|
|
2794
|
+
return import_neverthrow3.err(entryResult.error);
|
|
2795
|
+
if (entryResult.value.file != null) {
|
|
3584
2796
|
files.push({
|
|
3585
|
-
filename:
|
|
2797
|
+
filename: entryResult.value.file.filename,
|
|
3586
2798
|
vendor,
|
|
3587
|
-
loadAddress:
|
|
3588
|
-
size:
|
|
3589
|
-
crc32:
|
|
3590
|
-
type:
|
|
3591
|
-
timestamp:
|
|
3592
|
-
version:
|
|
2799
|
+
loadAddress: entryResult.value.file.loadAddress,
|
|
2800
|
+
size: entryResult.value.file.size,
|
|
2801
|
+
crc32: entryResult.value.file.crc32,
|
|
2802
|
+
type: entryResult.value.file.type,
|
|
2803
|
+
timestamp: entryResult.value.file.timestamp,
|
|
2804
|
+
version: entryResult.value.file.version
|
|
3593
2805
|
});
|
|
3594
2806
|
}
|
|
3595
2807
|
}
|
|
@@ -3625,10 +2837,10 @@ function listProgram(state) {
|
|
|
3625
2837
|
time: n,
|
|
3626
2838
|
requestedSlot: -1
|
|
3627
2839
|
};
|
|
3628
|
-
const
|
|
3629
|
-
if (
|
|
3630
|
-
program.slot =
|
|
3631
|
-
program.requestedSlot =
|
|
2840
|
+
const slotInfo = await conn.request(new GetProgramSlotInfoH2DPacket(1 /* USER */, program.binfile), GetProgramSlotInfoReplyD2HPacket);
|
|
2841
|
+
if (slotInfo.isOk()) {
|
|
2842
|
+
program.slot = slotInfo.value.slot;
|
|
2843
|
+
program.requestedSlot = slotInfo.value.requestedSlot;
|
|
3632
2844
|
}
|
|
3633
2845
|
programList.push(program);
|
|
3634
2846
|
}
|
|
@@ -3647,7 +2859,7 @@ function readFile(state, request, downloadTarget = 1 /* FILE_TARGET_QSPI */, pro
|
|
|
3647
2859
|
} else {
|
|
3648
2860
|
handle = request;
|
|
3649
2861
|
}
|
|
3650
|
-
return state.
|
|
2862
|
+
return state.withRefreshPaused(() => conn.downloadFileToHost(handle, downloadTarget, progressCallback));
|
|
3651
2863
|
})());
|
|
3652
2864
|
}
|
|
3653
2865
|
function removeFile(state, request) {
|
|
@@ -3656,7 +2868,7 @@ function removeFile(state, request) {
|
|
|
3656
2868
|
if (conn == null || !conn.isConnected) {
|
|
3657
2869
|
return import_neverthrow3.err(new VexNotConnectedError);
|
|
3658
2870
|
}
|
|
3659
|
-
return state.
|
|
2871
|
+
return state.withRefreshPaused(() => conn.removeFile(request));
|
|
3660
2872
|
})());
|
|
3661
2873
|
}
|
|
3662
2874
|
function removeAllFiles(state) {
|
|
@@ -3665,7 +2877,7 @@ function removeAllFiles(state) {
|
|
|
3665
2877
|
if (conn == null || !conn.isConnected) {
|
|
3666
2878
|
return import_neverthrow3.err(new VexNotConnectedError);
|
|
3667
2879
|
}
|
|
3668
|
-
return state.
|
|
2880
|
+
return state.withRefreshPaused(() => conn.removeAllFiles());
|
|
3669
2881
|
})());
|
|
3670
2882
|
}
|
|
3671
2883
|
function uploadProgram(state, iniConfig, binFileBuf, coldFileBuf, progressCallback) {
|
|
@@ -3678,7 +2890,7 @@ async function runUploadProgram(state, iniConfig, binFileBuf, coldFileBuf, progr
|
|
|
3678
2890
|
return import_neverthrow3.err(new VexNotConnectedError);
|
|
3679
2891
|
}
|
|
3680
2892
|
let switchedToDownload = false;
|
|
3681
|
-
return state.
|
|
2893
|
+
return state.withRefreshPaused(async () => {
|
|
3682
2894
|
try {
|
|
3683
2895
|
if (device.isV5Controller) {
|
|
3684
2896
|
await sleep(250);
|
|
@@ -3737,7 +2949,7 @@ function writeFile(state, request, progressCallback) {
|
|
|
3737
2949
|
if (conn == null || !conn.isConnected) {
|
|
3738
2950
|
return import_neverthrow3.err(new VexNotConnectedError);
|
|
3739
2951
|
}
|
|
3740
|
-
return state.
|
|
2952
|
+
return state.withRefreshPaused(() => conn.uploadFileToDevice(request, progressCallback));
|
|
3741
2953
|
})());
|
|
3742
2954
|
}
|
|
3743
2955
|
function captureScreen(state, progressCallback) {
|
|
@@ -3746,7 +2958,7 @@ function captureScreen(state, progressCallback) {
|
|
|
3746
2958
|
if (conn == null || !conn.isConnected) {
|
|
3747
2959
|
return import_neverthrow3.err(new VexNotConnectedError);
|
|
3748
2960
|
}
|
|
3749
|
-
return state.
|
|
2961
|
+
return state.withRefreshPaused(() => conn.captureScreen(progressCallback));
|
|
3750
2962
|
})());
|
|
3751
2963
|
}
|
|
3752
2964
|
|
|
@@ -3769,10 +2981,13 @@ class VexSerialDevice extends VexEventTarget {
|
|
|
3769
2981
|
class V5SerialDeviceState {
|
|
3770
2982
|
_instance;
|
|
3771
2983
|
refreshPauseDepth = 0;
|
|
3772
|
-
get
|
|
2984
|
+
get isRefreshPaused() {
|
|
3773
2985
|
return this.refreshPauseDepth > 0;
|
|
3774
2986
|
}
|
|
3775
|
-
|
|
2987
|
+
get isFileTransferring() {
|
|
2988
|
+
return this.isRefreshPaused;
|
|
2989
|
+
}
|
|
2990
|
+
async withRefreshPaused(operation) {
|
|
3776
2991
|
this.refreshPauseDepth++;
|
|
3777
2992
|
try {
|
|
3778
2993
|
return await operation();
|
|
@@ -3780,6 +2995,9 @@ class V5SerialDeviceState {
|
|
|
3780
2995
|
this.refreshPauseDepth--;
|
|
3781
2996
|
}
|
|
3782
2997
|
}
|
|
2998
|
+
async withFileTransfer(operation) {
|
|
2999
|
+
return this.withRefreshPaused(operation);
|
|
3000
|
+
}
|
|
3783
3001
|
brain = {
|
|
3784
3002
|
activeProgram: 0,
|
|
3785
3003
|
battery: {
|
|
@@ -3809,7 +3027,8 @@ class V5SerialDeviceState {
|
|
|
3809
3027
|
},
|
|
3810
3028
|
{
|
|
3811
3029
|
battery: 0,
|
|
3812
|
-
isAvailable: false
|
|
3030
|
+
isAvailable: false,
|
|
3031
|
+
isCharging: false
|
|
3813
3032
|
}
|
|
3814
3033
|
];
|
|
3815
3034
|
devices = [];
|
|
@@ -3832,8 +3051,14 @@ class V5SerialDeviceState {
|
|
|
3832
3051
|
|
|
3833
3052
|
class V5Brain {
|
|
3834
3053
|
state;
|
|
3054
|
+
batteryFacade;
|
|
3055
|
+
buttonFacade;
|
|
3056
|
+
settingsFacade;
|
|
3835
3057
|
constructor(state) {
|
|
3836
3058
|
this.state = state;
|
|
3059
|
+
this.batteryFacade = new V5Battery(state);
|
|
3060
|
+
this.buttonFacade = new V5BrainButton(state);
|
|
3061
|
+
this.settingsFacade = new V5BrainSettings(state);
|
|
3837
3062
|
}
|
|
3838
3063
|
get isRunningProgram() {
|
|
3839
3064
|
return this.activeProgram !== 0;
|
|
@@ -3866,9 +3091,8 @@ class V5Brain {
|
|
|
3866
3091
|
const reply = await conn.runProgram(slot);
|
|
3867
3092
|
if (reply.isErr())
|
|
3868
3093
|
return import_neverthrow4.err(reply.error);
|
|
3869
|
-
|
|
3870
|
-
|
|
3871
|
-
this.state.brain.activeProgram = slotNumber;
|
|
3094
|
+
if (typeof slot === "number")
|
|
3095
|
+
this.state.brain.activeProgram = slot;
|
|
3872
3096
|
return import_neverthrow4.ok(undefined);
|
|
3873
3097
|
})());
|
|
3874
3098
|
}
|
|
@@ -3885,10 +3109,10 @@ class V5Brain {
|
|
|
3885
3109
|
})());
|
|
3886
3110
|
}
|
|
3887
3111
|
get battery() {
|
|
3888
|
-
return
|
|
3112
|
+
return this.batteryFacade;
|
|
3889
3113
|
}
|
|
3890
3114
|
get button() {
|
|
3891
|
-
return
|
|
3115
|
+
return this.buttonFacade;
|
|
3892
3116
|
}
|
|
3893
3117
|
get cpu0Version() {
|
|
3894
3118
|
return this.state.brain.cpu0Version;
|
|
@@ -3900,7 +3124,7 @@ class V5Brain {
|
|
|
3900
3124
|
return this.state.brain.isAvailable;
|
|
3901
3125
|
}
|
|
3902
3126
|
get settings() {
|
|
3903
|
-
return
|
|
3127
|
+
return this.settingsFacade;
|
|
3904
3128
|
}
|
|
3905
3129
|
get systemVersion() {
|
|
3906
3130
|
return this.state.brain.systemVersion;
|
|
@@ -4055,67 +3279,144 @@ class V5Radio {
|
|
|
4055
3279
|
}
|
|
4056
3280
|
changeChannel(channel) {
|
|
4057
3281
|
return new import_neverthrow4.ResultAsync((async () => {
|
|
4058
|
-
const
|
|
4059
|
-
|
|
3282
|
+
const conn = this.state._instance.connection;
|
|
3283
|
+
if (conn == null || !conn.isConnected) {
|
|
3284
|
+
return import_neverthrow4.err(new VexNotConnectedError);
|
|
3285
|
+
}
|
|
3286
|
+
return conn.request(new FileControlH2DPacket(1, channel), FileControlReplyD2HPacket).map(() => {
|
|
3287
|
+
return;
|
|
3288
|
+
});
|
|
4060
3289
|
})());
|
|
4061
3290
|
}
|
|
4062
3291
|
}
|
|
4063
3292
|
|
|
4064
3293
|
// src/VexDevice.ts
|
|
4065
|
-
var import_neverthrow5 =
|
|
3294
|
+
var import_neverthrow5 = require("neverthrow");
|
|
3295
|
+
function unrefTimerIfPossible(timer) {
|
|
3296
|
+
if (typeof timer !== "object" || timer === null || !("unref" in timer))
|
|
3297
|
+
return;
|
|
3298
|
+
const unref = timer.unref;
|
|
3299
|
+
if (typeof unref === "function")
|
|
3300
|
+
unref.call(timer);
|
|
3301
|
+
}
|
|
3302
|
+
function describePort(port) {
|
|
3303
|
+
const info = port.getInfo();
|
|
3304
|
+
const identifier = info.path ?? info.id ?? info.serialNumber;
|
|
3305
|
+
return typeof identifier === "string" ? identifier : undefined;
|
|
3306
|
+
}
|
|
4066
3307
|
|
|
4067
3308
|
class V5SerialDevice extends VexSerialDevice {
|
|
4068
3309
|
autoReconnect = true;
|
|
4069
|
-
autoRefresh = true;
|
|
4070
3310
|
pauseRefreshOnFileTransfer = true;
|
|
4071
3311
|
_isReconnecting = false;
|
|
4072
3312
|
_isDisconnecting = false;
|
|
4073
3313
|
_refreshInterval;
|
|
4074
3314
|
state = new V5SerialDeviceState(this);
|
|
4075
3315
|
_disposed = false;
|
|
3316
|
+
_lifecycleGeneration = 0;
|
|
3317
|
+
_disconnectListener;
|
|
4076
3318
|
_refreshGeneration = 0;
|
|
4077
|
-
|
|
3319
|
+
_autoRefresh = false;
|
|
3320
|
+
_refreshIntervalMs = 200;
|
|
3321
|
+
_isLastRefreshComplete = true;
|
|
3322
|
+
_brain = new V5Brain(this.state);
|
|
3323
|
+
_controllers = [
|
|
3324
|
+
new V5Controller(this.state, 0),
|
|
3325
|
+
new V5Controller(this.state, 1)
|
|
3326
|
+
];
|
|
3327
|
+
_radio = new V5Radio(this.state);
|
|
3328
|
+
_deviceFacades = [];
|
|
3329
|
+
_emitSafely(eventName, data) {
|
|
3330
|
+
try {
|
|
3331
|
+
this.emit(eventName, data);
|
|
3332
|
+
} catch {}
|
|
3333
|
+
}
|
|
3334
|
+
constructor(defaultSerial, options = false) {
|
|
4078
3335
|
super(defaultSerial);
|
|
4079
|
-
|
|
3336
|
+
const autoRefresh = typeof options === "boolean" ? options : options.autoRefresh ?? false;
|
|
3337
|
+
this.refreshIntervalMs = typeof options === "boolean" ? 200 : options.refreshIntervalMs ?? 200;
|
|
3338
|
+
this.autoRefresh = autoRefresh;
|
|
3339
|
+
}
|
|
3340
|
+
get autoRefresh() {
|
|
3341
|
+
return this._autoRefresh;
|
|
3342
|
+
}
|
|
3343
|
+
set autoRefresh(value) {
|
|
3344
|
+
if (this._autoRefresh === value)
|
|
3345
|
+
return;
|
|
3346
|
+
this._autoRefresh = value;
|
|
3347
|
+
if (value) {
|
|
3348
|
+
this._startRefreshInterval();
|
|
3349
|
+
} else {
|
|
3350
|
+
this._stopRefreshInterval();
|
|
3351
|
+
}
|
|
3352
|
+
}
|
|
3353
|
+
get refreshIntervalMs() {
|
|
3354
|
+
return this._refreshIntervalMs;
|
|
3355
|
+
}
|
|
3356
|
+
set refreshIntervalMs(value) {
|
|
3357
|
+
if (!Number.isFinite(value) || value <= 0) {
|
|
3358
|
+
throw new VexInvalidArgumentError("refreshIntervalMs must be a positive finite number");
|
|
3359
|
+
}
|
|
3360
|
+
if (this._refreshIntervalMs === value)
|
|
3361
|
+
return;
|
|
3362
|
+
this._refreshIntervalMs = value;
|
|
3363
|
+
if (this._refreshInterval !== undefined) {
|
|
3364
|
+
this._stopRefreshInterval();
|
|
3365
|
+
this._startRefreshInterval();
|
|
3366
|
+
}
|
|
3367
|
+
}
|
|
3368
|
+
_startRefreshInterval() {
|
|
3369
|
+
if (this._refreshInterval !== undefined || this._disposed)
|
|
3370
|
+
return;
|
|
4080
3371
|
this._refreshInterval = setInterval(() => {
|
|
4081
3372
|
if (this._disposed)
|
|
4082
3373
|
return;
|
|
4083
|
-
if (this.
|
|
3374
|
+
if (this._autoRefresh && this._isLastRefreshComplete) {
|
|
4084
3375
|
if (!this.isConnected) {
|
|
4085
3376
|
this.state.brain.isAvailable = false;
|
|
4086
3377
|
return;
|
|
4087
3378
|
}
|
|
4088
|
-
if (!this.pauseRefreshOnFileTransfer || !this.state.
|
|
4089
|
-
|
|
3379
|
+
if (!this.pauseRefreshOnFileTransfer || !this.state.isRefreshPaused) {
|
|
3380
|
+
this._isLastRefreshComplete = false;
|
|
4090
3381
|
(async () => {
|
|
4091
3382
|
try {
|
|
4092
3383
|
const r = await this.refresh();
|
|
4093
3384
|
if (r.isErr())
|
|
4094
|
-
this.
|
|
3385
|
+
this._emitSafely("error", r.error);
|
|
4095
3386
|
} catch (error) {
|
|
4096
|
-
this.
|
|
3387
|
+
this._emitSafely("error", error);
|
|
4097
3388
|
} finally {
|
|
4098
|
-
|
|
3389
|
+
this._isLastRefreshComplete = true;
|
|
4099
3390
|
}
|
|
4100
3391
|
})();
|
|
4101
3392
|
}
|
|
4102
3393
|
}
|
|
4103
|
-
},
|
|
3394
|
+
}, this._refreshIntervalMs);
|
|
3395
|
+
unrefTimerIfPossible(this._refreshInterval);
|
|
3396
|
+
}
|
|
3397
|
+
_stopRefreshInterval() {
|
|
3398
|
+
if (this._refreshInterval === undefined)
|
|
3399
|
+
return;
|
|
3400
|
+
clearInterval(this._refreshInterval);
|
|
3401
|
+
this._refreshInterval = undefined;
|
|
4104
3402
|
}
|
|
4105
3403
|
get isV5Controller() {
|
|
4106
3404
|
return this.deviceType === 1283 /* V5_CONTROLLER */;
|
|
4107
3405
|
}
|
|
4108
3406
|
get brain() {
|
|
4109
|
-
return
|
|
3407
|
+
return this._brain;
|
|
4110
3408
|
}
|
|
4111
3409
|
get controllers() {
|
|
4112
|
-
return
|
|
3410
|
+
return this._controllers;
|
|
4113
3411
|
}
|
|
4114
3412
|
get devices() {
|
|
4115
3413
|
const rtn = [];
|
|
4116
|
-
for (let i = 1;i
|
|
4117
|
-
if (this.state.devices[i] != null)
|
|
4118
|
-
|
|
3414
|
+
for (let i = 1;i < this.state.devices.length; i++) {
|
|
3415
|
+
if (this.state.devices[i] != null) {
|
|
3416
|
+
const facade = this._deviceFacades[i] ?? new V5SmartDevice(this.state, i);
|
|
3417
|
+
this._deviceFacades[i] = facade;
|
|
3418
|
+
rtn.push(facade);
|
|
3419
|
+
}
|
|
4119
3420
|
}
|
|
4120
3421
|
return rtn;
|
|
4121
3422
|
}
|
|
@@ -4140,7 +3441,7 @@ class V5SerialDevice extends VexSerialDevice {
|
|
|
4140
3441
|
})());
|
|
4141
3442
|
}
|
|
4142
3443
|
get radio() {
|
|
4143
|
-
return
|
|
3444
|
+
return this._radio;
|
|
4144
3445
|
}
|
|
4145
3446
|
mockTouch(x, y, press) {
|
|
4146
3447
|
return new import_neverthrow5.ResultAsync((async () => {
|
|
@@ -4153,58 +3454,125 @@ class V5SerialDevice extends VexSerialDevice {
|
|
|
4153
3454
|
})());
|
|
4154
3455
|
}
|
|
4155
3456
|
connect(conn) {
|
|
4156
|
-
|
|
3457
|
+
if (this._disposed) {
|
|
3458
|
+
return new import_neverthrow5.ResultAsync(Promise.resolve(this._staleLifecycleResult()));
|
|
3459
|
+
}
|
|
3460
|
+
if (this.isConnected)
|
|
3461
|
+
return new import_neverthrow5.ResultAsync(Promise.resolve(import_neverthrow5.ok(undefined)));
|
|
3462
|
+
const generation = ++this._lifecycleGeneration;
|
|
3463
|
+
return new import_neverthrow5.ResultAsync(this._connect(conn, generation));
|
|
4157
3464
|
}
|
|
4158
|
-
async _connect(conn) {
|
|
3465
|
+
async _connect(conn, generation = this._lifecycleGeneration) {
|
|
3466
|
+
if (!this._isLifecycleCurrent(generation)) {
|
|
3467
|
+
return this._staleLifecycleResult();
|
|
3468
|
+
}
|
|
4159
3469
|
if (this.isConnected)
|
|
4160
3470
|
return import_neverthrow5.ok(undefined);
|
|
4161
3471
|
if (conn != null) {
|
|
4162
3472
|
if (!conn.isConnected) {
|
|
4163
3473
|
const opened = await conn.open();
|
|
4164
|
-
if (
|
|
3474
|
+
if (!this._isLifecycleCurrent(generation)) {
|
|
3475
|
+
await conn.close();
|
|
3476
|
+
return this._staleLifecycleResult();
|
|
3477
|
+
}
|
|
3478
|
+
if (opened.isErr() || opened.value !== "opened") {
|
|
4165
3479
|
return import_neverthrow5.err(new VexIoError("failed to open the supplied connection"));
|
|
4166
3480
|
}
|
|
4167
3481
|
}
|
|
4168
3482
|
const q = await conn.query1();
|
|
3483
|
+
if (!this._isLifecycleCurrent(generation)) {
|
|
3484
|
+
await conn.close();
|
|
3485
|
+
return this._staleLifecycleResult();
|
|
3486
|
+
}
|
|
4169
3487
|
if (q.isErr()) {
|
|
4170
3488
|
await conn.close();
|
|
4171
3489
|
return import_neverthrow5.err(q.error);
|
|
4172
3490
|
}
|
|
4173
|
-
this.
|
|
3491
|
+
if (!this._commitConnection(conn, generation)) {
|
|
3492
|
+
await conn.close();
|
|
3493
|
+
return this._staleLifecycleResult();
|
|
3494
|
+
}
|
|
4174
3495
|
} else {
|
|
4175
3496
|
let tryIdx = 0;
|
|
3497
|
+
let canRequestPort = true;
|
|
3498
|
+
const attemptedPorts = new Set;
|
|
3499
|
+
const attemptedPortNames = [];
|
|
4176
3500
|
while (true) {
|
|
4177
|
-
|
|
4178
|
-
|
|
3501
|
+
if (!this._isLifecycleCurrent(generation)) {
|
|
3502
|
+
return this._staleLifecycleResult();
|
|
3503
|
+
}
|
|
3504
|
+
const c = this.createConnection();
|
|
3505
|
+
let result = await c.open(tryIdx++, false);
|
|
3506
|
+
if (!this._isLifecycleCurrent(generation)) {
|
|
3507
|
+
await c.close();
|
|
3508
|
+
return this._staleLifecycleResult();
|
|
3509
|
+
}
|
|
3510
|
+
if (result.isOk() && result.value === "no-port" && canRequestPort) {
|
|
3511
|
+
canRequestPort = false;
|
|
3512
|
+
result = await c.open(tryIdx, true);
|
|
3513
|
+
if (!this._isLifecycleCurrent(generation)) {
|
|
3514
|
+
await c.close();
|
|
3515
|
+
return this._staleLifecycleResult();
|
|
3516
|
+
}
|
|
3517
|
+
}
|
|
4179
3518
|
if (result.isErr()) {
|
|
4180
3519
|
await c.close();
|
|
4181
3520
|
return import_neverthrow5.err(result.error);
|
|
4182
3521
|
}
|
|
4183
|
-
if (result.value ===
|
|
4184
|
-
|
|
3522
|
+
if (result.value === "no-port") {
|
|
3523
|
+
const attempted = attemptedPortNames.length ? `; attempted ${attemptedPortNames.join(", ")}` : "";
|
|
3524
|
+
return import_neverthrow5.err(new VexNotConnectedError(`no responsive V5 device was found${attempted}`));
|
|
4185
3525
|
}
|
|
4186
|
-
if (
|
|
3526
|
+
if (result.value === "busy") {
|
|
4187
3527
|
await c.close();
|
|
4188
|
-
|
|
3528
|
+
return import_neverthrow5.err(new VexNotConnectedError("the selected V5 serial port is busy"));
|
|
3529
|
+
}
|
|
3530
|
+
const port = c.port;
|
|
3531
|
+
if (port !== undefined && attemptedPorts.has(port)) {
|
|
3532
|
+
await c.close();
|
|
3533
|
+
const portName = describePort(port);
|
|
3534
|
+
return import_neverthrow5.err(new VexNotConnectedError(portName === undefined ? "the selected serial port did not respond as a V5 device" : `serial port ${portName} did not respond as a V5 device`));
|
|
3535
|
+
}
|
|
3536
|
+
if (port !== undefined) {
|
|
3537
|
+
attemptedPorts.add(port);
|
|
3538
|
+
const portName = describePort(port);
|
|
3539
|
+
if (portName !== undefined)
|
|
3540
|
+
attemptedPortNames.push(portName);
|
|
4189
3541
|
}
|
|
4190
3542
|
const q = await c.query1();
|
|
3543
|
+
if (!this._isLifecycleCurrent(generation)) {
|
|
3544
|
+
await c.close();
|
|
3545
|
+
return this._staleLifecycleResult();
|
|
3546
|
+
}
|
|
4191
3547
|
if (q.isErr()) {
|
|
4192
3548
|
await c.close();
|
|
4193
3549
|
continue;
|
|
4194
3550
|
}
|
|
4195
|
-
this.
|
|
3551
|
+
if (!this._commitConnection(c, generation)) {
|
|
3552
|
+
await c.close();
|
|
3553
|
+
return this._staleLifecycleResult();
|
|
3554
|
+
}
|
|
4196
3555
|
break;
|
|
4197
3556
|
}
|
|
4198
3557
|
}
|
|
4199
|
-
|
|
3558
|
+
const connection = this.connection;
|
|
3559
|
+
if (!this._isLifecycleCurrent(generation) || connection == null) {
|
|
3560
|
+
return this._staleLifecycleResult();
|
|
3561
|
+
}
|
|
3562
|
+
if (!connection.isConnected)
|
|
4200
3563
|
return import_neverthrow5.err(new VexNotConnectedError);
|
|
4201
|
-
await this.doAfterConnect();
|
|
3564
|
+
const initialized = await this.doAfterConnect(connection, generation);
|
|
3565
|
+
if (initialized.isErr())
|
|
3566
|
+
return initialized;
|
|
4202
3567
|
return import_neverthrow5.ok(undefined);
|
|
4203
3568
|
}
|
|
4204
3569
|
async disconnect() {
|
|
3570
|
+
this._lifecycleGeneration++;
|
|
3571
|
+
this._refreshGeneration++;
|
|
4205
3572
|
this._isDisconnecting = true;
|
|
4206
3573
|
const connection = this.connection;
|
|
4207
3574
|
this.connection = undefined;
|
|
3575
|
+
this._detachDisconnectListener();
|
|
4208
3576
|
try {
|
|
4209
3577
|
await connection?.close();
|
|
4210
3578
|
} finally {
|
|
@@ -4215,16 +3583,24 @@ class V5SerialDevice extends VexSerialDevice {
|
|
|
4215
3583
|
this.autoReconnect = false;
|
|
4216
3584
|
this.autoRefresh = false;
|
|
4217
3585
|
this._disposed = true;
|
|
4218
|
-
if (this._refreshInterval !== undefined) {
|
|
4219
|
-
clearInterval(this._refreshInterval);
|
|
4220
|
-
this._refreshInterval = undefined;
|
|
4221
|
-
}
|
|
4222
3586
|
await this.disconnect();
|
|
4223
3587
|
}
|
|
4224
3588
|
reconnect(timeout = 0) {
|
|
4225
|
-
|
|
3589
|
+
if (this._disposed) {
|
|
3590
|
+
return new import_neverthrow5.ResultAsync(Promise.resolve(this._staleLifecycleResult()));
|
|
3591
|
+
}
|
|
3592
|
+
if (timeout < 0) {
|
|
3593
|
+
return new import_neverthrow5.ResultAsync(Promise.resolve(import_neverthrow5.err(new VexInvalidArgumentError("timeout must be non-negative"))));
|
|
3594
|
+
}
|
|
3595
|
+
if (this.isConnected)
|
|
3596
|
+
return new import_neverthrow5.ResultAsync(Promise.resolve(import_neverthrow5.ok(undefined)));
|
|
3597
|
+
const generation = this._isReconnecting ? this._lifecycleGeneration : ++this._lifecycleGeneration;
|
|
3598
|
+
return new import_neverthrow5.ResultAsync(this._reconnect(timeout, generation));
|
|
4226
3599
|
}
|
|
4227
|
-
async _reconnect(timeout) {
|
|
3600
|
+
async _reconnect(timeout, generation = this._lifecycleGeneration) {
|
|
3601
|
+
if (!this._isLifecycleCurrent(generation)) {
|
|
3602
|
+
return this._staleLifecycleResult();
|
|
3603
|
+
}
|
|
4228
3604
|
if (this.isConnected)
|
|
4229
3605
|
return import_neverthrow5.ok(undefined);
|
|
4230
3606
|
if (timeout < 0) {
|
|
@@ -4240,6 +3616,9 @@ class V5SerialDevice extends VexSerialDevice {
|
|
|
4240
3616
|
return import_neverthrow5.err(new VexNotConnectedError);
|
|
4241
3617
|
}
|
|
4242
3618
|
}
|
|
3619
|
+
if (!this._isLifecycleCurrent(generation)) {
|
|
3620
|
+
return this._staleLifecycleResult();
|
|
3621
|
+
}
|
|
4243
3622
|
if (this.isConnected)
|
|
4244
3623
|
return import_neverthrow5.ok(undefined);
|
|
4245
3624
|
}
|
|
@@ -4248,19 +3627,30 @@ class V5SerialDevice extends VexSerialDevice {
|
|
|
4248
3627
|
while (timeout === 0 || Date.now() < endTime) {
|
|
4249
3628
|
let tryIdx = 0;
|
|
4250
3629
|
while (true) {
|
|
4251
|
-
|
|
3630
|
+
if (!this._isLifecycleCurrent(generation)) {
|
|
3631
|
+
return this._staleLifecycleResult();
|
|
3632
|
+
}
|
|
3633
|
+
const c = this.createConnection();
|
|
4252
3634
|
const result = await c.open(tryIdx++, false);
|
|
3635
|
+
if (!this._isLifecycleCurrent(generation)) {
|
|
3636
|
+
await c.close();
|
|
3637
|
+
return this._staleLifecycleResult();
|
|
3638
|
+
}
|
|
4253
3639
|
if (result.isErr()) {
|
|
4254
3640
|
await c.close();
|
|
4255
3641
|
return import_neverthrow5.err(result.error);
|
|
4256
3642
|
}
|
|
4257
|
-
if (result.value ===
|
|
3643
|
+
if (result.value === "no-port")
|
|
4258
3644
|
break;
|
|
4259
|
-
if (
|
|
3645
|
+
if (result.value === "busy") {
|
|
4260
3646
|
await c.close();
|
|
4261
3647
|
continue;
|
|
4262
3648
|
}
|
|
4263
3649
|
const status = await c.getSystemStatus(200);
|
|
3650
|
+
if (!this._isLifecycleCurrent(generation)) {
|
|
3651
|
+
await c.close();
|
|
3652
|
+
return this._staleLifecycleResult();
|
|
3653
|
+
}
|
|
4264
3654
|
if (status.isErr()) {
|
|
4265
3655
|
await c.close();
|
|
4266
3656
|
continue;
|
|
@@ -4269,23 +3659,38 @@ class V5SerialDevice extends VexSerialDevice {
|
|
|
4269
3659
|
await c.close();
|
|
4270
3660
|
continue;
|
|
4271
3661
|
}
|
|
4272
|
-
this.
|
|
3662
|
+
if (!this._commitConnection(c, generation)) {
|
|
3663
|
+
await c.close();
|
|
3664
|
+
return this._staleLifecycleResult();
|
|
3665
|
+
}
|
|
4273
3666
|
break;
|
|
4274
3667
|
}
|
|
4275
3668
|
if (this.isConnected)
|
|
4276
3669
|
break;
|
|
4277
3670
|
const getPortCount = async () => (await this.defaultSerial.getPorts()).length;
|
|
4278
3671
|
const portsCount = await getPortCount();
|
|
3672
|
+
if (!this._isLifecycleCurrent(generation)) {
|
|
3673
|
+
return this._staleLifecycleResult();
|
|
3674
|
+
}
|
|
4279
3675
|
await sleepUntilAsync(async () => await getPortCount() !== portsCount, 1000);
|
|
3676
|
+
if (!this._isLifecycleCurrent(generation)) {
|
|
3677
|
+
return this._staleLifecycleResult();
|
|
3678
|
+
}
|
|
4280
3679
|
}
|
|
4281
3680
|
} catch (e) {
|
|
4282
3681
|
return import_neverthrow5.err(toVexSerialError(e));
|
|
4283
3682
|
} finally {
|
|
4284
3683
|
this._isReconnecting = false;
|
|
4285
3684
|
}
|
|
4286
|
-
|
|
3685
|
+
const connection = this.connection;
|
|
3686
|
+
if (!this._isLifecycleCurrent(generation) || connection == null) {
|
|
3687
|
+
return this._staleLifecycleResult();
|
|
3688
|
+
}
|
|
3689
|
+
if (!connection.isConnected)
|
|
4287
3690
|
return import_neverthrow5.err(new VexNotConnectedError);
|
|
4288
|
-
await this.doAfterConnect();
|
|
3691
|
+
const initialized = await this.doAfterConnect(connection, generation);
|
|
3692
|
+
if (initialized.isErr())
|
|
3693
|
+
return initialized;
|
|
4289
3694
|
return import_neverthrow5.ok(undefined);
|
|
4290
3695
|
}
|
|
4291
3696
|
async waitForReconnectToFinish() {
|
|
@@ -4295,15 +3700,69 @@ class V5SerialDevice extends VexSerialDevice {
|
|
|
4295
3700
|
return;
|
|
4296
3701
|
}
|
|
4297
3702
|
}
|
|
4298
|
-
|
|
4299
|
-
|
|
4300
|
-
|
|
4301
|
-
|
|
4302
|
-
|
|
4303
|
-
|
|
3703
|
+
createConnection() {
|
|
3704
|
+
return new V5SerialConnection(this.defaultSerial);
|
|
3705
|
+
}
|
|
3706
|
+
_isLifecycleCurrent(generation) {
|
|
3707
|
+
return generation === this._lifecycleGeneration && !this._disposed;
|
|
3708
|
+
}
|
|
3709
|
+
_staleLifecycleResult() {
|
|
3710
|
+
return import_neverthrow5.err(new VexNotConnectedError("connection attempt was superseded"));
|
|
3711
|
+
}
|
|
3712
|
+
_commitConnection(connection, generation) {
|
|
3713
|
+
if (!this._isLifecycleCurrent(generation))
|
|
3714
|
+
return false;
|
|
3715
|
+
this._detachDisconnectListener();
|
|
3716
|
+
this.connection = connection;
|
|
3717
|
+
return true;
|
|
3718
|
+
}
|
|
3719
|
+
_detachDisconnectListener() {
|
|
3720
|
+
const subscription = this._disconnectListener;
|
|
3721
|
+
this._disconnectListener = undefined;
|
|
3722
|
+
subscription?.connection.remove("disconnected", subscription.listener);
|
|
3723
|
+
}
|
|
3724
|
+
async doAfterConnect(connection, generation) {
|
|
3725
|
+
if (!this._isLifecycleCurrent(generation) || this.connection !== connection) {
|
|
3726
|
+
return this._staleLifecycleResult();
|
|
3727
|
+
}
|
|
3728
|
+
const listener = () => {
|
|
3729
|
+
if (this._isDisconnecting || !this._isLifecycleCurrent(generation) || this.connection !== connection) {
|
|
3730
|
+
return;
|
|
4304
3731
|
}
|
|
4305
|
-
|
|
4306
|
-
|
|
3732
|
+
this._lifecycleGeneration++;
|
|
3733
|
+
this._refreshGeneration++;
|
|
3734
|
+
this.connection = undefined;
|
|
3735
|
+
this._detachDisconnectListener();
|
|
3736
|
+
this._emitSafely("disconnected", undefined);
|
|
3737
|
+
if (this.autoReconnect && !this._disposed) {
|
|
3738
|
+
this.reconnect().mapErr((error) => this._emitSafely("error", error));
|
|
3739
|
+
}
|
|
3740
|
+
};
|
|
3741
|
+
connection.on("disconnected", listener);
|
|
3742
|
+
this._disconnectListener = { connection, listener };
|
|
3743
|
+
const refreshed = await this.refresh();
|
|
3744
|
+
if (!this._isLifecycleCurrent(generation) || this.connection !== connection || !connection.isConnected) {
|
|
3745
|
+
return this._staleLifecycleResult();
|
|
3746
|
+
}
|
|
3747
|
+
if (refreshed.isErr()) {
|
|
3748
|
+
await this._discardConnection(connection, generation);
|
|
3749
|
+
return import_neverthrow5.err(refreshed.error);
|
|
3750
|
+
}
|
|
3751
|
+
if (!refreshed.value) {
|
|
3752
|
+
await this._discardConnection(connection, generation);
|
|
3753
|
+
return import_neverthrow5.err(new VexNotConnectedError("initial device refresh did not produce a current snapshot"));
|
|
3754
|
+
}
|
|
3755
|
+
return import_neverthrow5.ok(undefined);
|
|
3756
|
+
}
|
|
3757
|
+
async _discardConnection(connection, generation) {
|
|
3758
|
+
if (!this._isLifecycleCurrent(generation) || this.connection !== connection) {
|
|
3759
|
+
return;
|
|
3760
|
+
}
|
|
3761
|
+
this._lifecycleGeneration++;
|
|
3762
|
+
this._refreshGeneration++;
|
|
3763
|
+
this.connection = undefined;
|
|
3764
|
+
this._detachDisconnectListener();
|
|
3765
|
+
await connection.close();
|
|
4307
3766
|
}
|
|
4308
3767
|
refresh() {
|
|
4309
3768
|
return new import_neverthrow5.ResultAsync(this._refresh());
|
|
@@ -4317,31 +3776,15 @@ class V5SerialDevice extends VexSerialDevice {
|
|
|
4317
3776
|
this._applySnapshotIfCurrent(generation, { isAvailable: false });
|
|
4318
3777
|
return import_neverthrow5.ok(false);
|
|
4319
3778
|
}
|
|
4320
|
-
const ssPacket = await
|
|
4321
|
-
|
|
4322
|
-
|
|
4323
|
-
|
|
4324
|
-
|
|
4325
|
-
|
|
4326
|
-
}
|
|
4327
|
-
const sfPacket = await conn.getSystemFlags();
|
|
4328
|
-
if (generation !== this._refreshGeneration || this._disposed)
|
|
4329
|
-
return import_neverthrow5.ok(false);
|
|
4330
|
-
if (sfPacket.isErr()) {
|
|
4331
|
-
this._applySnapshotIfCurrent(generation, { isAvailable: false });
|
|
4332
|
-
return import_neverthrow5.ok(false);
|
|
4333
|
-
}
|
|
4334
|
-
const rdPacket = await conn.getRadioStatus();
|
|
3779
|
+
const [ssPacket, sfPacket, rdPacket, dsPacket] = await Promise.all([
|
|
3780
|
+
conn.getSystemStatus(),
|
|
3781
|
+
conn.getSystemFlags(),
|
|
3782
|
+
conn.getRadioStatus(),
|
|
3783
|
+
conn.getDeviceStatus()
|
|
3784
|
+
]);
|
|
4335
3785
|
if (generation !== this._refreshGeneration || this._disposed)
|
|
4336
3786
|
return import_neverthrow5.ok(false);
|
|
4337
|
-
if (rdPacket.isErr()) {
|
|
4338
|
-
this._applySnapshotIfCurrent(generation, { isAvailable: false });
|
|
4339
|
-
return import_neverthrow5.ok(false);
|
|
4340
|
-
}
|
|
4341
|
-
const dsPacket = await conn.getDeviceStatus();
|
|
4342
|
-
if (generation !== this._refreshGeneration || this._disposed)
|
|
4343
|
-
return import_neverthrow5.ok(false);
|
|
4344
|
-
if (dsPacket.isErr()) {
|
|
3787
|
+
if (ssPacket.isErr() || sfPacket.isErr() || rdPacket.isErr() || dsPacket.isErr()) {
|
|
4345
3788
|
this._applySnapshotIfCurrent(generation, { isAvailable: false });
|
|
4346
3789
|
return import_neverthrow5.ok(false);
|
|
4347
3790
|
}
|
|
@@ -4397,7 +3840,8 @@ class V5SerialDevice extends VexSerialDevice {
|
|
|
4397
3840
|
},
|
|
4398
3841
|
{
|
|
4399
3842
|
battery: controller1Battery,
|
|
4400
|
-
isAvailable: controller1Available
|
|
3843
|
+
isAvailable: controller1Available,
|
|
3844
|
+
isCharging: undefined
|
|
4401
3845
|
}
|
|
4402
3846
|
],
|
|
4403
3847
|
radio: {
|
|
@@ -4424,7 +3868,26 @@ class V5SerialDevice extends VexSerialDevice {
|
|
|
4424
3868
|
}
|
|
4425
3869
|
this.state.matchMode = snapshot.matchMode;
|
|
4426
3870
|
this.state.isFieldControllerConnected = snapshot.isFieldControllerConnected;
|
|
4427
|
-
|
|
3871
|
+
const brain = this.state.brain;
|
|
3872
|
+
brain.activeProgram = snapshot.brain.activeProgram;
|
|
3873
|
+
brain.battery.batteryPercent = snapshot.brain.battery.batteryPercent;
|
|
3874
|
+
brain.battery.isCharging = snapshot.brain.battery.isCharging;
|
|
3875
|
+
brain.button.isPressed = snapshot.brain.button.isPressed;
|
|
3876
|
+
brain.button.isDoublePressed = snapshot.brain.button.isDoublePressed;
|
|
3877
|
+
if (brain.cpu0Version.compare(snapshot.brain.cpu0Version) !== 0) {
|
|
3878
|
+
brain.cpu0Version = snapshot.brain.cpu0Version;
|
|
3879
|
+
}
|
|
3880
|
+
if (brain.cpu1Version.compare(snapshot.brain.cpu1Version) !== 0) {
|
|
3881
|
+
brain.cpu1Version = snapshot.brain.cpu1Version;
|
|
3882
|
+
}
|
|
3883
|
+
brain.isAvailable = snapshot.brain.isAvailable;
|
|
3884
|
+
brain.settings.isScreenReversed = snapshot.brain.settings.isScreenReversed;
|
|
3885
|
+
brain.settings.isWhiteTheme = snapshot.brain.settings.isWhiteTheme;
|
|
3886
|
+
brain.settings.usingLanguage = snapshot.brain.settings.usingLanguage;
|
|
3887
|
+
if (brain.systemVersion.compare(snapshot.brain.systemVersion) !== 0) {
|
|
3888
|
+
brain.systemVersion = snapshot.brain.systemVersion;
|
|
3889
|
+
}
|
|
3890
|
+
brain.uniqueId = snapshot.brain.uniqueId;
|
|
4428
3891
|
Object.assign(this.state.controllers[0], snapshot.controllers[0]);
|
|
4429
3892
|
Object.assign(this.state.controllers[1], snapshot.controllers[1]);
|
|
4430
3893
|
Object.assign(this.state.radio, snapshot.radio);
|
|
@@ -4433,10 +3896,18 @@ class V5SerialDevice extends VexSerialDevice {
|
|
|
4433
3896
|
if (device != null)
|
|
4434
3897
|
next[device.port] = device;
|
|
4435
3898
|
}
|
|
4436
|
-
this.state.devices
|
|
3899
|
+
if (!sameSmartDeviceSlots(this.state.devices, next)) {
|
|
3900
|
+
this.state.devices = next;
|
|
3901
|
+
}
|
|
4437
3902
|
return true;
|
|
4438
3903
|
}
|
|
4439
3904
|
}
|
|
3905
|
+
function sameSmartDeviceSlots(left, right) {
|
|
3906
|
+
return left.length === right.length && left.every((device, index) => {
|
|
3907
|
+
const next = right[index];
|
|
3908
|
+
return device === next || device !== undefined && next !== undefined && device.port === next.port && device.type === next.type && device.status === next.status && device.betaversion === next.betaversion && device.version === next.version && device.bootversion === next.bootversion;
|
|
3909
|
+
});
|
|
3910
|
+
}
|
|
4440
3911
|
// src/VexIniConfig.ts
|
|
4441
3912
|
class BaseIniBuilder {
|
|
4442
3913
|
str = "";
|
|
@@ -4445,7 +3916,7 @@ class BaseIniBuilder {
|
|
|
4445
3916
|
`;
|
|
4446
3917
|
}
|
|
4447
3918
|
addComment(comment) {
|
|
4448
|
-
this.addLine("; " + comment);
|
|
3919
|
+
this.addLine(comment.length === 0 ? ";" : "; " + comment);
|
|
4449
3920
|
return this;
|
|
4450
3921
|
}
|
|
4451
3922
|
getContent() {
|
|
@@ -4463,24 +3934,28 @@ class IniSectionBuilder extends BaseIniBuilder {
|
|
|
4463
3934
|
this.object = object;
|
|
4464
3935
|
this.keyTransform = keyTransform;
|
|
4465
3936
|
}
|
|
4466
|
-
addSingleObjProperty(key, maxValueLength) {
|
|
4467
|
-
|
|
3937
|
+
addSingleObjProperty(key, maxValueLength, omitIfEmpty = false) {
|
|
3938
|
+
const rawValue = this.object[key];
|
|
3939
|
+
if (rawValue == null)
|
|
4468
3940
|
return;
|
|
3941
|
+
const value = rawValue.toString();
|
|
3942
|
+
if (omitIfEmpty && value.length === 0)
|
|
3943
|
+
return;
|
|
3944
|
+
if (/["\u0000-\u001f\u007f]/.test(value)) {
|
|
3945
|
+
throw new Error(`INI value for ${this.name}.${String(key)} contains an unsupported character`);
|
|
3946
|
+
}
|
|
4469
3947
|
const formattedKey = this.keyTransform(key).padEnd(12).slice(0, 12);
|
|
4470
|
-
const
|
|
4471
|
-
|
|
4472
|
-
this.addLine(`${formattedKey} = "${escapedVal}"`);
|
|
3948
|
+
const trimmedValue = value.slice(0, maxValueLength);
|
|
3949
|
+
this.addLine(`${formattedKey} = "${trimmedValue}"`);
|
|
4473
3950
|
}
|
|
4474
|
-
addObjProperty(key, maxValueLength) {
|
|
4475
|
-
const
|
|
4476
|
-
|
|
4477
|
-
this.addSingleObjProperty(k, maxValueLength);
|
|
3951
|
+
addObjProperty(key, maxValueLength, omitIfEmpty = false) {
|
|
3952
|
+
for (const k of Array.isArray(key) ? key : [key]) {
|
|
3953
|
+
this.addSingleObjProperty(k, maxValueLength, omitIfEmpty);
|
|
4478
3954
|
}
|
|
4479
3955
|
return this;
|
|
4480
3956
|
}
|
|
4481
3957
|
addAllObjProps(maxValueLength) {
|
|
4482
|
-
const
|
|
4483
|
-
for (const k of keys) {
|
|
3958
|
+
for (const k of Object.keys(this.object)) {
|
|
4484
3959
|
this.addSingleObjProperty(k, maxValueLength);
|
|
4485
3960
|
}
|
|
4486
3961
|
return this;
|
|
@@ -4493,6 +3968,11 @@ class IniFileBuilder extends BaseIniBuilder {
|
|
|
4493
3968
|
this.str += section.getContent();
|
|
4494
3969
|
return this;
|
|
4495
3970
|
}
|
|
3971
|
+
addOptionalSection(section) {
|
|
3972
|
+
if (section.getContent().length === 0)
|
|
3973
|
+
return this;
|
|
3974
|
+
return this.addComment("").addSection(section);
|
|
3975
|
+
}
|
|
4496
3976
|
}
|
|
4497
3977
|
|
|
4498
3978
|
class ProgramIniConfig {
|
|
@@ -4509,33 +3989,26 @@ class ProgramIniConfig {
|
|
|
4509
3989
|
date: "",
|
|
4510
3990
|
timezone: "0"
|
|
4511
3991
|
};
|
|
4512
|
-
config = {};
|
|
3992
|
+
config = { 22: "adi" };
|
|
4513
3993
|
controller1 = {};
|
|
4514
3994
|
controller2 = {};
|
|
4515
|
-
constructor() {
|
|
4516
|
-
this.config = {
|
|
4517
|
-
22: "adi"
|
|
4518
|
-
};
|
|
4519
|
-
}
|
|
4520
3995
|
setProgramDate(date) {
|
|
4521
|
-
|
|
4522
|
-
|
|
4523
|
-
const
|
|
4524
|
-
const
|
|
4525
|
-
|
|
4526
|
-
this.program.timezone = (d.getTimezoneOffset() > 0 ? "-" : "+") + this.dec2(tzh) + ":" + this.dec2(tzm);
|
|
3996
|
+
this.program.date = date.toISOString();
|
|
3997
|
+
const offset = Math.abs(date.getTimezoneOffset());
|
|
3998
|
+
const hours = offset / 60 >>> 0;
|
|
3999
|
+
const minutes = offset - hours * 60;
|
|
4000
|
+
this.program.timezone = (date.getTimezoneOffset() > 0 ? "-" : "+") + this.dec2(hours) + ":" + this.dec2(minutes);
|
|
4527
4001
|
}
|
|
4528
4002
|
createIni() {
|
|
4529
4003
|
if (this.program.date.length === 0) {
|
|
4530
4004
|
this.setProgramDate(new Date);
|
|
4531
4005
|
}
|
|
4532
|
-
return new IniFileBuilder().addComment("").addComment("VEX program ini file").addComment("Generated by Vex V5 Serial Protocol Library").addComment("").addSection(new IniSectionBuilder("project", this.project).addObjProperty("ide", 16)).addComment("").addSection(new IniSectionBuilder("program", this.program).addObjProperty("name", 32).addObjProperty("
|
|
4006
|
+
return new IniFileBuilder().addComment("").addComment("VEX program ini file").addComment("Generated by Vex V5 Serial Protocol Library").addComment("").addSection(new IniSectionBuilder("project", this.project).addObjProperty("version").addObjProperty("ide", 16).addObjProperty("file")).addComment("").addSection(new IniSectionBuilder("program", this.program).addObjProperty("version").addObjProperty("name", 32).addObjProperty("slot").addObjProperty("icon", 16).addObjProperty("iconalt", 16, true).addObjProperty("description", 256).addObjProperty("date").addObjProperty("timezone")).addComment("").addSection(new IniSectionBuilder("config", this.config, (k) => "port_" + this.dec2(k)).addAllObjProps()).addOptionalSection(new IniSectionBuilder("controller_1", this.controller1).addAllObjProps()).addOptionalSection(new IniSectionBuilder("controller_2", this.controller2).addAllObjProps()).getContent();
|
|
4533
4007
|
}
|
|
4534
4008
|
dec2(value) {
|
|
4535
|
-
|
|
4536
|
-
return str.toUpperCase();
|
|
4009
|
+
return (value % 100).toString(10).padStart(2, "0").toUpperCase();
|
|
4537
4010
|
}
|
|
4538
4011
|
}
|
|
4539
4012
|
|
|
4540
|
-
//# debugId=
|
|
4013
|
+
//# debugId=60E9322CE95DA15264756E2164756E21
|
|
4541
4014
|
//# sourceMappingURL=index.cjs.map
|