@v5x/serial 0.5.4 → 0.5.6

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.
Files changed (56) hide show
  1. package/README.md +73 -9
  2. package/dist/Vex.d.ts +4 -4
  3. package/dist/VexCRC.d.ts +0 -12
  4. package/dist/VexConnection.d.ts +106 -26
  5. package/dist/VexDevice.d.ts +52 -157
  6. package/{dts/VexDevice.d.ts → dist/VexDeviceState.d.ts} +79 -62
  7. package/dist/VexError.d.ts +50 -0
  8. package/dist/VexEvent.d.ts +15 -10
  9. package/dist/VexFirmware.d.ts +47 -0
  10. package/dist/VexFirmwareVersion.d.ts +4 -43
  11. package/dist/VexIniConfig.d.ts +1 -2
  12. package/dist/VexPacket.d.ts +3 -512
  13. package/dist/VexPacketBase.d.ts +24 -0
  14. package/dist/VexPacketEncoder.d.ts +36 -0
  15. package/{dts/VexPacket.d.ts → dist/VexPacketModels.d.ts} +3 -118
  16. package/dist/VexPacketView.d.ts +5 -3
  17. package/dist/VexTransfers.d.ts +20 -0
  18. package/dist/index.cjs +4175 -0
  19. package/dist/index.cjs.map +25 -0
  20. package/dist/index.d.ts +9 -9
  21. package/dist/index.js +4093 -0
  22. package/dist/index.js.map +25 -0
  23. package/package.json +39 -71
  24. package/dist/v5-serial-protocol.cjs.js +0 -4516
  25. package/dist/v5-serial-protocol.cjs.js.map +0 -1
  26. package/dist/v5-serial-protocol.es.js +0 -4401
  27. package/dist/v5-serial-protocol.es.js.map +0 -1
  28. package/dts/Vex.d.ts +0 -235
  29. package/dts/Vex.js +0 -189
  30. package/dts/Vex.js.map +0 -1
  31. package/dts/VexCRC.d.ts +0 -19
  32. package/dts/VexCRC.js +0 -89
  33. package/dts/VexCRC.js.map +0 -1
  34. package/dts/VexConnection.d.ts +0 -45
  35. package/dts/VexConnection.js +0 -500
  36. package/dts/VexConnection.js.map +0 -1
  37. package/dts/VexDevice.js +0 -944
  38. package/dts/VexDevice.js.map +0 -1
  39. package/dts/VexEvent.d.ts +0 -16
  40. package/dts/VexEvent.js +0 -47
  41. package/dts/VexEvent.js.map +0 -1
  42. package/dts/VexFirmwareVersion.d.ts +0 -55
  43. package/dts/VexFirmwareVersion.js +0 -104
  44. package/dts/VexFirmwareVersion.js.map +0 -1
  45. package/dts/VexIniConfig.d.ts +0 -27
  46. package/dts/VexIniConfig.js +0 -122
  47. package/dts/VexIniConfig.js.map +0 -1
  48. package/dts/VexPacket.js +0 -1036
  49. package/dts/VexPacket.js.map +0 -1
  50. package/dts/VexPacketView.d.ts +0 -18
  51. package/dts/VexPacketView.js +0 -84
  52. package/dts/VexPacketView.js.map +0 -1
  53. package/dts/index.d.ts +0 -9
  54. package/dts/index.js +0 -10
  55. package/dts/index.js.map +0 -1
  56. package/index.d.ts +0 -1098
