@v5x/serial 0.5.5 → 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.
- package/README.md +7 -9
- package/dist/VexCRC.d.ts +0 -11
- package/dist/VexConnection.d.ts +30 -8
- package/dist/VexDevice.d.ts +11 -2
- package/dist/VexDeviceState.d.ts +23 -14
- package/dist/VexError.d.ts +4 -1
- package/dist/VexEvent.d.ts +15 -10
- package/dist/VexFirmware.d.ts +4 -2
- package/dist/VexFirmwareVersion.d.ts +4 -43
- package/dist/VexIniConfig.d.ts +0 -1
- package/dist/VexPacketBase.d.ts +5 -2
- package/dist/VexPacketEncoder.d.ts +11 -30
- package/dist/VexPacketModels.d.ts +0 -11
- package/dist/VexPacketView.d.ts +2 -0
- package/dist/index.cjs +680 -1046
- package/dist/index.cjs.map +16 -16
- package/dist/index.js +672 -1039
- package/dist/index.js.map +16 -16
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -200,6 +200,7 @@ var SelectDashScreen;
|
|
|
200
200
|
// src/VexError.ts
|
|
201
201
|
class VexSerialError extends Error {
|
|
202
202
|
kind;
|
|
203
|
+
ackType = undefined;
|
|
203
204
|
constructor(kind, message) {
|
|
204
205
|
super(message);
|
|
205
206
|
this.name = "VexSerialError";
|
|
@@ -222,9 +223,11 @@ class VexInvalidArgumentError extends VexSerialError {
|
|
|
222
223
|
}
|
|
223
224
|
|
|
224
225
|
class VexProtocolError extends VexSerialError {
|
|
225
|
-
|
|
226
|
+
ackType;
|
|
227
|
+
constructor(message, ackType) {
|
|
226
228
|
super("protocol", message);
|
|
227
229
|
this.name = "VexProtocolError";
|
|
230
|
+
this.ackType = ackType;
|
|
228
231
|
}
|
|
229
232
|
}
|
|
230
233
|
|
|
@@ -284,9 +287,19 @@ class VexEventEmitter {
|
|
|
284
287
|
this.handlerMap.set(eventName, listeners);
|
|
285
288
|
}
|
|
286
289
|
emit(eventName, data) {
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
+
const errors = [];
|
|
291
|
+
for (const callback of [...this.handlerMap.get(eventName) ?? []]) {
|
|
292
|
+
try {
|
|
293
|
+
callback(data);
|
|
294
|
+
} catch (error) {
|
|
295
|
+
errors.push(error);
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
if (errors.length === 1)
|
|
299
|
+
throw errors[0];
|
|
300
|
+
if (errors.length > 1) {
|
|
301
|
+
throw new AggregateError(errors, `listeners for ${String(eventName)} failed`);
|
|
302
|
+
}
|
|
290
303
|
}
|
|
291
304
|
clearListeners() {
|
|
292
305
|
this.handlerMap.clear();
|
|
@@ -299,17 +312,20 @@ class VexEventTarget {
|
|
|
299
312
|
this.emitter = new VexEventEmitter;
|
|
300
313
|
}
|
|
301
314
|
emit(eventName, data) {
|
|
302
|
-
this.emitter.emit(
|
|
315
|
+
this.emitter.emit(this.normalizeEventName(eventName), data);
|
|
303
316
|
}
|
|
304
317
|
on(eventName, listener) {
|
|
305
|
-
this.emitter.on(
|
|
318
|
+
this.emitter.on(this.normalizeEventName(eventName), listener);
|
|
306
319
|
}
|
|
307
320
|
remove(eventName, listener) {
|
|
308
|
-
this.emitter.remove(
|
|
321
|
+
this.emitter.remove(this.normalizeEventName(eventName), listener);
|
|
309
322
|
}
|
|
310
323
|
clearListeners() {
|
|
311
324
|
this.emitter.clearListeners();
|
|
312
325
|
}
|
|
326
|
+
normalizeEventName(eventName) {
|
|
327
|
+
return String(eventName);
|
|
328
|
+
}
|
|
313
329
|
}
|
|
314
330
|
|
|
315
331
|
// ../../node_modules/.bun/neverthrow@8.2.0/node_modules/neverthrow/dist/index.es.js
|
|
@@ -775,42 +791,32 @@ class Packet {
|
|
|
775
791
|
}
|
|
776
792
|
|
|
777
793
|
class DeviceBoundPacket extends Packet {
|
|
794
|
+
static COMMAND_ID;
|
|
795
|
+
static COMMAND_EXTENDED_ID;
|
|
778
796
|
get commandId() {
|
|
779
797
|
return this.constructor.COMMAND_ID;
|
|
780
798
|
}
|
|
781
799
|
get commandExtendedId() {
|
|
782
800
|
return this.constructor.COMMAND_EXTENDED_ID;
|
|
783
801
|
}
|
|
784
|
-
static COMMAND_ID;
|
|
785
|
-
static COMMAND_EXTENDED_ID;
|
|
786
802
|
constructor(payload) {
|
|
787
|
-
|
|
788
|
-
const
|
|
789
|
-
|
|
790
|
-
if (payload === undefined) {
|
|
791
|
-
this.data = Packet.ENCODER.cdcCommand(me.COMMAND_ID);
|
|
792
|
-
} else {
|
|
793
|
-
this.data = Packet.ENCODER.cdcCommandWithData(me.COMMAND_ID, payload);
|
|
794
|
-
}
|
|
795
|
-
} else {
|
|
796
|
-
if (payload === undefined) {
|
|
797
|
-
this.data = Packet.ENCODER.cdc2Command(me.COMMAND_ID, me.COMMAND_EXTENDED_ID);
|
|
798
|
-
} else {
|
|
799
|
-
this.data = Packet.ENCODER.cdc2CommandWithData(me.COMMAND_ID, me.COMMAND_EXTENDED_ID, payload);
|
|
800
|
-
}
|
|
801
|
-
}
|
|
803
|
+
const { COMMAND_ID: cmd, COMMAND_EXTENDED_ID: ext } = new.target;
|
|
804
|
+
const encoder = Packet.ENCODER;
|
|
805
|
+
super(ext === undefined ? payload === undefined ? encoder.cdcCommand(cmd) : encoder.cdcCommandWithData(cmd, payload) : payload === undefined ? encoder.cdc2Command(cmd, ext) : encoder.cdc2CommandWithData(cmd, ext, payload));
|
|
802
806
|
}
|
|
803
807
|
}
|
|
804
808
|
|
|
805
809
|
class HostBoundPacket extends Packet {
|
|
806
|
-
|
|
810
|
+
static COMMAND_ID;
|
|
811
|
+
static COMMAND_EXTENDED_ID;
|
|
812
|
+
ack;
|
|
807
813
|
payloadSize;
|
|
808
814
|
ackIndex;
|
|
809
815
|
constructor(data) {
|
|
810
816
|
super(data);
|
|
811
817
|
this.payloadSize = Packet.ENCODER.getPayloadSize(this.data);
|
|
812
|
-
|
|
813
|
-
this.ack = this.data[this.ackIndex
|
|
818
|
+
this.ackIndex = Packet.ENCODER.getHostHeaderLength(this.data) + 1;
|
|
819
|
+
this.ack = this.data[this.ackIndex];
|
|
814
820
|
}
|
|
815
821
|
static isValidPacket(data, n) {
|
|
816
822
|
const ack = data[n + 1];
|
|
@@ -819,309 +825,50 @@ class HostBoundPacket extends Packet {
|
|
|
819
825
|
}
|
|
820
826
|
|
|
821
827
|
// src/VexCRC.ts
|
|
822
|
-
var
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
33560,
|
|
849
|
-
45947,
|
|
850
|
-
41818,
|
|
851
|
-
54205,
|
|
852
|
-
50076,
|
|
853
|
-
62463,
|
|
854
|
-
58334,
|
|
855
|
-
9314,
|
|
856
|
-
13379,
|
|
857
|
-
1056,
|
|
858
|
-
5121,
|
|
859
|
-
25830,
|
|
860
|
-
29895,
|
|
861
|
-
17572,
|
|
862
|
-
21637,
|
|
863
|
-
42346,
|
|
864
|
-
46411,
|
|
865
|
-
34088,
|
|
866
|
-
38153,
|
|
867
|
-
58862,
|
|
868
|
-
62927,
|
|
869
|
-
50604,
|
|
870
|
-
54669,
|
|
871
|
-
13907,
|
|
872
|
-
9842,
|
|
873
|
-
5649,
|
|
874
|
-
1584,
|
|
875
|
-
30423,
|
|
876
|
-
26358,
|
|
877
|
-
22165,
|
|
878
|
-
18100,
|
|
879
|
-
46939,
|
|
880
|
-
42874,
|
|
881
|
-
38681,
|
|
882
|
-
34616,
|
|
883
|
-
63455,
|
|
884
|
-
59390,
|
|
885
|
-
55197,
|
|
886
|
-
51132,
|
|
887
|
-
18628,
|
|
888
|
-
22757,
|
|
889
|
-
26758,
|
|
890
|
-
30887,
|
|
891
|
-
2112,
|
|
892
|
-
6241,
|
|
893
|
-
10242,
|
|
894
|
-
14371,
|
|
895
|
-
51660,
|
|
896
|
-
55789,
|
|
897
|
-
59790,
|
|
898
|
-
63919,
|
|
899
|
-
35144,
|
|
900
|
-
39273,
|
|
901
|
-
43274,
|
|
902
|
-
47403,
|
|
903
|
-
23285,
|
|
904
|
-
19156,
|
|
905
|
-
31415,
|
|
906
|
-
27286,
|
|
907
|
-
6769,
|
|
908
|
-
2640,
|
|
909
|
-
14899,
|
|
910
|
-
10770,
|
|
911
|
-
56317,
|
|
912
|
-
52188,
|
|
913
|
-
64447,
|
|
914
|
-
60318,
|
|
915
|
-
39801,
|
|
916
|
-
35672,
|
|
917
|
-
47931,
|
|
918
|
-
43802,
|
|
919
|
-
27814,
|
|
920
|
-
31879,
|
|
921
|
-
19684,
|
|
922
|
-
23749,
|
|
923
|
-
11298,
|
|
924
|
-
15363,
|
|
925
|
-
3168,
|
|
926
|
-
7233,
|
|
927
|
-
60846,
|
|
928
|
-
64911,
|
|
929
|
-
52716,
|
|
930
|
-
56781,
|
|
931
|
-
44330,
|
|
932
|
-
48395,
|
|
933
|
-
36200,
|
|
934
|
-
40265,
|
|
935
|
-
32407,
|
|
936
|
-
28342,
|
|
937
|
-
24277,
|
|
938
|
-
20212,
|
|
939
|
-
15891,
|
|
940
|
-
11826,
|
|
941
|
-
7761,
|
|
942
|
-
3696,
|
|
943
|
-
65439,
|
|
944
|
-
61374,
|
|
945
|
-
57309,
|
|
946
|
-
53244,
|
|
947
|
-
48923,
|
|
948
|
-
44858,
|
|
949
|
-
40793,
|
|
950
|
-
36728,
|
|
951
|
-
37256,
|
|
952
|
-
33193,
|
|
953
|
-
45514,
|
|
954
|
-
41451,
|
|
955
|
-
53516,
|
|
956
|
-
49453,
|
|
957
|
-
61774,
|
|
958
|
-
57711,
|
|
959
|
-
4224,
|
|
960
|
-
161,
|
|
961
|
-
12482,
|
|
962
|
-
8419,
|
|
963
|
-
20484,
|
|
964
|
-
16421,
|
|
965
|
-
28742,
|
|
966
|
-
24679,
|
|
967
|
-
33721,
|
|
968
|
-
37784,
|
|
969
|
-
41979,
|
|
970
|
-
46042,
|
|
971
|
-
49981,
|
|
972
|
-
54044,
|
|
973
|
-
58239,
|
|
974
|
-
62302,
|
|
975
|
-
689,
|
|
976
|
-
4752,
|
|
977
|
-
8947,
|
|
978
|
-
13010,
|
|
979
|
-
16949,
|
|
980
|
-
21012,
|
|
981
|
-
25207,
|
|
982
|
-
29270,
|
|
983
|
-
46570,
|
|
984
|
-
42443,
|
|
985
|
-
38312,
|
|
986
|
-
34185,
|
|
987
|
-
62830,
|
|
988
|
-
58703,
|
|
989
|
-
54572,
|
|
990
|
-
50445,
|
|
991
|
-
13538,
|
|
992
|
-
9411,
|
|
993
|
-
5280,
|
|
994
|
-
1153,
|
|
995
|
-
29798,
|
|
996
|
-
25671,
|
|
997
|
-
21540,
|
|
998
|
-
17413,
|
|
999
|
-
42971,
|
|
1000
|
-
47098,
|
|
1001
|
-
34713,
|
|
1002
|
-
38840,
|
|
1003
|
-
59231,
|
|
1004
|
-
63358,
|
|
1005
|
-
50973,
|
|
1006
|
-
55100,
|
|
1007
|
-
9939,
|
|
1008
|
-
14066,
|
|
1009
|
-
1681,
|
|
1010
|
-
5808,
|
|
1011
|
-
26199,
|
|
1012
|
-
30326,
|
|
1013
|
-
17941,
|
|
1014
|
-
22068,
|
|
1015
|
-
55628,
|
|
1016
|
-
51565,
|
|
1017
|
-
63758,
|
|
1018
|
-
59695,
|
|
1019
|
-
39368,
|
|
1020
|
-
35305,
|
|
1021
|
-
47498,
|
|
1022
|
-
43435,
|
|
1023
|
-
22596,
|
|
1024
|
-
18533,
|
|
1025
|
-
30726,
|
|
1026
|
-
26663,
|
|
1027
|
-
6336,
|
|
1028
|
-
2273,
|
|
1029
|
-
14466,
|
|
1030
|
-
10403,
|
|
1031
|
-
52093,
|
|
1032
|
-
56156,
|
|
1033
|
-
60223,
|
|
1034
|
-
64286,
|
|
1035
|
-
35833,
|
|
1036
|
-
39896,
|
|
1037
|
-
43963,
|
|
1038
|
-
48026,
|
|
1039
|
-
19061,
|
|
1040
|
-
23124,
|
|
1041
|
-
27191,
|
|
1042
|
-
31254,
|
|
1043
|
-
2801,
|
|
1044
|
-
6864,
|
|
1045
|
-
10931,
|
|
1046
|
-
14994,
|
|
1047
|
-
64814,
|
|
1048
|
-
60687,
|
|
1049
|
-
56684,
|
|
1050
|
-
52557,
|
|
1051
|
-
48554,
|
|
1052
|
-
44427,
|
|
1053
|
-
40424,
|
|
1054
|
-
36297,
|
|
1055
|
-
31782,
|
|
1056
|
-
27655,
|
|
1057
|
-
23652,
|
|
1058
|
-
19525,
|
|
1059
|
-
15522,
|
|
1060
|
-
11395,
|
|
1061
|
-
7392,
|
|
1062
|
-
3265,
|
|
1063
|
-
61215,
|
|
1064
|
-
65342,
|
|
1065
|
-
53085,
|
|
1066
|
-
57212,
|
|
1067
|
-
44955,
|
|
1068
|
-
49082,
|
|
1069
|
-
36825,
|
|
1070
|
-
40952,
|
|
1071
|
-
28183,
|
|
1072
|
-
32310,
|
|
1073
|
-
20053,
|
|
1074
|
-
24180,
|
|
1075
|
-
11923,
|
|
1076
|
-
16050,
|
|
1077
|
-
3793,
|
|
1078
|
-
7920
|
|
1079
|
-
];
|
|
828
|
+
var POLYNOMIAL_CRC32 = 79764919;
|
|
829
|
+
var POLYNOMIAL_CRC16 = 4129;
|
|
830
|
+
function genTable16() {
|
|
831
|
+
const table = new Uint16Array(256);
|
|
832
|
+
for (let i = 0;i < 256; i++) {
|
|
833
|
+
let acc = i << 8;
|
|
834
|
+
for (let j = 0;j < 8; j++) {
|
|
835
|
+
acc = (acc & 32768) !== 0 ? acc << 1 ^ POLYNOMIAL_CRC16 : acc << 1;
|
|
836
|
+
}
|
|
837
|
+
table[i] = acc & 65535;
|
|
838
|
+
}
|
|
839
|
+
return table;
|
|
840
|
+
}
|
|
841
|
+
function genTable32() {
|
|
842
|
+
const table = new Uint32Array(256);
|
|
843
|
+
for (let i = 0;i < 256; i++) {
|
|
844
|
+
let acc = i << 24;
|
|
845
|
+
for (let j = 0;j < 8; j++) {
|
|
846
|
+
acc = (acc & 2147483648) !== 0 ? acc << 1 ^ POLYNOMIAL_CRC32 : acc << 1;
|
|
847
|
+
}
|
|
848
|
+
table[i] = acc;
|
|
849
|
+
}
|
|
850
|
+
return table;
|
|
851
|
+
}
|
|
852
|
+
var CRC16_TABLE = genTable16();
|
|
853
|
+
var CRC32_TABLE = genTable32();
|
|
1080
854
|
|
|
1081
855
|
class CrcGenerator {
|
|
1082
|
-
crc32Table;
|
|
1083
|
-
static POLYNOMIAL_CRC32 =
|
|
1084
|
-
static POLYNOMIAL_CRC16 =
|
|
1085
|
-
constructor() {
|
|
1086
|
-
this.crc32Table = new Uint32Array(256);
|
|
1087
|
-
this.crc32GenTable();
|
|
1088
|
-
}
|
|
856
|
+
crc32Table = CRC32_TABLE;
|
|
857
|
+
static POLYNOMIAL_CRC32 = POLYNOMIAL_CRC32;
|
|
858
|
+
static POLYNOMIAL_CRC16 = POLYNOMIAL_CRC16;
|
|
1089
859
|
crc16(buf, initValue) {
|
|
1090
|
-
|
|
1091
|
-
let
|
|
1092
|
-
|
|
1093
|
-
let j;
|
|
1094
|
-
for (j = 0;j < numberOfBytes; j++) {
|
|
1095
|
-
i = (accumulator >>> 8 ^ buf[j]) & 255;
|
|
1096
|
-
accumulator = (accumulator << 8 ^ CRC16TABLE[i]) >>> 0;
|
|
1097
|
-
}
|
|
1098
|
-
return (accumulator & 65535) >>> 0;
|
|
1099
|
-
}
|
|
1100
|
-
crc32GenTable() {
|
|
1101
|
-
let i;
|
|
1102
|
-
let j;
|
|
1103
|
-
let crcAccumulator;
|
|
1104
|
-
for (i = 0;i < 256; i++) {
|
|
1105
|
-
crcAccumulator = i << 24;
|
|
1106
|
-
for (j = 0;j < 8; j++) {
|
|
1107
|
-
if ((crcAccumulator & 2147483648) !== 0)
|
|
1108
|
-
crcAccumulator = crcAccumulator << 1 ^ CrcGenerator.POLYNOMIAL_CRC32;
|
|
1109
|
-
else
|
|
1110
|
-
crcAccumulator = crcAccumulator << 1;
|
|
1111
|
-
}
|
|
1112
|
-
this.crc32Table[i] = crcAccumulator;
|
|
860
|
+
let acc = initValue;
|
|
861
|
+
for (let j = 0;j < buf.length; j++) {
|
|
862
|
+
acc = (acc << 8 ^ CRC16_TABLE[(acc >>> 8 ^ buf[j]) & 255]) >>> 0;
|
|
1113
863
|
}
|
|
864
|
+
return acc & 65535;
|
|
1114
865
|
}
|
|
1115
866
|
crc32(buf, initValue) {
|
|
1116
|
-
|
|
1117
|
-
let
|
|
1118
|
-
|
|
1119
|
-
let j;
|
|
1120
|
-
for (j = 0;j < numberOfBytes; j++) {
|
|
1121
|
-
i = (crcAccumulator >>> 24 ^ buf[j]) & 255;
|
|
1122
|
-
crcAccumulator = (crcAccumulator << 8 ^ this.crc32Table[i]) >>> 0;
|
|
867
|
+
let acc = initValue;
|
|
868
|
+
for (let j = 0;j < buf.length; j++) {
|
|
869
|
+
acc = (acc << 8 ^ CRC32_TABLE[(acc >>> 24 ^ buf[j]) & 255]) >>> 0;
|
|
1123
870
|
}
|
|
1124
|
-
return
|
|
871
|
+
return acc >>> 0;
|
|
1125
872
|
}
|
|
1126
873
|
}
|
|
1127
874
|
|
|
@@ -1213,9 +960,8 @@ class VexFirmwareVersion {
|
|
|
1213
960
|
}
|
|
1214
961
|
static fromString(version) {
|
|
1215
962
|
const parts = version.toLowerCase().replace(/b/g, "").split(".").map((x) => parseInt(x, 10));
|
|
1216
|
-
while (parts.length < 4)
|
|
963
|
+
while (parts.length < 4)
|
|
1217
964
|
parts.push(0);
|
|
1218
|
-
}
|
|
1219
965
|
return new VexFirmwareVersion(parts[0], parts[1], parts[2], parts[3]);
|
|
1220
966
|
}
|
|
1221
967
|
static fromUint8Array(data, offset = 0, reverse = false) {
|
|
@@ -1245,24 +991,23 @@ class VexFirmwareVersion {
|
|
|
1245
991
|
return `${this.toUserString()}.b${this.beta}`;
|
|
1246
992
|
}
|
|
1247
993
|
compare(that) {
|
|
1248
|
-
const
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
return buildComp;
|
|
1258
|
-
} else if (betaComp !== 0) {
|
|
1259
|
-
return betaComp;
|
|
994
|
+
for (const [a, b] of [
|
|
995
|
+
[this.major, that.major],
|
|
996
|
+
[this.minor, that.minor],
|
|
997
|
+
[this.build, that.build],
|
|
998
|
+
[this.beta, that.beta]
|
|
999
|
+
]) {
|
|
1000
|
+
const delta = a - b;
|
|
1001
|
+
if (delta !== 0)
|
|
1002
|
+
return delta;
|
|
1260
1003
|
}
|
|
1261
1004
|
return 0;
|
|
1262
1005
|
}
|
|
1263
1006
|
}
|
|
1264
1007
|
|
|
1265
1008
|
// src/VexPacketView.ts
|
|
1009
|
+
var textDecoder = new TextDecoder("UTF-8");
|
|
1010
|
+
|
|
1266
1011
|
class PacketView extends DataView {
|
|
1267
1012
|
position = 0;
|
|
1268
1013
|
littleEndianDefault = true;
|
|
@@ -1275,14 +1020,10 @@ class PacketView extends DataView {
|
|
|
1275
1020
|
return view;
|
|
1276
1021
|
}
|
|
1277
1022
|
nextInt8() {
|
|
1278
|
-
|
|
1279
|
-
this.position += 1;
|
|
1280
|
-
return result;
|
|
1023
|
+
return this.getInt8(this.position++);
|
|
1281
1024
|
}
|
|
1282
1025
|
nextUint8() {
|
|
1283
|
-
|
|
1284
|
-
this.position += 1;
|
|
1285
|
-
return result;
|
|
1026
|
+
return this.getUint8(this.position++);
|
|
1286
1027
|
}
|
|
1287
1028
|
nextInt16(littleEndian = this.littleEndianDefault) {
|
|
1288
1029
|
const result = this.getInt16(this.position, littleEndian);
|
|
@@ -1305,37 +1046,28 @@ class PacketView extends DataView {
|
|
|
1305
1046
|
return result;
|
|
1306
1047
|
}
|
|
1307
1048
|
nextString(length) {
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
result += String.fromCharCode(this.nextUint8());
|
|
1311
|
-
}
|
|
1049
|
+
const result = textDecoder.decode(new Uint8Array(this.buffer, this.byteOffset + this.position, length));
|
|
1050
|
+
this.position += length;
|
|
1312
1051
|
return result;
|
|
1313
1052
|
}
|
|
1314
1053
|
nextNTBS(length) {
|
|
1315
|
-
|
|
1316
|
-
const
|
|
1317
|
-
|
|
1318
|
-
if (this.byteLength <= this.position)
|
|
1319
|
-
break;
|
|
1320
|
-
const g = this.nextUint8();
|
|
1321
|
-
if (g === 0)
|
|
1322
|
-
break;
|
|
1323
|
-
result += String.fromCharCode(g);
|
|
1324
|
-
}
|
|
1325
|
-
this.position = lastPosition + length;
|
|
1054
|
+
const start = this.position;
|
|
1055
|
+
const result = this.nextVarNTBS(length);
|
|
1056
|
+
this.position = start + length;
|
|
1326
1057
|
return result;
|
|
1327
1058
|
}
|
|
1328
1059
|
nextVarNTBS(length) {
|
|
1329
|
-
|
|
1060
|
+
const start = this.position;
|
|
1061
|
+
let byteLength = 0;
|
|
1330
1062
|
for (let i = 0;i < length; i++) {
|
|
1331
1063
|
if (this.byteLength <= this.position)
|
|
1332
1064
|
break;
|
|
1333
1065
|
const g = this.nextUint8();
|
|
1334
1066
|
if (g === 0)
|
|
1335
1067
|
break;
|
|
1336
|
-
|
|
1068
|
+
byteLength++;
|
|
1337
1069
|
}
|
|
1338
|
-
return
|
|
1070
|
+
return textDecoder.decode(new Uint8Array(this.buffer, this.byteOffset + start, byteLength));
|
|
1339
1071
|
}
|
|
1340
1072
|
nextVersion(reverse = false) {
|
|
1341
1073
|
const result = VexFirmwareVersion.fromUint8Array(new Uint8Array(this.buffer, this.byteOffset, this.byteLength), this.position, reverse);
|
|
@@ -1346,42 +1078,33 @@ class PacketView extends DataView {
|
|
|
1346
1078
|
|
|
1347
1079
|
// src/VexPacketModels.ts
|
|
1348
1080
|
var textEncoder = new TextEncoder;
|
|
1081
|
+
function filePayload(a, b, fileName) {
|
|
1082
|
+
const payload = new Uint8Array(26);
|
|
1083
|
+
payload[0] = a;
|
|
1084
|
+
payload[1] = b;
|
|
1085
|
+
payload.set(encodeFixedText(fileName, "Filename", 23), 2);
|
|
1086
|
+
return payload;
|
|
1087
|
+
}
|
|
1088
|
+
var clamp100 = (value) => value !== undefined && value > 100 ? 100 : value;
|
|
1349
1089
|
|
|
1350
1090
|
class Query1H2DPacket extends DeviceBoundPacket {
|
|
1351
1091
|
static COMMAND_ID = 33;
|
|
1352
1092
|
static COMMAND_EXTENDED_ID = undefined;
|
|
1353
|
-
constructor() {
|
|
1354
|
-
super(undefined);
|
|
1355
|
-
}
|
|
1356
1093
|
}
|
|
1357
1094
|
|
|
1358
1095
|
class SystemVersionH2DPacket extends DeviceBoundPacket {
|
|
1359
1096
|
static COMMAND_ID = 164;
|
|
1360
1097
|
static COMMAND_EXTENDED_ID = undefined;
|
|
1361
|
-
constructor() {
|
|
1362
|
-
super(undefined);
|
|
1363
|
-
}
|
|
1364
1098
|
}
|
|
1365
1099
|
|
|
1366
1100
|
class UpdateMatchModeH2DPacket extends DeviceBoundPacket {
|
|
1367
1101
|
static COMMAND_ID = 88;
|
|
1368
1102
|
static COMMAND_EXTENDED_ID = 193;
|
|
1369
1103
|
constructor(mode, matchClock) {
|
|
1370
|
-
|
|
1371
|
-
switch (mode) {
|
|
1372
|
-
case "autonomous":
|
|
1373
|
-
bit1 = 10;
|
|
1374
|
-
break;
|
|
1375
|
-
case "driver":
|
|
1376
|
-
bit1 = 8;
|
|
1377
|
-
break;
|
|
1378
|
-
case "disabled":
|
|
1379
|
-
bit1 = 11;
|
|
1380
|
-
}
|
|
1104
|
+
const bit1 = mode === "autonomous" ? 10 : mode === "driver" ? 8 : 11;
|
|
1381
1105
|
const payload = new Uint8Array(5);
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
view.setUint32(1, matchClock, true);
|
|
1106
|
+
payload[0] = bit1 & 15;
|
|
1107
|
+
new DataView(payload.buffer).setUint32(1, matchClock, true);
|
|
1385
1108
|
super(payload);
|
|
1386
1109
|
}
|
|
1387
1110
|
}
|
|
@@ -1389,18 +1112,13 @@ class UpdateMatchModeH2DPacket extends DeviceBoundPacket {
|
|
|
1389
1112
|
class GetMatchStatusH2DPacket extends DeviceBoundPacket {
|
|
1390
1113
|
static COMMAND_ID = 88;
|
|
1391
1114
|
static COMMAND_EXTENDED_ID = 194;
|
|
1392
|
-
constructor() {
|
|
1393
|
-
super(undefined);
|
|
1394
|
-
}
|
|
1395
1115
|
}
|
|
1396
1116
|
|
|
1397
1117
|
class GetRadioModeH2DPacket extends DeviceBoundPacket {
|
|
1398
1118
|
static COMMAND_ID = 88;
|
|
1399
1119
|
static COMMAND_EXTENDED_ID = 65;
|
|
1400
1120
|
constructor(mode) {
|
|
1401
|
-
|
|
1402
|
-
payload[0] = mode;
|
|
1403
|
-
super(payload);
|
|
1121
|
+
super(Uint8Array.of(mode));
|
|
1404
1122
|
}
|
|
1405
1123
|
}
|
|
1406
1124
|
|
|
@@ -1408,9 +1126,7 @@ class FileControlH2DPacket extends DeviceBoundPacket {
|
|
|
1408
1126
|
static COMMAND_ID = 86;
|
|
1409
1127
|
static COMMAND_EXTENDED_ID = 16;
|
|
1410
1128
|
constructor(a, b) {
|
|
1411
|
-
|
|
1412
|
-
payload.set([a, b], 0);
|
|
1413
|
-
super(payload);
|
|
1129
|
+
super(Uint8Array.of(a, b));
|
|
1414
1130
|
}
|
|
1415
1131
|
}
|
|
1416
1132
|
|
|
@@ -1420,25 +1136,21 @@ class InitFileTransferH2DPacket extends DeviceBoundPacket {
|
|
|
1420
1136
|
constructor(operation, target, vendor, options, binary, addr, name, type, version = new VexFirmwareVersion(1, 0, 0, 0)) {
|
|
1421
1137
|
const payload = new Uint8Array(52);
|
|
1422
1138
|
const view = new DataView(payload.buffer);
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1139
|
+
payload[0] = operation;
|
|
1140
|
+
payload[1] = target;
|
|
1141
|
+
payload[2] = vendor;
|
|
1142
|
+
payload[3] = options;
|
|
1427
1143
|
view.setUint32(4, binary.length, true);
|
|
1428
1144
|
view.setUint32(8, addr, true);
|
|
1429
1145
|
view.setUint32(12, operation === 1 /* WRITE */ ? Packet.ENCODER.crcgen.crc32(binary, 0) : 0, true);
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
ext ??= "";
|
|
1434
|
-
ext = ext === "gz" ? "bin" : ext;
|
|
1146
|
+
let ext = /(?:\.([^.]+))?$/.exec(name)?.[1] ?? "";
|
|
1147
|
+
if (ext === "gz")
|
|
1148
|
+
ext = "bin";
|
|
1435
1149
|
payload.set(encodeFixedText(type ?? ext, "File type", 4), 16);
|
|
1436
1150
|
const timestamp = (Date.now() / 1000 >>> 0) - PacketEncoder.J2000_EPOCH;
|
|
1437
1151
|
view.setUint32(20, timestamp, true);
|
|
1438
1152
|
payload.set(version.toUint8Array(), 24);
|
|
1439
|
-
|
|
1440
|
-
payload.set(nameEncoded, 28);
|
|
1441
|
-
view.setUint8(51, 0);
|
|
1153
|
+
payload.set(encodeFixedText(name, "Filename", 23), 28);
|
|
1442
1154
|
super(payload);
|
|
1443
1155
|
}
|
|
1444
1156
|
}
|
|
@@ -1447,9 +1159,7 @@ class ExitFileTransferH2DPacket extends DeviceBoundPacket {
|
|
|
1447
1159
|
static COMMAND_ID = 86;
|
|
1448
1160
|
static COMMAND_EXTENDED_ID = 18;
|
|
1449
1161
|
constructor(action) {
|
|
1450
|
-
|
|
1451
|
-
payload[0] = action;
|
|
1452
|
-
super(payload);
|
|
1162
|
+
super(Uint8Array.of(action));
|
|
1453
1163
|
}
|
|
1454
1164
|
}
|
|
1455
1165
|
|
|
@@ -1458,8 +1168,7 @@ class WriteFileH2DPacket extends DeviceBoundPacket {
|
|
|
1458
1168
|
static COMMAND_EXTENDED_ID = 19;
|
|
1459
1169
|
constructor(addr, buf) {
|
|
1460
1170
|
const payload = new Uint8Array(4 + buf.length);
|
|
1461
|
-
|
|
1462
|
-
view.setUint32(0, addr, true);
|
|
1171
|
+
new DataView(payload.buffer).setUint32(0, addr, true);
|
|
1463
1172
|
payload.set(buf, 4);
|
|
1464
1173
|
super(payload);
|
|
1465
1174
|
}
|
|
@@ -1481,11 +1190,7 @@ class LinkFileH2DPacket extends DeviceBoundPacket {
|
|
|
1481
1190
|
static COMMAND_ID = 86;
|
|
1482
1191
|
static COMMAND_EXTENDED_ID = 21;
|
|
1483
1192
|
constructor(vendor, fileName, options) {
|
|
1484
|
-
|
|
1485
|
-
const payload = new Uint8Array(26);
|
|
1486
|
-
payload.set([vendor, options], 0);
|
|
1487
|
-
payload.set(str, 2);
|
|
1488
|
-
super(payload);
|
|
1193
|
+
super(filePayload(vendor, options, fileName));
|
|
1489
1194
|
}
|
|
1490
1195
|
}
|
|
1491
1196
|
|
|
@@ -1493,9 +1198,7 @@ class GetDirectoryFileCountH2DPacket extends DeviceBoundPacket {
|
|
|
1493
1198
|
static COMMAND_ID = 86;
|
|
1494
1199
|
static COMMAND_EXTENDED_ID = 22;
|
|
1495
1200
|
constructor(vendor) {
|
|
1496
|
-
|
|
1497
|
-
payload.set([vendor, 0], 0);
|
|
1498
|
-
super(payload);
|
|
1201
|
+
super(Uint8Array.of(vendor, 0));
|
|
1499
1202
|
}
|
|
1500
1203
|
}
|
|
1501
1204
|
|
|
@@ -1503,9 +1206,7 @@ class GetDirectoryEntryH2DPacket extends DeviceBoundPacket {
|
|
|
1503
1206
|
static COMMAND_ID = 86;
|
|
1504
1207
|
static COMMAND_EXTENDED_ID = 23;
|
|
1505
1208
|
constructor(index) {
|
|
1506
|
-
|
|
1507
|
-
payload.set([index, 0], 0);
|
|
1508
|
-
super(payload);
|
|
1209
|
+
super(Uint8Array.of(index, 0));
|
|
1509
1210
|
}
|
|
1510
1211
|
}
|
|
1511
1212
|
|
|
@@ -1513,17 +1214,8 @@ class LoadFileActionH2DPacket extends DeviceBoundPacket {
|
|
|
1513
1214
|
static COMMAND_ID = 86;
|
|
1514
1215
|
static COMMAND_EXTENDED_ID = 24;
|
|
1515
1216
|
constructor(vendor, actionId, fileNameOrSlotNumber) {
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
fileName = fileNameOrSlotNumber;
|
|
1519
|
-
} else {
|
|
1520
|
-
fileName = "___s_" + (fileNameOrSlotNumber - 1) + ".bin";
|
|
1521
|
-
}
|
|
1522
|
-
const encodedName = encodeFixedText(fileName, "Filename", 23);
|
|
1523
|
-
const payload = new Uint8Array(26);
|
|
1524
|
-
payload.set([vendor, actionId], 0);
|
|
1525
|
-
payload.set(encodedName, 2);
|
|
1526
|
-
super(payload);
|
|
1217
|
+
const fileName = typeof fileNameOrSlotNumber === "string" ? fileNameOrSlotNumber : `___s_${fileNameOrSlotNumber - 1}.bin`;
|
|
1218
|
+
super(filePayload(vendor, actionId, fileName));
|
|
1527
1219
|
}
|
|
1528
1220
|
}
|
|
1529
1221
|
|
|
@@ -1531,11 +1223,7 @@ class GetFileMetadataH2DPacket extends DeviceBoundPacket {
|
|
|
1531
1223
|
static COMMAND_ID = 86;
|
|
1532
1224
|
static COMMAND_EXTENDED_ID = 25;
|
|
1533
1225
|
constructor(vendor, fileName, options) {
|
|
1534
|
-
|
|
1535
|
-
const payload = new Uint8Array(26);
|
|
1536
|
-
payload.set([vendor, options], 0);
|
|
1537
|
-
payload.set(encodedName, 2);
|
|
1538
|
-
super(payload);
|
|
1226
|
+
super(filePayload(vendor, options, fileName));
|
|
1539
1227
|
}
|
|
1540
1228
|
}
|
|
1541
1229
|
|
|
@@ -1543,11 +1231,7 @@ class EraseFileH2DPacket extends DeviceBoundPacket {
|
|
|
1543
1231
|
static COMMAND_ID = 86;
|
|
1544
1232
|
static COMMAND_EXTENDED_ID = 27;
|
|
1545
1233
|
constructor(vendor, fileName) {
|
|
1546
|
-
|
|
1547
|
-
const payload = new Uint8Array(26);
|
|
1548
|
-
payload.set([vendor, 128], 0);
|
|
1549
|
-
payload.set(encodedName, 2);
|
|
1550
|
-
super(payload);
|
|
1234
|
+
super(filePayload(vendor, 128, fileName));
|
|
1551
1235
|
}
|
|
1552
1236
|
}
|
|
1553
1237
|
|
|
@@ -1555,11 +1239,7 @@ class GetProgramSlotInfoH2DPacket extends DeviceBoundPacket {
|
|
|
1555
1239
|
static COMMAND_ID = 86;
|
|
1556
1240
|
static COMMAND_EXTENDED_ID = 28;
|
|
1557
1241
|
constructor(vendor, fileName) {
|
|
1558
|
-
|
|
1559
|
-
const payload = new Uint8Array(26);
|
|
1560
|
-
payload.set([vendor, 0], 0);
|
|
1561
|
-
payload.set(encodedName, 2);
|
|
1562
|
-
super(payload);
|
|
1242
|
+
super(filePayload(vendor, 0, fileName));
|
|
1563
1243
|
}
|
|
1564
1244
|
}
|
|
1565
1245
|
|
|
@@ -1567,9 +1247,7 @@ class FileClearUpH2DPacket extends DeviceBoundPacket {
|
|
|
1567
1247
|
static COMMAND_ID = 86;
|
|
1568
1248
|
static COMMAND_EXTENDED_ID = 30;
|
|
1569
1249
|
constructor(vendor) {
|
|
1570
|
-
|
|
1571
|
-
payload.set([vendor, 0], 0);
|
|
1572
|
-
super(payload);
|
|
1250
|
+
super(Uint8Array.of(vendor, 0));
|
|
1573
1251
|
}
|
|
1574
1252
|
}
|
|
1575
1253
|
|
|
@@ -1577,9 +1255,7 @@ class FileFormatH2DPacket extends DeviceBoundPacket {
|
|
|
1577
1255
|
static COMMAND_ID = 86;
|
|
1578
1256
|
static COMMAND_EXTENDED_ID = 31;
|
|
1579
1257
|
constructor() {
|
|
1580
|
-
|
|
1581
|
-
payload.set([68, 67, 66, 65], 0);
|
|
1582
|
-
super(payload);
|
|
1258
|
+
super(Uint8Array.of(68, 67, 66, 65));
|
|
1583
1259
|
}
|
|
1584
1260
|
}
|
|
1585
1261
|
|
|
@@ -1591,33 +1267,21 @@ class GetSystemFlagsH2DPacket extends DeviceBoundPacket {
|
|
|
1591
1267
|
class GetDeviceStatusH2DPacket extends DeviceBoundPacket {
|
|
1592
1268
|
static COMMAND_ID = 86;
|
|
1593
1269
|
static COMMAND_EXTENDED_ID = 33;
|
|
1594
|
-
constructor() {
|
|
1595
|
-
super(undefined);
|
|
1596
|
-
}
|
|
1597
1270
|
}
|
|
1598
1271
|
|
|
1599
1272
|
class GetSystemStatusH2DPacket extends DeviceBoundPacket {
|
|
1600
1273
|
static COMMAND_ID = 86;
|
|
1601
1274
|
static COMMAND_EXTENDED_ID = 34;
|
|
1602
|
-
constructor() {
|
|
1603
|
-
super(undefined);
|
|
1604
|
-
}
|
|
1605
1275
|
}
|
|
1606
1276
|
|
|
1607
1277
|
class GetFdtStatusH2DPacket extends DeviceBoundPacket {
|
|
1608
1278
|
static COMMAND_ID = 86;
|
|
1609
1279
|
static COMMAND_EXTENDED_ID = 35;
|
|
1610
|
-
constructor() {
|
|
1611
|
-
super(undefined);
|
|
1612
|
-
}
|
|
1613
1280
|
}
|
|
1614
1281
|
|
|
1615
1282
|
class GetLogCountH2DPacket extends DeviceBoundPacket {
|
|
1616
1283
|
static COMMAND_ID = 86;
|
|
1617
1284
|
static COMMAND_EXTENDED_ID = 36;
|
|
1618
|
-
constructor() {
|
|
1619
|
-
super(undefined);
|
|
1620
|
-
}
|
|
1621
1285
|
}
|
|
1622
1286
|
|
|
1623
1287
|
class ReadLogPageH2DPacket extends DeviceBoundPacket {
|
|
@@ -1635,18 +1299,13 @@ class ReadLogPageH2DPacket extends DeviceBoundPacket {
|
|
|
1635
1299
|
class GetRadioStatusH2DPacket extends DeviceBoundPacket {
|
|
1636
1300
|
static COMMAND_ID = 86;
|
|
1637
1301
|
static COMMAND_EXTENDED_ID = 38;
|
|
1638
|
-
constructor() {
|
|
1639
|
-
super(undefined);
|
|
1640
|
-
}
|
|
1641
1302
|
}
|
|
1642
1303
|
|
|
1643
1304
|
class ScreenCaptureH2DPacket extends DeviceBoundPacket {
|
|
1644
1305
|
static COMMAND_ID = 86;
|
|
1645
1306
|
static COMMAND_EXTENDED_ID = 40;
|
|
1646
1307
|
constructor(e) {
|
|
1647
|
-
|
|
1648
|
-
payload[0] = e;
|
|
1649
|
-
super(payload);
|
|
1308
|
+
super(Uint8Array.of(e));
|
|
1650
1309
|
}
|
|
1651
1310
|
}
|
|
1652
1311
|
|
|
@@ -1667,10 +1326,7 @@ class SelectDashH2DPacket extends DeviceBoundPacket {
|
|
|
1667
1326
|
static COMMAND_ID = 86;
|
|
1668
1327
|
static COMMAND_EXTENDED_ID = 43;
|
|
1669
1328
|
constructor(screen, port) {
|
|
1670
|
-
|
|
1671
|
-
payload[0] = screen;
|
|
1672
|
-
payload[1] = port;
|
|
1673
|
-
super(payload);
|
|
1329
|
+
super(Uint8Array.of(screen, port));
|
|
1674
1330
|
}
|
|
1675
1331
|
}
|
|
1676
1332
|
|
|
@@ -1678,9 +1334,8 @@ class ReadKeyValueH2DPacket extends DeviceBoundPacket {
|
|
|
1678
1334
|
static COMMAND_ID = 86;
|
|
1679
1335
|
static COMMAND_EXTENDED_ID = 46;
|
|
1680
1336
|
constructor(key) {
|
|
1681
|
-
const encodedKey = encodeFixedText(key, "Key", 31);
|
|
1682
1337
|
const payload = new Uint8Array(32);
|
|
1683
|
-
payload.set(
|
|
1338
|
+
payload.set(encodeFixedText(key, "Key", 31), 0);
|
|
1684
1339
|
super(payload);
|
|
1685
1340
|
}
|
|
1686
1341
|
}
|
|
@@ -1704,17 +1359,11 @@ class WriteKeyValueH2DPacket extends DeviceBoundPacket {
|
|
|
1704
1359
|
class GetSlot1to4InfoH2DPacket extends DeviceBoundPacket {
|
|
1705
1360
|
static COMMAND_ID = 86;
|
|
1706
1361
|
static COMMAND_EXTENDED_ID = 49;
|
|
1707
|
-
constructor() {
|
|
1708
|
-
super(undefined);
|
|
1709
|
-
}
|
|
1710
1362
|
}
|
|
1711
1363
|
|
|
1712
1364
|
class GetSlot5to8InfoH2DPacket extends DeviceBoundPacket {
|
|
1713
1365
|
static COMMAND_ID = 86;
|
|
1714
1366
|
static COMMAND_EXTENDED_ID = 50;
|
|
1715
|
-
constructor() {
|
|
1716
|
-
super(undefined);
|
|
1717
|
-
}
|
|
1718
1367
|
}
|
|
1719
1368
|
|
|
1720
1369
|
class FactoryStatusH2DPacket extends DeviceBoundPacket {
|
|
@@ -1726,9 +1375,7 @@ class FactoryEnableH2DPacket extends DeviceBoundPacket {
|
|
|
1726
1375
|
static COMMAND_ID = 86;
|
|
1727
1376
|
static COMMAND_EXTENDED_ID = 255;
|
|
1728
1377
|
constructor() {
|
|
1729
|
-
|
|
1730
|
-
payload.set([77, 76, 75, 74], 0);
|
|
1731
|
-
super(payload);
|
|
1378
|
+
super(Uint8Array.of(77, 76, 75, 74));
|
|
1732
1379
|
}
|
|
1733
1380
|
}
|
|
1734
1381
|
|
|
@@ -1770,8 +1417,7 @@ class MatchModeReplyD2HPacket extends HostBoundPacket {
|
|
|
1770
1417
|
modebit;
|
|
1771
1418
|
constructor(data) {
|
|
1772
1419
|
super(data);
|
|
1773
|
-
|
|
1774
|
-
this.modebit = dataView.nextUint8();
|
|
1420
|
+
this.modebit = PacketView.fromPacket(this).nextUint8();
|
|
1775
1421
|
}
|
|
1776
1422
|
}
|
|
1777
1423
|
|
|
@@ -1797,31 +1443,27 @@ class MatchStatusReplyD2HPacket extends HostBoundPacket {
|
|
|
1797
1443
|
rxSignalQuality;
|
|
1798
1444
|
constructor(data) {
|
|
1799
1445
|
super(data);
|
|
1800
|
-
const
|
|
1446
|
+
const view = PacketView.fromPacket(this);
|
|
1801
1447
|
const n = this.ackIndex;
|
|
1802
|
-
this.rssi =
|
|
1803
|
-
this.systemStatusBits =
|
|
1804
|
-
this.radioStatusBits =
|
|
1805
|
-
this.fieldStatusBits =
|
|
1806
|
-
this.matchClock =
|
|
1807
|
-
this.brainBatteryPercent =
|
|
1808
|
-
this.controllerBatteryPercent =
|
|
1809
|
-
this.partnerControllerBatteryPercent =
|
|
1810
|
-
this.pad =
|
|
1811
|
-
this.buttons =
|
|
1812
|
-
this.activeProgram =
|
|
1813
|
-
this.radioType =
|
|
1814
|
-
this.radioChannel =
|
|
1815
|
-
this.radioSlot =
|
|
1816
|
-
this.
|
|
1817
|
-
this.
|
|
1818
|
-
|
|
1819
|
-
|
|
1820
|
-
|
|
1821
|
-
if (endIdx > -1) {
|
|
1822
|
-
rawStr = rawStr.substr(0, endIdx);
|
|
1823
|
-
}
|
|
1824
|
-
this.robotName = rawStr;
|
|
1448
|
+
this.rssi = view.nextInt8();
|
|
1449
|
+
this.systemStatusBits = view.nextUint16();
|
|
1450
|
+
this.radioStatusBits = view.nextUint16();
|
|
1451
|
+
this.fieldStatusBits = view.nextUint8();
|
|
1452
|
+
this.matchClock = view.nextUint8();
|
|
1453
|
+
this.brainBatteryPercent = view.nextUint8();
|
|
1454
|
+
this.controllerBatteryPercent = view.nextUint8();
|
|
1455
|
+
this.partnerControllerBatteryPercent = view.nextUint8();
|
|
1456
|
+
this.pad = view.nextUint8();
|
|
1457
|
+
this.buttons = view.nextUint16();
|
|
1458
|
+
this.activeProgram = view.nextUint8();
|
|
1459
|
+
this.radioType = view.nextUint8();
|
|
1460
|
+
this.radioChannel = view.nextUint8();
|
|
1461
|
+
this.radioSlot = view.nextUint8();
|
|
1462
|
+
this.controllerFlags = view.getUint8(n + 28);
|
|
1463
|
+
this.rxSignalQuality = view.getUint8(n + 29);
|
|
1464
|
+
const raw = new TextDecoder("UTF-8").decode(this.data.slice(n + 18, n + this.payloadSize + 28));
|
|
1465
|
+
const end = raw.indexOf("\x00");
|
|
1466
|
+
this.robotName = end > -1 ? raw.slice(0, end) : raw;
|
|
1825
1467
|
}
|
|
1826
1468
|
}
|
|
1827
1469
|
|
|
@@ -1838,10 +1480,10 @@ class InitFileTransferReplyD2HPacket extends HostBoundPacket {
|
|
|
1838
1480
|
crc32;
|
|
1839
1481
|
constructor(data) {
|
|
1840
1482
|
super(data);
|
|
1841
|
-
const
|
|
1842
|
-
this.windowSize =
|
|
1843
|
-
this.fileSize =
|
|
1844
|
-
this.crc32 =
|
|
1483
|
+
const view = PacketView.fromPacket(this);
|
|
1484
|
+
this.windowSize = view.nextUint16();
|
|
1485
|
+
this.fileSize = view.nextUint32();
|
|
1486
|
+
this.crc32 = view.nextUint32();
|
|
1845
1487
|
}
|
|
1846
1488
|
}
|
|
1847
1489
|
|
|
@@ -1863,13 +1505,10 @@ class ReadFileReplyD2HPacket extends HostBoundPacket {
|
|
|
1863
1505
|
buf;
|
|
1864
1506
|
constructor(data) {
|
|
1865
1507
|
super(data);
|
|
1866
|
-
const
|
|
1867
|
-
this.addr =
|
|
1508
|
+
const view = PacketView.fromPacket(this);
|
|
1509
|
+
this.addr = view.nextUint32();
|
|
1868
1510
|
this.length = this.payloadSize - 8;
|
|
1869
|
-
this.buf = this.data.slice(
|
|
1870
|
-
}
|
|
1871
|
-
static isValidPacket(data, n) {
|
|
1872
|
-
return super.isValidPacket(data, n);
|
|
1511
|
+
this.buf = this.data.slice(view.position, view.position + this.length).buffer;
|
|
1873
1512
|
}
|
|
1874
1513
|
}
|
|
1875
1514
|
|
|
@@ -1884,8 +1523,7 @@ class GetDirectoryFileCountReplyD2HPacket extends HostBoundPacket {
|
|
|
1884
1523
|
count;
|
|
1885
1524
|
constructor(data) {
|
|
1886
1525
|
super(data);
|
|
1887
|
-
|
|
1888
|
-
this.count = dataView.nextUint16();
|
|
1526
|
+
this.count = PacketView.fromPacket(this).nextUint16();
|
|
1889
1527
|
}
|
|
1890
1528
|
}
|
|
1891
1529
|
|
|
@@ -1895,19 +1533,19 @@ class GetDirectoryEntryReplyD2HPacket extends HostBoundPacket {
|
|
|
1895
1533
|
file;
|
|
1896
1534
|
constructor(data) {
|
|
1897
1535
|
super(data);
|
|
1898
|
-
|
|
1899
|
-
|
|
1900
|
-
|
|
1901
|
-
|
|
1902
|
-
|
|
1903
|
-
|
|
1904
|
-
|
|
1905
|
-
|
|
1906
|
-
|
|
1907
|
-
|
|
1908
|
-
|
|
1909
|
-
|
|
1910
|
-
}
|
|
1536
|
+
if (this.payloadSize <= 4)
|
|
1537
|
+
return;
|
|
1538
|
+
const view = PacketView.fromPacket(this);
|
|
1539
|
+
this.file = {
|
|
1540
|
+
index: view.nextUint8(),
|
|
1541
|
+
size: view.nextUint32(),
|
|
1542
|
+
loadAddress: view.nextUint32(),
|
|
1543
|
+
crc32: view.nextUint32(),
|
|
1544
|
+
type: view.nextString(4),
|
|
1545
|
+
timestamp: view.nextUint32() + PacketEncoder.J2000_EPOCH,
|
|
1546
|
+
version: view.nextVersion(),
|
|
1547
|
+
filename: view.nextNTBS(32)
|
|
1548
|
+
};
|
|
1911
1549
|
}
|
|
1912
1550
|
}
|
|
1913
1551
|
|
|
@@ -1922,18 +1560,18 @@ class GetFileMetadataReplyD2HPacket extends HostBoundPacket {
|
|
|
1922
1560
|
file;
|
|
1923
1561
|
constructor(data) {
|
|
1924
1562
|
super(data);
|
|
1925
|
-
|
|
1926
|
-
|
|
1927
|
-
|
|
1928
|
-
|
|
1929
|
-
|
|
1930
|
-
|
|
1931
|
-
|
|
1932
|
-
|
|
1933
|
-
|
|
1934
|
-
|
|
1935
|
-
|
|
1936
|
-
}
|
|
1563
|
+
if (this.payloadSize <= 4)
|
|
1564
|
+
return;
|
|
1565
|
+
const view = PacketView.fromPacket(this);
|
|
1566
|
+
view.nextUint8();
|
|
1567
|
+
this.file = {
|
|
1568
|
+
size: view.nextUint32(),
|
|
1569
|
+
loadAddress: view.nextUint32(),
|
|
1570
|
+
crc32: view.nextUint32(),
|
|
1571
|
+
type: view.nextString(4),
|
|
1572
|
+
timestamp: view.nextUint32() + PacketEncoder.J2000_EPOCH,
|
|
1573
|
+
version: view.nextVersion()
|
|
1574
|
+
};
|
|
1937
1575
|
}
|
|
1938
1576
|
}
|
|
1939
1577
|
|
|
@@ -1949,9 +1587,9 @@ class GetProgramSlotInfoReplyD2HPacket extends HostBoundPacket {
|
|
|
1949
1587
|
slot;
|
|
1950
1588
|
constructor(data) {
|
|
1951
1589
|
super(data);
|
|
1952
|
-
const
|
|
1953
|
-
this.slot =
|
|
1954
|
-
this.requestedSlot =
|
|
1590
|
+
const view = PacketView.fromPacket(this);
|
|
1591
|
+
this.slot = view.nextUint8();
|
|
1592
|
+
this.requestedSlot = view.nextUint8();
|
|
1955
1593
|
}
|
|
1956
1594
|
}
|
|
1957
1595
|
|
|
@@ -1969,40 +1607,32 @@ class GetSystemFlagsReplyD2HPacket extends HostBoundPacket {
|
|
|
1969
1607
|
static COMMAND_ID = 86;
|
|
1970
1608
|
static COMMAND_EXTENDED_ID = 32;
|
|
1971
1609
|
flags;
|
|
1972
|
-
radioSearching;
|
|
1610
|
+
radioSearching = false;
|
|
1973
1611
|
radioQuality;
|
|
1974
1612
|
controllerBatteryPercent;
|
|
1975
1613
|
partnerControllerBatteryPercent;
|
|
1976
1614
|
battery;
|
|
1977
|
-
currentProgram;
|
|
1615
|
+
currentProgram = 0;
|
|
1978
1616
|
constructor(data) {
|
|
1979
1617
|
super(data);
|
|
1980
|
-
const
|
|
1981
|
-
this.
|
|
1982
|
-
this.currentProgram = 0;
|
|
1983
|
-
this.flags = dataView.nextUint32();
|
|
1618
|
+
const view = PacketView.fromPacket(this);
|
|
1619
|
+
this.flags = view.nextUint32();
|
|
1984
1620
|
const hasPartner = (8192 & this.flags) !== 0;
|
|
1985
1621
|
const hasRadio = (1536 & this.flags) === 1536;
|
|
1986
|
-
const byte1 =
|
|
1987
|
-
const byte2 =
|
|
1622
|
+
const byte1 = view.nextUint8();
|
|
1623
|
+
const byte2 = view.nextUint8();
|
|
1988
1624
|
if (this.payloadSize === 11) {
|
|
1989
|
-
this.battery = 8 * (byte1 & 15);
|
|
1990
|
-
if ((this.flags & 256) !== 0 || hasRadio)
|
|
1991
|
-
this.controllerBatteryPercent = 8 * (byte1 >> 4 & 15);
|
|
1625
|
+
this.battery = clamp100(8 * (byte1 & 15));
|
|
1626
|
+
if ((this.flags & 256) !== 0 || hasRadio) {
|
|
1627
|
+
this.controllerBatteryPercent = clamp100(8 * (byte1 >> 4 & 15));
|
|
1628
|
+
}
|
|
1992
1629
|
if (hasRadio)
|
|
1993
|
-
this.radioQuality = 8 * (byte2 & 15);
|
|
1630
|
+
this.radioQuality = clamp100(8 * (byte2 & 15));
|
|
1994
1631
|
this.radioSearching = (this.flags & 1536) === 512;
|
|
1995
|
-
if (hasPartner)
|
|
1996
|
-
this.partnerControllerBatteryPercent = 8 * (byte2 >> 4 & 15);
|
|
1997
|
-
|
|
1998
|
-
|
|
1999
|
-
this.battery = 100;
|
|
2000
|
-
if (this.controllerBatteryPercent != null && this.controllerBatteryPercent > 100)
|
|
2001
|
-
this.controllerBatteryPercent = 100;
|
|
2002
|
-
if (this.radioQuality != null && this.radioQuality > 100)
|
|
2003
|
-
this.radioQuality = 100;
|
|
2004
|
-
if (this.partnerControllerBatteryPercent != null && this.partnerControllerBatteryPercent > 100)
|
|
2005
|
-
this.partnerControllerBatteryPercent = 100;
|
|
1632
|
+
if (hasPartner) {
|
|
1633
|
+
this.partnerControllerBatteryPercent = clamp100(8 * (byte2 >> 4 & 15));
|
|
1634
|
+
}
|
|
1635
|
+
this.currentProgram = view.nextUint8();
|
|
2006
1636
|
}
|
|
2007
1637
|
}
|
|
2008
1638
|
}
|
|
@@ -2014,17 +1644,17 @@ class GetDeviceStatusReplyD2HPacket extends HostBoundPacket {
|
|
|
2014
1644
|
devices;
|
|
2015
1645
|
constructor(data) {
|
|
2016
1646
|
super(data);
|
|
2017
|
-
const
|
|
2018
|
-
this.count =
|
|
1647
|
+
const view = PacketView.fromPacket(this);
|
|
1648
|
+
this.count = view.nextUint8();
|
|
2019
1649
|
this.devices = [];
|
|
2020
1650
|
for (let i = 0;i < this.count; i++) {
|
|
2021
1651
|
this.devices.push({
|
|
2022
|
-
port:
|
|
2023
|
-
type:
|
|
2024
|
-
status:
|
|
2025
|
-
betaversion:
|
|
2026
|
-
version:
|
|
2027
|
-
bootversion:
|
|
1652
|
+
port: view.nextUint8(),
|
|
1653
|
+
type: view.nextUint8(),
|
|
1654
|
+
status: view.nextUint8(),
|
|
1655
|
+
betaversion: view.nextUint8(),
|
|
1656
|
+
version: view.nextUint16(),
|
|
1657
|
+
bootversion: view.nextUint16()
|
|
2028
1658
|
});
|
|
2029
1659
|
}
|
|
2030
1660
|
}
|
|
@@ -2036,48 +1666,42 @@ class GetSystemStatusReplyD2HPacket extends HostBoundPacket {
|
|
|
2036
1666
|
systemVersion;
|
|
2037
1667
|
cpu0Version;
|
|
2038
1668
|
cpu1Version;
|
|
2039
|
-
nxpVersion;
|
|
1669
|
+
nxpVersion = VexFirmwareVersion.allZero();
|
|
2040
1670
|
touchVersion;
|
|
2041
|
-
uniqueId;
|
|
2042
|
-
sysflags;
|
|
2043
|
-
eventBrain;
|
|
2044
|
-
romBootloaderActive;
|
|
2045
|
-
ramBootloaderActive;
|
|
2046
|
-
goldenVersion;
|
|
1671
|
+
uniqueId = 1234;
|
|
1672
|
+
sysflags = [0, 0, 0, 0, 0, 0, 0];
|
|
1673
|
+
eventBrain = false;
|
|
1674
|
+
romBootloaderActive = false;
|
|
1675
|
+
ramBootloaderActive = false;
|
|
1676
|
+
goldenVersion = VexFirmwareVersion.allZero();
|
|
2047
1677
|
constructor(data) {
|
|
2048
1678
|
super(data);
|
|
2049
|
-
const
|
|
2050
|
-
|
|
2051
|
-
this.systemVersion =
|
|
2052
|
-
this.cpu0Version =
|
|
2053
|
-
this.cpu1Version =
|
|
2054
|
-
this.touchVersion =
|
|
2055
|
-
this.uniqueId = 1234;
|
|
2056
|
-
this.sysflags = [0, 0, 0, 0, 0, 0, 0];
|
|
2057
|
-
this.goldenVersion = VexFirmwareVersion.allZero();
|
|
2058
|
-
this.nxpVersion = VexFirmwareVersion.allZero();
|
|
2059
|
-
this.eventBrain = false;
|
|
2060
|
-
this.romBootloaderActive = false;
|
|
2061
|
-
this.ramBootloaderActive = false;
|
|
1679
|
+
const view = PacketView.fromPacket(this);
|
|
1680
|
+
view.nextUint8();
|
|
1681
|
+
this.systemVersion = view.nextVersion();
|
|
1682
|
+
this.cpu0Version = view.nextVersion();
|
|
1683
|
+
this.cpu1Version = view.nextVersion();
|
|
1684
|
+
this.touchVersion = view.nextVersion(true);
|
|
2062
1685
|
if (this.payloadSize > 25) {
|
|
2063
|
-
this.uniqueId =
|
|
1686
|
+
this.uniqueId = view.nextUint32();
|
|
2064
1687
|
this.sysflags = [
|
|
2065
|
-
|
|
2066
|
-
|
|
2067
|
-
|
|
2068
|
-
|
|
2069
|
-
|
|
1688
|
+
view.nextUint8(),
|
|
1689
|
+
view.nextUint8(),
|
|
1690
|
+
view.nextUint8(),
|
|
1691
|
+
view.nextUint8(),
|
|
1692
|
+
view.nextUint8(),
|
|
2070
1693
|
0,
|
|
2071
|
-
|
|
1694
|
+
view.nextUint8()
|
|
2072
1695
|
];
|
|
2073
|
-
|
|
2074
|
-
this.
|
|
2075
|
-
this.
|
|
2076
|
-
|
|
2077
|
-
|
|
1696
|
+
const flags6 = this.sysflags[6];
|
|
1697
|
+
this.eventBrain = (1 & flags6) !== 0;
|
|
1698
|
+
this.romBootloaderActive = (2 & flags6) !== 0;
|
|
1699
|
+
this.ramBootloaderActive = (4 & flags6) !== 0;
|
|
1700
|
+
view.nextUint16();
|
|
1701
|
+
this.goldenVersion = view.nextVersion();
|
|
2078
1702
|
}
|
|
2079
1703
|
if (this.payloadSize > 37) {
|
|
2080
|
-
this.nxpVersion =
|
|
1704
|
+
this.nxpVersion = view.nextVersion();
|
|
2081
1705
|
}
|
|
2082
1706
|
}
|
|
2083
1707
|
}
|
|
@@ -2089,17 +1713,17 @@ class GetFdtStatusReplyD2HPacket extends HostBoundPacket {
|
|
|
2089
1713
|
status;
|
|
2090
1714
|
constructor(data) {
|
|
2091
1715
|
super(data);
|
|
2092
|
-
const
|
|
2093
|
-
this.count =
|
|
1716
|
+
const view = PacketView.fromPacket(this);
|
|
1717
|
+
this.count = view.nextUint8();
|
|
2094
1718
|
this.status = [];
|
|
2095
1719
|
for (let i = 0;i < this.count; i++) {
|
|
2096
1720
|
this.status.push({
|
|
2097
|
-
index:
|
|
2098
|
-
type:
|
|
2099
|
-
status:
|
|
2100
|
-
betaversion:
|
|
2101
|
-
version:
|
|
2102
|
-
bootversion:
|
|
1721
|
+
index: view.nextUint8(),
|
|
1722
|
+
type: view.nextUint8(),
|
|
1723
|
+
status: view.nextUint8(),
|
|
1724
|
+
betaversion: view.nextUint8(),
|
|
1725
|
+
version: view.nextUint16(),
|
|
1726
|
+
bootversion: view.nextUint16()
|
|
2103
1727
|
});
|
|
2104
1728
|
}
|
|
2105
1729
|
}
|
|
@@ -2111,9 +1735,9 @@ class GetLogCountReplyD2HPacket extends HostBoundPacket {
|
|
|
2111
1735
|
count;
|
|
2112
1736
|
constructor(data) {
|
|
2113
1737
|
super(data);
|
|
2114
|
-
const
|
|
2115
|
-
|
|
2116
|
-
this.count =
|
|
1738
|
+
const view = PacketView.fromPacket(this);
|
|
1739
|
+
view.nextUint8();
|
|
1740
|
+
this.count = view.nextUint32();
|
|
2117
1741
|
}
|
|
2118
1742
|
}
|
|
2119
1743
|
|
|
@@ -2125,20 +1749,19 @@ class ReadLogPageReplyD2HPacket extends HostBoundPacket {
|
|
|
2125
1749
|
entries;
|
|
2126
1750
|
constructor(data) {
|
|
2127
1751
|
super(data);
|
|
2128
|
-
const
|
|
2129
|
-
const
|
|
2130
|
-
|
|
2131
|
-
this.
|
|
2132
|
-
this.count = dataView.nextUint16();
|
|
1752
|
+
const view = PacketView.fromPacket(this);
|
|
1753
|
+
const size = view.nextUint8();
|
|
1754
|
+
this.offset = view.nextUint32();
|
|
1755
|
+
this.count = view.nextUint16();
|
|
2133
1756
|
this.entries = [];
|
|
2134
|
-
let j =
|
|
1757
|
+
let j = this.ackIndex + 8;
|
|
2135
1758
|
for (let i = 0;i < this.count; i++) {
|
|
2136
1759
|
this.entries.push({
|
|
2137
|
-
code:
|
|
2138
|
-
type:
|
|
2139
|
-
desc:
|
|
2140
|
-
spare:
|
|
2141
|
-
time:
|
|
1760
|
+
code: view.getUint8(j),
|
|
1761
|
+
type: view.getUint8(j + 1),
|
|
1762
|
+
desc: view.getUint8(j + 2),
|
|
1763
|
+
spare: view.getUint8(j + 3),
|
|
1764
|
+
time: view.getUint32(j + 4, true)
|
|
2142
1765
|
});
|
|
2143
1766
|
j += size;
|
|
2144
1767
|
}
|
|
@@ -2155,13 +1778,12 @@ class GetRadioStatusReplyD2HPacket extends HostBoundPacket {
|
|
|
2155
1778
|
timeslot;
|
|
2156
1779
|
constructor(data) {
|
|
2157
1780
|
super(data);
|
|
2158
|
-
const
|
|
2159
|
-
|
|
2160
|
-
this.
|
|
2161
|
-
this.
|
|
2162
|
-
this.
|
|
2163
|
-
this.
|
|
2164
|
-
this.timeslot = this.data[n + 7];
|
|
1781
|
+
const view = PacketView.fromPacket(this);
|
|
1782
|
+
this.device = view.nextUint8();
|
|
1783
|
+
this.quality = view.nextUint16();
|
|
1784
|
+
this.strength = view.nextInt16();
|
|
1785
|
+
this.channel = this.data[this.ackIndex + 6];
|
|
1786
|
+
this.timeslot = this.data[this.ackIndex + 7];
|
|
2165
1787
|
}
|
|
2166
1788
|
}
|
|
2167
1789
|
|
|
@@ -2186,8 +1808,7 @@ class ReadKeyValueReplyD2HPacket extends HostBoundPacket {
|
|
|
2186
1808
|
value;
|
|
2187
1809
|
constructor(data) {
|
|
2188
1810
|
super(data);
|
|
2189
|
-
|
|
2190
|
-
this.value = dataView.nextVarNTBS(255);
|
|
1811
|
+
this.value = PacketView.fromPacket(this).nextVarNTBS(255);
|
|
2191
1812
|
}
|
|
2192
1813
|
}
|
|
2193
1814
|
|
|
@@ -2203,20 +1824,18 @@ class GetSlot1to4InfoReplyD2HPacket extends HostBoundPacket {
|
|
|
2203
1824
|
slots;
|
|
2204
1825
|
constructor(data, start = 1) {
|
|
2205
1826
|
super(data);
|
|
2206
|
-
const
|
|
2207
|
-
this.slotFlags =
|
|
1827
|
+
const view = PacketView.fromPacket(this);
|
|
1828
|
+
this.slotFlags = view.nextUint8();
|
|
2208
1829
|
this.slots = [];
|
|
2209
1830
|
for (let i = 0;i < 4; i++) {
|
|
2210
|
-
|
|
2211
|
-
if (!hasData)
|
|
1831
|
+
if ((this.slotFlags & 1 << start - 1 + i) === 0)
|
|
2212
1832
|
continue;
|
|
2213
|
-
const
|
|
2214
|
-
const nameLen =
|
|
2215
|
-
const name = dataView.nextString(nameLen);
|
|
1833
|
+
const icon = view.nextUint16();
|
|
1834
|
+
const nameLen = view.nextUint8();
|
|
2216
1835
|
this.slots.push({
|
|
2217
1836
|
slot: start + i,
|
|
2218
|
-
icon
|
|
2219
|
-
name
|
|
1837
|
+
icon,
|
|
1838
|
+
name: view.nextString(nameLen)
|
|
2220
1839
|
});
|
|
2221
1840
|
}
|
|
2222
1841
|
}
|
|
@@ -2238,9 +1857,9 @@ class FactoryStatusReplyD2HPacket extends HostBoundPacket {
|
|
|
2238
1857
|
percent;
|
|
2239
1858
|
constructor(data) {
|
|
2240
1859
|
super(data);
|
|
2241
|
-
const
|
|
2242
|
-
this.status =
|
|
2243
|
-
this.percent =
|
|
1860
|
+
const view = PacketView.fromPacket(this);
|
|
1861
|
+
this.status = view.nextUint8();
|
|
1862
|
+
this.percent = view.nextUint8();
|
|
2244
1863
|
}
|
|
2245
1864
|
}
|
|
2246
1865
|
|
|
@@ -2251,6 +1870,7 @@ class FactoryEnableReplyD2HPacket extends HostBoundPacket {
|
|
|
2251
1870
|
|
|
2252
1871
|
// src/VexPacketEncoder.ts
|
|
2253
1872
|
var textEncoder2 = new TextEncoder;
|
|
1873
|
+
var HEADER_TO_DEVICE = Uint8Array.of(201, 54, 184, 71);
|
|
2254
1874
|
function encodeFixedText(value, field, maxBytes) {
|
|
2255
1875
|
const encoded = textEncoder2.encode(value);
|
|
2256
1876
|
if (encoded.byteLength > maxBytes) {
|
|
@@ -2264,92 +1884,96 @@ class PacketEncoder {
|
|
|
2264
1884
|
static HEADER_TO_DEVICE = [201, 54, 184, 71];
|
|
2265
1885
|
static HEADER_TO_HOST = [170, 85];
|
|
2266
1886
|
static J2000_EPOCH = 946684800;
|
|
2267
|
-
vexVersion;
|
|
2268
|
-
crcgen;
|
|
2269
|
-
allPacketsTable =
|
|
1887
|
+
vexVersion = 0;
|
|
1888
|
+
crcgen = new CrcGenerator;
|
|
1889
|
+
allPacketsTable = new Map;
|
|
2270
1890
|
static getInstance() {
|
|
2271
|
-
|
|
2272
|
-
Packet.ENCODER = new PacketEncoder;
|
|
2273
|
-
}
|
|
1891
|
+
Packet.ENCODER ??= new PacketEncoder;
|
|
2274
1892
|
return Packet.ENCODER;
|
|
2275
1893
|
}
|
|
2276
1894
|
constructor() {
|
|
2277
|
-
|
|
2278
|
-
this.crcgen = new CrcGenerator;
|
|
2279
|
-
Object.values(exports_VexPacketModels).forEach((packet) => {
|
|
1895
|
+
for (const packet of Object.values(exports_VexPacketModels)) {
|
|
2280
1896
|
if (typeof packet === "function" && packet.prototype instanceof HostBoundPacket) {
|
|
2281
|
-
const
|
|
2282
|
-
this.allPacketsTable
|
|
1897
|
+
const type = packet;
|
|
1898
|
+
let byExtendedId = this.allPacketsTable.get(type.COMMAND_ID);
|
|
1899
|
+
if (byExtendedId === undefined) {
|
|
1900
|
+
byExtendedId = new Map;
|
|
1901
|
+
this.allPacketsTable.set(type.COMMAND_ID, byExtendedId);
|
|
1902
|
+
}
|
|
1903
|
+
byExtendedId.set(type.COMMAND_EXTENDED_ID, type);
|
|
2283
1904
|
}
|
|
2284
|
-
}
|
|
1905
|
+
}
|
|
1906
|
+
}
|
|
1907
|
+
getPacketType(commandId, commandExtendedId) {
|
|
1908
|
+
if (commandId === undefined)
|
|
1909
|
+
return;
|
|
1910
|
+
return this.allPacketsTable.get(commandId)?.get(commandExtendedId);
|
|
2285
1911
|
}
|
|
2286
1912
|
createHeader(buf) {
|
|
2287
1913
|
if (buf === undefined || buf.byteLength < PacketEncoder.HEADERS_LENGTH) {
|
|
2288
1914
|
buf = new ArrayBuffer(PacketEncoder.HEADERS_LENGTH);
|
|
2289
1915
|
}
|
|
2290
1916
|
const h = new Uint8Array(buf);
|
|
2291
|
-
h.set(
|
|
1917
|
+
h.set(HEADER_TO_DEVICE);
|
|
2292
1918
|
return h;
|
|
2293
1919
|
}
|
|
2294
1920
|
cdcCommand(cmd) {
|
|
2295
|
-
const
|
|
2296
|
-
|
|
2297
|
-
h
|
|
1921
|
+
const h = new Uint8Array(5);
|
|
1922
|
+
h.set(HEADER_TO_DEVICE);
|
|
1923
|
+
h[4] = cmd;
|
|
2298
1924
|
return h;
|
|
2299
1925
|
}
|
|
2300
1926
|
cdcCommandWithData(cmd, data) {
|
|
2301
|
-
const
|
|
2302
|
-
|
|
2303
|
-
h
|
|
2304
|
-
h
|
|
1927
|
+
const h = new Uint8Array(6 + data.length);
|
|
1928
|
+
h.set(HEADER_TO_DEVICE);
|
|
1929
|
+
h[4] = cmd;
|
|
1930
|
+
h[5] = data.length;
|
|
1931
|
+
h.set(data, 6);
|
|
2305
1932
|
return h;
|
|
2306
1933
|
}
|
|
2307
1934
|
cdc2Command(cmd, ext) {
|
|
2308
|
-
const
|
|
2309
|
-
|
|
2310
|
-
h
|
|
2311
|
-
|
|
2312
|
-
h
|
|
1935
|
+
const h = new Uint8Array(9);
|
|
1936
|
+
h.set(HEADER_TO_DEVICE);
|
|
1937
|
+
h[4] = cmd;
|
|
1938
|
+
h[5] = ext;
|
|
1939
|
+
h[6] = 0;
|
|
1940
|
+
this.appendCrc16(h);
|
|
2313
1941
|
return h;
|
|
2314
1942
|
}
|
|
2315
1943
|
cdc2CommandBufferLength(data) {
|
|
2316
|
-
|
|
2317
|
-
if (data.length > 127)
|
|
2318
|
-
length += 1;
|
|
2319
|
-
return length;
|
|
1944
|
+
return PacketEncoder.HEADERS_LENGTH + data.length + 5 + (data.length > 127 ? 1 : 0);
|
|
2320
1945
|
}
|
|
2321
1946
|
cdc2CommandWithData(cmd, ext, data) {
|
|
2322
|
-
const
|
|
2323
|
-
|
|
1947
|
+
const h = new Uint8Array(this.cdc2CommandBufferLength(data));
|
|
1948
|
+
h.set(HEADER_TO_DEVICE);
|
|
1949
|
+
h[4] = cmd;
|
|
1950
|
+
h[5] = ext;
|
|
2324
1951
|
if (data.length < 128) {
|
|
2325
|
-
h
|
|
2326
|
-
h.set(data,
|
|
1952
|
+
h[6] = data.length;
|
|
1953
|
+
h.set(data, 7);
|
|
2327
1954
|
} else {
|
|
2328
|
-
|
|
2329
|
-
|
|
2330
|
-
h.set(
|
|
2331
|
-
h.set(data, PacketEncoder.HEADERS_LENGTH + 4);
|
|
1955
|
+
h[6] = data.length >>> 8 | 128;
|
|
1956
|
+
h[7] = data.length & 255;
|
|
1957
|
+
h.set(data, 8);
|
|
2332
1958
|
}
|
|
2333
|
-
|
|
2334
|
-
h.set([crc >>> 8, crc & 255], buf.byteLength - 2);
|
|
1959
|
+
this.appendCrc16(h);
|
|
2335
1960
|
return h;
|
|
2336
1961
|
}
|
|
1962
|
+
appendCrc16(h) {
|
|
1963
|
+
const crc = this.crcgen.crc16(h.subarray(0, h.length - 2), 0);
|
|
1964
|
+
h[h.length - 2] = crc >>> 8;
|
|
1965
|
+
h[h.length - 1] = crc & 255;
|
|
1966
|
+
}
|
|
2337
1967
|
validateHeader(data) {
|
|
2338
|
-
return
|
|
1968
|
+
return data[0] === PacketEncoder.HEADER_TO_HOST[0] && data[1] === PacketEncoder.HEADER_TO_HOST[1];
|
|
2339
1969
|
}
|
|
2340
1970
|
validateMessageCdc(data) {
|
|
2341
|
-
const
|
|
2342
|
-
|
|
2343
|
-
return this.crcgen.crc16(message, 0) === lastTwoBytes;
|
|
1971
|
+
const crc = (data[data.byteLength - 2] << 8) + data[data.byteLength - 1];
|
|
1972
|
+
return this.crcgen.crc16(data.subarray(0, data.byteLength - 2), 0) === crc;
|
|
2344
1973
|
}
|
|
2345
1974
|
getPayloadSize(data) {
|
|
2346
|
-
|
|
2347
|
-
|
|
2348
|
-
if ((128 & a) !== 0) {
|
|
2349
|
-
t = 127 & a;
|
|
2350
|
-
a = data[4];
|
|
2351
|
-
}
|
|
2352
|
-
return (t << 8) + a;
|
|
1975
|
+
const a = data[3];
|
|
1976
|
+
return (a & 128) === 0 ? a : ((a & 127) << 8) + data[4];
|
|
2353
1977
|
}
|
|
2354
1978
|
getHostHeaderLength(data) {
|
|
2355
1979
|
return (data[3] & 128) === 0 ? 4 : 5;
|
|
@@ -2386,6 +2010,9 @@ class VexSerialConnection extends VexEventTarget {
|
|
|
2386
2010
|
super();
|
|
2387
2011
|
this.serial = serial;
|
|
2388
2012
|
}
|
|
2013
|
+
reportWarning(message, details) {
|
|
2014
|
+
this.emit("warning", { message, details });
|
|
2015
|
+
}
|
|
2389
2016
|
async close() {
|
|
2390
2017
|
if (this._closePromise)
|
|
2391
2018
|
return this._closePromise;
|
|
@@ -2448,7 +2075,7 @@ class VexSerialConnection extends VexEventTarget {
|
|
|
2448
2075
|
try {
|
|
2449
2076
|
await port.close();
|
|
2450
2077
|
} catch (e) {
|
|
2451
|
-
|
|
2078
|
+
this.reportWarning("failed to close the serial port", e);
|
|
2452
2079
|
}
|
|
2453
2080
|
}
|
|
2454
2081
|
if (this._wasConnected) {
|
|
@@ -2457,29 +2084,28 @@ class VexSerialConnection extends VexEventTarget {
|
|
|
2457
2084
|
}
|
|
2458
2085
|
}
|
|
2459
2086
|
open(use = 0, askUser = true) {
|
|
2460
|
-
if (this.port !== undefined) {
|
|
2461
|
-
return errAsyncVex(new VexIoError("Already connected."));
|
|
2462
|
-
}
|
|
2463
2087
|
return new ResultAsync(this._open(use, askUser));
|
|
2464
2088
|
}
|
|
2465
2089
|
async _open(use, askUser) {
|
|
2466
|
-
|
|
2467
|
-
|
|
2468
|
-
|
|
2469
|
-
|
|
2470
|
-
return this.filters.find((f) => (f.usbVendorId === undefined || f.usbVendorId === info.usbVendorId) && (f.usbProductId === undefined || f.usbProductId === info.usbProductId));
|
|
2471
|
-
}).filter((candidate) => candidate.readable === null);
|
|
2472
|
-
port = ports[use];
|
|
2090
|
+
if (this._closePromise !== null)
|
|
2091
|
+
await this._closePromise;
|
|
2092
|
+
if (this.port !== undefined) {
|
|
2093
|
+
return err(new VexIoError("Already connected."));
|
|
2473
2094
|
}
|
|
2095
|
+
const ports = (await this.serial.getPorts()).filter((p) => {
|
|
2096
|
+
const info = p.getInfo();
|
|
2097
|
+
return this.filters.find((f) => (f.usbVendorId === undefined || f.usbVendorId === info.usbVendorId) && (f.usbProductId === undefined || f.usbProductId === info.usbProductId));
|
|
2098
|
+
}).filter((candidate) => candidate.readable === null);
|
|
2099
|
+
let port = ports[use];
|
|
2474
2100
|
if (port == null && askUser) {
|
|
2475
2101
|
try {
|
|
2476
2102
|
port = await this.serial.requestPort({ filters: this.filters });
|
|
2477
2103
|
} catch {}
|
|
2478
2104
|
}
|
|
2479
2105
|
if (port == null)
|
|
2480
|
-
return ok(
|
|
2106
|
+
return ok("no-port");
|
|
2481
2107
|
if (port.readable != null)
|
|
2482
|
-
return ok(
|
|
2108
|
+
return ok("busy");
|
|
2483
2109
|
try {
|
|
2484
2110
|
this.port = port;
|
|
2485
2111
|
await port.open({ baudRate: 115200 });
|
|
@@ -2492,15 +2118,12 @@ class VexSerialConnection extends VexEventTarget {
|
|
|
2492
2118
|
this.startReader();
|
|
2493
2119
|
this._wasConnected = true;
|
|
2494
2120
|
this.emit("connected", undefined);
|
|
2495
|
-
return ok(
|
|
2496
|
-
} catch {
|
|
2121
|
+
return ok("opened");
|
|
2122
|
+
} catch (e) {
|
|
2497
2123
|
await this.close();
|
|
2498
|
-
return
|
|
2124
|
+
return err(toVexSerialError(e, "io"));
|
|
2499
2125
|
}
|
|
2500
2126
|
}
|
|
2501
|
-
writeData(rawData, resolve, timeout = 1000) {
|
|
2502
|
-
this.writeDataAsync(rawData, timeout).then(resolve);
|
|
2503
|
-
}
|
|
2504
2127
|
async writeDataAsync(rawData, timeout = 1000) {
|
|
2505
2128
|
return new Promise((resolve) => {
|
|
2506
2129
|
if (this.writer === undefined) {
|
|
@@ -2531,6 +2154,14 @@ class VexSerialConnection extends VexEventTarget {
|
|
|
2531
2154
|
});
|
|
2532
2155
|
});
|
|
2533
2156
|
}
|
|
2157
|
+
request(packet, ReplyType, timeout = 1000) {
|
|
2158
|
+
return new ResultAsync((async () => {
|
|
2159
|
+
const result = await this.writeDataAsync(packet, timeout);
|
|
2160
|
+
if (result instanceof ReplyType)
|
|
2161
|
+
return ok(result);
|
|
2162
|
+
return err(new VexProtocolError(expectedReplyMessage(packet, ReplyType, result), typeof result === "number" ? result : undefined));
|
|
2163
|
+
})());
|
|
2164
|
+
}
|
|
2534
2165
|
async readData(cache, expectedSize) {
|
|
2535
2166
|
if (this.reader == null)
|
|
2536
2167
|
throw new Error("No reader");
|
|
@@ -2571,39 +2202,56 @@ class VexSerialConnection extends VexEventTarget {
|
|
|
2571
2202
|
if (!thePacketEncoder.validateMessageCdc(cache))
|
|
2572
2203
|
throw new Error("Invalid message CDC");
|
|
2573
2204
|
}
|
|
2574
|
-
let
|
|
2575
|
-
let
|
|
2576
|
-
let
|
|
2577
|
-
|
|
2578
|
-
|
|
2579
|
-
|
|
2580
|
-
|
|
2581
|
-
if (wantedCmdId !== undefined && wantedCmdId !== cmdId || wantedCmdExId !== undefined && wantedCmdExId !== cmdExId) {
|
|
2205
|
+
let matchIdx = -1;
|
|
2206
|
+
let untypedIdx = -1;
|
|
2207
|
+
for (let i = 0;i < this.callbacksQueue.length; i++) {
|
|
2208
|
+
const candidate = this.callbacksQueue[i];
|
|
2209
|
+
if (candidate.wantedCommandId === undefined && candidate.wantedCommandExId === undefined) {
|
|
2210
|
+
if (untypedIdx === -1)
|
|
2211
|
+
untypedIdx = i;
|
|
2582
2212
|
continue;
|
|
2583
2213
|
}
|
|
2584
|
-
|
|
2214
|
+
if ((candidate.wantedCommandId === undefined || candidate.wantedCommandId === cmdId) && (candidate.wantedCommandExId === undefined || candidate.wantedCommandExId === cmdExId)) {
|
|
2215
|
+
matchIdx = i;
|
|
2216
|
+
break;
|
|
2217
|
+
}
|
|
2585
2218
|
}
|
|
2586
|
-
if (
|
|
2587
|
-
|
|
2219
|
+
if (matchIdx === -1)
|
|
2220
|
+
matchIdx = untypedIdx;
|
|
2221
|
+
if (matchIdx === -1) {
|
|
2222
|
+
this.reportWarning("received a reply with no matching request", {
|
|
2223
|
+
commandId: cmdId,
|
|
2224
|
+
commandExtendedId: cmdExId,
|
|
2225
|
+
ack
|
|
2226
|
+
});
|
|
2588
2227
|
continue;
|
|
2589
2228
|
}
|
|
2229
|
+
const callbackInfo = this.callbacksQueue[matchIdx];
|
|
2230
|
+
const wantedCmdId = callbackInfo.wantedCommandId;
|
|
2231
|
+
const wantedCmdExId = callbackInfo.wantedCommandExId;
|
|
2590
2232
|
const data = cache.slice(0, sliceIdx);
|
|
2591
|
-
const PackageType = thePacketEncoder.
|
|
2592
|
-
if (wantedCmdId === undefined
|
|
2233
|
+
const PackageType = thePacketEncoder.getPacketType(wantedCmdId, wantedCmdExId);
|
|
2234
|
+
if (wantedCmdId === undefined || PackageType === undefined) {
|
|
2235
|
+
if (wantedCmdId !== undefined) {
|
|
2236
|
+
this.reportWarning("no packet class is registered for the wanted command", { commandId: wantedCmdId, commandExtendedId: wantedCmdExId });
|
|
2237
|
+
}
|
|
2593
2238
|
callbackInfo.callback(data.buffer.slice(data.byteOffset, data.byteOffset + data.byteLength));
|
|
2594
2239
|
} else {
|
|
2595
2240
|
if (!hasExtId || PackageType.isValidPacket(data, n)) {
|
|
2596
2241
|
callbackInfo.callback(new PackageType(data));
|
|
2597
2242
|
} else {
|
|
2598
|
-
|
|
2243
|
+
this.reportWarning("reply failed packet validation; delivering its ack instead", { commandId: cmdId, commandExtendedId: cmdExId, ack });
|
|
2599
2244
|
callbackInfo.callback(ack);
|
|
2600
2245
|
}
|
|
2601
2246
|
}
|
|
2602
2247
|
clearTimeout(callbackInfo.timeout);
|
|
2603
|
-
this.callbacksQueue.splice(
|
|
2248
|
+
this.callbacksQueue.splice(matchIdx, 1);
|
|
2604
2249
|
} catch (e) {
|
|
2605
2250
|
if (!(e instanceof Error && e.message === "No data")) {
|
|
2606
|
-
|
|
2251
|
+
this.reportWarning("reader loop stopped by a read error", {
|
|
2252
|
+
error: e,
|
|
2253
|
+
pendingBytes: cache
|
|
2254
|
+
});
|
|
2607
2255
|
}
|
|
2608
2256
|
await this.close();
|
|
2609
2257
|
break;
|
|
@@ -2612,19 +2260,10 @@ class VexSerialConnection extends VexEventTarget {
|
|
|
2612
2260
|
}
|
|
2613
2261
|
}
|
|
2614
2262
|
query1() {
|
|
2615
|
-
return new
|
|
2616
|
-
const result = await this.writeDataAsync(new Query1H2DPacket, 100);
|
|
2617
|
-
return result instanceof Query1ReplyD2HPacket ? ok(result) : err(new VexProtocolError("query1 was not acknowledged"));
|
|
2618
|
-
})());
|
|
2263
|
+
return this.request(new Query1H2DPacket, Query1ReplyD2HPacket, 100);
|
|
2619
2264
|
}
|
|
2620
2265
|
getSystemVersion() {
|
|
2621
|
-
return new
|
|
2622
|
-
const result = await this.writeDataAsync(new SystemVersionH2DPacket);
|
|
2623
|
-
if (result instanceof SystemVersionReplyD2HPacket) {
|
|
2624
|
-
return ok(result.version);
|
|
2625
|
-
}
|
|
2626
|
-
return err(new VexProtocolError("system version was not acknowledged"));
|
|
2627
|
-
})());
|
|
2266
|
+
return this.request(new SystemVersionH2DPacket, SystemVersionReplyD2HPacket).map((result) => result.version);
|
|
2628
2267
|
}
|
|
2629
2268
|
}
|
|
2630
2269
|
|
|
@@ -2651,34 +2290,19 @@ class V5SerialConnection extends VexSerialConnection {
|
|
|
2651
2290
|
}
|
|
2652
2291
|
}
|
|
2653
2292
|
getDeviceStatus() {
|
|
2654
|
-
return new
|
|
2655
|
-
const result = await this.writeDataAsync(new GetDeviceStatusH2DPacket);
|
|
2656
|
-
return result instanceof GetDeviceStatusReplyD2HPacket ? ok(result) : err(new VexProtocolError("device status was not acknowledged"));
|
|
2657
|
-
})());
|
|
2293
|
+
return this.request(new GetDeviceStatusH2DPacket, GetDeviceStatusReplyD2HPacket);
|
|
2658
2294
|
}
|
|
2659
2295
|
getRadioStatus() {
|
|
2660
|
-
return new
|
|
2661
|
-
const result = await this.writeDataAsync(new GetRadioStatusH2DPacket);
|
|
2662
|
-
return result instanceof GetRadioStatusReplyD2HPacket ? ok(result) : err(new VexProtocolError("radio status was not acknowledged"));
|
|
2663
|
-
})());
|
|
2296
|
+
return this.request(new GetRadioStatusH2DPacket, GetRadioStatusReplyD2HPacket);
|
|
2664
2297
|
}
|
|
2665
2298
|
getSystemFlags() {
|
|
2666
|
-
return new
|
|
2667
|
-
const result = await this.writeDataAsync(new GetSystemFlagsH2DPacket);
|
|
2668
|
-
return result instanceof GetSystemFlagsReplyD2HPacket ? ok(result) : err(new VexProtocolError("system flags were not acknowledged"));
|
|
2669
|
-
})());
|
|
2299
|
+
return this.request(new GetSystemFlagsH2DPacket, GetSystemFlagsReplyD2HPacket);
|
|
2670
2300
|
}
|
|
2671
2301
|
getSystemStatus(timeout = 1000) {
|
|
2672
|
-
return new
|
|
2673
|
-
const result = await this.writeDataAsync(new GetSystemStatusH2DPacket, timeout);
|
|
2674
|
-
return result instanceof GetSystemStatusReplyD2HPacket ? ok(result) : err(new VexProtocolError("system status was not acknowledged"));
|
|
2675
|
-
})());
|
|
2302
|
+
return this.request(new GetSystemStatusH2DPacket, GetSystemStatusReplyD2HPacket, timeout);
|
|
2676
2303
|
}
|
|
2677
2304
|
getMatchStatus() {
|
|
2678
|
-
return new
|
|
2679
|
-
const result = await this.writeDataAsync(new GetMatchStatusH2DPacket);
|
|
2680
|
-
return result instanceof MatchStatusReplyD2HPacket ? ok(result) : err(new VexProtocolError("match status was not acknowledged"));
|
|
2681
|
-
})());
|
|
2305
|
+
return this.request(new GetMatchStatusH2DPacket, MatchStatusReplyD2HPacket);
|
|
2682
2306
|
}
|
|
2683
2307
|
uploadProgramToDevice(iniConfig, binFileBuf, coldFileBuf, progressCallback) {
|
|
2684
2308
|
return wrapTransfer(this, () => this._uploadProgramToDevice(iniConfig, binFileBuf, coldFileBuf, progressCallback));
|
|
@@ -2739,23 +2363,23 @@ class V5SerialConnection extends VexSerialConnection {
|
|
|
2739
2363
|
async _downloadFileToHostUnlocked(request, downloadTarget, progressCallback) {
|
|
2740
2364
|
const { filename, vendor, loadAddress, size } = request;
|
|
2741
2365
|
let nextAddress = loadAddress ?? USER_FLASH_USR_CODE_START;
|
|
2742
|
-
const
|
|
2743
|
-
if (
|
|
2744
|
-
return err(
|
|
2745
|
-
}
|
|
2366
|
+
const p1Result = await this.request(new InitFileTransferH2DPacket(2 /* READ */, downloadTarget, vendor, 0 /* NONE */, new Uint8Array, nextAddress, filename, ""), InitFileTransferReplyD2HPacket);
|
|
2367
|
+
if (p1Result.isErr())
|
|
2368
|
+
return err(p1Result.error);
|
|
2746
2369
|
let transferFailed = true;
|
|
2747
2370
|
let result = ok(new Uint8Array);
|
|
2748
2371
|
try {
|
|
2372
|
+
const p1 = p1Result.value;
|
|
2749
2373
|
const fileSize = size ?? p1.fileSize;
|
|
2750
2374
|
const bufferChunkSize = getTransferChunkSize(p1.windowSize);
|
|
2751
2375
|
let bufferOffset = 0;
|
|
2752
2376
|
const fileBuf = new Uint8Array(fileSize);
|
|
2753
2377
|
while (bufferOffset < fileSize) {
|
|
2754
2378
|
const requestedSize = Math.min(bufferChunkSize, fileSize - bufferOffset);
|
|
2755
|
-
const
|
|
2756
|
-
if (
|
|
2757
|
-
throw
|
|
2758
|
-
|
|
2379
|
+
const p2Result = await this.request(new ReadFileH2DPacket(nextAddress, requestedSize), ReadFileReplyD2HPacket, 3000);
|
|
2380
|
+
if (p2Result.isErr())
|
|
2381
|
+
throw p2Result.error;
|
|
2382
|
+
const p2 = p2Result.value;
|
|
2759
2383
|
if (p2.addr !== nextAddress) {
|
|
2760
2384
|
throw new VexTransferError(`ReadFileReplyD2HPacket returned address ${p2.addr}, expected ${nextAddress}`);
|
|
2761
2385
|
}
|
|
@@ -2773,11 +2397,12 @@ class V5SerialConnection extends VexSerialConnection {
|
|
|
2773
2397
|
result = err(e instanceof VexSerialError ? e : toVexSerialError(e, "transfer"));
|
|
2774
2398
|
} finally {
|
|
2775
2399
|
try {
|
|
2776
|
-
await this.
|
|
2777
|
-
|
|
2778
|
-
|
|
2779
|
-
|
|
2780
|
-
|
|
2400
|
+
const exitResult = await this.request(new ExitFileTransferH2DPacket(3 /* EXIT_HALT */), ExitFileTransferReplyD2HPacket, 30000);
|
|
2401
|
+
if (!transferFailed && exitResult.isErr())
|
|
2402
|
+
result = err(exitResult.error);
|
|
2403
|
+
} catch (e) {
|
|
2404
|
+
if (!transferFailed)
|
|
2405
|
+
result = err(toVexSerialError(e, "io"));
|
|
2781
2406
|
}
|
|
2782
2407
|
}
|
|
2783
2408
|
return result;
|
|
@@ -2802,22 +2427,20 @@ class V5SerialConnection extends VexSerialConnection {
|
|
|
2802
2427
|
downloadTarget = downloadTarget ?? 1 /* FILE_TARGET_QSPI */;
|
|
2803
2428
|
vendor = vendor ?? 1 /* USER */;
|
|
2804
2429
|
let nextAddress = loadAddress ?? USER_FLASH_USR_CODE_START;
|
|
2805
|
-
const
|
|
2806
|
-
if (
|
|
2807
|
-
return err(
|
|
2808
|
-
|
|
2430
|
+
const p1Result = await this.request(new InitFileTransferH2DPacket(1 /* WRITE */, downloadTarget, vendor, 1 /* OVERWRITE */, buf, nextAddress, filename, exttype), InitFileTransferReplyD2HPacket);
|
|
2431
|
+
if (p1Result.isErr())
|
|
2432
|
+
return err(p1Result.error);
|
|
2433
|
+
const p1 = p1Result.value;
|
|
2809
2434
|
const bufferChunkSize = getTransferChunkSize(p1.windowSize);
|
|
2810
2435
|
let bufferOffset = 0;
|
|
2811
2436
|
let lastBlock = false;
|
|
2812
2437
|
let transferFailed = true;
|
|
2813
|
-
let exitReply;
|
|
2814
2438
|
let result = ok(false);
|
|
2815
2439
|
try {
|
|
2816
2440
|
if (linkedFile !== undefined) {
|
|
2817
|
-
const
|
|
2818
|
-
if (
|
|
2819
|
-
throw
|
|
2820
|
-
}
|
|
2441
|
+
const p3Result = await this.request(new LinkFileH2DPacket(linkedFile.vendor ?? 1 /* USER */, linkedFile.filename, 0), LinkFileReplyD2HPacket, 1e4);
|
|
2442
|
+
if (p3Result.isErr())
|
|
2443
|
+
throw p3Result.error;
|
|
2821
2444
|
}
|
|
2822
2445
|
while (!lastBlock) {
|
|
2823
2446
|
let tmpbuf;
|
|
@@ -2829,23 +2452,21 @@ class V5SerialConnection extends VexSerialConnection {
|
|
|
2829
2452
|
tmpbuf.set(buf.subarray(bufferOffset, buf.byteLength));
|
|
2830
2453
|
lastBlock = true;
|
|
2831
2454
|
}
|
|
2832
|
-
const
|
|
2833
|
-
if (
|
|
2834
|
-
throw
|
|
2835
|
-
if (progressCallback != null)
|
|
2836
|
-
progressCallback(bufferOffset, buf.byteLength);
|
|
2455
|
+
const p2Result = await this.request(new WriteFileH2DPacket(nextAddress, tmpbuf), WriteFileReplyD2HPacket, 3000);
|
|
2456
|
+
if (p2Result.isErr())
|
|
2457
|
+
throw p2Result.error;
|
|
2837
2458
|
bufferOffset += bufferChunkSize;
|
|
2838
2459
|
nextAddress += bufferChunkSize;
|
|
2460
|
+
progressCallback?.(Math.min(bufferOffset, buf.byteLength), buf.byteLength);
|
|
2839
2461
|
}
|
|
2840
|
-
progressCallback?.(buf.byteLength, buf.byteLength);
|
|
2841
2462
|
transferFailed = false;
|
|
2842
2463
|
} catch (e) {
|
|
2843
2464
|
result = err(e instanceof VexSerialError ? e : toVexSerialError(e, "transfer"));
|
|
2844
2465
|
} finally {
|
|
2845
2466
|
try {
|
|
2846
|
-
|
|
2467
|
+
const exitResult = await this.request(new ExitFileTransferH2DPacket(transferFailed ? 3 /* EXIT_HALT */ : autoRun ? 1 /* EXIT_RUN */ : 3 /* EXIT_HALT */), ExitFileTransferReplyD2HPacket, 30000);
|
|
2847
2468
|
if (!transferFailed) {
|
|
2848
|
-
result =
|
|
2469
|
+
result = exitResult.map(() => true);
|
|
2849
2470
|
}
|
|
2850
2471
|
} catch (cleanupError) {
|
|
2851
2472
|
if (!transferFailed) {
|
|
@@ -2867,14 +2488,20 @@ class V5SerialConnection extends VexSerialConnection {
|
|
|
2867
2488
|
}
|
|
2868
2489
|
let result;
|
|
2869
2490
|
try {
|
|
2870
|
-
const
|
|
2871
|
-
result =
|
|
2491
|
+
const eraseResult = await this.request(new EraseFileH2DPacket(vendor, filename), EraseFileReplyD2HPacket);
|
|
2492
|
+
result = eraseResult.map(() => {
|
|
2493
|
+
return;
|
|
2494
|
+
});
|
|
2872
2495
|
} catch (e) {
|
|
2873
2496
|
result = err(toVexSerialError(e, "io"));
|
|
2874
|
-
}
|
|
2875
|
-
|
|
2876
|
-
|
|
2877
|
-
|
|
2497
|
+
}
|
|
2498
|
+
try {
|
|
2499
|
+
const exitResult = await this.request(new ExitFileTransferH2DPacket(3 /* EXIT_HALT */), ExitFileTransferReplyD2HPacket, 30000);
|
|
2500
|
+
if (result.isOk() && exitResult.isErr())
|
|
2501
|
+
result = err(exitResult.error);
|
|
2502
|
+
} catch (e) {
|
|
2503
|
+
if (result.isOk())
|
|
2504
|
+
result = err(toVexSerialError(e, "io"));
|
|
2878
2505
|
}
|
|
2879
2506
|
return result;
|
|
2880
2507
|
}));
|
|
@@ -2883,23 +2510,26 @@ class V5SerialConnection extends VexSerialConnection {
|
|
|
2883
2510
|
return new ResultAsync(this.withFileTransfer(async () => {
|
|
2884
2511
|
let result;
|
|
2885
2512
|
try {
|
|
2886
|
-
const
|
|
2887
|
-
result =
|
|
2513
|
+
const clearResult = await this.request(new FileClearUpH2DPacket(1 /* USER */), FileClearUpReplyD2HPacket, 30000);
|
|
2514
|
+
result = clearResult.map(() => {
|
|
2515
|
+
return;
|
|
2516
|
+
});
|
|
2888
2517
|
} catch (e) {
|
|
2889
2518
|
result = err(toVexSerialError(e, "io"));
|
|
2890
|
-
}
|
|
2891
|
-
|
|
2892
|
-
|
|
2893
|
-
|
|
2519
|
+
}
|
|
2520
|
+
try {
|
|
2521
|
+
const exitResult = await this.request(new ExitFileTransferH2DPacket(3 /* EXIT_HALT */), ExitFileTransferReplyD2HPacket, 30000);
|
|
2522
|
+
if (result.isOk() && exitResult.isErr())
|
|
2523
|
+
result = err(exitResult.error);
|
|
2524
|
+
} catch (e) {
|
|
2525
|
+
if (result.isOk())
|
|
2526
|
+
result = err(toVexSerialError(e, "io"));
|
|
2894
2527
|
}
|
|
2895
2528
|
return result;
|
|
2896
2529
|
}));
|
|
2897
2530
|
}
|
|
2898
2531
|
captureScreenSetup() {
|
|
2899
|
-
return new
|
|
2900
|
-
const result = await this.writeDataAsync(new ScreenCaptureH2DPacket(0));
|
|
2901
|
-
return result instanceof ScreenCaptureReplyD2HPacket ? ok(result) : err(new VexProtocolError("screen capture was rejected"));
|
|
2902
|
-
})());
|
|
2532
|
+
return this.request(new ScreenCaptureH2DPacket(0), ScreenCaptureReplyD2HPacket);
|
|
2903
2533
|
}
|
|
2904
2534
|
captureScreen(progressCallback) {
|
|
2905
2535
|
return wrapTransfer(this, () => this._captureScreen(progressCallback));
|
|
@@ -2920,37 +2550,22 @@ class V5SerialConnection extends VexSerialConnection {
|
|
|
2920
2550
|
return ok(convertScreenCapture(framebuffer.value));
|
|
2921
2551
|
}
|
|
2922
2552
|
setMatchMode(mode) {
|
|
2923
|
-
return new
|
|
2924
|
-
const result = await this.writeDataAsync(new UpdateMatchModeH2DPacket(mode, 0));
|
|
2925
|
-
return result instanceof MatchModeReplyD2HPacket ? ok(result) : err(new VexProtocolError("setMatchMode was not acknowledged"));
|
|
2926
|
-
})());
|
|
2553
|
+
return this.request(new UpdateMatchModeH2DPacket(mode, 0), MatchModeReplyD2HPacket);
|
|
2927
2554
|
}
|
|
2928
2555
|
runProgram(value) {
|
|
2929
2556
|
return this.loadProgram(value);
|
|
2930
2557
|
}
|
|
2931
2558
|
loadProgram(value) {
|
|
2932
|
-
return new
|
|
2933
|
-
const result = await this.writeDataAsync(new LoadFileActionH2DPacket(1 /* USER */, 0 /* RUN */, value));
|
|
2934
|
-
return result instanceof LoadFileActionReplyD2HPacket ? ok(result) : err(new VexProtocolError("loadProgram was not acknowledged"));
|
|
2935
|
-
})());
|
|
2559
|
+
return this.request(new LoadFileActionH2DPacket(1 /* USER */, 0 /* RUN */, value), LoadFileActionReplyD2HPacket);
|
|
2936
2560
|
}
|
|
2937
2561
|
stopProgram() {
|
|
2938
|
-
return new
|
|
2939
|
-
const result = await this.writeDataAsync(new LoadFileActionH2DPacket(1 /* USER */, 128 /* STOP */, ""));
|
|
2940
|
-
return result instanceof LoadFileActionReplyD2HPacket ? ok(result) : err(new VexProtocolError("stopProgram was not acknowledged"));
|
|
2941
|
-
})());
|
|
2562
|
+
return this.request(new LoadFileActionH2DPacket(1 /* USER */, 128 /* STOP */, ""), LoadFileActionReplyD2HPacket);
|
|
2942
2563
|
}
|
|
2943
2564
|
mockTouch(x, y, press) {
|
|
2944
|
-
return new
|
|
2945
|
-
const result = await this.writeDataAsync(new SendDashTouchH2DPacket(x, y, press));
|
|
2946
|
-
return result instanceof SendDashTouchReplyD2HPacket ? ok(result) : err(new VexProtocolError("mockTouch was not acknowledged"));
|
|
2947
|
-
})());
|
|
2565
|
+
return this.request(new SendDashTouchH2DPacket(x, y, press), SendDashTouchReplyD2HPacket);
|
|
2948
2566
|
}
|
|
2949
2567
|
openScreen(screen, port) {
|
|
2950
|
-
return new
|
|
2951
|
-
const result = await this.writeDataAsync(new SelectDashH2DPacket(screen, port));
|
|
2952
|
-
return result instanceof SelectDashReplyD2HPacket ? ok(result) : err(new VexProtocolError("openScreen was not acknowledged"));
|
|
2953
|
-
})());
|
|
2568
|
+
return this.request(new SelectDashH2DPacket(screen, port), SelectDashReplyD2HPacket);
|
|
2954
2569
|
}
|
|
2955
2570
|
}
|
|
2956
2571
|
function binaryArrayJoin(left, right) {
|
|
@@ -2992,17 +2607,22 @@ function wrapTransfer(conn, operation) {
|
|
|
2992
2607
|
}
|
|
2993
2608
|
}));
|
|
2994
2609
|
}
|
|
2995
|
-
function
|
|
2996
|
-
|
|
2610
|
+
function expectedReplyMessage(packet, ReplyType, reply) {
|
|
2611
|
+
const expected = `expected ${ReplyType.name} for ${packet.constructor.name}`;
|
|
2612
|
+
if (typeof reply === "number")
|
|
2613
|
+
return `${expected}; received ${ackTypeName(reply)}`;
|
|
2614
|
+
if (reply instanceof ArrayBuffer)
|
|
2615
|
+
return `${expected}; received raw ArrayBuffer`;
|
|
2616
|
+
return `${expected}; received ${reply.constructor.name}`;
|
|
2617
|
+
}
|
|
2618
|
+
function ackTypeName(ackType) {
|
|
2619
|
+
return `AckType.${AckType[ackType] ?? "UNKNOWN"} (${ackType})`;
|
|
2997
2620
|
}
|
|
2998
2621
|
// src/VexFirmware.ts
|
|
2999
2622
|
var MAX_CATALOG_BYTES = 4 * 1024;
|
|
3000
2623
|
var MAX_VEXOS_BYTES = 64 * 1024 * 1024;
|
|
3001
2624
|
var MAX_FIRMWARE_IMAGE_BYTES = 32 * 1024 * 1024;
|
|
3002
2625
|
var MAX_AGGREGATE_IMAGE_BYTES = 48 * 1024 * 1024;
|
|
3003
|
-
function fromAsyncFn(fn) {
|
|
3004
|
-
return new ResultAsync(fn());
|
|
3005
|
-
}
|
|
3006
2626
|
function downloadFileFromInternet(link, options = {}) {
|
|
3007
2627
|
const { maxBytes = Number.POSITIVE_INFINITY, timeout = 30000 } = options;
|
|
3008
2628
|
if (maxBytes <= 0) {
|
|
@@ -3011,7 +2631,7 @@ function downloadFileFromInternet(link, options = {}) {
|
|
|
3011
2631
|
if (timeout < 0) {
|
|
3012
2632
|
return errAsync(new VexInvalidArgumentError("timeout must be non-negative"));
|
|
3013
2633
|
}
|
|
3014
|
-
return
|
|
2634
|
+
return new ResultAsync(runDownload(link, maxBytes, timeout));
|
|
3015
2635
|
}
|
|
3016
2636
|
async function runDownload(link, maxBytes, timeout) {
|
|
3017
2637
|
const controller = new AbortController;
|
|
@@ -3078,7 +2698,7 @@ function sleepUntilAsync(f, timeout, interval = 20) {
|
|
|
3078
2698
|
if (interval <= 0) {
|
|
3079
2699
|
return errAsync(new VexInvalidArgumentError("interval must be positive"));
|
|
3080
2700
|
}
|
|
3081
|
-
return
|
|
2701
|
+
return new ResultAsync(runSleepUntilAsync(f, timeout, interval));
|
|
3082
2702
|
}
|
|
3083
2703
|
async function runSleepUntilAsync(f, timeout, interval) {
|
|
3084
2704
|
const deadline = Date.now() + timeout;
|
|
@@ -3103,7 +2723,7 @@ function sleepUntil(f, timeout, interval = 20) {
|
|
|
3103
2723
|
if (interval <= 0) {
|
|
3104
2724
|
return errAsync(new VexInvalidArgumentError("interval must be positive"));
|
|
3105
2725
|
}
|
|
3106
|
-
return
|
|
2726
|
+
return new ResultAsync(runSleepUntil(f, timeout, interval));
|
|
3107
2727
|
}
|
|
3108
2728
|
async function runSleepUntil(f, timeout, interval) {
|
|
3109
2729
|
const deadline = Date.now() + timeout;
|
|
@@ -3130,6 +2750,59 @@ function sleep(ms) {
|
|
|
3130
2750
|
async function sleepInner(ms) {
|
|
3131
2751
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
3132
2752
|
}
|
|
2753
|
+
async function flashFactoryImage(conn, options, pcb) {
|
|
2754
|
+
const { image, label, downloadTarget } = options;
|
|
2755
|
+
pcb(`FACTORY ENB ${label}`, 0, 0);
|
|
2756
|
+
const enableReply = await conn.request(new FactoryEnableH2DPacket, FactoryEnableReplyD2HPacket);
|
|
2757
|
+
if (enableReply.isErr())
|
|
2758
|
+
return err(enableReply.error);
|
|
2759
|
+
const writeRequest = {
|
|
2760
|
+
filename: "null.bin",
|
|
2761
|
+
vendor: 1 /* USER */,
|
|
2762
|
+
loadAddress: USER_FLASH_USR_CODE_START,
|
|
2763
|
+
buf: image.buf,
|
|
2764
|
+
downloadTarget,
|
|
2765
|
+
exttype: "bin",
|
|
2766
|
+
autoRun: true,
|
|
2767
|
+
linkedFile: undefined
|
|
2768
|
+
};
|
|
2769
|
+
const upload = await conn.uploadFileToDevice(writeRequest, (c, t) => {
|
|
2770
|
+
pcb(`UPLOAD ${label}`, c, t);
|
|
2771
|
+
});
|
|
2772
|
+
if (upload.isErr())
|
|
2773
|
+
return err(upload.error);
|
|
2774
|
+
if (!upload.value) {
|
|
2775
|
+
return err(new VexFirmwareError(`${label} upload was rejected by device`));
|
|
2776
|
+
}
|
|
2777
|
+
const deadline = Date.now() + 120000;
|
|
2778
|
+
while (Date.now() < deadline) {
|
|
2779
|
+
const statusReply = await conn.request(new FactoryStatusH2DPacket, FactoryStatusReplyD2HPacket, 1e4);
|
|
2780
|
+
if (statusReply.isErr())
|
|
2781
|
+
return err(statusReply.error);
|
|
2782
|
+
reportFactoryStatus(label, statusReply.value, pcb);
|
|
2783
|
+
if (statusReply.value.status === 0 && statusReply.value.percent === 100) {
|
|
2784
|
+
return ok(undefined);
|
|
2785
|
+
}
|
|
2786
|
+
await sleepInner(500);
|
|
2787
|
+
}
|
|
2788
|
+
return err(new VexFirmwareError(`${label} factory status timed out`));
|
|
2789
|
+
}
|
|
2790
|
+
function reportFactoryStatus(label, reply, pcb) {
|
|
2791
|
+
switch (reply.status) {
|
|
2792
|
+
case 2:
|
|
2793
|
+
pcb(`ERASE ${label}`, reply.percent, 100);
|
|
2794
|
+
break;
|
|
2795
|
+
case 3:
|
|
2796
|
+
pcb(`WRITE ${label}`, reply.percent, 100);
|
|
2797
|
+
break;
|
|
2798
|
+
case 4:
|
|
2799
|
+
pcb(`VERIFY ${label}`, reply.percent, 100);
|
|
2800
|
+
break;
|
|
2801
|
+
case 8:
|
|
2802
|
+
pcb(`FINISHING ${label}`, reply.percent, 100);
|
|
2803
|
+
break;
|
|
2804
|
+
}
|
|
2805
|
+
}
|
|
3133
2806
|
async function extractFirmwareImages(usingVersion, vexos) {
|
|
3134
2807
|
const { unzip } = await import("unzipit");
|
|
3135
2808
|
const { entries } = await unzip(vexos);
|
|
@@ -3177,7 +2850,7 @@ async function extractFirmwareImages(usingVersion, vexos) {
|
|
|
3177
2850
|
return ordered;
|
|
3178
2851
|
}
|
|
3179
2852
|
function uploadFirmware(state, publicUrl = "https://content.vexrobotics.com/vexos/public/V5/", usingVersion, progressCallback) {
|
|
3180
|
-
return
|
|
2853
|
+
return new ResultAsync(runUploadFirmware(state, publicUrl, usingVersion, progressCallback));
|
|
3181
2854
|
}
|
|
3182
2855
|
async function runUploadFirmware(state, publicUrl, usingVersion, progressCallback) {
|
|
3183
2856
|
const device = state._instance;
|
|
@@ -3219,12 +2892,7 @@ async function runUploadFirmware(state, publicUrl, usingVersion, progressCallbac
|
|
|
3219
2892
|
return err(toVexSerialError(e, "firmware"));
|
|
3220
2893
|
}
|
|
3221
2894
|
pcb("UNZIP VEXOS", 1, 1);
|
|
3222
|
-
return state.
|
|
3223
|
-
pcb("FACTORY ENB BOOT", 0, 0);
|
|
3224
|
-
const result = await conn.writeDataAsync(new FactoryEnableH2DPacket);
|
|
3225
|
-
if (!(result instanceof FactoryEnableReplyD2HPacket)) {
|
|
3226
|
-
return err(new VexProtocolError("FactoryEnableH2DPacket failed"));
|
|
3227
|
-
}
|
|
2895
|
+
return state.withRefreshPaused(async () => {
|
|
3228
2896
|
const boot = images.find((image) => image.name.endsWith("BOOT.bin"));
|
|
3229
2897
|
if (boot === undefined) {
|
|
3230
2898
|
return err(new VexFirmwareError("VEXos archive is missing BOOT.bin"));
|
|
@@ -3233,105 +2901,20 @@ async function runUploadFirmware(state, publicUrl, usingVersion, progressCallbac
|
|
|
3233
2901
|
if (assertImage === undefined) {
|
|
3234
2902
|
return err(new VexFirmwareError("VEXos archive is missing assets.bin"));
|
|
3235
2903
|
}
|
|
3236
|
-
const
|
|
3237
|
-
|
|
3238
|
-
|
|
3239
|
-
|
|
3240
|
-
|
|
3241
|
-
|
|
3242
|
-
|
|
3243
|
-
|
|
3244
|
-
|
|
3245
|
-
|
|
3246
|
-
|
|
3247
|
-
|
|
3248
|
-
|
|
3249
|
-
|
|
3250
|
-
return err(bootUpload.error);
|
|
3251
|
-
if (!bootUpload.value)
|
|
3252
|
-
return ok(false);
|
|
3253
|
-
const bootDeadline = Date.now() + 120000;
|
|
3254
|
-
let bootComplete = false;
|
|
3255
|
-
while (Date.now() < bootDeadline) {
|
|
3256
|
-
const result3 = await conn.writeDataAsync(new FactoryStatusH2DPacket, 1e4);
|
|
3257
|
-
if (result3 instanceof FactoryStatusReplyD2HPacket) {
|
|
3258
|
-
switch (result3.status) {
|
|
3259
|
-
case 2:
|
|
3260
|
-
pcb("ERASE BOOT", result3.percent, 100);
|
|
3261
|
-
break;
|
|
3262
|
-
case 3:
|
|
3263
|
-
pcb("WRITE BOOT", result3.percent, 100);
|
|
3264
|
-
break;
|
|
3265
|
-
case 4:
|
|
3266
|
-
pcb("VERIFY BOOT", result3.percent, 100);
|
|
3267
|
-
break;
|
|
3268
|
-
case 8:
|
|
3269
|
-
pcb("FINISHING BOOT", result3.percent, 100);
|
|
3270
|
-
break;
|
|
3271
|
-
}
|
|
3272
|
-
if (result3.status === 0 && result3.percent === 100) {
|
|
3273
|
-
bootComplete = true;
|
|
3274
|
-
break;
|
|
3275
|
-
}
|
|
3276
|
-
} else {
|
|
3277
|
-
return ok(false);
|
|
3278
|
-
}
|
|
3279
|
-
await sleepInner(500);
|
|
3280
|
-
}
|
|
3281
|
-
if (!bootComplete)
|
|
3282
|
-
return ok(false);
|
|
3283
|
-
pcb("FACTORY ENB ASSERT", 0, 0);
|
|
3284
|
-
const result5 = await conn.writeDataAsync(new FactoryEnableH2DPacket);
|
|
3285
|
-
if (!(result5 instanceof FactoryEnableReplyD2HPacket)) {
|
|
3286
|
-
return err(new VexProtocolError("FactoryEnableH2DPacket failed"));
|
|
3287
|
-
}
|
|
3288
|
-
const assertWriteRequest = {
|
|
3289
|
-
filename: "null.bin",
|
|
3290
|
-
vendor: 1 /* USER */,
|
|
3291
|
-
loadAddress: USER_FLASH_USR_CODE_START,
|
|
3292
|
-
buf: assertImage.buf,
|
|
3293
|
-
downloadTarget: 13 /* FILE_TARGET_A1 */,
|
|
3294
|
-
exttype: "bin",
|
|
3295
|
-
autoRun: true,
|
|
3296
|
-
linkedFile: undefined
|
|
3297
|
-
};
|
|
3298
|
-
const assertUpload = await conn.uploadFileToDevice(assertWriteRequest, (c, t) => {
|
|
3299
|
-
pcb("UPLOAD ASSERT", c, t);
|
|
3300
|
-
});
|
|
3301
|
-
if (assertUpload.isErr())
|
|
3302
|
-
return err(assertUpload.error);
|
|
3303
|
-
if (!assertUpload.value)
|
|
3304
|
-
return ok(false);
|
|
3305
|
-
const assertDeadline = Date.now() + 120000;
|
|
3306
|
-
let assertComplete = false;
|
|
3307
|
-
while (Date.now() < assertDeadline) {
|
|
3308
|
-
const result7 = await conn.writeDataAsync(new FactoryStatusH2DPacket, 1e4);
|
|
3309
|
-
if (result7 instanceof FactoryStatusReplyD2HPacket) {
|
|
3310
|
-
switch (result7.status) {
|
|
3311
|
-
case 2:
|
|
3312
|
-
pcb("ERASE ASSERT", result7.percent, 100);
|
|
3313
|
-
break;
|
|
3314
|
-
case 3:
|
|
3315
|
-
pcb("WRITE ASSERT", result7.percent, 100);
|
|
3316
|
-
break;
|
|
3317
|
-
case 4:
|
|
3318
|
-
pcb("VERIFY ASSERT", result7.percent, 100);
|
|
3319
|
-
break;
|
|
3320
|
-
case 8:
|
|
3321
|
-
pcb("FINISHING ASSERT", result7.percent, 100);
|
|
3322
|
-
break;
|
|
3323
|
-
}
|
|
3324
|
-
if (result7.status === 0 && result7.percent === 100) {
|
|
3325
|
-
assertComplete = true;
|
|
3326
|
-
break;
|
|
3327
|
-
}
|
|
3328
|
-
} else {
|
|
3329
|
-
return ok(false);
|
|
3330
|
-
}
|
|
3331
|
-
await sleepInner(500);
|
|
3332
|
-
}
|
|
3333
|
-
if (!assertComplete)
|
|
3334
|
-
return ok(false);
|
|
2904
|
+
const bootFlash = await flashFactoryImage(conn, {
|
|
2905
|
+
image: boot,
|
|
2906
|
+
label: "BOOT",
|
|
2907
|
+
downloadTarget: 14 /* FILE_TARGET_B1 */
|
|
2908
|
+
}, pcb);
|
|
2909
|
+
if (bootFlash.isErr())
|
|
2910
|
+
return err(bootFlash.error);
|
|
2911
|
+
const assetsFlash = await flashFactoryImage(conn, {
|
|
2912
|
+
image: assertImage,
|
|
2913
|
+
label: "ASSETS",
|
|
2914
|
+
downloadTarget: 13 /* FILE_TARGET_A1 */
|
|
2915
|
+
}, pcb);
|
|
2916
|
+
if (assetsFlash.isErr())
|
|
2917
|
+
return err(assetsFlash.error);
|
|
3335
2918
|
return ok(true);
|
|
3336
2919
|
});
|
|
3337
2920
|
}
|
|
@@ -3343,8 +2926,7 @@ function getValue(state, key) {
|
|
|
3343
2926
|
if (conn == null || !conn.isConnected) {
|
|
3344
2927
|
return err(new VexNotConnectedError);
|
|
3345
2928
|
}
|
|
3346
|
-
|
|
3347
|
-
return result instanceof ReadKeyValueReplyD2HPacket ? ok(result.value) : err(new VexProtocolError("getValue was not acknowledged"));
|
|
2929
|
+
return conn.request(new ReadKeyValueH2DPacket(key), ReadKeyValueReplyD2HPacket).map((result) => result.value);
|
|
3348
2930
|
})());
|
|
3349
2931
|
}
|
|
3350
2932
|
function setValue(state, key, value) {
|
|
@@ -3353,8 +2935,9 @@ function setValue(state, key, value) {
|
|
|
3353
2935
|
if (conn == null || !conn.isConnected) {
|
|
3354
2936
|
return err(new VexNotConnectedError);
|
|
3355
2937
|
}
|
|
3356
|
-
|
|
3357
|
-
|
|
2938
|
+
return conn.request(new WriteKeyValueH2DPacket(key, value), WriteKeyValueReplyD2HPacket).map(() => {
|
|
2939
|
+
return;
|
|
2940
|
+
});
|
|
3358
2941
|
})());
|
|
3359
2942
|
}
|
|
3360
2943
|
function listFiles(state, vendor = 1 /* USER */) {
|
|
@@ -3363,26 +2946,24 @@ function listFiles(state, vendor = 1 /* USER */) {
|
|
|
3363
2946
|
if (conn == null || !conn.isConnected) {
|
|
3364
2947
|
return err(new VexNotConnectedError);
|
|
3365
2948
|
}
|
|
3366
|
-
const
|
|
3367
|
-
if (
|
|
3368
|
-
return err(
|
|
3369
|
-
}
|
|
2949
|
+
const countResult = await conn.request(new GetDirectoryFileCountH2DPacket(vendor), GetDirectoryFileCountReplyD2HPacket);
|
|
2950
|
+
if (countResult.isErr())
|
|
2951
|
+
return err(countResult.error);
|
|
3370
2952
|
const files = [];
|
|
3371
|
-
for (let i = 0;i <
|
|
3372
|
-
const
|
|
3373
|
-
if (
|
|
3374
|
-
return err(
|
|
3375
|
-
|
|
3376
|
-
if (result2.file != null) {
|
|
2953
|
+
for (let i = 0;i < countResult.value.count; i++) {
|
|
2954
|
+
const entryResult = await conn.request(new GetDirectoryEntryH2DPacket(i), GetDirectoryEntryReplyD2HPacket);
|
|
2955
|
+
if (entryResult.isErr())
|
|
2956
|
+
return err(entryResult.error);
|
|
2957
|
+
if (entryResult.value.file != null) {
|
|
3377
2958
|
files.push({
|
|
3378
|
-
filename:
|
|
2959
|
+
filename: entryResult.value.file.filename,
|
|
3379
2960
|
vendor,
|
|
3380
|
-
loadAddress:
|
|
3381
|
-
size:
|
|
3382
|
-
crc32:
|
|
3383
|
-
type:
|
|
3384
|
-
timestamp:
|
|
3385
|
-
version:
|
|
2961
|
+
loadAddress: entryResult.value.file.loadAddress,
|
|
2962
|
+
size: entryResult.value.file.size,
|
|
2963
|
+
crc32: entryResult.value.file.crc32,
|
|
2964
|
+
type: entryResult.value.file.type,
|
|
2965
|
+
timestamp: entryResult.value.file.timestamp,
|
|
2966
|
+
version: entryResult.value.file.version
|
|
3386
2967
|
});
|
|
3387
2968
|
}
|
|
3388
2969
|
}
|
|
@@ -3418,10 +2999,10 @@ function listProgram(state) {
|
|
|
3418
2999
|
time: n,
|
|
3419
3000
|
requestedSlot: -1
|
|
3420
3001
|
};
|
|
3421
|
-
const
|
|
3422
|
-
if (
|
|
3423
|
-
program.slot =
|
|
3424
|
-
program.requestedSlot =
|
|
3002
|
+
const slotInfo = await conn.request(new GetProgramSlotInfoH2DPacket(1 /* USER */, program.binfile), GetProgramSlotInfoReplyD2HPacket);
|
|
3003
|
+
if (slotInfo.isOk()) {
|
|
3004
|
+
program.slot = slotInfo.value.slot;
|
|
3005
|
+
program.requestedSlot = slotInfo.value.requestedSlot;
|
|
3425
3006
|
}
|
|
3426
3007
|
programList.push(program);
|
|
3427
3008
|
}
|
|
@@ -3440,7 +3021,7 @@ function readFile(state, request, downloadTarget = 1 /* FILE_TARGET_QSPI */, pro
|
|
|
3440
3021
|
} else {
|
|
3441
3022
|
handle = request;
|
|
3442
3023
|
}
|
|
3443
|
-
return state.
|
|
3024
|
+
return state.withRefreshPaused(() => conn.downloadFileToHost(handle, downloadTarget, progressCallback));
|
|
3444
3025
|
})());
|
|
3445
3026
|
}
|
|
3446
3027
|
function removeFile(state, request) {
|
|
@@ -3449,7 +3030,7 @@ function removeFile(state, request) {
|
|
|
3449
3030
|
if (conn == null || !conn.isConnected) {
|
|
3450
3031
|
return err(new VexNotConnectedError);
|
|
3451
3032
|
}
|
|
3452
|
-
return state.
|
|
3033
|
+
return state.withRefreshPaused(() => conn.removeFile(request));
|
|
3453
3034
|
})());
|
|
3454
3035
|
}
|
|
3455
3036
|
function removeAllFiles(state) {
|
|
@@ -3458,7 +3039,7 @@ function removeAllFiles(state) {
|
|
|
3458
3039
|
if (conn == null || !conn.isConnected) {
|
|
3459
3040
|
return err(new VexNotConnectedError);
|
|
3460
3041
|
}
|
|
3461
|
-
return state.
|
|
3042
|
+
return state.withRefreshPaused(() => conn.removeAllFiles());
|
|
3462
3043
|
})());
|
|
3463
3044
|
}
|
|
3464
3045
|
function uploadProgram(state, iniConfig, binFileBuf, coldFileBuf, progressCallback) {
|
|
@@ -3471,7 +3052,7 @@ async function runUploadProgram(state, iniConfig, binFileBuf, coldFileBuf, progr
|
|
|
3471
3052
|
return err(new VexNotConnectedError);
|
|
3472
3053
|
}
|
|
3473
3054
|
let switchedToDownload = false;
|
|
3474
|
-
return state.
|
|
3055
|
+
return state.withRefreshPaused(async () => {
|
|
3475
3056
|
try {
|
|
3476
3057
|
if (device.isV5Controller) {
|
|
3477
3058
|
await sleep(250);
|
|
@@ -3530,7 +3111,7 @@ function writeFile(state, request, progressCallback) {
|
|
|
3530
3111
|
if (conn == null || !conn.isConnected) {
|
|
3531
3112
|
return err(new VexNotConnectedError);
|
|
3532
3113
|
}
|
|
3533
|
-
return state.
|
|
3114
|
+
return state.withRefreshPaused(() => conn.uploadFileToDevice(request, progressCallback));
|
|
3534
3115
|
})());
|
|
3535
3116
|
}
|
|
3536
3117
|
function captureScreen(state, progressCallback) {
|
|
@@ -3539,7 +3120,7 @@ function captureScreen(state, progressCallback) {
|
|
|
3539
3120
|
if (conn == null || !conn.isConnected) {
|
|
3540
3121
|
return err(new VexNotConnectedError);
|
|
3541
3122
|
}
|
|
3542
|
-
return state.
|
|
3123
|
+
return state.withRefreshPaused(() => conn.captureScreen(progressCallback));
|
|
3543
3124
|
})());
|
|
3544
3125
|
}
|
|
3545
3126
|
|
|
@@ -3562,10 +3143,13 @@ class VexSerialDevice extends VexEventTarget {
|
|
|
3562
3143
|
class V5SerialDeviceState {
|
|
3563
3144
|
_instance;
|
|
3564
3145
|
refreshPauseDepth = 0;
|
|
3565
|
-
get
|
|
3146
|
+
get isRefreshPaused() {
|
|
3566
3147
|
return this.refreshPauseDepth > 0;
|
|
3567
3148
|
}
|
|
3568
|
-
|
|
3149
|
+
get isFileTransferring() {
|
|
3150
|
+
return this.isRefreshPaused;
|
|
3151
|
+
}
|
|
3152
|
+
async withRefreshPaused(operation) {
|
|
3569
3153
|
this.refreshPauseDepth++;
|
|
3570
3154
|
try {
|
|
3571
3155
|
return await operation();
|
|
@@ -3573,6 +3157,9 @@ class V5SerialDeviceState {
|
|
|
3573
3157
|
this.refreshPauseDepth--;
|
|
3574
3158
|
}
|
|
3575
3159
|
}
|
|
3160
|
+
async withFileTransfer(operation) {
|
|
3161
|
+
return this.withRefreshPaused(operation);
|
|
3162
|
+
}
|
|
3576
3163
|
brain = {
|
|
3577
3164
|
activeProgram: 0,
|
|
3578
3165
|
battery: {
|
|
@@ -3602,7 +3189,8 @@ class V5SerialDeviceState {
|
|
|
3602
3189
|
},
|
|
3603
3190
|
{
|
|
3604
3191
|
battery: 0,
|
|
3605
|
-
isAvailable: false
|
|
3192
|
+
isAvailable: false,
|
|
3193
|
+
isCharging: false
|
|
3606
3194
|
}
|
|
3607
3195
|
];
|
|
3608
3196
|
devices = [];
|
|
@@ -3625,8 +3213,14 @@ class V5SerialDeviceState {
|
|
|
3625
3213
|
|
|
3626
3214
|
class V5Brain {
|
|
3627
3215
|
state;
|
|
3216
|
+
batteryFacade;
|
|
3217
|
+
buttonFacade;
|
|
3218
|
+
settingsFacade;
|
|
3628
3219
|
constructor(state) {
|
|
3629
3220
|
this.state = state;
|
|
3221
|
+
this.batteryFacade = new V5Battery(state);
|
|
3222
|
+
this.buttonFacade = new V5BrainButton(state);
|
|
3223
|
+
this.settingsFacade = new V5BrainSettings(state);
|
|
3630
3224
|
}
|
|
3631
3225
|
get isRunningProgram() {
|
|
3632
3226
|
return this.activeProgram !== 0;
|
|
@@ -3659,9 +3253,8 @@ class V5Brain {
|
|
|
3659
3253
|
const reply = await conn.runProgram(slot);
|
|
3660
3254
|
if (reply.isErr())
|
|
3661
3255
|
return err(reply.error);
|
|
3662
|
-
|
|
3663
|
-
|
|
3664
|
-
this.state.brain.activeProgram = slotNumber;
|
|
3256
|
+
if (typeof slot === "number")
|
|
3257
|
+
this.state.brain.activeProgram = slot;
|
|
3665
3258
|
return ok(undefined);
|
|
3666
3259
|
})());
|
|
3667
3260
|
}
|
|
@@ -3678,10 +3271,10 @@ class V5Brain {
|
|
|
3678
3271
|
})());
|
|
3679
3272
|
}
|
|
3680
3273
|
get battery() {
|
|
3681
|
-
return
|
|
3274
|
+
return this.batteryFacade;
|
|
3682
3275
|
}
|
|
3683
3276
|
get button() {
|
|
3684
|
-
return
|
|
3277
|
+
return this.buttonFacade;
|
|
3685
3278
|
}
|
|
3686
3279
|
get cpu0Version() {
|
|
3687
3280
|
return this.state.brain.cpu0Version;
|
|
@@ -3693,7 +3286,7 @@ class V5Brain {
|
|
|
3693
3286
|
return this.state.brain.isAvailable;
|
|
3694
3287
|
}
|
|
3695
3288
|
get settings() {
|
|
3696
|
-
return
|
|
3289
|
+
return this.settingsFacade;
|
|
3697
3290
|
}
|
|
3698
3291
|
get systemVersion() {
|
|
3699
3292
|
return this.state.brain.systemVersion;
|
|
@@ -3848,16 +3441,28 @@ class V5Radio {
|
|
|
3848
3441
|
}
|
|
3849
3442
|
changeChannel(channel) {
|
|
3850
3443
|
return new ResultAsync((async () => {
|
|
3851
|
-
const
|
|
3852
|
-
|
|
3444
|
+
const conn = this.state._instance.connection;
|
|
3445
|
+
if (conn == null || !conn.isConnected) {
|
|
3446
|
+
return err(new VexNotConnectedError);
|
|
3447
|
+
}
|
|
3448
|
+
return conn.request(new FileControlH2DPacket(1, channel), FileControlReplyD2HPacket).map(() => {
|
|
3449
|
+
return;
|
|
3450
|
+
});
|
|
3853
3451
|
})());
|
|
3854
3452
|
}
|
|
3855
3453
|
}
|
|
3856
3454
|
|
|
3857
3455
|
// src/VexDevice.ts
|
|
3456
|
+
function unrefTimerIfPossible(timer) {
|
|
3457
|
+
if (typeof timer !== "object" || timer === null || !("unref" in timer))
|
|
3458
|
+
return;
|
|
3459
|
+
const unref = timer.unref;
|
|
3460
|
+
if (typeof unref === "function")
|
|
3461
|
+
unref.call(timer);
|
|
3462
|
+
}
|
|
3463
|
+
|
|
3858
3464
|
class V5SerialDevice extends VexSerialDevice {
|
|
3859
3465
|
autoReconnect = true;
|
|
3860
|
-
autoRefresh = true;
|
|
3861
3466
|
pauseRefreshOnFileTransfer = true;
|
|
3862
3467
|
_isReconnecting = false;
|
|
3863
3468
|
_isDisconnecting = false;
|
|
@@ -3865,19 +3470,45 @@ class V5SerialDevice extends VexSerialDevice {
|
|
|
3865
3470
|
state = new V5SerialDeviceState(this);
|
|
3866
3471
|
_disposed = false;
|
|
3867
3472
|
_refreshGeneration = 0;
|
|
3868
|
-
|
|
3473
|
+
_autoRefresh = false;
|
|
3474
|
+
_isLastRefreshComplete = true;
|
|
3475
|
+
_brain = new V5Brain(this.state);
|
|
3476
|
+
_controllers = [
|
|
3477
|
+
new V5Controller(this.state, 0),
|
|
3478
|
+
new V5Controller(this.state, 1)
|
|
3479
|
+
];
|
|
3480
|
+
_radio = new V5Radio(this.state);
|
|
3481
|
+
_deviceFacades = [];
|
|
3482
|
+
constructor(defaultSerial, autoRefresh = false) {
|
|
3869
3483
|
super(defaultSerial);
|
|
3870
|
-
|
|
3484
|
+
this.autoRefresh = autoRefresh;
|
|
3485
|
+
}
|
|
3486
|
+
get autoRefresh() {
|
|
3487
|
+
return this._autoRefresh;
|
|
3488
|
+
}
|
|
3489
|
+
set autoRefresh(value) {
|
|
3490
|
+
if (this._autoRefresh === value)
|
|
3491
|
+
return;
|
|
3492
|
+
this._autoRefresh = value;
|
|
3493
|
+
if (value) {
|
|
3494
|
+
this._startRefreshInterval();
|
|
3495
|
+
} else {
|
|
3496
|
+
this._stopRefreshInterval();
|
|
3497
|
+
}
|
|
3498
|
+
}
|
|
3499
|
+
_startRefreshInterval() {
|
|
3500
|
+
if (this._refreshInterval !== undefined || this._disposed)
|
|
3501
|
+
return;
|
|
3871
3502
|
this._refreshInterval = setInterval(() => {
|
|
3872
3503
|
if (this._disposed)
|
|
3873
3504
|
return;
|
|
3874
|
-
if (this.
|
|
3505
|
+
if (this._autoRefresh && this._isLastRefreshComplete) {
|
|
3875
3506
|
if (!this.isConnected) {
|
|
3876
3507
|
this.state.brain.isAvailable = false;
|
|
3877
3508
|
return;
|
|
3878
3509
|
}
|
|
3879
|
-
if (!this.pauseRefreshOnFileTransfer || !this.state.
|
|
3880
|
-
|
|
3510
|
+
if (!this.pauseRefreshOnFileTransfer || !this.state.isRefreshPaused) {
|
|
3511
|
+
this._isLastRefreshComplete = false;
|
|
3881
3512
|
(async () => {
|
|
3882
3513
|
try {
|
|
3883
3514
|
const r = await this.refresh();
|
|
@@ -3886,27 +3517,37 @@ class V5SerialDevice extends VexSerialDevice {
|
|
|
3886
3517
|
} catch (error) {
|
|
3887
3518
|
this.emit("error", error);
|
|
3888
3519
|
} finally {
|
|
3889
|
-
|
|
3520
|
+
this._isLastRefreshComplete = true;
|
|
3890
3521
|
}
|
|
3891
3522
|
})();
|
|
3892
3523
|
}
|
|
3893
3524
|
}
|
|
3894
3525
|
}, 200);
|
|
3526
|
+
unrefTimerIfPossible(this._refreshInterval);
|
|
3527
|
+
}
|
|
3528
|
+
_stopRefreshInterval() {
|
|
3529
|
+
if (this._refreshInterval === undefined)
|
|
3530
|
+
return;
|
|
3531
|
+
clearInterval(this._refreshInterval);
|
|
3532
|
+
this._refreshInterval = undefined;
|
|
3895
3533
|
}
|
|
3896
3534
|
get isV5Controller() {
|
|
3897
3535
|
return this.deviceType === 1283 /* V5_CONTROLLER */;
|
|
3898
3536
|
}
|
|
3899
3537
|
get brain() {
|
|
3900
|
-
return
|
|
3538
|
+
return this._brain;
|
|
3901
3539
|
}
|
|
3902
3540
|
get controllers() {
|
|
3903
|
-
return
|
|
3541
|
+
return this._controllers;
|
|
3904
3542
|
}
|
|
3905
3543
|
get devices() {
|
|
3906
3544
|
const rtn = [];
|
|
3907
|
-
for (let i = 1;i
|
|
3908
|
-
if (this.state.devices[i] != null)
|
|
3909
|
-
|
|
3545
|
+
for (let i = 1;i < this.state.devices.length; i++) {
|
|
3546
|
+
if (this.state.devices[i] != null) {
|
|
3547
|
+
const facade = this._deviceFacades[i] ?? new V5SmartDevice(this.state, i);
|
|
3548
|
+
this._deviceFacades[i] = facade;
|
|
3549
|
+
rtn.push(facade);
|
|
3550
|
+
}
|
|
3910
3551
|
}
|
|
3911
3552
|
return rtn;
|
|
3912
3553
|
}
|
|
@@ -3931,7 +3572,7 @@ class V5SerialDevice extends VexSerialDevice {
|
|
|
3931
3572
|
})());
|
|
3932
3573
|
}
|
|
3933
3574
|
get radio() {
|
|
3934
|
-
return
|
|
3575
|
+
return this._radio;
|
|
3935
3576
|
}
|
|
3936
3577
|
mockTouch(x, y, press) {
|
|
3937
3578
|
return new ResultAsync((async () => {
|
|
@@ -3952,7 +3593,7 @@ class V5SerialDevice extends VexSerialDevice {
|
|
|
3952
3593
|
if (conn != null) {
|
|
3953
3594
|
if (!conn.isConnected) {
|
|
3954
3595
|
const opened = await conn.open();
|
|
3955
|
-
if (opened.isErr() || opened.value !==
|
|
3596
|
+
if (opened.isErr() || opened.value !== "opened") {
|
|
3956
3597
|
return err(new VexIoError("failed to open the supplied connection"));
|
|
3957
3598
|
}
|
|
3958
3599
|
}
|
|
@@ -3971,10 +3612,10 @@ class V5SerialDevice extends VexSerialDevice {
|
|
|
3971
3612
|
await c.close();
|
|
3972
3613
|
return err(result.error);
|
|
3973
3614
|
}
|
|
3974
|
-
if (result.value ===
|
|
3615
|
+
if (result.value === "no-port") {
|
|
3975
3616
|
return err(new VexNotConnectedError("no V5 device was found"));
|
|
3976
3617
|
}
|
|
3977
|
-
if (
|
|
3618
|
+
if (result.value === "busy") {
|
|
3978
3619
|
await c.close();
|
|
3979
3620
|
continue;
|
|
3980
3621
|
}
|
|
@@ -4006,10 +3647,6 @@ class V5SerialDevice extends VexSerialDevice {
|
|
|
4006
3647
|
this.autoReconnect = false;
|
|
4007
3648
|
this.autoRefresh = false;
|
|
4008
3649
|
this._disposed = true;
|
|
4009
|
-
if (this._refreshInterval !== undefined) {
|
|
4010
|
-
clearInterval(this._refreshInterval);
|
|
4011
|
-
this._refreshInterval = undefined;
|
|
4012
|
-
}
|
|
4013
3650
|
await this.disconnect();
|
|
4014
3651
|
}
|
|
4015
3652
|
reconnect(timeout = 0) {
|
|
@@ -4045,9 +3682,9 @@ class V5SerialDevice extends VexSerialDevice {
|
|
|
4045
3682
|
await c.close();
|
|
4046
3683
|
return err(result.error);
|
|
4047
3684
|
}
|
|
4048
|
-
if (result.value ===
|
|
3685
|
+
if (result.value === "no-port")
|
|
4049
3686
|
break;
|
|
4050
|
-
if (
|
|
3687
|
+
if (result.value === "busy") {
|
|
4051
3688
|
await c.close();
|
|
4052
3689
|
continue;
|
|
4053
3690
|
}
|
|
@@ -4090,7 +3727,10 @@ class V5SerialDevice extends VexSerialDevice {
|
|
|
4090
3727
|
if (this.connection == null)
|
|
4091
3728
|
return;
|
|
4092
3729
|
this.connection.on("disconnected", (_data) => {
|
|
4093
|
-
if (this.
|
|
3730
|
+
if (this._isDisconnecting)
|
|
3731
|
+
return;
|
|
3732
|
+
this.emit("disconnected", undefined);
|
|
3733
|
+
if (this.autoReconnect) {
|
|
4094
3734
|
this.reconnect().mapErr((e) => this.emit("error", e));
|
|
4095
3735
|
}
|
|
4096
3736
|
});
|
|
@@ -4188,7 +3828,8 @@ class V5SerialDevice extends VexSerialDevice {
|
|
|
4188
3828
|
},
|
|
4189
3829
|
{
|
|
4190
3830
|
battery: controller1Battery,
|
|
4191
|
-
isAvailable: controller1Available
|
|
3831
|
+
isAvailable: controller1Available,
|
|
3832
|
+
isCharging: (flags2 & 128) !== 0
|
|
4192
3833
|
}
|
|
4193
3834
|
],
|
|
4194
3835
|
radio: {
|
|
@@ -4255,23 +3896,22 @@ class IniSectionBuilder extends BaseIniBuilder {
|
|
|
4255
3896
|
this.keyTransform = keyTransform;
|
|
4256
3897
|
}
|
|
4257
3898
|
addSingleObjProperty(key, maxValueLength) {
|
|
4258
|
-
|
|
3899
|
+
const value = this.object[key];
|
|
3900
|
+
if (value == null || value.toString().length === 0)
|
|
4259
3901
|
return;
|
|
4260
3902
|
const formattedKey = this.keyTransform(key).padEnd(12).slice(0, 12);
|
|
4261
|
-
const trimmedVal =
|
|
3903
|
+
const trimmedVal = value.toString().slice(0, maxValueLength);
|
|
4262
3904
|
const escapedVal = trimmedVal.replace(/["\\\u0000-\u001f\u007f]/g, (character) => `\\x${character.charCodeAt(0).toString(16).padStart(2, "0")}`);
|
|
4263
3905
|
this.addLine(`${formattedKey} = "${escapedVal}"`);
|
|
4264
3906
|
}
|
|
4265
3907
|
addObjProperty(key, maxValueLength) {
|
|
4266
|
-
const
|
|
4267
|
-
for (const k of keys) {
|
|
3908
|
+
for (const k of Array.isArray(key) ? key : [key]) {
|
|
4268
3909
|
this.addSingleObjProperty(k, maxValueLength);
|
|
4269
3910
|
}
|
|
4270
3911
|
return this;
|
|
4271
3912
|
}
|
|
4272
3913
|
addAllObjProps(maxValueLength) {
|
|
4273
|
-
const
|
|
4274
|
-
for (const k of keys) {
|
|
3914
|
+
for (const k of Object.keys(this.object)) {
|
|
4275
3915
|
this.addSingleObjProperty(k, maxValueLength);
|
|
4276
3916
|
}
|
|
4277
3917
|
return this;
|
|
@@ -4300,21 +3940,15 @@ class ProgramIniConfig {
|
|
|
4300
3940
|
date: "",
|
|
4301
3941
|
timezone: "0"
|
|
4302
3942
|
};
|
|
4303
|
-
config = {};
|
|
3943
|
+
config = { 22: "adi" };
|
|
4304
3944
|
controller1 = {};
|
|
4305
3945
|
controller2 = {};
|
|
4306
|
-
constructor() {
|
|
4307
|
-
this.config = {
|
|
4308
|
-
22: "adi"
|
|
4309
|
-
};
|
|
4310
|
-
}
|
|
4311
3946
|
setProgramDate(date) {
|
|
4312
|
-
|
|
4313
|
-
|
|
4314
|
-
const
|
|
4315
|
-
const
|
|
4316
|
-
|
|
4317
|
-
this.program.timezone = (d.getTimezoneOffset() > 0 ? "-" : "+") + this.dec2(tzh) + ":" + this.dec2(tzm);
|
|
3947
|
+
this.program.date = date.toISOString();
|
|
3948
|
+
const offset = Math.abs(date.getTimezoneOffset());
|
|
3949
|
+
const hours = offset / 60 >>> 0;
|
|
3950
|
+
const minutes = offset - hours * 60;
|
|
3951
|
+
this.program.timezone = (date.getTimezoneOffset() > 0 ? "-" : "+") + this.dec2(hours) + ":" + this.dec2(minutes);
|
|
4318
3952
|
}
|
|
4319
3953
|
createIni() {
|
|
4320
3954
|
if (this.program.date.length === 0) {
|
|
@@ -4323,8 +3957,7 @@ class ProgramIniConfig {
|
|
|
4323
3957
|
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("description", 256).addObjProperty("icon", 16).addObjProperty("iconalt", 16).addObjProperty("slot", 16)).addComment("").addSection(new IniSectionBuilder("config", this.config, (k) => "port_" + this.dec2(k)).addAllObjProps()).addComment("").addSection(new IniSectionBuilder("controller_1", this.controller1).addAllObjProps()).addComment("").addSection(new IniSectionBuilder("controller_2", this.controller2).addAllObjProps()).getContent();
|
|
4324
3958
|
}
|
|
4325
3959
|
dec2(value) {
|
|
4326
|
-
|
|
4327
|
-
return str.toUpperCase();
|
|
3960
|
+
return (value % 100).toString(10).padStart(2, "0").toUpperCase();
|
|
4328
3961
|
}
|
|
4329
3962
|
}
|
|
4330
3963
|
export {
|
|
@@ -4456,5 +4089,5 @@ export {
|
|
|
4456
4089
|
AckType
|
|
4457
4090
|
};
|
|
4458
4091
|
|
|
4459
|
-
//# debugId=
|
|
4092
|
+
//# debugId=658BAE3B57868EE064756E2164756E21
|
|
4460
4093
|
//# sourceMappingURL=index.js.map
|