package/dts/VexDevice.js DELETED
@@ -1,944 +0,0 @@
1
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
- return new (P || (P = Promise))(function (resolve, reject) {
4
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
- step((generator = generator.apply(thisArg, _arguments || [])).next());
8
- });
9
- };
10
- import { SerialDeviceType, SmartDeviceType, FileVendor, FileExitAction, FileDownloadTarget, USER_FLASH_USR_CODE_START, RadioChannelType, } from "./Vex";
11
- import { V5SerialConnection } from "./VexConnection";
12
- import { VexEventTarget } from "./VexEvent";
13
- import { VexFirmwareVersion } from "./VexFirmwareVersion";
14
- import { EraseFileH2DPacket, EraseFileReplyD2HPacket, ExitFileTransferH2DPacket, ExitFileTransferReplyD2HPacket, FactoryEnableH2DPacket, FactoryEnableReplyD2HPacket, FactoryStatusH2DPacket, FactoryStatusReplyD2HPacket, FileClearUpH2DPacket, FileClearUpReplyD2HPacket, FileControlH2DPacket, FileControlReplyD2HPacket, GetDirectoryEntryH2DPacket, GetDirectoryEntryReplyD2HPacket, GetDirectoryFileCountH2DPacket, GetDirectoryFileCountReplyD2HPacket, GetProgramSlotInfoH2DPacket, GetProgramSlotInfoReplyD2HPacket, ReadKeyValueH2DPacket, ReadKeyValueReplyD2HPacket, ScreenCaptureH2DPacket, WriteKeyValueH2DPacket, WriteKeyValueReplyD2HPacket, } from "./VexPacket";
15
- export function downloadFileFromInternet(link) {
16
- return __awaiter(this, void 0, void 0, function* () {
17
- return yield new Promise((resolve, reject) => {
18
- const oReq = new XMLHttpRequest();
19
- oReq.open("GET", link, true);
20
- oReq.responseType = "arraybuffer";
21
- oReq.onload = function (_oEvent) {
22
- const arrayBuffer = oReq.response; // Note: not oReq.responseText
23
- resolve(arrayBuffer);
24
- };
25
- oReq.onerror = function (oEvent) {
26
- reject(oEvent);
27
- };
28
- oReq.send(null);
29
- });
30
- });
31
- }
32
- export function sleepUntilAsync(f, timeout, interval = 20) {
33
- return __awaiter(this, void 0, void 0, function* () {
34
- return yield new Promise((resolve) => {
35
- let lastTime = new Date().getTime();
36
- let stopped = false;
37
- const stopper = setTimeout(() => {
38
- stopped = true;
39
- resolve(false);
40
- }, timeout);
41
- const checker = (val) => {
42
- if (stopped)
43
- return;
44
- if (val) {
45
- clearTimeout(stopper);
46
- resolve(true);
47
- }
48
- else if (new Date().getTime() - lastTime > interval) {
49
- lastTime = new Date().getTime();
50
- void f().then(checker);
51
- }
52
- else
53
- setTimeout(() => {
54
- lastTime = new Date().getTime();
55
- void f().then(checker);
56
- }, new Date().getTime() - lastTime);
57
- };
58
- void f().then(checker);
59
- });
60
- });
61
- }
62
- export function sleepUntil(f, timeout, interval = 20) {
63
- return __awaiter(this, void 0, void 0, function* () {
64
- return yield new Promise((resolve) => {
65
- const timeWas = new Date().getTime();
66
- const wait = setInterval(function () {
67
- if (f()) {
68
- clearInterval(wait);
69
- resolve(true);
70
- }
71
- else if (new Date().getTime() - timeWas > timeout) {
72
- // Timeout
73
- clearInterval(wait);
74
- resolve(false);
75
- }
76
- }, interval);
77
- });
78
- });
79
- }
80
- export function sleep(ms) {
81
- return __awaiter(this, void 0, void 0, function* () {
82
- return yield new Promise((resolve) => setTimeout(resolve, ms));
83
- });
84
- }
85
- export class VexSerialDevice extends VexEventTarget {
86
- get isConnected() {
87
- return this.connection != null ? this.connection.isConnected : false;
88
- }
89
- get deviceType() {
90
- var _a, _b;
91
- return this.isConnected
92
- ? (_b = (_a = this.connection) === null || _a === void 0 ? void 0 : _a.port) === null || _b === void 0 ? void 0 : _b.getInfo().usbProductId
93
- : undefined;
94
- }
95
- constructor(defaultSerial) {
96
- super();
97
- this.defaultSerial = defaultSerial;
98
- }
99
- }
100
- class V5SerialDeviceState {
101
- constructor(instance) {
102
- this._isFileTransferring = false;
103
- this.brain = {
104
- activeProgram: 0,
105
- battery: {
106
- batteryPercent: 0,
107
- isCharging: false,
108
- },
109
- button: {
110
- isPressed: false,
111
- isDoublePressed: false,
112
- },
113
- cpu0Version: VexFirmwareVersion.allZero(),
114
- cpu1Version: VexFirmwareVersion.allZero(),
115
- isAvailable: false,
116
- settings: {
117
- isScreenReversed: false,
118
- isWhiteTheme: false,
119
- usingLanguage: 0,
120
- },
121
- systemVersion: VexFirmwareVersion.allZero(),
122
- uniqueId: 0,
123
- };
124
- this.controllers = [
125
- {
126
- battery: 0,
127
- isAvailable: false,
128
- isCharging: false,
129
- },
130
- {
131
- battery: 0,
132
- isAvailable: false,
133
- },
134
- ];
135
- this.devices = [];
136
- this.isFieldControllerConnected = false;
137
- this.matchMode = "disabled";
138
- this.radio = {
139
- channel: 0,
140
- isAvailable: false,
141
- isConnected: false,
142
- isVexNet: false,
143
- isRadioData: false,
144
- latency: 0,
145
- signalQuality: 0,
146
- signalStrength: 0,
147
- };
148
- this._instance = instance;
149
- }
150
- }
151
- export class V5Brain {
152
- constructor(state) {
153
- this.state = state;
154
- }
155
- get isRunningProgram() {
156
- return this.activeProgram !== 0;
157
- }
158
- get activeProgram() {
159
- return this.state.brain.activeProgram;
160
- }
161
- set activeProgram(value) {
162
- void (() => __awaiter(this, void 0, void 0, function* () {
163
- if (this.state.brain.activeProgram === value)
164
- return;
165
- const conn = this.state._instance.connection;
166
- if (conn == null)
167
- return;
168
- const fn = value === 0
169
- ? yield conn.stopProgram()
170
- : yield conn.loadProgram(value);
171
- if (fn != null)
172
- this.state.brain.activeProgram = value;
173
- }))();
174
- }
175
- get battery() {
176
- return new V5Battery(this.state);
177
- }
178
- get button() {
179
- return new V5BrainButton(this.state);
180
- }
181
- get cpu0Version() {
182
- return this.state.brain.cpu0Version;
183
- }
184
- get cpu1Version() {
185
- return this.state.brain.cpu1Version;
186
- }
187
- get isAvailable() {
188
- return this.state.brain.isAvailable;
189
- }
190
- get settings() {
191
- return new V5BrainSettings(this.state);
192
- }
193
- get systemVersion() {
194
- return this.state.brain.systemVersion;
195
- }
196
- get uniqueId() {
197
- return this.state.brain.uniqueId;
198
- }
199
- getValue(key) {
200
- var _a;
201
- return __awaiter(this, void 0, void 0, function* () {
202
- const result = yield ((_a = this.state._instance.connection) === null || _a === void 0 ? void 0 : _a.writeDataAsync(new ReadKeyValueH2DPacket(key)));
203
- return result instanceof ReadKeyValueReplyD2HPacket
204
- ? result.value
205
- : undefined;
206
- });
207
- }
208
- setValue(key, value) {
209
- var _a;
210
- return __awaiter(this, void 0, void 0, function* () {
211
- const result = yield ((_a = this.state._instance.connection) === null || _a === void 0 ? void 0 : _a.writeDataAsync(new WriteKeyValueH2DPacket(key, value)));
212
- return result instanceof WriteKeyValueReplyD2HPacket;
213
- });
214
- }
215
- listFiles(vendor = FileVendor.USER) {
216
- return __awaiter(this, void 0, void 0, function* () {
217
- const conn = this.state._instance.connection;
218
- if (conn == null || !conn.isConnected)
219
- return;
220
- const result = yield conn.writeDataAsync(new GetDirectoryFileCountH2DPacket(vendor));
221
- if (!(result instanceof GetDirectoryFileCountReplyD2HPacket))
222
- return;
223
- const files = [];
224
- for (let i = 0; i < result.count; i++) {
225
- const result2 = yield conn.writeDataAsync(new GetDirectoryEntryH2DPacket(i));
226
- if (!(result2 instanceof GetDirectoryEntryReplyD2HPacket))
227
- return;
228
- // .file is undefined if the file is not found
229
- // .file is a file entry but not a file handle
230
- if (result2.file != null) {
231
- files.push({
232
- filename: result2.file.filename,
233
- vendor,
234
- loadAddress: result2.file.loadAddress,
235
- size: result2.file.size,
236
- crc32: result2.file.crc32,
237
- type: result2.file.type,
238
- timestamp: result2.file.timestamp,
239
- version: result2.file.version,
240
- });
241
- }
242
- }
243
- return files;
244
- });
245
- }
246
- listProgram() {
247
- var _a, _b;
248
- return __awaiter(this, void 0, void 0, function* () {
249
- const conn = this.state._instance.connection;
250
- if (conn == null || !conn.isConnected)
251
- return;
252
- const files = yield this.listFiles(FileVendor.USER);
253
- if (files === undefined)
254
- return;
255
- const programList = [];
256
- const iniFiles = files.filter((file) => { var _a; return (_a = (file === null || file === void 0 ? void 0 : file.filename.search(/.ini$/)) > 0) !== null && _a !== void 0 ? _a : false; });
257
- for (let i = 0; i < iniFiles.length; i++) {
258
- const ini = iniFiles[i];
259
- if (ini.size === 0)
260
- continue;
261
- const programName = (_b = (_a = /(.+?)(\.[^.]*$|$)/.exec(ini.filename)) === null || _a === void 0 ? void 0 : _a[1]) !== null && _b !== void 0 ? _b : "";
262
- const bin = files.filter((e) => e != null && e.filename === programName + ".bin")[0];
263
- if (bin == null || bin.timestamp === 0 || bin.size === 0)
264
- continue;
265
- const n = new Date();
266
- n.setTime(1000 * bin.timestamp);
267
- const program = {
268
- name: programName,
269
- binfile: bin.filename,
270
- size: ini.size + bin.size,
271
- slot: -1,
272
- time: n,
273
- requestedSlot: -1,
274
- };
275
- const result2 = yield (conn === null || conn === void 0 ? void 0 : conn.writeDataAsync(new GetProgramSlotInfoH2DPacket(FileVendor.USER, program.binfile)));
276
- if (result2 instanceof GetProgramSlotInfoReplyD2HPacket) {
277
- program.slot = result2.slot;
278
- program.requestedSlot = result2.requestedSlot;
279
- }
280
- programList.push(program);
281
- }
282
- return programList;
283
- });
284
- }
285
- readFile(request, downloadTarget = FileDownloadTarget.FILE_TARGET_QSPI, progressCallback) {
286
- return __awaiter(this, void 0, void 0, function* () {
287
- const conn = this.state._instance.connection;
288
- if (conn == null || !conn.isConnected)
289
- return;
290
- this.state._isFileTransferring = true;
291
- let handle;
292
- // If request is a string, then it is a filename
293
- if (typeof request === "string") {
294
- handle = { filename: request, vendor: FileVendor.USER };
295
- }
296
- else {
297
- handle = request;
298
- }
299
- try {
300
- return yield conn.downloadFileToHost(handle, downloadTarget, progressCallback);
301
- }
302
- catch (e) {
303
- this.state._isFileTransferring = false;
304
- throw e;
305
- }
306
- });
307
- }
308
- removeFile(request) {
309
- return __awaiter(this, void 0, void 0, function* () {
310
- const conn = this.state._instance.connection;
311
- if (conn == null || !conn.isConnected)
312
- return;
313
- let vendor, filename;
314
- // If request is a string, then it is a filename
315
- if (typeof request === "string") {
316
- vendor = FileVendor.USER;
317
- filename = request;
318
- }
319
- else {
320
- vendor = request.vendor;
321
- filename = request.filename;
322
- }
323
- const result = yield conn.writeDataAsync(new EraseFileH2DPacket(vendor, filename));
324
- const result2 = yield conn.writeDataAsync(new ExitFileTransferH2DPacket(FileExitAction.EXIT_HALT));
325
- if (!(result instanceof EraseFileReplyD2HPacket))
326
- return false;
327
- if (!(result2 instanceof ExitFileTransferReplyD2HPacket))
328
- return false;
329
- return true;
330
- });
331
- }
332
- removeAllFiles() {
333
- return __awaiter(this, void 0, void 0, function* () {
334
- const conn = this.state._instance.connection;
335
- if (conn == null || !conn.isConnected)
336
- return undefined;
337
- const result = yield conn.writeDataAsync(new FileClearUpH2DPacket(FileVendor.USER), 30000);
338
- return result instanceof FileClearUpReplyD2HPacket;
339
- });
340
- }
341
- uploadFirmware(publicUrl = "https://content.vexrobotics.com/vexos/public/V5/", usingVersion, progressCallback) {
342
- return __awaiter(this, void 0, void 0, function* () {
343
- const device = this.state._instance;
344
- const conn = device.connection;
345
- if (conn == null || !conn.isConnected)
346
- return;
347
- const pcb = progressCallback !== null && progressCallback !== void 0 ? progressCallback : (() => { });
348
- let vexos, bootBin, assertBin;
349
- try {
350
- if (usingVersion === undefined) {
351
- pcb("FETCH CATALOG", 0, 1);
352
- const catalog = yield downloadFileFromInternet(publicUrl + "catalog.txt");
353
- const latestVersion = new TextDecoder().decode(catalog);
354
- usingVersion = latestVersion;
355
- pcb("FETCH CATALOG", 1, 1);
356
- console.log("fetched catalog.txt", latestVersion);
357
- }
358
- pcb("FETCH VEXOS", 0, 1);
359
- vexos = yield downloadFileFromInternet(publicUrl + usingVersion + ".vexos");
360
- pcb("FETCH VEXOS", 1, 1);
361
- pcb("UNZIP VEXOS", 0, 1);
362
- const { unzip } = yield import("unzipit");
363
- const { entries } = yield unzip(vexos);
364
- bootBin = yield entries[usingVersion + "/BOOT.bin"].arrayBuffer();
365
- assertBin = yield entries[usingVersion + "/assets.bin"].arrayBuffer();
366
- pcb("UNZIP VEXOS", 1, 1);
367
- }
368
- catch (e) {
369
- return undefined;
370
- }
371
- try {
372
- this.state._isFileTransferring = true;
373
- pcb("FACTORY ENB BOOT", 0, 0);
374
- const result = yield conn.writeDataAsync(new FactoryEnableH2DPacket());
375
- if (!(result instanceof FactoryEnableReplyD2HPacket))
376
- return false;
377
- const bootWriteRequest = {
378
- filename: "null.bin",
379
- vendor: FileVendor.USER,
380
- loadAddress: USER_FLASH_USR_CODE_START,
381
- buf: new Uint8Array(bootBin),
382
- downloadTarget: FileDownloadTarget.FILE_TARGET_B1,
383
- exttype: "bin",
384
- autoRun: true,
385
- linkedFile: undefined,
386
- };
387
- const result2 = yield conn.uploadFileToDevice(bootWriteRequest, (c, t) => {
388
- pcb("UPLOAD BOOT", c, t);
389
- });
390
- if (!result2)
391
- return false;
392
- while (true) {
393
- const result3 = yield conn.writeDataAsync(new FactoryStatusH2DPacket(), 10000);
394
- if (result3 instanceof FactoryStatusReplyD2HPacket) {
395
- switch (result3.status) {
396
- case 2:
397
- pcb("ERASE BOOT", result3.percent, 100);
398
- break;
399
- case 3:
400
- pcb("WRITE BOOT", result3.percent, 100);
401
- break;
402
- case 4:
403
- pcb("VERIFY BOOT", result3.percent, 100);
404
- break;
405
- case 8:
406
- pcb("FINISHING BOOT", result3.percent, 100);
407
- break;
408
- }
409
- if (result3.status === 0 && result3.percent === 100)
410
- break;
411
- }
412
- else {
413
- return false;
414
- }
415
- yield sleep(500);
416
- }
417
- pcb("FACTORY ENB ASSERT", 0, 0);
418
- const result5 = yield conn.writeDataAsync(new FactoryEnableH2DPacket());
419
- if (!(result5 instanceof FactoryEnableReplyD2HPacket))
420
- return false;
421
- const assertWriteRequest = {
422
- filename: "null.bin",
423
- vendor: FileVendor.USER,
424
- loadAddress: USER_FLASH_USR_CODE_START,
425
- buf: new Uint8Array(assertBin),
426
- downloadTarget: FileDownloadTarget.FILE_TARGET_A1,
427
- exttype: "bin",
428
- autoRun: true,
429
- linkedFile: undefined,
430
- };
431
- const result6 = yield conn.uploadFileToDevice(assertWriteRequest, (c, t) => {
432
- pcb("UPLOAD ASSERT", c, t);
433
- });
434
- if (!result6)
435
- return false;
436
- while (true) {
437
- const result7 = yield conn.writeDataAsync(new FactoryStatusH2DPacket(), 10000);
438
- if (result7 instanceof FactoryStatusReplyD2HPacket) {
439
- switch (result7.status) {
440
- case 2:
441
- pcb("ERASE ASSERT", result7.percent, 100);
442
- break;
443
- case 3:
444
- pcb("WRITE ASSERT", result7.percent, 100);
445
- break;
446
- case 4:
447
- pcb("VERIFY ASSERT", result7.percent, 100);
448
- break;
449
- case 8:
450
- pcb("FINISHING ASSERT", result7.percent, 100);
451
- break;
452
- }
453
- if (result7.status === 0 && result7.percent === 100)
454
- break;
455
- }
456
- else {
457
- return false;
458
- }
459
- yield sleep(500);
460
- }
461
- }
462
- catch (e) {
463
- this.state._isFileTransferring = false;
464
- throw e;
465
- }
466
- return true;
467
- });
468
- }
469
- uploadProgram(iniConfig, binFileBuf, coldFileBuf, progressCallback) {
470
- return __awaiter(this, void 0, void 0, function* () {
471
- const device = this.state._instance;
472
- const conn = device.connection;
473
- if (conn == null || !conn.isConnected)
474
- return;
475
- this.state._isFileTransferring = true;
476
- try {
477
- if (device.isV5Controller) {
478
- yield sleep(250);
479
- // V5 Controller doesn\'t appear to be connected to a V5 Brain
480
- if (!(yield device.refresh()))
481
- return;
482
- console.log("Transferring to download channel");
483
- const p1 = yield device.radio.changeChannel(RadioChannelType.DOWNLOAD);
484
- if (!p1)
485
- return false;
486
- yield sleep(250);
487
- yield sleepUntilAsync(() => __awaiter(this, void 0, void 0, function* () { return (yield (conn === null || conn === void 0 ? void 0 : conn.getSystemStatus(150))) != null; }), 10000, 200);
488
- console.log("Transferred to download channel");
489
- }
490
- const p2 = yield conn.uploadProgramToDevice(iniConfig, binFileBuf, coldFileBuf, progressCallback);
491
- if (!(p2 !== null && p2 !== void 0 ? p2 : false))
492
- return false;
493
- if (device.isV5Controller) {
494
- // Disconnected
495
- if (!device.brain.isAvailable)
496
- return false;
497
- console.log("Transferring back to pit channel");
498
- const p3 = yield device.radio.changeChannel(RadioChannelType.PIT);
499
- if (!p3)
500
- return false;
501
- yield sleep(250);
502
- yield sleepUntilAsync(() => __awaiter(this, void 0, void 0, function* () { return (yield (conn === null || conn === void 0 ? void 0 : conn.getSystemStatus(150))) != null; }), 10000, 200);
503
- console.log("All done");
504
- }
505
- return true;
506
- }
507
- catch (e) {
508
- this.state._isFileTransferring = false;
509
- throw e;
510
- }
511
- });
512
- }
513
- writeFile(request, progressCallback) {
514
- return __awaiter(this, void 0, void 0, function* () {
515
- this.state._isFileTransferring = true;
516
- const conn = this.state._instance.connection;
517
- if (conn == null || !conn.isConnected)
518
- return undefined;
519
- try {
520
- return yield conn.uploadFileToDevice(request, progressCallback);
521
- }
522
- catch (e) {
523
- this.state._isFileTransferring = false;
524
- throw e;
525
- }
526
- });
527
- }
528
- /**
529
- *
530
- * @param progressCallback Informs the progress of the download.
531
- * @returns array of bytes where each pixel is represented by 3 consecutive bytes (rgb).
532
- * This array's length is 272 width * 480 height * 3 channels = 391680 bytes.
533
- */
534
- captureScreen(progressCallback) {
535
- return __awaiter(this, void 0, void 0, function* () {
536
- // pros implementation: https://github.com/purduesigbots/pros-cli/blob/5ee18656faeb48f51d680bab4b53d5b59cc5a7d5/pros/serial/devices/vex/v5_device.py#L578
537
- const conn = this.state._instance.connection;
538
- if (conn == null || !conn.isConnected)
539
- return undefined;
540
- yield new Promise((resolve) => {
541
- conn.writeData(new ScreenCaptureH2DPacket(0), resolve);
542
- });
543
- const height = 272;
544
- const width = 480;
545
- const channels = 3;
546
- const messageWidth = 512; // brain goofiness
547
- const messageChannels = 4; // brain goofiness
548
- let buf = yield (conn === null || conn === void 0 ? void 0 : conn.downloadFileToHost({
549
- filename: "screen",
550
- vendor: FileVendor.SYS,
551
- loadAddress: 0,
552
- size: messageWidth * height * messageChannels, // RGBA ig
553
- }, FileDownloadTarget.FILE_TARGET_CBUF, progressCallback));
554
- if (buf == null)
555
- return;
556
- buf = buf
557
- // remove the extra columns
558
- .filter((_byte, i) => i % (messageWidth * messageChannels) < width * messageChannels)
559
- // remove the fake alpha channel
560
- .filter((_byte, i) => (i + 1) % messageChannels !== 0);
561
- // reverse the pixel (bgr -> rgb)
562
- for (let i = 0; i < buf.length; i += channels) {
563
- const px = buf.slice(i, i + channels).reverse();
564
- for (let j = 0; j < px.length; j++) {
565
- buf[i + j] = px[j];
566
- }
567
- }
568
- return buf;
569
- });
570
- }
571
- }
572
- export class V5Battery {
573
- constructor(state) {
574
- this.state = state;
575
- }
576
- get batteryPercent() {
577
- return this.state.brain.battery.batteryPercent;
578
- }
579
- get isCharging() {
580
- return this.state.brain.battery.isCharging;
581
- }
582
- }
583
- export class V5BrainButton {
584
- constructor(state) {
585
- this.state = state;
586
- }
587
- get isPressed() {
588
- return this.state.brain.button.isPressed;
589
- }
590
- get isDoublePressed() {
591
- return this.state.brain.button.isDoublePressed;
592
- }
593
- }
594
- export class V5BrainSettings {
595
- constructor(state) {
596
- this.state = state;
597
- }
598
- get isScreenReversed() {
599
- return this.state.brain.settings.isScreenReversed;
600
- }
601
- get isWhiteTheme() {
602
- return this.state.brain.settings.isWhiteTheme;
603
- }
604
- get usingLanguage() {
605
- return this.state.brain.settings.usingLanguage;
606
- }
607
- }
608
- export class V5Controller {
609
- constructor(state, controllerIndex) {
610
- this.state = state;
611
- this.controllerIndex = controllerIndex;
612
- }
613
- get batteryPercent() {
614
- return this.state.controllers[this.controllerIndex].battery;
615
- }
616
- get isMasterController() {
617
- return this.controllerIndex === 0;
618
- }
619
- get isAvailable() {
620
- return this.state.controllers[this.controllerIndex].isAvailable;
621
- }
622
- get isCharging() {
623
- return this.state.controllers[this.controllerIndex].isCharging;
624
- }
625
- }
626
- export class V5SmartDevice {
627
- constructor(state, index) {
628
- this.state = state;
629
- this.deviceIndex = index;
630
- }
631
- getDeviceInfo() {
632
- return this.state.devices[this.deviceIndex];
633
- }
634
- get isAvailable() {
635
- return this.getDeviceInfo() !== undefined;
636
- }
637
- get port() {
638
- return this.deviceIndex;
639
- }
640
- get type() {
641
- var _a, _b;
642
- return (_b = (_a = this.getDeviceInfo()) === null || _a === void 0 ? void 0 : _a.type) !== null && _b !== void 0 ? _b : SmartDeviceType.EMPTY;
643
- }
644
- get version() {
645
- var _a, _b;
646
- return (_b = (_a = this.getDeviceInfo()) === null || _a === void 0 ? void 0 : _a.version) !== null && _b !== void 0 ? _b : 0;
647
- }
648
- }
649
- export class V5Radio {
650
- constructor(state) {
651
- this.state = state;
652
- }
653
- get channel() {
654
- return this.state.radio.channel;
655
- }
656
- get isAvailable() {
657
- return this.state.radio.isAvailable;
658
- }
659
- get isConnected() {
660
- return this.state.radio.isConnected;
661
- }
662
- get isVexNet() {
663
- return this.state.radio.isVexNet;
664
- }
665
- get isRadioData() {
666
- return this.state.radio.isRadioData;
667
- }
668
- get latency() {
669
- return this.state.radio.latency;
670
- }
671
- changeChannel(channel) {
672
- var _a;
673
- return __awaiter(this, void 0, void 0, function* () {
674
- const result = yield ((_a = this.state._instance.connection) === null || _a === void 0 ? void 0 : _a.writeDataAsync(new FileControlH2DPacket(1, channel)));
675
- return result instanceof FileControlReplyD2HPacket;
676
- });
677
- }
678
- }
679
- export class V5SerialDevice extends VexSerialDevice {
680
- constructor(defaultSerial) {
681
- super(defaultSerial);
682
- this.autoReconnect = true;
683
- this.autoRefresh = true;
684
- this.pauseRefreshOnFileTransfer = true;
685
- this._isReconnecting = false;
686
- this.state = new V5SerialDeviceState(this);
687
- let isLastRefreshComplete = true;
688
- this._refreshInterval = setInterval(() => {
689
- if (this.autoRefresh && isLastRefreshComplete) {
690
- if (!this.isConnected) {
691
- this.state.brain.isAvailable = false;
692
- return;
693
- }
694
- if (!this.pauseRefreshOnFileTransfer ||
695
- !this.state._isFileTransferring) {
696
- isLastRefreshComplete = false;
697
- void this.refresh().finally(() => (isLastRefreshComplete = true));
698
- }
699
- }
700
- }, 200);
701
- }
702
- get isV5Controller() {
703
- return this.deviceType === SerialDeviceType.V5_CONTROLLER;
704
- }
705
- get brain() {
706
- return new V5Brain(this.state);
707
- }
708
- get controllers() {
709
- return [new V5Controller(this.state, 0), new V5Controller(this.state, 1)];
710
- }
711
- get devices() {
712
- const rtn = [];
713
- for (let i = 1; i <= this.state.devices.length; i++) {
714
- if (this.state.devices[i] != null)
715
- rtn.push(new V5SmartDevice(this.state, i));
716
- }
717
- return rtn;
718
- }
719
- get isFieldControllerConnected() {
720
- return this.state.isFieldControllerConnected;
721
- }
722
- get matchMode() {
723
- return this.state.matchMode;
724
- }
725
- set matchMode(value) {
726
- void (() => __awaiter(this, void 0, void 0, function* () {
727
- var _a;
728
- if ((yield ((_a = this.connection) === null || _a === void 0 ? void 0 : _a.setMatchMode(value))) != null)
729
- this.state.matchMode = value;
730
- }))();
731
- }
732
- get radio() {
733
- return new V5Radio(this.state);
734
- }
735
- mockTouch(x, y, press) {
736
- var _a;
737
- return __awaiter(this, void 0, void 0, function* () {
738
- return !((yield ((_a = this.connection) === null || _a === void 0 ? void 0 : _a.mockTouch(x, y, press))) == null);
739
- });
740
- }
741
- connect(conn) {
742
- return __awaiter(this, void 0, void 0, function* () {
743
- if (this.isConnected)
744
- return true;
745
- if (conn != null && !conn.isConnected) {
746
- if ((yield conn.query1()) === null)
747
- return false;
748
- this.connection = conn;
749
- }
750
- else {
751
- let tryIdx = 0;
752
- while (true) {
753
- const c = new V5SerialConnection(this.defaultSerial);
754
- const result = yield c.open(tryIdx++, true);
755
- if (result === undefined)
756
- return false; // no port left
757
- if (!result) {
758
- // has been opened
759
- yield c.close();
760
- continue;
761
- }
762
- if ((yield c.query1()) === null) {
763
- // no response
764
- yield c.close();
765
- continue;
766
- }
767
- this.connection = c;
768
- break;
769
- }
770
- }
771
- if (!this.isConnected)
772
- return false;
773
- yield this.doAfterConnect();
774
- return true;
775
- });
776
- }
777
- disconnect() {
778
- var _a;
779
- return __awaiter(this, void 0, void 0, function* () {
780
- yield ((_a = this.connection) === null || _a === void 0 ? void 0 : _a.close());
781
- this.connection = undefined;
782
- });
783
- }
784
- dispose() {
785
- return __awaiter(this, void 0, void 0, function* () {
786
- this.autoReconnect = false;
787
- this.autoRefresh = false;
788
- clearInterval(this._refreshInterval);
789
- yield this.disconnect();
790
- });
791
- }
792
- /**
793
- * @param timeout defaults to 0. If timeout is 0, then it will attempt to reconnect forever
794
- * @returns
795
- */
796
- reconnect(timeout = 0) {
797
- return __awaiter(this, void 0, void 0, function* () {
798
- if (this.isConnected)
799
- return true;
800
- if (timeout < 0)
801
- return false;
802
- const endTime = new Date().getTime() + timeout;
803
- if (this._isReconnecting) {
804
- let successBeforeTimeout;
805
- do {
806
- successBeforeTimeout = yield sleepUntil(() => !this._isReconnecting, timeout === 0 ? 1000 : timeout);
807
- // eslint-disable-next-line no-unmodified-loop-condition
808
- } while (timeout === 0 && !successBeforeTimeout);
809
- if (this.isConnected)
810
- return true;
811
- if (!successBeforeTimeout)
812
- return false;
813
- }
814
- this._isReconnecting = true;
815
- // eslint-disable-next-line no-unmodified-loop-condition
816
- while (timeout === 0 || new Date().getTime() < endTime) {
817
- // console.log("try to reconnect");
818
- let tryIdx = 0;
819
- while (true) {
820
- const c = new V5SerialConnection(this.defaultSerial);
821
- const result = yield c.open(tryIdx++, false);
822
- if (result === undefined)
823
- break; // no port left
824
- if (!result) {
825
- // has been opened
826
- yield c.close();
827
- continue;
828
- }
829
- const result2 = yield c.getSystemStatus(200);
830
- if (result2 === null) {
831
- // no response
832
- yield c.close();
833
- continue;
834
- }
835
- if (this.brain.uniqueId !== 0 &&
836
- result2.uniqueId !== this.brain.uniqueId) {
837
- // uuid not match
838
- yield c.close();
839
- continue;
840
- }
841
- this.connection = c;
842
- break;
843
- }
844
- if (this.isConnected)
845
- break;
846
- // try again every second or when the number of ports is different
847
- const getPortCount = () => __awaiter(this, void 0, void 0, function* () { return (yield this.defaultSerial.getPorts()).length; });
848
- const portsCount = yield getPortCount();
849
- yield sleepUntilAsync(() => __awaiter(this, void 0, void 0, function* () { return (yield getPortCount()) !== portsCount; }), 1000);
850
- }
851
- this._isReconnecting = false;
852
- if (!this.isConnected)
853
- return false;
854
- void this.doAfterConnect();
855
- return true;
856
- });
857
- }
858
- doAfterConnect() {
859
- return __awaiter(this, void 0, void 0, function* () {
860
- if (this.connection == null)
861
- return;
862
- //console.log("doAfterConnect");
863
- this.connection.on("disconnected", (_data) => {
864
- if (this.autoReconnect)
865
- void this.reconnect();
866
- });
867
- yield this.refresh();
868
- });
869
- }
870
- refresh() {
871
- var _a, _b, _c, _d, _e, _f, _g;
872
- return __awaiter(this, void 0, void 0, function* () {
873
- const ssPacket = yield ((_a = this.connection) === null || _a === void 0 ? void 0 : _a.getSystemStatus());
874
- if (ssPacket == null) {
875
- this.state.brain.isAvailable = false;
876
- return false;
877
- }
878
- this.state.brain.cpu0Version = ssPacket.cpu0Version;
879
- this.state.brain.cpu1Version = ssPacket.cpu1Version;
880
- this.state.brain.systemVersion = ssPacket.systemVersion;
881
- const flags2 = ssPacket.sysflags[2];
882
- this.state.controllers[0].isCharging = (flags2 & 0b10000000) !== 0;
883
- this.state.matchMode =
884
- (flags2 & 0b00100000) !== 0
885
- ? "disabled"
886
- : (flags2 & 0b01000000) !== 0
887
- ? "autonomous"
888
- : "driver";
889
- this.state.isFieldControllerConnected = (flags2 & 0b00010000) !== 0;
890
- const flags4 = ssPacket.sysflags[4];
891
- this.state.brain.settings.usingLanguage = (flags4 & 0b11110000) >> 4;
892
- this.state.brain.settings.isWhiteTheme = (flags4 & 0b00000100) !== 0;
893
- this.state.brain.settings.isScreenReversed = (flags4 & 0b00000001) === 0;
894
- this.state.brain.uniqueId = ssPacket.uniqueId;
895
- const sfPacket = yield ((_b = this.connection) === null || _b === void 0 ? void 0 : _b.getSystemFlags());
896
- if (sfPacket == null)
897
- return false;
898
- const flags5 = sfPacket.flags; // Math.pow(2, 32 - i);
899
- this.state.radio.isRadioData = (flags5 & Math.pow(2, 32 - 12)) !== 0;
900
- this.state.brain.button.isDoublePressed =
901
- (flags5 & Math.pow(2, 32 - 14)) !== 0;
902
- this.state.brain.battery.isCharging = (flags5 & Math.pow(2, 32 - 15)) !== 0;
903
- this.state.brain.button.isPressed = (flags5 & Math.pow(2, 32 - 17)) !== 0;
904
- this.state.radio.isVexNet = (flags5 & Math.pow(2, 32 - 18)) !== 0;
905
- this.state.controllers[1].isAvailable =
906
- (flags5 & Math.pow(2, 32 - 19)) !== 0;
907
- this.state.radio.isConnected = (flags5 & Math.pow(2, 32 - 22)) !== 0;
908
- this.state.radio.isAvailable = (flags5 & Math.pow(2, 32 - 23)) !== 0;
909
- this.state.brain.battery.batteryPercent = (_c = sfPacket.battery) !== null && _c !== void 0 ? _c : 0;
910
- this.state.controllers[0].isAvailable =
911
- this.state.radio.isConnected || this.state.controllers[0].isCharging;
912
- this.state.controllers[0].battery = (_d = sfPacket.controllerBatteryPercent) !== null && _d !== void 0 ? _d : 0;
913
- this.state.controllers[1].battery =
914
- (_e = sfPacket.partnerControllerBatteryPercent) !== null && _e !== void 0 ? _e : 0;
915
- this.state.brain.activeProgram = sfPacket.currentProgram;
916
- this.state.brain.isAvailable =
917
- !this.isV5Controller || this.state.radio.isConnected;
918
- const rdPacket = yield ((_f = this.connection) === null || _f === void 0 ? void 0 : _f.getRadioStatus());
919
- if (rdPacket == null)
920
- return false;
921
- this.state.radio.channel = rdPacket.channel;
922
- this.state.radio.latency = rdPacket.timeslot;
923
- this.state.radio.signalQuality = rdPacket.quality;
924
- this.state.radio.signalStrength = rdPacket.strength;
925
- const dsPacket = yield ((_g = this.connection) === null || _g === void 0 ? void 0 : _g.getDeviceStatus());
926
- if (dsPacket == null)
927
- return false;
928
- let missingPorts = this.state.devices
929
- .map((d) => d === null || d === void 0 ? void 0 : d.port)
930
- .filter((p) => p !== undefined);
931
- for (let i = 0; i < dsPacket.devices.length; i++) {
932
- const device = dsPacket.devices[i];
933
- this.state.devices[device.port] = device;
934
- // remove device port from missing ports
935
- missingPorts = missingPorts.filter((p) => p !== device.port);
936
- }
937
- missingPorts.forEach((port) => {
938
- this.state.devices[port] = undefined;
939
- });
940
- return true;
941
- });
942
- }
943
- }
944
- //# sourceMappingURL=VexDevice.js.map