@v5x/serial 0.5.1 → 0.5.3

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.
@@ -0,0 +1,4516 @@
1
+ /**
2
+ * V5 Serial Protocol v0.5.2
3
+ * Copyright 2022-2026 jerrylum <me@jerryio.com>
4
+ */
5
+
6
+ 'use strict';
7
+
8
+ Object.defineProperty(exports, '__esModule', { value: true });
9
+
10
+ var AllPackets = /*#__PURE__*/Object.freeze({
11
+ __proto__: null,
12
+ get PacketEncoder () { return PacketEncoder; },
13
+ get Packet () { return Packet; },
14
+ get DeviceBoundPacket () { return DeviceBoundPacket; },
15
+ get Query1H2DPacket () { return Query1H2DPacket; },
16
+ get SystemVersionH2DPacket () { return SystemVersionH2DPacket; },
17
+ get UpdateMatchModeH2DPacket () { return UpdateMatchModeH2DPacket; },
18
+ get GetMatchStatusH2DPacket () { return GetMatchStatusH2DPacket; },
19
+ get GetRadioModeH2DPacket () { return GetRadioModeH2DPacket; },
20
+ get FileControlH2DPacket () { return FileControlH2DPacket; },
21
+ get InitFileTransferH2DPacket () { return InitFileTransferH2DPacket; },
22
+ get ExitFileTransferH2DPacket () { return ExitFileTransferH2DPacket; },
23
+ get WriteFileH2DPacket () { return WriteFileH2DPacket; },
24
+ get ReadFileH2DPacket () { return ReadFileH2DPacket; },
25
+ get LinkFileH2DPacket () { return LinkFileH2DPacket; },
26
+ get GetDirectoryFileCountH2DPacket () { return GetDirectoryFileCountH2DPacket; },
27
+ get GetDirectoryEntryH2DPacket () { return GetDirectoryEntryH2DPacket; },
28
+ get LoadFileActionH2DPacket () { return LoadFileActionH2DPacket; },
29
+ get GetFileMetadataH2DPacket () { return GetFileMetadataH2DPacket; },
30
+ get SetFileMetadataH2DPacket () { return SetFileMetadataH2DPacket; },
31
+ get EraseFileH2DPacket () { return EraseFileH2DPacket; },
32
+ get GetProgramSlotInfoH2DPacket () { return GetProgramSlotInfoH2DPacket; },
33
+ get FileClearUpH2DPacket () { return FileClearUpH2DPacket; },
34
+ get FileFormatH2DPacket () { return FileFormatH2DPacket; },
35
+ get GetSystemFlagsH2DPacket () { return GetSystemFlagsH2DPacket; },
36
+ get GetDeviceStatusH2DPacket () { return GetDeviceStatusH2DPacket; },
37
+ get GetSystemStatusH2DPacket () { return GetSystemStatusH2DPacket; },
38
+ get GetFdtStatusH2DPacket () { return GetFdtStatusH2DPacket; },
39
+ get GetLogCountH2DPacket () { return GetLogCountH2DPacket; },
40
+ get ReadLogPageH2DPacket () { return ReadLogPageH2DPacket; },
41
+ get GetRadioStatusH2DPacket () { return GetRadioStatusH2DPacket; },
42
+ get GetUserDataH2DPacket () { return GetUserDataH2DPacket; },
43
+ get ScreenCaptureH2DPacket () { return ScreenCaptureH2DPacket; },
44
+ get SendDashTouchH2DPacket () { return SendDashTouchH2DPacket; },
45
+ get SelectDashH2DPacket () { return SelectDashH2DPacket; },
46
+ get EnableDashH2DPacket () { return EnableDashH2DPacket; },
47
+ get DisableDashH2DPacket () { return DisableDashH2DPacket; },
48
+ get ReadKeyValueH2DPacket () { return ReadKeyValueH2DPacket; },
49
+ get WriteKeyValueH2DPacket () { return WriteKeyValueH2DPacket; },
50
+ get GetSlot1to4InfoH2DPacket () { return GetSlot1to4InfoH2DPacket; },
51
+ get GetSlot5to8InfoH2DPacket () { return GetSlot5to8InfoH2DPacket; },
52
+ get FactoryStatusH2DPacket () { return FactoryStatusH2DPacket; },
53
+ get FactoryEnableH2DPacket () { return FactoryEnableH2DPacket; },
54
+ get HostBoundPacket () { return HostBoundPacket; },
55
+ get Query1ReplyD2HPacket () { return Query1ReplyD2HPacket; },
56
+ get SystemVersionReplyD2HPacket () { return SystemVersionReplyD2HPacket; },
57
+ get MatchModeReplyD2HPacket () { return MatchModeReplyD2HPacket; },
58
+ get MatchStatusReplyD2HPacket () { return MatchStatusReplyD2HPacket; },
59
+ get FileControlReplyD2HPacket () { return FileControlReplyD2HPacket; },
60
+ get InitFileTransferReplyD2HPacket () { return InitFileTransferReplyD2HPacket; },
61
+ get ExitFileTransferReplyD2HPacket () { return ExitFileTransferReplyD2HPacket; },
62
+ get WriteFileReplyD2HPacket () { return WriteFileReplyD2HPacket; },
63
+ get ReadFileReplyD2HPacket () { return ReadFileReplyD2HPacket; },
64
+ get LinkFileReplyD2HPacket () { return LinkFileReplyD2HPacket; },
65
+ get GetDirectoryFileCountReplyD2HPacket () { return GetDirectoryFileCountReplyD2HPacket; },
66
+ get GetDirectoryEntryReplyD2HPacket () { return GetDirectoryEntryReplyD2HPacket; },
67
+ get LoadFileActionReplyD2HPacket () { return LoadFileActionReplyD2HPacket; },
68
+ get GetFileMetadataReplyD2HPacket () { return GetFileMetadataReplyD2HPacket; },
69
+ get SetFileMetadataReplyD2HPacket () { return SetFileMetadataReplyD2HPacket; },
70
+ get EraseFileReplyD2HPacket () { return EraseFileReplyD2HPacket; },
71
+ get GetProgramSlotInfoReplyD2HPacket () { return GetProgramSlotInfoReplyD2HPacket; },
72
+ get FileClearUpReplyD2HPacket () { return FileClearUpReplyD2HPacket; },
73
+ get FileFormatReplyD2HPacket () { return FileFormatReplyD2HPacket; },
74
+ get GetSystemFlagsReplyD2HPacket () { return GetSystemFlagsReplyD2HPacket; },
75
+ get GetDeviceStatusReplyD2HPacket () { return GetDeviceStatusReplyD2HPacket; },
76
+ get GetSystemStatusReplyD2HPacket () { return GetSystemStatusReplyD2HPacket; },
77
+ get GetFdtStatusReplyD2HPacket () { return GetFdtStatusReplyD2HPacket; },
78
+ get GetLogCountReplyD2HPacket () { return GetLogCountReplyD2HPacket; },
79
+ get ReadLogPageReplyD2HPacket () { return ReadLogPageReplyD2HPacket; },
80
+ get GetRadioStatusReplyD2HPacket () { return GetRadioStatusReplyD2HPacket; },
81
+ get GetUserDataReplyD2HPacket () { return GetUserDataReplyD2HPacket; },
82
+ get ScreenCaptureReplyD2HPacket () { return ScreenCaptureReplyD2HPacket; },
83
+ get SendDashTouchReplyD2HPacket () { return SendDashTouchReplyD2HPacket; },
84
+ get SelectDashReplyD2HPacket () { return SelectDashReplyD2HPacket; },
85
+ get EnableDashReplyD2HPacket () { return EnableDashReplyD2HPacket; },
86
+ get DisableDashReplyD2HPacket () { return DisableDashReplyD2HPacket; },
87
+ get ReadKeyValueReplyD2HPacket () { return ReadKeyValueReplyD2HPacket; },
88
+ get WriteKeyValueReplyD2HPacket () { return WriteKeyValueReplyD2HPacket; },
89
+ get GetSlot1to4InfoReplyD2HPacket () { return GetSlot1to4InfoReplyD2HPacket; },
90
+ get GetSlot5to8InfoReplyD2HPacket () { return GetSlot5to8InfoReplyD2HPacket; },
91
+ get FactoryStatusReplyD2HPacket () { return FactoryStatusReplyD2HPacket; },
92
+ get FactoryEnableReplyD2HPacket () { return FactoryEnableReplyD2HPacket; }
93
+ });
94
+
95
+ const USER_PROG_CHUNK_SIZE = 4096; // chunk size
96
+ const USER_FLASH_START = 0x03000000; // start address of memory
97
+ const USER_FLASH_SYS_CODE_START = 0x03400000; // start address of system code
98
+ const USER_FLASH_USR_CODE_START = 0x03800000; // start address of user code
99
+ const USER_FLASH_END = 0x08000000; // end address of memory
100
+ const USER_FLASH_MAX_FILE_SIZE = 0x200000; // maximum file size for qspi
101
+ const USER_FLASH_START_B = 0x10200000; // special app flash start
102
+ const USER_FLASH_END_B = 0x10400000; // special app flash end
103
+ const USER_FLASH_START_C = 0x30200000; // special app flash start
104
+ const USER_FLASH_END_C = 0x31000000; // special app flash end
105
+ exports.FileVendor = void 0;
106
+ (function (FileVendor) {
107
+ // a.k.a vid
108
+ FileVendor[FileVendor["USER"] = 1] = "USER";
109
+ FileVendor[FileVendor["SYS"] = 15] = "SYS";
110
+ FileVendor[FileVendor["DEV1"] = 16] = "DEV1";
111
+ FileVendor[FileVendor["DEV2"] = 24] = "DEV2";
112
+ FileVendor[FileVendor["DEV3"] = 32] = "DEV3";
113
+ FileVendor[FileVendor["DEV4"] = 40] = "DEV4";
114
+ FileVendor[FileVendor["DEV5"] = 48] = "DEV5";
115
+ FileVendor[FileVendor["DEV6"] = 56] = "DEV6";
116
+ FileVendor[FileVendor["VEXVM"] = 64] = "VEXVM";
117
+ FileVendor[FileVendor["VEX"] = 240] = "VEX";
118
+ FileVendor[FileVendor["UNDEFINED"] = 241] = "UNDEFINED";
119
+ })(exports.FileVendor || (exports.FileVendor = {}));
120
+ exports.FileDownloadTarget = void 0;
121
+ (function (FileDownloadTarget) {
122
+ FileDownloadTarget[FileDownloadTarget["FILE_TARGET_DDR"] = 0] = "FILE_TARGET_DDR";
123
+ FileDownloadTarget[FileDownloadTarget["FILE_TARGET_QSPI"] = 1] = "FILE_TARGET_QSPI";
124
+ FileDownloadTarget[FileDownloadTarget["FILE_TARGET_CBUF"] = 2] = "FILE_TARGET_CBUF";
125
+ FileDownloadTarget[FileDownloadTarget["FILE_TARGET_VBUF"] = 3] = "FILE_TARGET_VBUF";
126
+ FileDownloadTarget[FileDownloadTarget["FILE_TARGET_DDRC"] = 4] = "FILE_TARGET_DDRC";
127
+ FileDownloadTarget[FileDownloadTarget["FILE_TARGET_DDRE"] = 5] = "FILE_TARGET_DDRE";
128
+ FileDownloadTarget[FileDownloadTarget["FILE_TARGET_FLASH"] = 6] = "FILE_TARGET_FLASH";
129
+ FileDownloadTarget[FileDownloadTarget["FILE_TARGET_RADIO"] = 7] = "FILE_TARGET_RADIO";
130
+ FileDownloadTarget[FileDownloadTarget["FILE_TARGET_A1"] = 13] = "FILE_TARGET_A1";
131
+ FileDownloadTarget[FileDownloadTarget["FILE_TARGET_B1"] = 14] = "FILE_TARGET_B1";
132
+ FileDownloadTarget[FileDownloadTarget["FILE_TARGET_B2"] = 15] = "FILE_TARGET_B2";
133
+ })(exports.FileDownloadTarget || (exports.FileDownloadTarget = {}));
134
+ exports.FileInitAction = void 0;
135
+ (function (FileInitAction) {
136
+ FileInitAction[FileInitAction["WRITE"] = 1] = "WRITE";
137
+ FileInitAction[FileInitAction["READ"] = 2] = "READ";
138
+ })(exports.FileInitAction || (exports.FileInitAction = {}));
139
+ exports.FileInitOption = void 0;
140
+ (function (FileInitOption) {
141
+ FileInitOption[FileInitOption["NONE"] = 0] = "NONE";
142
+ FileInitOption[FileInitOption["OVERWRITE"] = 1] = "OVERWRITE";
143
+ })(exports.FileInitOption || (exports.FileInitOption = {}));
144
+ exports.FileLoadAction = void 0;
145
+ (function (FileLoadAction) {
146
+ FileLoadAction[FileLoadAction["RUN"] = 0] = "RUN";
147
+ FileLoadAction[FileLoadAction["STOP"] = 128] = "STOP";
148
+ })(exports.FileLoadAction || (exports.FileLoadAction = {}));
149
+ exports.FileExitAction = void 0;
150
+ (function (FileExitAction) {
151
+ FileExitAction[FileExitAction["EXIT_NONE"] = 0] = "EXIT_NONE";
152
+ FileExitAction[FileExitAction["EXIT_RUN"] = 1] = "EXIT_RUN";
153
+ FileExitAction[FileExitAction["EXIT_HALT"] = 3] = "EXIT_HALT";
154
+ })(exports.FileExitAction || (exports.FileExitAction = {}));
155
+ exports.RadioChannelType = void 0;
156
+ (function (RadioChannelType) {
157
+ RadioChannelType[RadioChannelType["PIT"] = 0] = "PIT";
158
+ RadioChannelType[RadioChannelType["DOWNLOAD"] = 1] = "DOWNLOAD";
159
+ })(exports.RadioChannelType || (exports.RadioChannelType = {}));
160
+ exports.AckType = void 0;
161
+ (function (AckType) {
162
+ AckType[AckType["CDC2_ACK"] = 118] = "CDC2_ACK";
163
+ AckType[AckType["CDC2_NACK"] = 255] = "CDC2_NACK";
164
+ AckType[AckType["CDC2_NACK_PACKET_CRC"] = 206] = "CDC2_NACK_PACKET_CRC";
165
+ AckType[AckType["CDC2_NACK_CMD_LENGTH"] = 208] = "CDC2_NACK_CMD_LENGTH";
166
+ AckType[AckType["CDC2_NACK_SIZE"] = 209] = "CDC2_NACK_SIZE";
167
+ AckType[AckType["CDC2_NACK_CRC"] = 210] = "CDC2_NACK_CRC";
168
+ AckType[AckType["CDC2_NACK_FILE"] = 211] = "CDC2_NACK_FILE";
169
+ AckType[AckType["CDC2_NACK_INIT"] = 212] = "CDC2_NACK_INIT";
170
+ AckType[AckType["CDC2_NACK_FUNC"] = 213] = "CDC2_NACK_FUNC";
171
+ AckType[AckType["CDC2_NACK_ALIGN"] = 214] = "CDC2_NACK_ALIGN";
172
+ AckType[AckType["CDC2_NACK_ADDR"] = 215] = "CDC2_NACK_ADDR";
173
+ AckType[AckType["CDC2_NACK_INCOMPLETE"] = 216] = "CDC2_NACK_INCOMPLETE";
174
+ AckType[AckType["CDC2_NACK_DIR_INDEX"] = 217] = "CDC2_NACK_DIR_INDEX";
175
+ AckType[AckType["CDC2_NACK_MAX_USER_FILES"] = 218] = "CDC2_NACK_MAX_USER_FILES";
176
+ AckType[AckType["CDC2_NACK_FILE_EXISTS"] = 219] = "CDC2_NACK_FILE_EXISTS";
177
+ AckType[AckType["CDC2_NACK_FILE_SYS_FULL"] = 220] = "CDC2_NACK_FILE_SYS_FULL";
178
+ AckType[AckType["TIMEOUT"] = 256] = "TIMEOUT";
179
+ AckType[AckType["WRITE_ERROR"] = 257] = "WRITE_ERROR";
180
+ })(exports.AckType || (exports.AckType = {}));
181
+ exports.SmartDeviceType = void 0;
182
+ (function (SmartDeviceType) {
183
+ SmartDeviceType[SmartDeviceType["EMPTY"] = 0] = "EMPTY";
184
+ SmartDeviceType[SmartDeviceType["V5_POWER"] = 1] = "V5_POWER";
185
+ SmartDeviceType[SmartDeviceType["MOTOR"] = 2] = "MOTOR";
186
+ SmartDeviceType[SmartDeviceType["LED"] = 3] = "LED";
187
+ SmartDeviceType[SmartDeviceType["ABS_ENCODER_SENSOR"] = 4] = "ABS_ENCODER_SENSOR";
188
+ SmartDeviceType[SmartDeviceType["CR_MOTOR"] = 5] = "CR_MOTOR";
189
+ SmartDeviceType[SmartDeviceType["IMU_SENSOR"] = 6] = "IMU_SENSOR";
190
+ SmartDeviceType[SmartDeviceType["DISTANCE_SENSOR"] = 7] = "DISTANCE_SENSOR";
191
+ SmartDeviceType[SmartDeviceType["RADIO_SENSOR"] = 8] = "RADIO_SENSOR";
192
+ SmartDeviceType[SmartDeviceType["CONTROLLER"] = 9] = "CONTROLLER";
193
+ SmartDeviceType[SmartDeviceType["BRAIN"] = 10] = "BRAIN";
194
+ SmartDeviceType[SmartDeviceType["VISION_SENSOR"] = 11] = "VISION_SENSOR";
195
+ SmartDeviceType[SmartDeviceType["ADI"] = 12] = "ADI";
196
+ SmartDeviceType[SmartDeviceType["PARTNER_CONTROLLER"] = 13] = "PARTNER_CONTROLLER";
197
+ SmartDeviceType[SmartDeviceType["BATTERY"] = 14] = "BATTERY";
198
+ SmartDeviceType[SmartDeviceType["SOL"] = 15] = "SOL";
199
+ SmartDeviceType[SmartDeviceType["OPTICAL_SENSOR"] = 16] = "OPTICAL_SENSOR";
200
+ SmartDeviceType[SmartDeviceType["MAGNET"] = 17] = "MAGNET";
201
+ SmartDeviceType[SmartDeviceType["GPS_SENSOR"] = 20] = "GPS_SENSOR";
202
+ SmartDeviceType[SmartDeviceType["UNDEFINED_SENSOR"] = 255] = "UNDEFINED_SENSOR";
203
+ })(exports.SmartDeviceType || (exports.SmartDeviceType = {}));
204
+ exports.SerialDeviceType = void 0;
205
+ (function (SerialDeviceType) {
206
+ SerialDeviceType[SerialDeviceType["V5_BRAIN"] = 1281] = "V5_BRAIN";
207
+ SerialDeviceType[SerialDeviceType["V5_BRAIN_DFU"] = 1282] = "V5_BRAIN_DFU";
208
+ SerialDeviceType[SerialDeviceType["V5_CONTROLLER"] = 1283] = "V5_CONTROLLER";
209
+ SerialDeviceType[SerialDeviceType["XILINX"] = 256] = "XILINX";
210
+ SerialDeviceType[SerialDeviceType["IQ_BRAIN"] = 2] = "IQ_BRAIN";
211
+ SerialDeviceType[SerialDeviceType["IQ_BRAIN2"] = 3] = "IQ_BRAIN2";
212
+ SerialDeviceType[SerialDeviceType["IQ_BRAIN_DFU"] = 255] = "IQ_BRAIN_DFU";
213
+ SerialDeviceType[SerialDeviceType["IQ2_BRAIN"] = 512] = "IQ2_BRAIN";
214
+ SerialDeviceType[SerialDeviceType["IQ2_BRAIN_DFU"] = 527] = "IQ2_BRAIN_DFU";
215
+ SerialDeviceType[SerialDeviceType["IQ2_CONTROLLER"] = 528] = "IQ2_CONTROLLER";
216
+ SerialDeviceType[SerialDeviceType["IQ2_CONTROLLER_DFU"] = 543] = "IQ2_CONTROLLER_DFU";
217
+ SerialDeviceType[SerialDeviceType["EXP_BRAIN"] = 1536] = "EXP_BRAIN";
218
+ SerialDeviceType[SerialDeviceType["EXP_BRAIN_DFU"] = 1551] = "EXP_BRAIN_DFU";
219
+ SerialDeviceType[SerialDeviceType["EXP_CONTROLLER"] = 1552] = "EXP_CONTROLLER";
220
+ SerialDeviceType[SerialDeviceType["EXP_CONTROLLER_DFU"] = 1567] = "EXP_CONTROLLER_DFU";
221
+ SerialDeviceType[SerialDeviceType["PIXY"] = 61440] = "PIXY";
222
+ SerialDeviceType[SerialDeviceType["PIXY_DFU"] = 12] = "PIXY_DFU";
223
+ SerialDeviceType[SerialDeviceType["VEXCAM"] = 1287] = "VEXCAM";
224
+ SerialDeviceType[SerialDeviceType["VEXCAM_DFU"] = 1288] = "VEXCAM_DFU";
225
+ SerialDeviceType[SerialDeviceType["SENSOR_TEST"] = 1535] = "SENSOR_TEST";
226
+ SerialDeviceType[SerialDeviceType["CORTEX_PROGCBL"] = 10] = "CORTEX_PROGCBL";
227
+ SerialDeviceType[SerialDeviceType["CORTEX_BRAIN"] = 11] = "CORTEX_BRAIN";
228
+ // Jerry says this was copied from the official source code ¯\_(ツ)_/¯
229
+ // eslint-disable-next-line @typescript-eslint/no-duplicate-enum-values
230
+ SerialDeviceType[SerialDeviceType["CORTEX_JOYSTK"] = 12] = "CORTEX_JOYSTK";
231
+ SerialDeviceType[SerialDeviceType["VEXNET_KEY_20"] = 7] = "VEXNET_KEY_20";
232
+ SerialDeviceType[SerialDeviceType["VEXNET_KEY_10"] = 9587] = "VEXNET_KEY_10";
233
+ SerialDeviceType[SerialDeviceType["PROLIFIC"] = 8963] = "PROLIFIC";
234
+ })(exports.SerialDeviceType || (exports.SerialDeviceType = {}));
235
+ /**
236
+ * found from {@link https://gist.github.com/meisZWFLZ/9ebdd694060137b44959ff7ac80ff4e8 gist}
237
+ * @see {@link https://drive.google.com/drive/folders/11pSNKakbXp7hOYBQ3HNwprFaLalnXOgR screen images}
238
+ */
239
+ exports.SelectDashScreen = void 0;
240
+ (function (SelectDashScreen) {
241
+ SelectDashScreen[SelectDashScreen["HOME"] = 0] = "HOME";
242
+ SelectDashScreen[SelectDashScreen["BATTERY"] = 1] = "BATTERY";
243
+ SelectDashScreen[SelectDashScreen["LED"] = 3] = "LED";
244
+ SelectDashScreen[SelectDashScreen["MATCH_CONFIG"] = 4] = "MATCH_CONFIG";
245
+ SelectDashScreen[SelectDashScreen["MATCH_CONFIG_MORE"] = 5] = "MATCH_CONFIG_MORE";
246
+ SelectDashScreen[SelectDashScreen["WIRING"] = 6] = "WIRING";
247
+ SelectDashScreen[SelectDashScreen["RADIO"] = 8] = "RADIO";
248
+ SelectDashScreen[SelectDashScreen["BRAIN"] = 10] = "BRAIN";
249
+ SelectDashScreen[SelectDashScreen["RUN_PROGRAM"] = 13] = "RUN_PROGRAM";
250
+ SelectDashScreen[SelectDashScreen["DRIVE_PROGRAM_CONTROL_LEFT_MAPPING"] = 14] = "DRIVE_PROGRAM_CONTROL_LEFT_MAPPING";
251
+ SelectDashScreen[SelectDashScreen["DRIVE_PROGRAM_MENU"] = 15] = "DRIVE_PROGRAM_MENU";
252
+ SelectDashScreen[SelectDashScreen["DEVICES"] = 16] = "DEVICES";
253
+ SelectDashScreen[SelectDashScreen["USER_PROGRAM_FOLDER"] = 17] = "USER_PROGRAM_FOLDER";
254
+ SelectDashScreen[SelectDashScreen["VEX_PROGRAM_FOLDER"] = 18] = "VEX_PROGRAM_FOLDER";
255
+ SelectDashScreen[SelectDashScreen["SETTINGS"] = 19] = "SETTINGS";
256
+ /** theres some scary looking stuff in here */
257
+ SelectDashScreen[SelectDashScreen["SCARY_CONFIGURATION"] = 20] = "SCARY_CONFIGURATION";
258
+ SelectDashScreen[SelectDashScreen["LANGUAGE"] = 21] = "LANGUAGE";
259
+ SelectDashScreen[SelectDashScreen["DRIVE_MOTOR_CONFIG"] = 22] = "DRIVE_MOTOR_CONFIG";
260
+ SelectDashScreen[SelectDashScreen["PROGRAM_MENU"] = 24] = "PROGRAM_MENU";
261
+ SelectDashScreen[SelectDashScreen["SHUTDOWN"] = 25] = "SHUTDOWN";
262
+ SelectDashScreen[SelectDashScreen["CONTROLLER_2_MAPPING"] = 26] = "CONTROLLER_2_MAPPING";
263
+ /** theres some even more scary looking stuff in here */
264
+ SelectDashScreen[SelectDashScreen["SCARY_CONFIGURATION_MORE"] = 27] = "SCARY_CONFIGURATION_MORE";
265
+ /** maybe this is scarier.. */
266
+ SelectDashScreen[SelectDashScreen["CONFIRM_XX"] = 28] = "CONFIRM_XX";
267
+ SelectDashScreen[SelectDashScreen["CONTROLLER_1_MAPPING"] = 29] = "CONTROLLER_1_MAPPING";
268
+ SelectDashScreen[SelectDashScreen["DRIVE_PROGRAM_CONTROL_DUAL_MAPPING"] = 30] = "DRIVE_PROGRAM_CONTROL_DUAL_MAPPING";
269
+ SelectDashScreen[SelectDashScreen["DRIVE_PROGRAM_CONTROL_SPLIT_MAPPING"] = 31] = "DRIVE_PROGRAM_CONTROL_SPLIT_MAPPING";
270
+ SelectDashScreen[SelectDashScreen["DRIVE_PROGRAM_CONTROL_RIGHT_MAPPING"] = 32] = "DRIVE_PROGRAM_CONTROL_RIGHT_MAPPING";
271
+ /** thats such a bad name */
272
+ SelectDashScreen[SelectDashScreen["MATCH_2_4_PLAYERS"] = 33] = "MATCH_2_4_PLAYERS";
273
+ SelectDashScreen[SelectDashScreen["EVENT_LOG"] = 34] = "EVENT_LOG";
274
+ SelectDashScreen[SelectDashScreen["USER_PROGRAM_WIRING"] = 40] = "USER_PROGRAM_WIRING";
275
+ SelectDashScreen[SelectDashScreen["CLAWBOT_PROGRAM_MENU"] = 41] = "CLAWBOT_PROGRAM_MENU";
276
+ /** aka regulatory */
277
+ SelectDashScreen[SelectDashScreen["ABOUT"] = 42] = "ABOUT";
278
+ SelectDashScreen[SelectDashScreen["LANGUAGE_MORE"] = 43] = "LANGUAGE_MORE";
279
+ SelectDashScreen[SelectDashScreen["OBJECT_COLOR"] = 45] = "OBJECT_COLOR";
280
+ SelectDashScreen[SelectDashScreen["SIGNATURE_ID"] = 46] = "SIGNATURE_ID";
281
+ SelectDashScreen[SelectDashScreen["LOG_DATA"] = 47] = "LOG_DATA";
282
+ })(exports.SelectDashScreen || (exports.SelectDashScreen = {}));
283
+
284
+ /******************************************************************************
285
+ Copyright (c) Microsoft Corporation.
286
+
287
+ Permission to use, copy, modify, and/or distribute this software for any
288
+ purpose with or without fee is hereby granted.
289
+
290
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
291
+ REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
292
+ AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
293
+ INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
294
+ LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
295
+ OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
296
+ PERFORMANCE OF THIS SOFTWARE.
297
+ ***************************************************************************** */
298
+
299
+ function __awaiter(thisArg, _arguments, P, generator) {
300
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
301
+ return new (P || (P = Promise))(function (resolve, reject) {
302
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
303
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
304
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
305
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
306
+ });
307
+ }
308
+
309
+ typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
310
+ var e = new Error(message);
311
+ return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
312
+ };
313
+
314
+ class VexEventEmitter {
315
+ constructor() {
316
+ this.handlerMap = new Map();
317
+ }
318
+ on(eventName, listener) {
319
+ let listeners = this.handlerMap.get(eventName);
320
+ listeners !== null && listeners !== void 0 ? listeners : (listeners = []);
321
+ listeners.push(listener);
322
+ this.handlerMap.set(eventName, listeners);
323
+ }
324
+ remove(eventName, listener) {
325
+ let listeners = this.handlerMap.get(eventName);
326
+ listeners !== null && listeners !== void 0 ? listeners : (listeners = []);
327
+ const index = listeners.indexOf(listener);
328
+ if (index > -1) {
329
+ listeners.splice(index, 1);
330
+ }
331
+ this.handlerMap.set(eventName, listeners);
332
+ }
333
+ emit(eventName, data) {
334
+ var _a;
335
+ ((_a = this.handlerMap.get(eventName)) !== null && _a !== void 0 ? _a : []).forEach((callback) => {
336
+ callback(data);
337
+ });
338
+ }
339
+ clearListeners() {
340
+ this.handlerMap.clear();
341
+ }
342
+ }
343
+ class VexEventTarget {
344
+ constructor() {
345
+ this.emitter = new VexEventEmitter();
346
+ }
347
+ emit(eventName, data) {
348
+ this.emitter.emit(String(eventName), data);
349
+ }
350
+ on(eventName, listener) {
351
+ this.emitter.on(String(eventName), listener);
352
+ }
353
+ remove(eventName, listener) {
354
+ this.emitter.remove(String(eventName), listener);
355
+ }
356
+ clearListeners() {
357
+ this.emitter.clearListeners();
358
+ }
359
+ }
360
+
361
+ /**
362
+ * This is a class to make it easier to handle passing the VEXos version
363
+ * information around in the application. This provides ways to get any
364
+ * form of the string representation and quickly compare versions.
365
+ */
366
+ class VexFirmwareVersion {
367
+ constructor(major, minor, build, beta) {
368
+ this.major = major;
369
+ this.minor = minor;
370
+ this.build = build;
371
+ this.beta = beta;
372
+ }
373
+ /**
374
+ * Take a a string of MAJOR.MINOR.BUILD.bBETA and converts it to a
375
+ * VexFirmwareVersion instance
376
+ * @param version the string to process
377
+ * @returns a VexFirmwareVersion representing the provided string
378
+ */
379
+ static fromString(version) {
380
+ const parts = version
381
+ .toLowerCase()
382
+ .replace(/b/g, "")
383
+ .split(".")
384
+ .map((x) => parseInt(x, 10));
385
+ while (parts.length < 4) {
386
+ parts.push(0);
387
+ }
388
+ return new VexFirmwareVersion(parts[0], parts[1], parts[2], parts[3]);
389
+ }
390
+ /**
391
+ * Take a a Uint8Array and converts it to a VexFirmwareVersion instance
392
+ * @param data the array to process
393
+ * @param offset the offset to start at
394
+ * @returns a VexFirmwareVersion representing the provided string
395
+ */
396
+ static fromUint8Array(data, offset = 0, reverse = false) {
397
+ return new VexFirmwareVersion(data[offset + (reverse ? 3 : 0)], data[offset + (reverse ? 2 : 1)], data[offset + (reverse ? 1 : 2)], data[offset + (reverse ? 0 : 3)]);
398
+ }
399
+ static allZero() {
400
+ return new VexFirmwareVersion(0, 0, 0, 0);
401
+ }
402
+ /**
403
+ * Take a a string of MAJOR_MINOR_BUILD_BETA and converts it to a
404
+ * VexFirmwareVersion instance
405
+ * @param version the string to process
406
+ * @returns a VexFirmwareVersion representing the provided string
407
+ */
408
+ static fromCatalogString(version) {
409
+ return VexFirmwareVersion.fromString(version.replace(/_/g, "."));
410
+ }
411
+ isBeta() {
412
+ return this.beta !== 0;
413
+ }
414
+ /**
415
+ * returns version as Uint Array
416
+ */
417
+ toUint8Array(reverse = false) {
418
+ const data = new Uint8Array(4);
419
+ data[reverse ? 3 : 0] = this.major;
420
+ data[reverse ? 2 : 1] = this.minor;
421
+ data[reverse ? 1 : 2] = this.build;
422
+ data[reverse ? 0 : 3] = this.beta;
423
+ return data;
424
+ }
425
+ /**
426
+ * returns version as major.minor.build
427
+ */
428
+ toUserString() {
429
+ return `${this.major}.${this.minor}.${this.build}`;
430
+ }
431
+ /**
432
+ * returns version as ${major}.${minor}.{build}.b${beta}
433
+ */
434
+ toInternalString() {
435
+ return `${this.toUserString()}.b${this.beta}`;
436
+ }
437
+ /**
438
+ * compares this version to the provided version.
439
+ * * if this < b: negative
440
+ * * if this = b: 0
441
+ * * if this > b: positive
442
+ * @param that the version to compare again
443
+ */
444
+ compare(that) {
445
+ const majorComp = this.major - that.major;
446
+ const minorComp = this.minor - that.minor;
447
+ const buildComp = this.build - that.build;
448
+ const betaComp = this.beta - that.beta;
449
+ if (majorComp !== 0) {
450
+ return majorComp;
451
+ }
452
+ else if (minorComp !== 0) {
453
+ return minorComp;
454
+ }
455
+ else if (buildComp !== 0) {
456
+ return buildComp;
457
+ }
458
+ else if (betaComp !== 0) {
459
+ return betaComp;
460
+ }
461
+ return 0;
462
+ }
463
+ }
464
+
465
+ class PacketView extends DataView {
466
+ constructor(buffer, offset = 0, length = buffer.byteLength - offset) {
467
+ super(buffer, offset, length);
468
+ this.position = 0;
469
+ this.littleEndianDefault = true;
470
+ }
471
+ static fromPacket(packet) {
472
+ const view = new PacketView(packet.data.buffer, packet.data.byteOffset);
473
+ view.position = packet.ackIndex + 1;
474
+ return view;
475
+ }
476
+ nextInt8() {
477
+ const result = this.getInt8(this.position);
478
+ this.position += 1;
479
+ return result;
480
+ }
481
+ nextUint8() {
482
+ const result = this.getUint8(this.position);
483
+ this.position += 1;
484
+ return result;
485
+ }
486
+ nextInt16(littleEndian = this.littleEndianDefault) {
487
+ const result = this.getInt16(this.position, littleEndian);
488
+ this.position += 2;
489
+ return result;
490
+ }
491
+ nextUint16(littleEndian = this.littleEndianDefault) {
492
+ const result = this.getUint16(this.position, littleEndian);
493
+ this.position += 2;
494
+ return result;
495
+ }
496
+ nextInt32(littleEndian = this.littleEndianDefault) {
497
+ const result = this.getInt32(this.position, littleEndian);
498
+ this.position += 4;
499
+ return result;
500
+ }
501
+ nextUint32(littleEndian = this.littleEndianDefault) {
502
+ const result = this.getUint32(this.position, littleEndian);
503
+ this.position += 4;
504
+ return result;
505
+ }
506
+ nextString(length) {
507
+ let result = "";
508
+ for (let i = 0; i < length; i++) {
509
+ result += String.fromCharCode(this.nextUint8());
510
+ }
511
+ return result;
512
+ }
513
+ nextNTBS(length) {
514
+ // this length is different from the document
515
+ let result = "";
516
+ const lastPosition = this.position;
517
+ for (let i = 0; i < length; i++) {
518
+ if (this.byteLength <= this.position)
519
+ break;
520
+ const g = this.nextUint8();
521
+ if (g === 0)
522
+ break;
523
+ result += String.fromCharCode(g);
524
+ }
525
+ this.position = lastPosition + length;
526
+ return result;
527
+ }
528
+ nextVarNTBS(length) {
529
+ // this length is different from the document
530
+ let result = "";
531
+ for (let i = 0; i < length; i++) {
532
+ if (this.byteLength <= this.position)
533
+ break;
534
+ const g = this.nextUint8();
535
+ if (g === 0)
536
+ break;
537
+ result += String.fromCharCode(g);
538
+ }
539
+ return result;
540
+ }
541
+ nextVersion(reverse = false) {
542
+ const result = VexFirmwareVersion.fromUint8Array(new Uint8Array(this.buffer), this.position, reverse);
543
+ this.position += 4;
544
+ return result;
545
+ }
546
+ }
547
+
548
+ const CRC16TABLE = [
549
+ 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7, 0x8108,
550
+ 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef, 0x1231, 0x0210,
551
+ 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6, 0x9339, 0x8318, 0xb37b,
552
+ 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de, 0x2462, 0x3443, 0x0420, 0x1401,
553
+ 0x64e6, 0x74c7, 0x44a4, 0x5485, 0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee,
554
+ 0xf5cf, 0xc5ac, 0xd58d, 0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6,
555
+ 0x5695, 0x46b4, 0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d,
556
+ 0xc7bc, 0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823,
557
+ 0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b, 0x5af5,
558
+ 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12, 0xdbfd, 0xcbdc,
559
+ 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a, 0x6ca6, 0x7c87, 0x4ce4,
560
+ 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41, 0xedae, 0xfd8f, 0xcdec, 0xddcd,
561
+ 0xad2a, 0xbd0b, 0x8d68, 0x9d49, 0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13,
562
+ 0x2e32, 0x1e51, 0x0e70, 0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a,
563
+ 0x9f59, 0x8f78, 0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e,
564
+ 0xe16f, 0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067,
565
+ 0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e, 0x02b1,
566
+ 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256, 0xb5ea, 0xa5cb,
567
+ 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d, 0x34e2, 0x24c3, 0x14a0,
568
+ 0x0481, 0x7466, 0x6447, 0x5424, 0x4405, 0xa7db, 0xb7fa, 0x8799, 0x97b8,
569
+ 0xe75f, 0xf77e, 0xc71d, 0xd73c, 0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657,
570
+ 0x7676, 0x4615, 0x5634, 0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9,
571
+ 0xb98a, 0xa9ab, 0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882,
572
+ 0x28a3, 0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a,
573
+ 0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92, 0xfd2e,
574
+ 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9, 0x7c26, 0x6c07,
575
+ 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1, 0xef1f, 0xff3e, 0xcf5d,
576
+ 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8, 0x6e17, 0x7e36, 0x4e55, 0x5e74,
577
+ 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0,
578
+ ];
579
+ class CrcGenerator {
580
+ constructor() {
581
+ this.crc32Table = new Uint32Array(256);
582
+ this.crc32GenTable();
583
+ }
584
+ /**
585
+ * Calculate CRC16 for buffer
586
+ */
587
+ crc16(buf, initValue) {
588
+ const numberOfBytes = buf.byteLength;
589
+ let accumulator = initValue;
590
+ let i;
591
+ let j;
592
+ // now calculate CRC16
593
+ for (j = 0; j < numberOfBytes; j++) {
594
+ i = ((accumulator >>> 8) ^ buf[j]) & 0xff;
595
+ accumulator = ((accumulator << 8) ^ CRC16TABLE[i]) >>> 0;
596
+ }
597
+ return (accumulator & 0xffff) >>> 0;
598
+ }
599
+ /**
600
+ * Generate CRC32 reverse table
601
+ */
602
+ crc32GenTable() {
603
+ let i;
604
+ let j;
605
+ let crcAccumulator;
606
+ for (i = 0; i < 256; i++) {
607
+ crcAccumulator = i << 24;
608
+ for (j = 0; j < 8; j++) {
609
+ if ((crcAccumulator & 0x80000000) !== 0)
610
+ crcAccumulator =
611
+ (crcAccumulator << 1) ^ CrcGenerator.POLYNOMIAL_CRC32;
612
+ else
613
+ crcAccumulator = crcAccumulator << 1;
614
+ }
615
+ this.crc32Table[i] = crcAccumulator;
616
+ }
617
+ }
618
+ /**
619
+ * Calculate CRC32 for buffer
620
+ */
621
+ crc32(buf, initValue) {
622
+ const numberOfBytes = buf.byteLength;
623
+ let crcAccumulator = initValue;
624
+ let i;
625
+ let j;
626
+ // now calculate CRC32
627
+ for (j = 0; j < numberOfBytes; j++) {
628
+ i = ((crcAccumulator >>> 24) ^ buf[j]) & 0xff;
629
+ crcAccumulator = ((crcAccumulator << 8) ^ this.crc32Table[i]) >>> 0;
630
+ }
631
+ return (crcAccumulator & 0xffffffff) >>> 0;
632
+ }
633
+ }
634
+ CrcGenerator.POLYNOMIAL_CRC32 = 79764919;
635
+ CrcGenerator.POLYNOMIAL_CRC16 = 4129;
636
+
637
+ class PacketEncoder {
638
+ static getInstance() {
639
+ if (Packet.ENCODER === undefined) {
640
+ Packet.ENCODER = new PacketEncoder();
641
+ }
642
+ return Packet.ENCODER;
643
+ }
644
+ constructor() {
645
+ this.allPacketsTable = {};
646
+ this.vexVersion = 0;
647
+ this.crcgen = new CrcGenerator();
648
+ Object.values(AllPackets).forEach((packet) => {
649
+ if (packet.prototype instanceof HostBoundPacket) {
650
+ this.allPacketsTable[
651
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
652
+ packet.COMMAND_ID + " " + packet.COMMAND_EXTENDED_ID] = packet;
653
+ }
654
+ });
655
+ }
656
+ /**
657
+ * Create the vex CDC header
658
+ * @param buf the bytes to send
659
+ */
660
+ createHeader(buf) {
661
+ // create a buffer if is is not defined
662
+ if (buf === undefined || buf.byteLength < PacketEncoder.HEADERS_LENGTH) {
663
+ buf = new ArrayBuffer(PacketEncoder.HEADERS_LENGTH);
664
+ }
665
+ const h = new Uint8Array(buf);
666
+ h.set(PacketEncoder.HEADER_TO_DEVICE);
667
+ return h;
668
+ }
669
+ /**
670
+ * Create the vex CDC simple message
671
+ * @param cmd the CDC command byte
672
+ */
673
+ cdcCommand(cmd) {
674
+ const buf = new ArrayBuffer(PacketEncoder.HEADERS_LENGTH + 1);
675
+ const h = this.createHeader(buf);
676
+ h.set([cmd], PacketEncoder.HEADERS_LENGTH);
677
+ return h;
678
+ }
679
+ /**
680
+ * Create the vex CDC simple message
681
+ * @param cmd the CDC command byte
682
+ * @param data the data to send
683
+ */
684
+ cdcCommandWithData(cmd, data) {
685
+ const buf = new ArrayBuffer(PacketEncoder.HEADERS_LENGTH + 2 + data.length);
686
+ const h = this.createHeader(buf);
687
+ // add command and length bytes
688
+ h.set([cmd, data.length], PacketEncoder.HEADERS_LENGTH);
689
+ // add the message data
690
+ h.set(data, PacketEncoder.HEADERS_LENGTH + 2);
691
+ return h;
692
+ }
693
+ /**
694
+ * Create the vex CDC extended message
695
+ * @param cmd the CDC command byte
696
+ * @param ext the CDC extended command byte
697
+ * @return a message
698
+ */
699
+ cdc2Command(cmd, ext) {
700
+ const buf = new ArrayBuffer(PacketEncoder.HEADERS_LENGTH + 5);
701
+ const h = this.createHeader(buf);
702
+ h.set([cmd, ext, 0], PacketEncoder.HEADERS_LENGTH);
703
+ // Add CRC
704
+ const crc = this.crcgen.crc16(h.subarray(0, buf.byteLength - 2), 0) >>> 0;
705
+ h.set([crc >>> 8, crc & 0xff], buf.byteLength - 2);
706
+ return h;
707
+ }
708
+ /**
709
+ * Calculate buffer length for new CDC extended command
710
+ * @param data the CDC extended command payload
711
+ * @returns the required buffer length of the command message
712
+ */
713
+ cdc2CommandBufferLength(data) {
714
+ // New command use header + 1 byte command
715
+ // + 1 byte function
716
+ // + 1 byte data length
717
+ let length = PacketEncoder.HEADERS_LENGTH + data.length + 3 + 2;
718
+ // If data length is > 127 bytes then an additional data length byte is added
719
+ if (data.length > 127)
720
+ length += 1;
721
+ return length;
722
+ }
723
+ /**
724
+ * Create the vex CDC extended message with some data
725
+ * @param cmd the CDC command byte
726
+ * @param ext the CDC extended command byte
727
+ * @param data the CDC extended command payload
728
+ * @return a message
729
+ */
730
+ cdc2CommandWithData(cmd, ext, data) {
731
+ const buf = new ArrayBuffer(this.cdc2CommandBufferLength(data));
732
+ const h = this.createHeader(buf);
733
+ // add command and length bytes
734
+ if (data.length < 128) {
735
+ h.set([cmd, ext, data.length], PacketEncoder.HEADERS_LENGTH);
736
+ // add the message data
737
+ h.set(data, PacketEncoder.HEADERS_LENGTH + 3);
738
+ }
739
+ else {
740
+ const lengthMsb = ((data.length >>> 8) | 0x80) >>> 0;
741
+ const lengthLsb = (data.length & 0xff) >>> 0;
742
+ h.set([cmd, ext, lengthMsb, lengthLsb], PacketEncoder.HEADERS_LENGTH);
743
+ // add the message data
744
+ h.set(data, PacketEncoder.HEADERS_LENGTH + 4);
745
+ }
746
+ // Add CRC (little endian)
747
+ const crc = this.crcgen.crc16(h.subarray(0, buf.byteLength - 2), 0);
748
+ h.set([crc >>> 8, crc & 0xff], buf.byteLength - 2);
749
+ return h;
750
+ }
751
+ validateHeader(data) {
752
+ return !(data[0] !== PacketEncoder.HEADER_TO_HOST[0] ||
753
+ data[1] !== PacketEncoder.HEADER_TO_HOST[1]);
754
+ }
755
+ validateMessageCdc(data) {
756
+ const message = data.subarray(0, data.byteLength - 2);
757
+ const lastTwoBytes = (data[data.byteLength - 2] << 8) + data[data.byteLength - 1];
758
+ return this.crcgen.crc16(message, 0) === lastTwoBytes;
759
+ }
760
+ getPayloadSize(data) {
761
+ let t = 0;
762
+ let a = data[3];
763
+ if ((128 & a) !== 0) {
764
+ t = 127 & a;
765
+ a = data[4];
766
+ }
767
+ return (t << 8) + a;
768
+ }
769
+ }
770
+ PacketEncoder.HEADERS_LENGTH = 4;
771
+ PacketEncoder.HEADER_TO_DEVICE = [201, 54, 184, 71];
772
+ PacketEncoder.HEADER_TO_HOST = [170, 85];
773
+ PacketEncoder.J2000_EPOCH = 946684800;
774
+ class Packet {
775
+ constructor(rawData) {
776
+ this.data =
777
+ rawData instanceof ArrayBuffer ? new Uint8Array(rawData) : rawData;
778
+ }
779
+ }
780
+ class DeviceBoundPacket extends Packet {
781
+ constructor(payload) {
782
+ super(new Uint8Array());
783
+ // eslint-disable-next-line no-proto, @typescript-eslint/no-explicit-any
784
+ const me = this.__proto__.constructor;
785
+ if (me.COMMAND_EXTENDED_ID === undefined) {
786
+ if (payload === undefined) {
787
+ this.data = Packet.ENCODER.cdcCommand(me.COMMAND_ID);
788
+ }
789
+ else {
790
+ this.data = Packet.ENCODER.cdcCommandWithData(me.COMMAND_ID, payload);
791
+ }
792
+ }
793
+ else {
794
+ if (payload === undefined) {
795
+ this.data = Packet.ENCODER.cdc2Command(me.COMMAND_ID, me.COMMAND_EXTENDED_ID);
796
+ }
797
+ else {
798
+ this.data = Packet.ENCODER.cdc2CommandWithData(me.COMMAND_ID, me.COMMAND_EXTENDED_ID, payload);
799
+ }
800
+ }
801
+ }
802
+ }
803
+ class Query1H2DPacket extends DeviceBoundPacket {
804
+ constructor() {
805
+ super(undefined);
806
+ }
807
+ }
808
+ Query1H2DPacket.COMMAND_ID = 33;
809
+ Query1H2DPacket.COMMAND_EXTENDED_ID = undefined;
810
+ class SystemVersionH2DPacket extends DeviceBoundPacket {
811
+ constructor() {
812
+ super(undefined);
813
+ }
814
+ }
815
+ SystemVersionH2DPacket.COMMAND_ID = 164;
816
+ SystemVersionH2DPacket.COMMAND_EXTENDED_ID = undefined;
817
+ class UpdateMatchModeH2DPacket extends DeviceBoundPacket {
818
+ constructor(mode, matchClock) {
819
+ let bit1;
820
+ switch (mode) {
821
+ case "autonomous":
822
+ bit1 = 10;
823
+ break;
824
+ case "driver":
825
+ bit1 = 8;
826
+ break;
827
+ case "disabled":
828
+ bit1 = 11;
829
+ }
830
+ const payload = new Uint8Array(5);
831
+ const view = new DataView(payload.buffer);
832
+ payload[0] = (15 & bit1) >>> 0;
833
+ view.setUint32(1, matchClock, true);
834
+ super(payload);
835
+ }
836
+ }
837
+ UpdateMatchModeH2DPacket.COMMAND_ID = 88;
838
+ UpdateMatchModeH2DPacket.COMMAND_EXTENDED_ID = 193;
839
+ class GetMatchStatusH2DPacket extends DeviceBoundPacket {
840
+ constructor() {
841
+ super(undefined);
842
+ }
843
+ }
844
+ GetMatchStatusH2DPacket.COMMAND_ID = 88;
845
+ GetMatchStatusH2DPacket.COMMAND_EXTENDED_ID = 194;
846
+ class GetRadioModeH2DPacket extends DeviceBoundPacket {
847
+ constructor(mode) {
848
+ const payload = new Uint8Array(1);
849
+ payload[0] = mode;
850
+ super(payload);
851
+ }
852
+ }
853
+ GetRadioModeH2DPacket.COMMAND_ID = 88;
854
+ GetRadioModeH2DPacket.COMMAND_EXTENDED_ID = 65;
855
+ class FileControlH2DPacket extends DeviceBoundPacket {
856
+ constructor(a, b) {
857
+ const payload = new Uint8Array(2);
858
+ payload.set([a, b], 0);
859
+ super(payload);
860
+ }
861
+ }
862
+ FileControlH2DPacket.COMMAND_ID = 86;
863
+ FileControlH2DPacket.COMMAND_EXTENDED_ID = 16;
864
+ class InitFileTransferH2DPacket extends DeviceBoundPacket {
865
+ constructor(operation, target, vendor, options, binary, addr, name, type, version = new VexFirmwareVersion(1, 0, 0, 0)) {
866
+ const payload = new Uint8Array(52);
867
+ const view = new DataView(payload.buffer);
868
+ view.setUint8(0, operation);
869
+ view.setUint8(1, target);
870
+ view.setUint8(2, vendor);
871
+ view.setUint8(3, options);
872
+ view.setUint32(4, binary.length, true);
873
+ view.setUint32(8, addr, true);
874
+ view.setUint32(12, operation === exports.FileInitAction.WRITE
875
+ ? Packet.ENCODER.crcgen.crc32(binary, 0)
876
+ : 0, true);
877
+ const re = /(?:\.([^.]+))?$/;
878
+ const reResult = re.exec(name);
879
+ let ext = reResult != null ? reResult[1] : undefined;
880
+ ext !== null && ext !== void 0 ? ext : (ext = "");
881
+ // files with gz extension are also type bin
882
+ ext = ext === "gz" ? "bin" : ext;
883
+ payload.set(new TextEncoder().encode(type !== null && type !== void 0 ? type : ext), 16);
884
+ const timestamp = ((Date.now() / 1000) >>> 0) - PacketEncoder.J2000_EPOCH;
885
+ view.setUint32(20, timestamp, true);
886
+ payload.set(version.toUint8Array(), 24);
887
+ // filename
888
+ const nameEncoded = new TextEncoder().encode(name);
889
+ let offset = nameEncoded.length - 23;
890
+ if (offset < 0)
891
+ offset = 0;
892
+ payload.set(nameEncoded.subarray(offset, offset + 23), 28);
893
+ view.setUint8(51, 0);
894
+ super(payload);
895
+ }
896
+ }
897
+ InitFileTransferH2DPacket.COMMAND_ID = 86;
898
+ InitFileTransferH2DPacket.COMMAND_EXTENDED_ID = 17;
899
+ class ExitFileTransferH2DPacket extends DeviceBoundPacket {
900
+ constructor(action) {
901
+ const payload = new Uint8Array(1);
902
+ payload[0] = action;
903
+ super(payload);
904
+ }
905
+ }
906
+ ExitFileTransferH2DPacket.COMMAND_ID = 86;
907
+ ExitFileTransferH2DPacket.COMMAND_EXTENDED_ID = 18;
908
+ class WriteFileH2DPacket extends DeviceBoundPacket {
909
+ constructor(addr, buf) {
910
+ const payload = new Uint8Array(4 + buf.length);
911
+ const view = new DataView(payload.buffer);
912
+ view.setUint32(0, addr, true);
913
+ payload.set(buf, 4);
914
+ super(payload);
915
+ }
916
+ }
917
+ WriteFileH2DPacket.COMMAND_ID = 86;
918
+ WriteFileH2DPacket.COMMAND_EXTENDED_ID = 19;
919
+ class ReadFileH2DPacket extends DeviceBoundPacket {
920
+ constructor(addr, size) {
921
+ const payload = new Uint8Array(6);
922
+ const view = new DataView(payload.buffer);
923
+ view.setUint32(0, addr, true);
924
+ view.setUint16(4, size, true);
925
+ super(payload);
926
+ }
927
+ }
928
+ ReadFileH2DPacket.COMMAND_ID = 86;
929
+ ReadFileH2DPacket.COMMAND_EXTENDED_ID = 20;
930
+ class LinkFileH2DPacket extends DeviceBoundPacket {
931
+ constructor(vendor, fileName, options) {
932
+ const str = new TextEncoder().encode(fileName);
933
+ const payload = new Uint8Array(26);
934
+ payload.set([vendor, options], 0);
935
+ payload.set(str.subarray(0, 23), 2);
936
+ super(payload);
937
+ }
938
+ }
939
+ LinkFileH2DPacket.COMMAND_ID = 86;
940
+ LinkFileH2DPacket.COMMAND_EXTENDED_ID = 21;
941
+ class GetDirectoryFileCountH2DPacket extends DeviceBoundPacket {
942
+ constructor(vendor) {
943
+ const payload = new Uint8Array(2);
944
+ payload.set([vendor, 0], 0);
945
+ super(payload);
946
+ }
947
+ }
948
+ GetDirectoryFileCountH2DPacket.COMMAND_ID = 86;
949
+ GetDirectoryFileCountH2DPacket.COMMAND_EXTENDED_ID = 22;
950
+ class GetDirectoryEntryH2DPacket extends DeviceBoundPacket {
951
+ constructor(index) {
952
+ const payload = new Uint8Array(2);
953
+ payload.set([index, 0], 0);
954
+ super(payload);
955
+ }
956
+ }
957
+ GetDirectoryEntryH2DPacket.COMMAND_ID = 86;
958
+ GetDirectoryEntryH2DPacket.COMMAND_EXTENDED_ID = 23;
959
+ class LoadFileActionH2DPacket extends DeviceBoundPacket {
960
+ constructor(vendor, actionId, fileNameOrSlotNumber) {
961
+ let fileName;
962
+ if (typeof fileNameOrSlotNumber === "string") {
963
+ fileName = fileNameOrSlotNumber;
964
+ }
965
+ else {
966
+ fileName = "___s_" + (fileNameOrSlotNumber - 1) + ".bin";
967
+ }
968
+ const encodedName = new TextEncoder().encode(fileName);
969
+ const payload = new Uint8Array(26);
970
+ payload.set([vendor, actionId], 0);
971
+ payload.set(encodedName.subarray(0, 23), 2);
972
+ super(payload);
973
+ }
974
+ }
975
+ LoadFileActionH2DPacket.COMMAND_ID = 86;
976
+ LoadFileActionH2DPacket.COMMAND_EXTENDED_ID = 24;
977
+ class GetFileMetadataH2DPacket extends DeviceBoundPacket {
978
+ constructor(vendor, fileName, options) {
979
+ const encodedName = new TextEncoder().encode(fileName);
980
+ const payload = new Uint8Array(26);
981
+ payload.set([vendor, options], 0);
982
+ payload.set(encodedName.subarray(0, 23), 2);
983
+ super(payload);
984
+ }
985
+ }
986
+ GetFileMetadataH2DPacket.COMMAND_ID = 86;
987
+ GetFileMetadataH2DPacket.COMMAND_EXTENDED_ID = 25;
988
+ class SetFileMetadataH2DPacket extends DeviceBoundPacket {
989
+ constructor(vendor, fileName, fileInfo, options) {
990
+ const encodedName = new TextEncoder().encode(fileName);
991
+ const encodedType = new TextEncoder().encode(fileInfo.type);
992
+ const payload = new Uint8Array(42);
993
+ const view = new DataView(payload.buffer);
994
+ view.setUint8(0, vendor);
995
+ view.setUint8(1, options);
996
+ view.setUint32(2, fileInfo.loadAddress, true);
997
+ payload.set(encodedType.subarray(0, 4), 6);
998
+ const timestamp = fileInfo.timestamp - PacketEncoder.J2000_EPOCH + 100; // XXX: + 100 TEST ONLY
999
+ view.setUint32(10, timestamp, true);
1000
+ payload.set(fileInfo.version.toUint8Array(), 14);
1001
+ payload.set(encodedName.subarray(0, 23), 18);
1002
+ super(payload);
1003
+ }
1004
+ }
1005
+ // DOES NOT WORK
1006
+ SetFileMetadataH2DPacket.COMMAND_ID = 86;
1007
+ SetFileMetadataH2DPacket.COMMAND_EXTENDED_ID = 26;
1008
+ class EraseFileH2DPacket extends DeviceBoundPacket {
1009
+ constructor(vendor, fileName) {
1010
+ const encodedName = new TextEncoder().encode(fileName);
1011
+ const payload = new Uint8Array(26);
1012
+ payload.set([vendor, 128], 0);
1013
+ payload.set(encodedName.subarray(0, 23), 2);
1014
+ super(payload);
1015
+ }
1016
+ }
1017
+ EraseFileH2DPacket.COMMAND_ID = 86;
1018
+ EraseFileH2DPacket.COMMAND_EXTENDED_ID = 27;
1019
+ class GetProgramSlotInfoH2DPacket extends DeviceBoundPacket {
1020
+ constructor(vendor, fileName) {
1021
+ const encodedName = new TextEncoder().encode(fileName);
1022
+ const payload = new Uint8Array(26);
1023
+ payload.set([vendor, 0], 0);
1024
+ payload.set(encodedName.subarray(0, 23), 2);
1025
+ super(payload);
1026
+ }
1027
+ }
1028
+ GetProgramSlotInfoH2DPacket.COMMAND_ID = 86;
1029
+ GetProgramSlotInfoH2DPacket.COMMAND_EXTENDED_ID = 28;
1030
+ class FileClearUpH2DPacket extends DeviceBoundPacket {
1031
+ constructor(vendor) {
1032
+ const payload = new Uint8Array(2);
1033
+ payload.set([vendor, 0], 0);
1034
+ super(payload);
1035
+ }
1036
+ }
1037
+ FileClearUpH2DPacket.COMMAND_ID = 86;
1038
+ FileClearUpH2DPacket.COMMAND_EXTENDED_ID = 30;
1039
+ class FileFormatH2DPacket extends DeviceBoundPacket {
1040
+ constructor() {
1041
+ const payload = new Uint8Array(4);
1042
+ payload.set([68, 67, 66, 65], 0);
1043
+ super(payload);
1044
+ }
1045
+ }
1046
+ FileFormatH2DPacket.COMMAND_ID = 86;
1047
+ FileFormatH2DPacket.COMMAND_EXTENDED_ID = 31;
1048
+ class GetSystemFlagsH2DPacket extends DeviceBoundPacket {
1049
+ }
1050
+ GetSystemFlagsH2DPacket.COMMAND_ID = 86;
1051
+ GetSystemFlagsH2DPacket.COMMAND_EXTENDED_ID = 32;
1052
+ class GetDeviceStatusH2DPacket extends DeviceBoundPacket {
1053
+ constructor() {
1054
+ super(undefined);
1055
+ }
1056
+ }
1057
+ GetDeviceStatusH2DPacket.COMMAND_ID = 86;
1058
+ GetDeviceStatusH2DPacket.COMMAND_EXTENDED_ID = 33;
1059
+ class GetSystemStatusH2DPacket extends DeviceBoundPacket {
1060
+ constructor() {
1061
+ super(undefined);
1062
+ }
1063
+ }
1064
+ GetSystemStatusH2DPacket.COMMAND_ID = 86;
1065
+ GetSystemStatusH2DPacket.COMMAND_EXTENDED_ID = 34;
1066
+ class GetFdtStatusH2DPacket extends DeviceBoundPacket {
1067
+ constructor() {
1068
+ super(undefined);
1069
+ }
1070
+ }
1071
+ GetFdtStatusH2DPacket.COMMAND_ID = 86;
1072
+ GetFdtStatusH2DPacket.COMMAND_EXTENDED_ID = 35;
1073
+ class GetLogCountH2DPacket extends DeviceBoundPacket {
1074
+ constructor() {
1075
+ super(undefined);
1076
+ }
1077
+ }
1078
+ GetLogCountH2DPacket.COMMAND_ID = 86;
1079
+ GetLogCountH2DPacket.COMMAND_EXTENDED_ID = 36;
1080
+ class ReadLogPageH2DPacket extends DeviceBoundPacket {
1081
+ constructor(offset, count) {
1082
+ const payload = new Uint8Array(8);
1083
+ const view = new DataView(payload.buffer);
1084
+ view.setUint32(0, offset, true);
1085
+ view.setUint32(4, count, true);
1086
+ super(payload);
1087
+ }
1088
+ }
1089
+ ReadLogPageH2DPacket.COMMAND_ID = 86;
1090
+ ReadLogPageH2DPacket.COMMAND_EXTENDED_ID = 37;
1091
+ class GetRadioStatusH2DPacket extends DeviceBoundPacket {
1092
+ constructor() {
1093
+ super(undefined);
1094
+ }
1095
+ }
1096
+ GetRadioStatusH2DPacket.COMMAND_ID = 86;
1097
+ GetRadioStatusH2DPacket.COMMAND_EXTENDED_ID = 38;
1098
+ class GetUserDataH2DPacket extends DeviceBoundPacket {
1099
+ constructor(e) {
1100
+ var _a;
1101
+ const input = (_a = e === null || e === void 0 ? void 0 : e.slice(0, 224)) !== null && _a !== void 0 ? _a : new Uint8Array(0);
1102
+ const payload = new Uint8Array(2 + input.length);
1103
+ payload[0] = 1; // stdio channel
1104
+ payload[1] = input.length;
1105
+ payload.set(input, 2);
1106
+ super(payload);
1107
+ }
1108
+ }
1109
+ // UNCONFIRMED
1110
+ GetUserDataH2DPacket.COMMAND_ID = 86;
1111
+ GetUserDataH2DPacket.COMMAND_EXTENDED_ID = 39;
1112
+ class ScreenCaptureH2DPacket extends DeviceBoundPacket {
1113
+ constructor(e) {
1114
+ const payload = new Uint8Array(1);
1115
+ payload[0] = e;
1116
+ super(payload);
1117
+ }
1118
+ }
1119
+ ScreenCaptureH2DPacket.COMMAND_ID = 86;
1120
+ ScreenCaptureH2DPacket.COMMAND_EXTENDED_ID = 40;
1121
+ class SendDashTouchH2DPacket extends DeviceBoundPacket {
1122
+ constructor(x, y, press) {
1123
+ const payload = new Uint8Array(6);
1124
+ const view = new DataView(payload.buffer);
1125
+ view.setUint16(0, x, true);
1126
+ view.setUint16(2, y, true);
1127
+ view.setUint16(4, press ? 1 : 0, true);
1128
+ super(payload);
1129
+ }
1130
+ }
1131
+ SendDashTouchH2DPacket.COMMAND_ID = 86;
1132
+ SendDashTouchH2DPacket.COMMAND_EXTENDED_ID = 42;
1133
+ class SelectDashH2DPacket extends DeviceBoundPacket {
1134
+ /** @param port untested */
1135
+ constructor(screen, port) {
1136
+ const payload = new Uint8Array(2);
1137
+ payload[0] = screen;
1138
+ payload[1] = port;
1139
+ super(payload);
1140
+ }
1141
+ }
1142
+ // UNSURE
1143
+ SelectDashH2DPacket.COMMAND_ID = 86;
1144
+ SelectDashH2DPacket.COMMAND_EXTENDED_ID = 43;
1145
+ class EnableDashH2DPacket extends DeviceBoundPacket {
1146
+ constructor(unknown1) {
1147
+ if (unknown1 === undefined) {
1148
+ super(undefined);
1149
+ }
1150
+ else {
1151
+ const payload = new Uint8Array(1);
1152
+ payload[0] = unknown1;
1153
+ super(payload);
1154
+ }
1155
+ }
1156
+ }
1157
+ // UNSURE
1158
+ EnableDashH2DPacket.COMMAND_ID = 86;
1159
+ EnableDashH2DPacket.COMMAND_EXTENDED_ID = 44;
1160
+ class DisableDashH2DPacket extends DeviceBoundPacket {
1161
+ constructor() {
1162
+ super(undefined);
1163
+ }
1164
+ }
1165
+ // UNSURE
1166
+ DisableDashH2DPacket.COMMAND_ID = 86;
1167
+ DisableDashH2DPacket.COMMAND_EXTENDED_ID = 45;
1168
+ class ReadKeyValueH2DPacket extends DeviceBoundPacket {
1169
+ constructor(key) {
1170
+ const payload = new Uint8Array(32);
1171
+ payload.set(new TextEncoder().encode(key), 0);
1172
+ super(payload);
1173
+ }
1174
+ }
1175
+ // UNSURE
1176
+ ReadKeyValueH2DPacket.COMMAND_ID = 86;
1177
+ ReadKeyValueH2DPacket.COMMAND_EXTENDED_ID = 46;
1178
+ class WriteKeyValueH2DPacket extends DeviceBoundPacket {
1179
+ constructor(key, value) {
1180
+ let strk = new TextEncoder().encode(key);
1181
+ const strv = new TextEncoder().encode(value);
1182
+ if (strk.byteLength > 31)
1183
+ strk = strk.subarray(0, 31);
1184
+ const payload = new Uint8Array(strk.length + strv.length + 20);
1185
+ payload.set(strk, 0);
1186
+ payload.set(strv, strk.length + 1);
1187
+ super(payload);
1188
+ }
1189
+ }
1190
+ // UNSURE
1191
+ WriteKeyValueH2DPacket.COMMAND_ID = 86;
1192
+ WriteKeyValueH2DPacket.COMMAND_EXTENDED_ID = 47;
1193
+ class GetSlot1to4InfoH2DPacket extends DeviceBoundPacket {
1194
+ constructor() {
1195
+ super(undefined);
1196
+ }
1197
+ }
1198
+ GetSlot1to4InfoH2DPacket.COMMAND_ID = 86;
1199
+ GetSlot1to4InfoH2DPacket.COMMAND_EXTENDED_ID = 49;
1200
+ class GetSlot5to8InfoH2DPacket extends DeviceBoundPacket {
1201
+ constructor() {
1202
+ super(undefined);
1203
+ }
1204
+ }
1205
+ GetSlot5to8InfoH2DPacket.COMMAND_ID = 86;
1206
+ GetSlot5to8InfoH2DPacket.COMMAND_EXTENDED_ID = 50;
1207
+ class FactoryStatusH2DPacket extends DeviceBoundPacket {
1208
+ }
1209
+ FactoryStatusH2DPacket.COMMAND_ID = 86;
1210
+ FactoryStatusH2DPacket.COMMAND_EXTENDED_ID = 241;
1211
+ class FactoryEnableH2DPacket extends DeviceBoundPacket {
1212
+ constructor() {
1213
+ const payload = new Uint8Array(4);
1214
+ payload.set([77, 76, 75, 74], 0);
1215
+ super(payload);
1216
+ }
1217
+ }
1218
+ FactoryEnableH2DPacket.COMMAND_ID = 86;
1219
+ FactoryEnableH2DPacket.COMMAND_EXTENDED_ID = 255;
1220
+ class HostBoundPacket extends Packet {
1221
+ constructor(data) {
1222
+ super(data);
1223
+ this.ack = exports.AckType.CDC2_NACK;
1224
+ this.payloadSize = Packet.ENCODER.getPayloadSize(this.data);
1225
+ const n = this.payloadSize > 128 ? 5 : 4;
1226
+ // skip command id check
1227
+ this.ack = this.data[(this.ackIndex = n + 1)];
1228
+ }
1229
+ static isValidPacket(data, n) {
1230
+ const ack = data[n + 1];
1231
+ return ack === exports.AckType.CDC2_ACK || ack === 167; // XXX: got 167 from MatchStatusReplyD2HPacket
1232
+ }
1233
+ }
1234
+ class Query1ReplyD2HPacket extends HostBoundPacket {
1235
+ constructor(data) {
1236
+ super(data);
1237
+ this.joystickFlag1 = this.data[4];
1238
+ this.joystickFlag2 = this.data[5];
1239
+ this.brainFlag1 = this.data[6]; // a.k.a vex version
1240
+ this.brainFlag2 = this.data[7];
1241
+ this.bootloadFlag1 = this.data[10];
1242
+ this.bootloadFlag2 = this.data[11];
1243
+ }
1244
+ }
1245
+ Query1ReplyD2HPacket.COMMAND_ID = 33;
1246
+ Query1ReplyD2HPacket.COMMAND_EXTENDED_ID = undefined;
1247
+ class SystemVersionReplyD2HPacket extends HostBoundPacket {
1248
+ constructor(data) {
1249
+ super(data);
1250
+ this.version = new VexFirmwareVersion(this.data[4], this.data[5], this.data[6], this.data[8]);
1251
+ this.hardware = this.data[7];
1252
+ }
1253
+ }
1254
+ SystemVersionReplyD2HPacket.COMMAND_ID = 164;
1255
+ SystemVersionReplyD2HPacket.COMMAND_EXTENDED_ID = undefined;
1256
+ class MatchModeReplyD2HPacket extends HostBoundPacket {
1257
+ constructor(data) {
1258
+ super(data);
1259
+ const dataView = PacketView.fromPacket(this);
1260
+ this.modebit = dataView.nextUint8();
1261
+ }
1262
+ }
1263
+ MatchModeReplyD2HPacket.COMMAND_ID = 88;
1264
+ MatchModeReplyD2HPacket.COMMAND_EXTENDED_ID = 193;
1265
+ class MatchStatusReplyD2HPacket extends HostBoundPacket {
1266
+ constructor(data) {
1267
+ super(data);
1268
+ const dataView = PacketView.fromPacket(this);
1269
+ const n = this.ackIndex;
1270
+ this.rssi = dataView.nextInt8();
1271
+ this.systemStatusBits = dataView.nextUint16();
1272
+ this.radioStatusBits = dataView.nextUint16();
1273
+ this.fieldStatusBits = dataView.nextUint8();
1274
+ this.matchClock = dataView.nextUint8();
1275
+ this.brainBatteryPercent = dataView.nextUint8();
1276
+ this.controllerBatteryPercent = dataView.nextUint8();
1277
+ this.partnerControllerBatteryPercent = dataView.nextUint8();
1278
+ this.pad = dataView.nextUint8();
1279
+ this.buttons = dataView.nextUint16();
1280
+ this.activeProgram = dataView.nextUint8();
1281
+ this.radioType = dataView.nextUint8();
1282
+ this.radioChannel = dataView.nextUint8();
1283
+ this.radioSlot = dataView.nextUint8();
1284
+ this.robotName = dataView.nextNTBS(10);
1285
+ this.controllerFlags = dataView.getUint8(n + 28);
1286
+ this.rxSignalQuality = dataView.getUint8(n + 29);
1287
+ let rawStr = new TextDecoder("UTF-8").decode(data.slice(n + 18, n + this.payloadSize + 28));
1288
+ const endIdx = rawStr.indexOf("\0");
1289
+ if (endIdx > -1) {
1290
+ rawStr = rawStr.substr(0, endIdx);
1291
+ }
1292
+ this.robotName = rawStr;
1293
+ }
1294
+ }
1295
+ MatchStatusReplyD2HPacket.COMMAND_ID = 88;
1296
+ MatchStatusReplyD2HPacket.COMMAND_EXTENDED_ID = 194;
1297
+ class FileControlReplyD2HPacket extends HostBoundPacket {
1298
+ }
1299
+ FileControlReplyD2HPacket.COMMAND_ID = 86;
1300
+ FileControlReplyD2HPacket.COMMAND_EXTENDED_ID = 16;
1301
+ class InitFileTransferReplyD2HPacket extends HostBoundPacket {
1302
+ constructor(data) {
1303
+ super(data);
1304
+ const dataView = PacketView.fromPacket(this);
1305
+ this.windowSize = dataView.nextUint16();
1306
+ this.fileSize = dataView.nextUint32();
1307
+ this.crc32 = dataView.nextUint32();
1308
+ }
1309
+ }
1310
+ InitFileTransferReplyD2HPacket.COMMAND_ID = 86;
1311
+ InitFileTransferReplyD2HPacket.COMMAND_EXTENDED_ID = 17;
1312
+ class ExitFileTransferReplyD2HPacket extends HostBoundPacket {
1313
+ }
1314
+ ExitFileTransferReplyD2HPacket.COMMAND_ID = 86;
1315
+ ExitFileTransferReplyD2HPacket.COMMAND_EXTENDED_ID = 18;
1316
+ class WriteFileReplyD2HPacket extends HostBoundPacket {
1317
+ }
1318
+ WriteFileReplyD2HPacket.COMMAND_ID = 86;
1319
+ WriteFileReplyD2HPacket.COMMAND_EXTENDED_ID = 19;
1320
+ class ReadFileReplyD2HPacket extends HostBoundPacket {
1321
+ constructor(data) {
1322
+ super(data);
1323
+ const dataView = PacketView.fromPacket(this);
1324
+ const n = this.ackIndex;
1325
+ this.addr = dataView.getUint32(n, true);
1326
+ this.length = this.payloadSize - 7;
1327
+ this.buf = data.slice(n + 4, n + 4 + this.length);
1328
+ }
1329
+ static isValidPacket(data, n) {
1330
+ return data[4] === 4 ? data[n + 1] === exports.AckType.CDC2_ACK : true;
1331
+ }
1332
+ }
1333
+ ReadFileReplyD2HPacket.COMMAND_ID = 86;
1334
+ ReadFileReplyD2HPacket.COMMAND_EXTENDED_ID = 20;
1335
+ class LinkFileReplyD2HPacket extends HostBoundPacket {
1336
+ }
1337
+ LinkFileReplyD2HPacket.COMMAND_ID = 86;
1338
+ LinkFileReplyD2HPacket.COMMAND_EXTENDED_ID = 21;
1339
+ class GetDirectoryFileCountReplyD2HPacket extends HostBoundPacket {
1340
+ constructor(data) {
1341
+ super(data);
1342
+ const dataView = PacketView.fromPacket(this);
1343
+ this.count = dataView.nextUint16();
1344
+ }
1345
+ }
1346
+ GetDirectoryFileCountReplyD2HPacket.COMMAND_ID = 86;
1347
+ GetDirectoryFileCountReplyD2HPacket.COMMAND_EXTENDED_ID = 22;
1348
+ class GetDirectoryEntryReplyD2HPacket extends HostBoundPacket {
1349
+ constructor(data) {
1350
+ super(data);
1351
+ const dataView = PacketView.fromPacket(this);
1352
+ if (this.payloadSize > 4) {
1353
+ this.file = {
1354
+ index: dataView.nextUint8(),
1355
+ size: dataView.nextUint32(),
1356
+ loadAddress: dataView.nextUint32(),
1357
+ crc32: dataView.nextUint32(),
1358
+ type: dataView.nextString(4),
1359
+ timestamp: dataView.nextUint32() + PacketEncoder.J2000_EPOCH,
1360
+ version: dataView.nextVersion(),
1361
+ filename: dataView.nextNTBS(32),
1362
+ };
1363
+ }
1364
+ }
1365
+ }
1366
+ GetDirectoryEntryReplyD2HPacket.COMMAND_ID = 86;
1367
+ GetDirectoryEntryReplyD2HPacket.COMMAND_EXTENDED_ID = 23;
1368
+ class LoadFileActionReplyD2HPacket extends HostBoundPacket {
1369
+ }
1370
+ LoadFileActionReplyD2HPacket.COMMAND_ID = 86;
1371
+ LoadFileActionReplyD2HPacket.COMMAND_EXTENDED_ID = 24;
1372
+ class GetFileMetadataReplyD2HPacket extends HostBoundPacket {
1373
+ constructor(data) {
1374
+ super(data);
1375
+ const dataView = PacketView.fromPacket(this);
1376
+ dataView.nextUint8();
1377
+ if (this.payloadSize > 4) {
1378
+ this.file = {
1379
+ size: dataView.nextUint32(),
1380
+ loadAddress: dataView.nextUint32(),
1381
+ crc32: dataView.nextUint32(),
1382
+ type: dataView.nextString(4),
1383
+ timestamp: dataView.nextUint32() + PacketEncoder.J2000_EPOCH,
1384
+ version: dataView.nextVersion(),
1385
+ };
1386
+ }
1387
+ }
1388
+ }
1389
+ GetFileMetadataReplyD2HPacket.COMMAND_ID = 86;
1390
+ GetFileMetadataReplyD2HPacket.COMMAND_EXTENDED_ID = 25;
1391
+ class SetFileMetadataReplyD2HPacket extends HostBoundPacket {
1392
+ }
1393
+ SetFileMetadataReplyD2HPacket.COMMAND_ID = 86;
1394
+ SetFileMetadataReplyD2HPacket.COMMAND_EXTENDED_ID = 26;
1395
+ class EraseFileReplyD2HPacket extends HostBoundPacket {
1396
+ }
1397
+ EraseFileReplyD2HPacket.COMMAND_ID = 86;
1398
+ EraseFileReplyD2HPacket.COMMAND_EXTENDED_ID = 27;
1399
+ class GetProgramSlotInfoReplyD2HPacket extends HostBoundPacket {
1400
+ constructor(data) {
1401
+ super(data);
1402
+ const dataView = PacketView.fromPacket(this);
1403
+ this.slot = dataView.nextUint8();
1404
+ this.requestedSlot = dataView.nextUint8();
1405
+ }
1406
+ }
1407
+ GetProgramSlotInfoReplyD2HPacket.COMMAND_ID = 86;
1408
+ GetProgramSlotInfoReplyD2HPacket.COMMAND_EXTENDED_ID = 28;
1409
+ class FileClearUpReplyD2HPacket extends HostBoundPacket {
1410
+ }
1411
+ FileClearUpReplyD2HPacket.COMMAND_ID = 86;
1412
+ FileClearUpReplyD2HPacket.COMMAND_EXTENDED_ID = 30;
1413
+ class FileFormatReplyD2HPacket extends HostBoundPacket {
1414
+ }
1415
+ FileFormatReplyD2HPacket.COMMAND_ID = 86;
1416
+ FileFormatReplyD2HPacket.COMMAND_EXTENDED_ID = 31;
1417
+ class GetSystemFlagsReplyD2HPacket extends HostBoundPacket {
1418
+ constructor(data) {
1419
+ super(data);
1420
+ const dataView = PacketView.fromPacket(this);
1421
+ this.radioSearching = false;
1422
+ this.currentProgram = 0;
1423
+ this.flags = dataView.nextUint32();
1424
+ const hasPartner = (8192 & this.flags) !== 0;
1425
+ const hasRadio = (1536 & this.flags) === 1536;
1426
+ const byte1 = dataView.nextUint8();
1427
+ const byte2 = dataView.nextUint8();
1428
+ if (this.payloadSize === 11) {
1429
+ this.battery = 8 * (byte1 & 0x0f);
1430
+ if ((this.flags & 0x100) !== 0 || hasRadio)
1431
+ this.controllerBatteryPercent = 8 * ((byte1 >> 4) & 0x0f);
1432
+ if (hasRadio)
1433
+ this.radioQuality = 8 * (byte2 & 0x0f);
1434
+ this.radioSearching = (this.flags & 0x600) === 0x200;
1435
+ if (hasPartner)
1436
+ this.partnerControllerBatteryPercent = 8 * ((byte2 >> 4) & 0x0f);
1437
+ this.currentProgram = dataView.nextUint8();
1438
+ if (this.battery != null && this.battery > 100)
1439
+ this.battery = 100;
1440
+ if (this.controllerBatteryPercent != null &&
1441
+ this.controllerBatteryPercent > 100)
1442
+ this.controllerBatteryPercent = 100;
1443
+ if (this.radioQuality != null && this.radioQuality > 100)
1444
+ this.radioQuality = 100;
1445
+ if (this.partnerControllerBatteryPercent != null &&
1446
+ this.partnerControllerBatteryPercent > 100)
1447
+ this.partnerControllerBatteryPercent = 100;
1448
+ }
1449
+ }
1450
+ }
1451
+ GetSystemFlagsReplyD2HPacket.COMMAND_ID = 86;
1452
+ GetSystemFlagsReplyD2HPacket.COMMAND_EXTENDED_ID = 32;
1453
+ class GetDeviceStatusReplyD2HPacket extends HostBoundPacket {
1454
+ constructor(data) {
1455
+ super(data);
1456
+ const dataView = PacketView.fromPacket(this);
1457
+ this.count = dataView.nextUint8();
1458
+ this.devices = [];
1459
+ for (let i = 0; i < this.count; i++) {
1460
+ this.devices.push({
1461
+ port: dataView.nextUint8(),
1462
+ type: dataView.nextUint8(),
1463
+ status: dataView.nextUint8(),
1464
+ betaversion: dataView.nextUint8(),
1465
+ version: dataView.nextUint16(),
1466
+ bootversion: dataView.nextUint16(),
1467
+ });
1468
+ }
1469
+ }
1470
+ }
1471
+ GetDeviceStatusReplyD2HPacket.COMMAND_ID = 86;
1472
+ GetDeviceStatusReplyD2HPacket.COMMAND_EXTENDED_ID = 33;
1473
+ class GetSystemStatusReplyD2HPacket extends HostBoundPacket {
1474
+ constructor(data) {
1475
+ super(data);
1476
+ const dataView = PacketView.fromPacket(this);
1477
+ dataView.nextUint8();
1478
+ this.systemVersion = dataView.nextVersion();
1479
+ this.cpu0Version = dataView.nextVersion();
1480
+ this.cpu1Version = dataView.nextVersion();
1481
+ this.touchVersion = dataView.nextVersion(true);
1482
+ this.uniqueId = 1234;
1483
+ this.sysflags = [0, 0, 0, 0, 0, 0, 0];
1484
+ this.goldenVersion = VexFirmwareVersion.allZero();
1485
+ this.nxpVersion = VexFirmwareVersion.allZero();
1486
+ this.eventBrain = false;
1487
+ this.romBootloaderActive = false;
1488
+ this.ramBootloaderActive = false;
1489
+ if (this.payloadSize > 25) {
1490
+ this.uniqueId = dataView.nextUint32();
1491
+ this.sysflags = [
1492
+ dataView.nextUint8(),
1493
+ dataView.nextUint8(),
1494
+ dataView.nextUint8(),
1495
+ dataView.nextUint8(),
1496
+ dataView.nextUint8(),
1497
+ 0,
1498
+ dataView.nextUint8(),
1499
+ ];
1500
+ this.eventBrain = (1 & this.sysflags[6]) !== 0;
1501
+ this.romBootloaderActive = (2 & this.sysflags[6]) !== 0;
1502
+ this.ramBootloaderActive = (4 & this.sysflags[6]) !== 0;
1503
+ dataView.nextUint16();
1504
+ this.goldenVersion = dataView.nextVersion();
1505
+ }
1506
+ if (this.payloadSize > 37) {
1507
+ this.nxpVersion = dataView.nextVersion();
1508
+ }
1509
+ }
1510
+ }
1511
+ GetSystemStatusReplyD2HPacket.COMMAND_ID = 86;
1512
+ GetSystemStatusReplyD2HPacket.COMMAND_EXTENDED_ID = 34;
1513
+ class GetFdtStatusReplyD2HPacket extends HostBoundPacket {
1514
+ constructor(data) {
1515
+ super(data);
1516
+ const dataView = PacketView.fromPacket(this);
1517
+ this.count = dataView.nextUint8();
1518
+ this.status = [];
1519
+ for (let i = 0; i < this.count; i++) {
1520
+ this.status.push({
1521
+ index: dataView.nextUint8(),
1522
+ type: dataView.nextUint8(),
1523
+ status: dataView.nextUint8(),
1524
+ betaversion: dataView.nextUint8(),
1525
+ version: dataView.nextUint16(),
1526
+ bootversion: dataView.nextUint16(),
1527
+ });
1528
+ }
1529
+ }
1530
+ }
1531
+ GetFdtStatusReplyD2HPacket.COMMAND_ID = 86;
1532
+ GetFdtStatusReplyD2HPacket.COMMAND_EXTENDED_ID = 35;
1533
+ class GetLogCountReplyD2HPacket extends HostBoundPacket {
1534
+ constructor(data) {
1535
+ super(data);
1536
+ const dataView = PacketView.fromPacket(this);
1537
+ dataView.nextUint8();
1538
+ this.count = dataView.nextUint32();
1539
+ }
1540
+ }
1541
+ GetLogCountReplyD2HPacket.COMMAND_ID = 86;
1542
+ GetLogCountReplyD2HPacket.COMMAND_EXTENDED_ID = 36;
1543
+ class ReadLogPageReplyD2HPacket extends HostBoundPacket {
1544
+ constructor(data) {
1545
+ super(data);
1546
+ const dataView = PacketView.fromPacket(this);
1547
+ const n = this.ackIndex;
1548
+ const size = dataView.nextUint8();
1549
+ this.offset = dataView.nextUint32();
1550
+ this.count = dataView.nextUint16();
1551
+ this.entries = [];
1552
+ let j = n + 8;
1553
+ for (let i = 0; i < this.count; i++) {
1554
+ this.entries.push({
1555
+ code: dataView.getUint8(j),
1556
+ type: dataView.getUint8(j + 1),
1557
+ desc: dataView.getUint8(j + 2),
1558
+ spare: dataView.getUint8(j + 3),
1559
+ time: dataView.getUint32(j + 4, true),
1560
+ });
1561
+ j += size;
1562
+ }
1563
+ }
1564
+ }
1565
+ ReadLogPageReplyD2HPacket.COMMAND_ID = 86;
1566
+ ReadLogPageReplyD2HPacket.COMMAND_EXTENDED_ID = 37;
1567
+ class GetRadioStatusReplyD2HPacket extends HostBoundPacket {
1568
+ constructor(data) {
1569
+ super(data);
1570
+ const dataView = PacketView.fromPacket(this);
1571
+ const n = this.ackIndex;
1572
+ this.device = dataView.nextUint8();
1573
+ this.quality = dataView.nextUint16();
1574
+ this.strength = dataView.nextInt16();
1575
+ this.channel = this.data[n + 6];
1576
+ this.timeslot = this.data[n + 7];
1577
+ }
1578
+ }
1579
+ GetRadioStatusReplyD2HPacket.COMMAND_ID = 86;
1580
+ GetRadioStatusReplyD2HPacket.COMMAND_EXTENDED_ID = 38;
1581
+ class GetUserDataReplyD2HPacket extends HostBoundPacket {
1582
+ }
1583
+ GetUserDataReplyD2HPacket.COMMAND_ID = 86;
1584
+ GetUserDataReplyD2HPacket.COMMAND_EXTENDED_ID = 39;
1585
+ class ScreenCaptureReplyD2HPacket extends HostBoundPacket {
1586
+ }
1587
+ ScreenCaptureReplyD2HPacket.COMMAND_ID = 86;
1588
+ ScreenCaptureReplyD2HPacket.COMMAND_EXTENDED_ID = 40;
1589
+ // export class UserProgramControlReplyD2HPacket extends HostBoundPacket {
1590
+ // static COMMAND_ID = 86;
1591
+ // static COMMAND_EXTENDED_ID = 41;
1592
+ // }
1593
+ class SendDashTouchReplyD2HPacket extends HostBoundPacket {
1594
+ }
1595
+ SendDashTouchReplyD2HPacket.COMMAND_ID = 86;
1596
+ SendDashTouchReplyD2HPacket.COMMAND_EXTENDED_ID = 42;
1597
+ class SelectDashReplyD2HPacket extends HostBoundPacket {
1598
+ }
1599
+ SelectDashReplyD2HPacket.COMMAND_ID = 86;
1600
+ SelectDashReplyD2HPacket.COMMAND_EXTENDED_ID = 43;
1601
+ class EnableDashReplyD2HPacket extends HostBoundPacket {
1602
+ }
1603
+ EnableDashReplyD2HPacket.COMMAND_ID = 86;
1604
+ EnableDashReplyD2HPacket.COMMAND_EXTENDED_ID = 44;
1605
+ class DisableDashReplyD2HPacket extends HostBoundPacket {
1606
+ }
1607
+ DisableDashReplyD2HPacket.COMMAND_ID = 86;
1608
+ DisableDashReplyD2HPacket.COMMAND_EXTENDED_ID = 45;
1609
+ class ReadKeyValueReplyD2HPacket extends HostBoundPacket {
1610
+ constructor(data) {
1611
+ super(data);
1612
+ const dataView = PacketView.fromPacket(this);
1613
+ this.value = dataView.nextVarNTBS(255);
1614
+ }
1615
+ }
1616
+ ReadKeyValueReplyD2HPacket.COMMAND_ID = 86;
1617
+ ReadKeyValueReplyD2HPacket.COMMAND_EXTENDED_ID = 46;
1618
+ class WriteKeyValueReplyD2HPacket extends HostBoundPacket {
1619
+ }
1620
+ WriteKeyValueReplyD2HPacket.COMMAND_ID = 86;
1621
+ WriteKeyValueReplyD2HPacket.COMMAND_EXTENDED_ID = 47;
1622
+ class GetSlot1to4InfoReplyD2HPacket extends HostBoundPacket {
1623
+ constructor(data, start = 1) {
1624
+ super(data);
1625
+ const dataView = PacketView.fromPacket(this);
1626
+ this.slotFlags = dataView.nextUint8();
1627
+ this.slots = [];
1628
+ for (let i = 0; i < 4; i++) {
1629
+ const hasData = (this.slotFlags & Math.pow(2, start - 1 + i)) !== 0;
1630
+ if (!hasData)
1631
+ continue;
1632
+ const iconNum = dataView.nextUint16();
1633
+ const nameLen = dataView.nextUint8();
1634
+ const name = dataView.nextString(nameLen);
1635
+ this.slots.push({
1636
+ slot: start + i,
1637
+ icon: iconNum,
1638
+ name,
1639
+ });
1640
+ }
1641
+ }
1642
+ }
1643
+ GetSlot1to4InfoReplyD2HPacket.COMMAND_ID = 86;
1644
+ GetSlot1to4InfoReplyD2HPacket.COMMAND_EXTENDED_ID = 49;
1645
+ class GetSlot5to8InfoReplyD2HPacket extends GetSlot1to4InfoReplyD2HPacket {
1646
+ constructor(data) {
1647
+ super(data, 5);
1648
+ this.slotStartIndex = 5;
1649
+ }
1650
+ }
1651
+ GetSlot5to8InfoReplyD2HPacket.COMMAND_ID = 86;
1652
+ GetSlot5to8InfoReplyD2HPacket.COMMAND_EXTENDED_ID = 50;
1653
+ class FactoryStatusReplyD2HPacket extends HostBoundPacket {
1654
+ constructor(data) {
1655
+ super(data);
1656
+ const dataView = PacketView.fromPacket(this);
1657
+ this.status = dataView.nextUint8();
1658
+ this.percent = dataView.nextUint8();
1659
+ }
1660
+ }
1661
+ FactoryStatusReplyD2HPacket.COMMAND_ID = 86;
1662
+ FactoryStatusReplyD2HPacket.COMMAND_EXTENDED_ID = 241;
1663
+ class FactoryEnableReplyD2HPacket extends HostBoundPacket {
1664
+ }
1665
+ FactoryEnableReplyD2HPacket.COMMAND_ID = 86;
1666
+ FactoryEnableReplyD2HPacket.COMMAND_EXTENDED_ID = 255;
1667
+
1668
+ const thePacketEncoder = PacketEncoder.getInstance();
1669
+ /**
1670
+ * A connection to a V5 device.
1671
+ * Emit events: connected, disconnected
1672
+ */
1673
+ class VexSerialConnection extends VexEventTarget {
1674
+ get isConnected() {
1675
+ return (this.port !== undefined &&
1676
+ this.reader !== undefined &&
1677
+ this.writer !== undefined);
1678
+ }
1679
+ constructor(serial) {
1680
+ super();
1681
+ this.filters = [{ usbVendorId: 10376 }];
1682
+ this.callbacksQueue = [];
1683
+ this.serial = serial;
1684
+ }
1685
+ close() {
1686
+ var _a, _b, _c;
1687
+ return __awaiter(this, void 0, void 0, function* () {
1688
+ if (!this.isConnected)
1689
+ return;
1690
+ try {
1691
+ yield ((_a = this.writer) === null || _a === void 0 ? void 0 : _a.close());
1692
+ this.writer = undefined;
1693
+ }
1694
+ catch (e) { }
1695
+ try {
1696
+ yield ((_b = this.reader) === null || _b === void 0 ? void 0 : _b.cancel());
1697
+ try {
1698
+ while (this.reader != null) {
1699
+ const { done } = yield this.reader.read();
1700
+ if (done)
1701
+ break;
1702
+ }
1703
+ }
1704
+ catch (e) { }
1705
+ this.reader = undefined;
1706
+ }
1707
+ catch (e) { }
1708
+ try {
1709
+ yield new Promise((resolve) => setTimeout(resolve, 1)); // HACK: wait for the lock to be released
1710
+ yield ((_c = this.port) === null || _c === void 0 ? void 0 : _c.close());
1711
+ this.port = undefined;
1712
+ }
1713
+ catch (e) {
1714
+ console.warn("Close port error.", e);
1715
+ }
1716
+ finally {
1717
+ this.emit("disconnected", undefined);
1718
+ }
1719
+ });
1720
+ }
1721
+ open(use = 0, askUser = true) {
1722
+ return __awaiter(this, void 0, void 0, function* () {
1723
+ if (this.port !== undefined)
1724
+ throw new Error("Already connected.");
1725
+ let port;
1726
+ if (use !== undefined) {
1727
+ const ports = (yield this.serial.getPorts())
1728
+ .filter((p) => {
1729
+ const info = p.getInfo();
1730
+ return this.filters.find((f) => (f.usbVendorId === undefined ||
1731
+ f.usbVendorId === info.usbVendorId) &&
1732
+ (f.usbProductId === undefined ||
1733
+ f.usbProductId === info.usbProductId));
1734
+ })
1735
+ .filter((e) => e.readable !== null);
1736
+ port = ports[use];
1737
+ }
1738
+ if (port == null && askUser) {
1739
+ try {
1740
+ port = yield this.serial.requestPort({ filters: this.filters });
1741
+ }
1742
+ catch (e) {
1743
+ //console.warn("No valid port selected.");
1744
+ }
1745
+ }
1746
+ if (port == null)
1747
+ return undefined;
1748
+ if (port.readable != null)
1749
+ return false;
1750
+ try {
1751
+ yield port.open({ baudRate: 115200 });
1752
+ this.port = port;
1753
+ this.port.addEventListener("disconnect", () => {
1754
+ void this.close();
1755
+ });
1756
+ this.emit("connected", undefined);
1757
+ this.writer = this.port.writable.getWriter();
1758
+ this.reader = this.port.readable.getReader();
1759
+ void this.startReader();
1760
+ return true;
1761
+ }
1762
+ catch (e) {
1763
+ return false;
1764
+ }
1765
+ });
1766
+ }
1767
+ writeData(rawData, resolve, timeout = 1000) {
1768
+ void this.writeDataAsync(rawData, timeout).then(resolve);
1769
+ }
1770
+ writeDataAsync(rawData, timeout = 1000) {
1771
+ return __awaiter(this, void 0, void 0, function* () {
1772
+ return yield new Promise((resolve) => {
1773
+ if (this.writer === undefined) {
1774
+ resolve(exports.AckType.CDC2_NACK);
1775
+ return;
1776
+ }
1777
+ const data = rawData instanceof DeviceBoundPacket ? rawData.data : rawData;
1778
+ const cb = {
1779
+ callback: resolve,
1780
+ timeout: setTimeout(() => {
1781
+ var _a;
1782
+ (_a = this.callbacksQueue.shift()) === null || _a === void 0 ? void 0 : _a.callback(exports.AckType.TIMEOUT);
1783
+ }, timeout),
1784
+ wantedCommandId: rawData instanceof DeviceBoundPacket
1785
+ ? // eslint-disable-next-line @typescript-eslint/no-explicit-any
1786
+ rawData.constructor.COMMAND_ID
1787
+ : undefined,
1788
+ wantedCommandExId: rawData instanceof DeviceBoundPacket
1789
+ ? // eslint-disable-next-line @typescript-eslint/no-explicit-any
1790
+ rawData.constructor.COMMAND_EXTENDED_ID
1791
+ : undefined,
1792
+ };
1793
+ this.callbacksQueue.push(cb);
1794
+ this.writer
1795
+ .write(data)
1796
+ .then(() => {
1797
+ logData(data, 100);
1798
+ })
1799
+ .catch(() => {
1800
+ this.callbacksQueue.splice(this.callbacksQueue.indexOf(cb), 1);
1801
+ resolve(exports.AckType.WRITE_ERROR);
1802
+ });
1803
+ });
1804
+ });
1805
+ }
1806
+ readData(cache, expectedSize) {
1807
+ return __awaiter(this, void 0, void 0, function* () {
1808
+ if (this.reader == null)
1809
+ throw new Error("No reader");
1810
+ while (cache.byteLength < expectedSize) {
1811
+ const { value: readData, done: isDone } = yield this.reader.read();
1812
+ if (isDone)
1813
+ throw new Error("No data");
1814
+ cache = binaryArrayJoin(cache, readData);
1815
+ }
1816
+ return cache;
1817
+ });
1818
+ }
1819
+ startReader() {
1820
+ return __awaiter(this, void 0, void 0, function* () {
1821
+ let cache = new Uint8Array([]);
1822
+ let sliceIdx = 0;
1823
+ for (;;)
1824
+ try {
1825
+ cache = yield this.readData(cache, 5);
1826
+ sliceIdx = 0;
1827
+ if (!thePacketEncoder.validateHeader(cache))
1828
+ throw new Error("Invalid header");
1829
+ const payloadExpectedSize = thePacketEncoder.getPayloadSize(cache);
1830
+ const n = payloadExpectedSize > 128 ? 5 : 4;
1831
+ const totalSize = n + payloadExpectedSize;
1832
+ cache = yield this.readData(cache, totalSize);
1833
+ sliceIdx = totalSize;
1834
+ const cmdId = cache[2];
1835
+ const hasExtId = cmdId === 88 || cmdId === 86;
1836
+ const cmdExId = hasExtId ? cache[n] : undefined;
1837
+ const ack = cache[n + 1];
1838
+ if (hasExtId) {
1839
+ if (!thePacketEncoder.validateMessageCdc(cache))
1840
+ throw new Error("Invalid message CDC");
1841
+ }
1842
+ let callbackInfo;
1843
+ let wantedCmdId;
1844
+ let wantedCmdExId;
1845
+ let tryIdx = 0;
1846
+ while ((callbackInfo = this.callbacksQueue[tryIdx++]) !== null) {
1847
+ wantedCmdId = callbackInfo === null || callbackInfo === void 0 ? void 0 : callbackInfo.wantedCommandId;
1848
+ wantedCmdExId = callbackInfo === null || callbackInfo === void 0 ? void 0 : callbackInfo.wantedCommandExId;
1849
+ if ((wantedCmdId !== undefined && wantedCmdId !== cmdId) ||
1850
+ (wantedCmdExId !== undefined && wantedCmdExId !== cmdExId)) {
1851
+ continue;
1852
+ }
1853
+ break;
1854
+ }
1855
+ if (callbackInfo === undefined) {
1856
+ console.warn("Unexpected command", cmdId, cmdExId, ack);
1857
+ // TODO: trigger event
1858
+ continue;
1859
+ }
1860
+ const data = cache.slice(0, sliceIdx);
1861
+ const PackageType = thePacketEncoder.allPacketsTable[wantedCmdId + " " + wantedCmdExId];
1862
+ if ((wantedCmdId === undefined && wantedCmdExId === undefined) ||
1863
+ PackageType === undefined) {
1864
+ callbackInfo.callback(data.buffer.slice(data.byteOffset, data.byteOffset + data.byteLength));
1865
+ }
1866
+ else {
1867
+ if (!hasExtId || PackageType.isValidPacket(data, n)) {
1868
+ callbackInfo.callback(new PackageType(data));
1869
+ }
1870
+ else {
1871
+ console.warn("ack", ack);
1872
+ callbackInfo.callback(ack);
1873
+ }
1874
+ }
1875
+ clearTimeout(callbackInfo.timeout);
1876
+ this.callbacksQueue.splice(tryIdx - 1, 1);
1877
+ }
1878
+ catch (e) {
1879
+ if (!(e instanceof Error && e.message === "No data")) {
1880
+ console.warn("Read error.", e, cache);
1881
+ }
1882
+ yield this.close();
1883
+ break;
1884
+ }
1885
+ finally {
1886
+ cache = cache.slice(sliceIdx);
1887
+ }
1888
+ });
1889
+ }
1890
+ query1() {
1891
+ return __awaiter(this, void 0, void 0, function* () {
1892
+ const result = yield this.writeDataAsync(new Query1H2DPacket(), 100);
1893
+ return result instanceof Query1ReplyD2HPacket ? result : null;
1894
+ });
1895
+ }
1896
+ getSystemVersion() {
1897
+ return __awaiter(this, void 0, void 0, function* () {
1898
+ const result = yield this.writeDataAsync(new SystemVersionH2DPacket());
1899
+ return result instanceof SystemVersionReplyD2HPacket
1900
+ ? result.version
1901
+ : null;
1902
+ });
1903
+ }
1904
+ }
1905
+ class V5SerialConnection extends VexSerialConnection {
1906
+ constructor() {
1907
+ super(...arguments);
1908
+ this.filters = [
1909
+ { usbVendorId: 10376, usbProductId: exports.SerialDeviceType.V5_BRAIN },
1910
+ { usbVendorId: 10376, usbProductId: exports.SerialDeviceType.V5_BRAIN_DFU },
1911
+ { usbVendorId: 10376, usbProductId: exports.SerialDeviceType.V5_CONTROLLER },
1912
+ ];
1913
+ }
1914
+ getDeviceStatus() {
1915
+ return __awaiter(this, void 0, void 0, function* () {
1916
+ const result = yield this.writeDataAsync(new GetDeviceStatusH2DPacket());
1917
+ return result instanceof GetDeviceStatusReplyD2HPacket ? result : null;
1918
+ });
1919
+ }
1920
+ getRadioStatus() {
1921
+ return __awaiter(this, void 0, void 0, function* () {
1922
+ const result = yield this.writeDataAsync(new GetRadioStatusH2DPacket());
1923
+ return result instanceof GetRadioStatusReplyD2HPacket ? result : null;
1924
+ });
1925
+ }
1926
+ getSystemFlags() {
1927
+ return __awaiter(this, void 0, void 0, function* () {
1928
+ const result = yield this.writeDataAsync(new GetSystemFlagsH2DPacket());
1929
+ return result instanceof GetSystemFlagsReplyD2HPacket ? result : null;
1930
+ });
1931
+ }
1932
+ getSystemStatus(timeout = 1000) {
1933
+ return __awaiter(this, void 0, void 0, function* () {
1934
+ const result = yield this.writeDataAsync(new GetSystemStatusH2DPacket(), timeout);
1935
+ return result instanceof GetSystemStatusReplyD2HPacket ? result : null;
1936
+ });
1937
+ }
1938
+ getMatchStatus() {
1939
+ return __awaiter(this, void 0, void 0, function* () {
1940
+ const result = yield this.writeDataAsync(new GetMatchStatusH2DPacket());
1941
+ return result instanceof MatchStatusReplyD2HPacket ? result : null;
1942
+ });
1943
+ }
1944
+ uploadProgramToDevice(iniConfig, binFileBuf, coldFileBuf, progressCallback) {
1945
+ return __awaiter(this, void 0, void 0, function* () {
1946
+ const iniFileBuffer = new TextEncoder().encode(iniConfig.createIni());
1947
+ const basename = iniConfig.baseName;
1948
+ const iniRequest = {
1949
+ filename: basename + ".ini",
1950
+ buf: iniFileBuffer,
1951
+ downloadTarget: exports.FileDownloadTarget.FILE_TARGET_QSPI,
1952
+ vendor: exports.FileVendor.USER,
1953
+ autoRun: false,
1954
+ };
1955
+ const r1 = yield this.uploadFileToDevice(iniRequest, (current, total) => {
1956
+ progressCallback("INI", current, total);
1957
+ });
1958
+ if (!r1)
1959
+ return false;
1960
+ // let prjRequest = { filename: basename + '.prj', buf: prjfile, vid: FileVendor.USER, loadAddr: undefined, exttype: 0, linkedFile: undefined };
1961
+ // await this.uploadFileToDeviceAsync(prjRequest, onProgress);
1962
+ const coldRequest = coldFileBuf !== undefined
1963
+ ? {
1964
+ filename: basename + "_lib.bin",
1965
+ buf: coldFileBuf,
1966
+ downloadTarget: exports.FileDownloadTarget.FILE_TARGET_QSPI,
1967
+ vendor: exports.FileVendor.DEV2,
1968
+ autoRun: false,
1969
+ }
1970
+ : undefined;
1971
+ if (coldRequest != null) {
1972
+ const r2 = yield this.uploadFileToDevice(coldRequest, (current, total) => {
1973
+ progressCallback("COLD", current, total);
1974
+ });
1975
+ if (!r2)
1976
+ return;
1977
+ }
1978
+ const binRequest = {
1979
+ filename: basename + ".bin",
1980
+ buf: binFileBuf,
1981
+ downloadTarget: exports.FileDownloadTarget.FILE_TARGET_QSPI,
1982
+ vendor: exports.FileVendor.USER,
1983
+ loadAddress: coldFileBuf != null ? 0x07800000 : undefined,
1984
+ autoRun: iniConfig.autorun,
1985
+ linkedFile: coldRequest,
1986
+ };
1987
+ const r3 = yield this.uploadFileToDevice(binRequest, (current, total) => {
1988
+ progressCallback("BIN", current, total);
1989
+ });
1990
+ return r3;
1991
+ });
1992
+ }
1993
+ downloadFileToHost(request, downloadTarget = exports.FileDownloadTarget.FILE_TARGET_QSPI, progressCallback) {
1994
+ return __awaiter(this, void 0, void 0, function* () {
1995
+ // TODO assert that the device is connected
1996
+ const { filename, vendor, loadAddress, size } = request;
1997
+ let nextAddress = loadAddress !== null && loadAddress !== void 0 ? loadAddress : USER_FLASH_USR_CODE_START;
1998
+ const p1 = yield this.writeDataAsync(new InitFileTransferH2DPacket(exports.FileInitAction.READ, downloadTarget, vendor, exports.FileInitOption.NONE, new Uint8Array(), nextAddress, filename, ""));
1999
+ if (!(p1 instanceof InitFileTransferReplyD2HPacket))
2000
+ throw new Error("InitFileTransferH2DPacket failed");
2001
+ const fileSize = size !== null && size !== void 0 ? size : p1.fileSize;
2002
+ // console.log("size:", fileSize);
2003
+ const bufferChunkSize = p1.windowSize > 0 && p1.windowSize <= USER_PROG_CHUNK_SIZE
2004
+ ? p1.windowSize
2005
+ : USER_PROG_CHUNK_SIZE;
2006
+ let bufferOffset = 0;
2007
+ let fileBuf = new Uint8Array(fileSize + bufferChunkSize);
2008
+ let lastBlock = false;
2009
+ while (!lastBlock) {
2010
+ if (fileSize <= bufferOffset + bufferChunkSize) {
2011
+ lastBlock = true;
2012
+ }
2013
+ const p2 = yield this.writeDataAsync(new ReadFileH2DPacket(nextAddress, bufferChunkSize), 3000);
2014
+ if (!(p2 instanceof ReadFileReplyD2HPacket))
2015
+ throw new Error("ReadFileReplyD2HPacket failed");
2016
+ fileBuf.set(new Uint8Array(p2.buf), bufferOffset);
2017
+ if (progressCallback != null)
2018
+ progressCallback(bufferOffset, fileSize);
2019
+ // next chunk
2020
+ bufferOffset += bufferChunkSize;
2021
+ nextAddress += bufferChunkSize;
2022
+ }
2023
+ yield this.writeDataAsync(new ExitFileTransferH2DPacket(exports.FileExitAction.EXIT_HALT), 30000);
2024
+ // console.log(p3);
2025
+ fileBuf = fileBuf.slice(0, fileSize);
2026
+ return fileBuf;
2027
+ });
2028
+ }
2029
+ uploadFileToDevice(request, progressCallback) {
2030
+ var _a;
2031
+ return __awaiter(this, void 0, void 0, function* () {
2032
+ let { filename, buf, downloadTarget, vendor, loadAddress, exttype, autoRun, linkedFile, } = request;
2033
+ if (buf === undefined) {
2034
+ // TODO: check connection status
2035
+ return false;
2036
+ }
2037
+ // no download to special capture or vision buffers
2038
+ // if (this.downloadTarget === VexDeviceWebSerial.FILE_TARGET_CBUF || this.downloadTarget === VexDeviceWebSerial.FILE_TARGET_VBUF) {
2039
+ // // error !
2040
+ // if (doneCallback != undefined) {
2041
+ // doneCallback(false);
2042
+ // }
2043
+ // return;
2044
+ // }
2045
+ downloadTarget = downloadTarget !== null && downloadTarget !== void 0 ? downloadTarget : exports.FileDownloadTarget.FILE_TARGET_QSPI;
2046
+ vendor = vendor !== null && vendor !== void 0 ? vendor : exports.FileVendor.USER;
2047
+ let nextAddress = loadAddress !== null && loadAddress !== void 0 ? loadAddress : USER_FLASH_USR_CODE_START;
2048
+ // TODO if downloadTarget is FILE_TARGET_A1, FactoryEnable
2049
+ //console.log("init file transfer", filename);
2050
+ const p1 = yield this.writeDataAsync(new InitFileTransferH2DPacket(exports.FileInitAction.WRITE, downloadTarget, vendor, exports.FileInitOption.OVERWRITE, buf, nextAddress, filename, exttype));
2051
+ if (!(p1 instanceof InitFileTransferReplyD2HPacket))
2052
+ throw new Error("InitFileTransferH2DPacket failed");
2053
+ //console.log(p1);
2054
+ if (linkedFile !== undefined) {
2055
+ const p3 = yield this.writeDataAsync(new LinkFileH2DPacket((_a = linkedFile.vendor) !== null && _a !== void 0 ? _a : exports.FileVendor.USER, linkedFile.filename, 0), 10000);
2056
+ if (!(p3 instanceof LinkFileReplyD2HPacket))
2057
+ throw new Error("LinkFileH2DPacket failed");
2058
+ }
2059
+ const bufferChunkSize = p1.windowSize > 0 && p1.windowSize <= USER_PROG_CHUNK_SIZE
2060
+ ? p1.windowSize
2061
+ : USER_PROG_CHUNK_SIZE;
2062
+ let bufferOffset = 0;
2063
+ let lastBlock = false;
2064
+ let transferFailed = true;
2065
+ let exitReply;
2066
+ try {
2067
+ while (!lastBlock) {
2068
+ let tmpbuf;
2069
+ if (buf.byteLength - bufferOffset > bufferChunkSize) {
2070
+ tmpbuf = buf.subarray(bufferOffset, bufferOffset + bufferChunkSize);
2071
+ }
2072
+ else {
2073
+ // last chunk
2074
+ // word align length
2075
+ const length = ((buf.byteLength - bufferOffset + 3) / 4) >>> 0;
2076
+ tmpbuf = new Uint8Array(length * 4);
2077
+ tmpbuf.set(buf.subarray(bufferOffset, buf.byteLength));
2078
+ lastBlock = true;
2079
+ }
2080
+ const p2 = yield this.writeDataAsync(new WriteFileH2DPacket(nextAddress, tmpbuf), 3000);
2081
+ if (!(p2 instanceof WriteFileReplyD2HPacket))
2082
+ throw new Error("WriteFileReplyD2HPacket failed");
2083
+ if (progressCallback != null)
2084
+ progressCallback(bufferOffset, buf.byteLength);
2085
+ // next chunk
2086
+ bufferOffset += bufferChunkSize;
2087
+ nextAddress += bufferChunkSize;
2088
+ }
2089
+ progressCallback === null || progressCallback === void 0 ? void 0 : progressCallback(buf.byteLength, buf.byteLength);
2090
+ transferFailed = false;
2091
+ }
2092
+ finally {
2093
+ exitReply = yield this.writeDataAsync(new ExitFileTransferH2DPacket(transferFailed
2094
+ ? exports.FileExitAction.EXIT_HALT
2095
+ : autoRun
2096
+ ? exports.FileExitAction.EXIT_RUN
2097
+ : exports.FileExitAction.EXIT_HALT), 30000);
2098
+ }
2099
+ return exitReply instanceof ExitFileTransferReplyD2HPacket;
2100
+ });
2101
+ }
2102
+ setMatchMode(mode) {
2103
+ return __awaiter(this, void 0, void 0, function* () {
2104
+ const result = yield this.writeDataAsync(new UpdateMatchModeH2DPacket(mode, 0));
2105
+ return result instanceof MatchModeReplyD2HPacket ? result : null;
2106
+ });
2107
+ }
2108
+ loadProgram(value) {
2109
+ return __awaiter(this, void 0, void 0, function* () {
2110
+ const result = yield this.writeDataAsync(new LoadFileActionH2DPacket(exports.FileVendor.USER, exports.FileLoadAction.RUN, value));
2111
+ return result instanceof LoadFileActionReplyD2HPacket ? result : null;
2112
+ });
2113
+ }
2114
+ stopProgram() {
2115
+ return __awaiter(this, void 0, void 0, function* () {
2116
+ const result = yield this.writeDataAsync(new LoadFileActionH2DPacket(exports.FileVendor.USER, exports.FileLoadAction.STOP, ""));
2117
+ return result instanceof LoadFileActionReplyD2HPacket ? result : null;
2118
+ });
2119
+ }
2120
+ mockTouch(x, y, press) {
2121
+ return __awaiter(this, void 0, void 0, function* () {
2122
+ const result = yield this.writeDataAsync(new SendDashTouchH2DPacket(x, y, press));
2123
+ return result instanceof SendDashTouchReplyD2HPacket ? result : null;
2124
+ });
2125
+ }
2126
+ /** @param port untested */
2127
+ openScreen(screen, port) {
2128
+ return __awaiter(this, void 0, void 0, function* () {
2129
+ const result = yield this.writeDataAsync(new SelectDashH2DPacket(screen, port));
2130
+ return result instanceof SendDashTouchReplyD2HPacket ? result : null;
2131
+ });
2132
+ }
2133
+ }
2134
+ function logData(data, limitedSize) {
2135
+ if (data === undefined)
2136
+ return;
2137
+ limitedSize || (limitedSize = data.length);
2138
+ let a = "";
2139
+ for (let n = 0; n < data.length && n < limitedSize; n++)
2140
+ a += ("00" + data[n].toString(16)).substr(-2, 2) + " ";
2141
+ limitedSize < data.length && (a += " ... ");
2142
+ // console.log(a);
2143
+ // XXX: NOT USED?
2144
+ }
2145
+ function binaryArrayJoin(left, right) {
2146
+ const leftSize = left != null ? left.byteLength : 0;
2147
+ const rightSize = right != null ? right.byteLength : 0;
2148
+ const all = new Uint8Array(leftSize + rightSize);
2149
+ return all.length === 0
2150
+ ? new Uint8Array()
2151
+ : (left != null && all.set(new Uint8Array(left), 0),
2152
+ right != null && all.set(new Uint8Array(right), leftSize),
2153
+ all);
2154
+ }
2155
+
2156
+ function downloadFileFromInternet(link) {
2157
+ return __awaiter(this, void 0, void 0, function* () {
2158
+ return yield new Promise((resolve, reject) => {
2159
+ const oReq = new XMLHttpRequest();
2160
+ oReq.open("GET", link, true);
2161
+ oReq.responseType = "arraybuffer";
2162
+ oReq.onload = function (_oEvent) {
2163
+ const arrayBuffer = oReq.response; // Note: not oReq.responseText
2164
+ resolve(arrayBuffer);
2165
+ };
2166
+ oReq.onerror = function (oEvent) {
2167
+ reject(oEvent);
2168
+ };
2169
+ oReq.send(null);
2170
+ });
2171
+ });
2172
+ }
2173
+ function sleepUntilAsync(f, timeout, interval = 20) {
2174
+ return __awaiter(this, void 0, void 0, function* () {
2175
+ return yield new Promise((resolve) => {
2176
+ let lastTime = new Date().getTime();
2177
+ let stopped = false;
2178
+ const stopper = setTimeout(() => {
2179
+ stopped = true;
2180
+ resolve(false);
2181
+ }, timeout);
2182
+ const checker = (val) => {
2183
+ if (stopped)
2184
+ return;
2185
+ if (val) {
2186
+ clearTimeout(stopper);
2187
+ resolve(true);
2188
+ }
2189
+ else if (new Date().getTime() - lastTime > interval) {
2190
+ lastTime = new Date().getTime();
2191
+ void f().then(checker);
2192
+ }
2193
+ else
2194
+ setTimeout(() => {
2195
+ lastTime = new Date().getTime();
2196
+ void f().then(checker);
2197
+ }, new Date().getTime() - lastTime);
2198
+ };
2199
+ void f().then(checker);
2200
+ });
2201
+ });
2202
+ }
2203
+ function sleepUntil(f, timeout, interval = 20) {
2204
+ return __awaiter(this, void 0, void 0, function* () {
2205
+ return yield new Promise((resolve) => {
2206
+ const timeWas = new Date().getTime();
2207
+ const wait = setInterval(function () {
2208
+ if (f()) {
2209
+ clearInterval(wait);
2210
+ resolve(true);
2211
+ }
2212
+ else if (new Date().getTime() - timeWas > timeout) {
2213
+ // Timeout
2214
+ clearInterval(wait);
2215
+ resolve(false);
2216
+ }
2217
+ }, interval);
2218
+ });
2219
+ });
2220
+ }
2221
+ function sleep(ms) {
2222
+ return __awaiter(this, void 0, void 0, function* () {
2223
+ return yield new Promise((resolve) => setTimeout(resolve, ms));
2224
+ });
2225
+ }
2226
+ class VexSerialDevice extends VexEventTarget {
2227
+ get isConnected() {
2228
+ return this.connection != null ? this.connection.isConnected : false;
2229
+ }
2230
+ get deviceType() {
2231
+ var _a, _b;
2232
+ return this.isConnected
2233
+ ? (_b = (_a = this.connection) === null || _a === void 0 ? void 0 : _a.port) === null || _b === void 0 ? void 0 : _b.getInfo().usbProductId
2234
+ : undefined;
2235
+ }
2236
+ constructor(defaultSerial) {
2237
+ super();
2238
+ this.defaultSerial = defaultSerial;
2239
+ }
2240
+ }
2241
+ class V5SerialDeviceState {
2242
+ constructor(instance) {
2243
+ this._isFileTransferring = false;
2244
+ this.brain = {
2245
+ activeProgram: 0,
2246
+ battery: {
2247
+ batteryPercent: 0,
2248
+ isCharging: false,
2249
+ },
2250
+ button: {
2251
+ isPressed: false,
2252
+ isDoublePressed: false,
2253
+ },
2254
+ cpu0Version: VexFirmwareVersion.allZero(),
2255
+ cpu1Version: VexFirmwareVersion.allZero(),
2256
+ isAvailable: false,
2257
+ settings: {
2258
+ isScreenReversed: false,
2259
+ isWhiteTheme: false,
2260
+ usingLanguage: 0,
2261
+ },
2262
+ systemVersion: VexFirmwareVersion.allZero(),
2263
+ uniqueId: 0,
2264
+ };
2265
+ this.controllers = [
2266
+ {
2267
+ battery: 0,
2268
+ isAvailable: false,
2269
+ isCharging: false,
2270
+ },
2271
+ {
2272
+ battery: 0,
2273
+ isAvailable: false,
2274
+ },
2275
+ ];
2276
+ this.devices = [];
2277
+ this.isFieldControllerConnected = false;
2278
+ this.matchMode = "disabled";
2279
+ this.radio = {
2280
+ channel: 0,
2281
+ isAvailable: false,
2282
+ isConnected: false,
2283
+ isVexNet: false,
2284
+ isRadioData: false,
2285
+ latency: 0,
2286
+ signalQuality: 0,
2287
+ signalStrength: 0,
2288
+ };
2289
+ this._instance = instance;
2290
+ }
2291
+ }
2292
+ class V5Brain {
2293
+ constructor(state) {
2294
+ this.state = state;
2295
+ }
2296
+ get isRunningProgram() {
2297
+ return this.activeProgram !== 0;
2298
+ }
2299
+ get activeProgram() {
2300
+ return this.state.brain.activeProgram;
2301
+ }
2302
+ set activeProgram(value) {
2303
+ void (() => __awaiter(this, void 0, void 0, function* () {
2304
+ if (this.state.brain.activeProgram === value)
2305
+ return;
2306
+ const conn = this.state._instance.connection;
2307
+ if (conn == null)
2308
+ return;
2309
+ const fn = value === 0
2310
+ ? yield conn.stopProgram()
2311
+ : yield conn.loadProgram(value);
2312
+ if (fn != null)
2313
+ this.state.brain.activeProgram = value;
2314
+ }))();
2315
+ }
2316
+ get battery() {
2317
+ return new V5Battery(this.state);
2318
+ }
2319
+ get button() {
2320
+ return new V5BrainButton(this.state);
2321
+ }
2322
+ get cpu0Version() {
2323
+ return this.state.brain.cpu0Version;
2324
+ }
2325
+ get cpu1Version() {
2326
+ return this.state.brain.cpu1Version;
2327
+ }
2328
+ get isAvailable() {
2329
+ return this.state.brain.isAvailable;
2330
+ }
2331
+ get settings() {
2332
+ return new V5BrainSettings(this.state);
2333
+ }
2334
+ get systemVersion() {
2335
+ return this.state.brain.systemVersion;
2336
+ }
2337
+ get uniqueId() {
2338
+ return this.state.brain.uniqueId;
2339
+ }
2340
+ getValue(key) {
2341
+ var _a;
2342
+ return __awaiter(this, void 0, void 0, function* () {
2343
+ const result = yield ((_a = this.state._instance.connection) === null || _a === void 0 ? void 0 : _a.writeDataAsync(new ReadKeyValueH2DPacket(key)));
2344
+ return result instanceof ReadKeyValueReplyD2HPacket
2345
+ ? result.value
2346
+ : undefined;
2347
+ });
2348
+ }
2349
+ setValue(key, value) {
2350
+ var _a;
2351
+ return __awaiter(this, void 0, void 0, function* () {
2352
+ const result = yield ((_a = this.state._instance.connection) === null || _a === void 0 ? void 0 : _a.writeDataAsync(new WriteKeyValueH2DPacket(key, value)));
2353
+ return result instanceof WriteKeyValueReplyD2HPacket;
2354
+ });
2355
+ }
2356
+ listFiles(vendor = exports.FileVendor.USER) {
2357
+ return __awaiter(this, void 0, void 0, function* () {
2358
+ const conn = this.state._instance.connection;
2359
+ if (conn == null || !conn.isConnected)
2360
+ return;
2361
+ const result = yield conn.writeDataAsync(new GetDirectoryFileCountH2DPacket(vendor));
2362
+ if (!(result instanceof GetDirectoryFileCountReplyD2HPacket))
2363
+ return;
2364
+ const files = [];
2365
+ for (let i = 0; i < result.count; i++) {
2366
+ const result2 = yield conn.writeDataAsync(new GetDirectoryEntryH2DPacket(i));
2367
+ if (!(result2 instanceof GetDirectoryEntryReplyD2HPacket))
2368
+ return;
2369
+ // .file is undefined if the file is not found
2370
+ // .file is a file entry but not a file handle
2371
+ if (result2.file != null) {
2372
+ files.push({
2373
+ filename: result2.file.filename,
2374
+ vendor,
2375
+ loadAddress: result2.file.loadAddress,
2376
+ size: result2.file.size,
2377
+ crc32: result2.file.crc32,
2378
+ type: result2.file.type,
2379
+ timestamp: result2.file.timestamp,
2380
+ version: result2.file.version,
2381
+ });
2382
+ }
2383
+ }
2384
+ return files;
2385
+ });
2386
+ }
2387
+ listProgram() {
2388
+ var _a, _b;
2389
+ return __awaiter(this, void 0, void 0, function* () {
2390
+ const conn = this.state._instance.connection;
2391
+ if (conn == null || !conn.isConnected)
2392
+ return;
2393
+ const files = yield this.listFiles(exports.FileVendor.USER);
2394
+ if (files === undefined)
2395
+ return;
2396
+ const programList = [];
2397
+ const iniFiles = files.filter((file) => { var _a; return (_a = (file === null || file === void 0 ? void 0 : file.filename.search(/.ini$/)) > 0) !== null && _a !== void 0 ? _a : false; });
2398
+ for (let i = 0; i < iniFiles.length; i++) {
2399
+ const ini = iniFiles[i];
2400
+ if (ini.size === 0)
2401
+ continue;
2402
+ const programName = (_b = (_a = /(.+?)(\.[^.]*$|$)/.exec(ini.filename)) === null || _a === void 0 ? void 0 : _a[1]) !== null && _b !== void 0 ? _b : "";
2403
+ const bin = files.filter((e) => e != null && e.filename === programName + ".bin")[0];
2404
+ if (bin == null || bin.timestamp === 0 || bin.size === 0)
2405
+ continue;
2406
+ const n = new Date();
2407
+ n.setTime(1000 * bin.timestamp);
2408
+ const program = {
2409
+ name: programName,
2410
+ binfile: bin.filename,
2411
+ size: ini.size + bin.size,
2412
+ slot: -1,
2413
+ time: n,
2414
+ requestedSlot: -1,
2415
+ };
2416
+ const result2 = yield (conn === null || conn === void 0 ? void 0 : conn.writeDataAsync(new GetProgramSlotInfoH2DPacket(exports.FileVendor.USER, program.binfile)));
2417
+ if (result2 instanceof GetProgramSlotInfoReplyD2HPacket) {
2418
+ program.slot = result2.slot;
2419
+ program.requestedSlot = result2.requestedSlot;
2420
+ }
2421
+ programList.push(program);
2422
+ }
2423
+ return programList;
2424
+ });
2425
+ }
2426
+ readFile(request, downloadTarget = exports.FileDownloadTarget.FILE_TARGET_QSPI, progressCallback) {
2427
+ return __awaiter(this, void 0, void 0, function* () {
2428
+ const conn = this.state._instance.connection;
2429
+ if (conn == null || !conn.isConnected)
2430
+ return;
2431
+ this.state._isFileTransferring = true;
2432
+ let handle;
2433
+ // If request is a string, then it is a filename
2434
+ if (typeof request === "string") {
2435
+ handle = { filename: request, vendor: exports.FileVendor.USER };
2436
+ }
2437
+ else {
2438
+ handle = request;
2439
+ }
2440
+ try {
2441
+ return yield conn.downloadFileToHost(handle, downloadTarget, progressCallback);
2442
+ }
2443
+ catch (e) {
2444
+ this.state._isFileTransferring = false;
2445
+ throw e;
2446
+ }
2447
+ });
2448
+ }
2449
+ removeFile(request) {
2450
+ return __awaiter(this, void 0, void 0, function* () {
2451
+ const conn = this.state._instance.connection;
2452
+ if (conn == null || !conn.isConnected)
2453
+ return;
2454
+ let vendor, filename;
2455
+ // If request is a string, then it is a filename
2456
+ if (typeof request === "string") {
2457
+ vendor = exports.FileVendor.USER;
2458
+ filename = request;
2459
+ }
2460
+ else {
2461
+ vendor = request.vendor;
2462
+ filename = request.filename;
2463
+ }
2464
+ const result = yield conn.writeDataAsync(new EraseFileH2DPacket(vendor, filename));
2465
+ const result2 = yield conn.writeDataAsync(new ExitFileTransferH2DPacket(exports.FileExitAction.EXIT_HALT));
2466
+ if (!(result instanceof EraseFileReplyD2HPacket))
2467
+ return false;
2468
+ if (!(result2 instanceof ExitFileTransferReplyD2HPacket))
2469
+ return false;
2470
+ return true;
2471
+ });
2472
+ }
2473
+ removeAllFiles() {
2474
+ return __awaiter(this, void 0, void 0, function* () {
2475
+ const conn = this.state._instance.connection;
2476
+ if (conn == null || !conn.isConnected)
2477
+ return undefined;
2478
+ const result = yield conn.writeDataAsync(new FileClearUpH2DPacket(exports.FileVendor.USER), 30000);
2479
+ return result instanceof FileClearUpReplyD2HPacket;
2480
+ });
2481
+ }
2482
+ uploadFirmware(publicUrl = "https://content.vexrobotics.com/vexos/public/V5/", usingVersion, progressCallback) {
2483
+ return __awaiter(this, void 0, void 0, function* () {
2484
+ const device = this.state._instance;
2485
+ const conn = device.connection;
2486
+ if (conn == null || !conn.isConnected)
2487
+ return;
2488
+ const pcb = progressCallback !== null && progressCallback !== void 0 ? progressCallback : (() => { });
2489
+ let vexos, bootBin, assertBin;
2490
+ try {
2491
+ if (usingVersion === undefined) {
2492
+ pcb("FETCH CATALOG", 0, 1);
2493
+ const catalog = yield downloadFileFromInternet(publicUrl + "catalog.txt");
2494
+ const latestVersion = new TextDecoder().decode(catalog);
2495
+ usingVersion = latestVersion;
2496
+ pcb("FETCH CATALOG", 1, 1);
2497
+ console.log("fetched catalog.txt", latestVersion);
2498
+ }
2499
+ pcb("FETCH VEXOS", 0, 1);
2500
+ vexos = yield downloadFileFromInternet(publicUrl + usingVersion + ".vexos");
2501
+ pcb("FETCH VEXOS", 1, 1);
2502
+ pcb("UNZIP VEXOS", 0, 1);
2503
+ const { unzip } = yield Promise.resolve().then(function () { return unzipit_module; });
2504
+ const { entries } = yield unzip(vexos);
2505
+ bootBin = yield entries[usingVersion + "/BOOT.bin"].arrayBuffer();
2506
+ assertBin = yield entries[usingVersion + "/assets.bin"].arrayBuffer();
2507
+ pcb("UNZIP VEXOS", 1, 1);
2508
+ }
2509
+ catch (e) {
2510
+ return undefined;
2511
+ }
2512
+ try {
2513
+ this.state._isFileTransferring = true;
2514
+ pcb("FACTORY ENB BOOT", 0, 0);
2515
+ const result = yield conn.writeDataAsync(new FactoryEnableH2DPacket());
2516
+ if (!(result instanceof FactoryEnableReplyD2HPacket))
2517
+ return false;
2518
+ const bootWriteRequest = {
2519
+ filename: "null.bin",
2520
+ vendor: exports.FileVendor.USER,
2521
+ loadAddress: USER_FLASH_USR_CODE_START,
2522
+ buf: new Uint8Array(bootBin),
2523
+ downloadTarget: exports.FileDownloadTarget.FILE_TARGET_B1,
2524
+ exttype: "bin",
2525
+ autoRun: true,
2526
+ linkedFile: undefined,
2527
+ };
2528
+ const result2 = yield conn.uploadFileToDevice(bootWriteRequest, (c, t) => {
2529
+ pcb("UPLOAD BOOT", c, t);
2530
+ });
2531
+ if (!result2)
2532
+ return false;
2533
+ while (true) {
2534
+ const result3 = yield conn.writeDataAsync(new FactoryStatusH2DPacket(), 10000);
2535
+ if (result3 instanceof FactoryStatusReplyD2HPacket) {
2536
+ switch (result3.status) {
2537
+ case 2:
2538
+ pcb("ERASE BOOT", result3.percent, 100);
2539
+ break;
2540
+ case 3:
2541
+ pcb("WRITE BOOT", result3.percent, 100);
2542
+ break;
2543
+ case 4:
2544
+ pcb("VERIFY BOOT", result3.percent, 100);
2545
+ break;
2546
+ case 8:
2547
+ pcb("FINISHING BOOT", result3.percent, 100);
2548
+ break;
2549
+ }
2550
+ if (result3.status === 0 && result3.percent === 100)
2551
+ break;
2552
+ }
2553
+ else {
2554
+ return false;
2555
+ }
2556
+ yield sleep(500);
2557
+ }
2558
+ pcb("FACTORY ENB ASSERT", 0, 0);
2559
+ const result5 = yield conn.writeDataAsync(new FactoryEnableH2DPacket());
2560
+ if (!(result5 instanceof FactoryEnableReplyD2HPacket))
2561
+ return false;
2562
+ const assertWriteRequest = {
2563
+ filename: "null.bin",
2564
+ vendor: exports.FileVendor.USER,
2565
+ loadAddress: USER_FLASH_USR_CODE_START,
2566
+ buf: new Uint8Array(assertBin),
2567
+ downloadTarget: exports.FileDownloadTarget.FILE_TARGET_A1,
2568
+ exttype: "bin",
2569
+ autoRun: true,
2570
+ linkedFile: undefined,
2571
+ };
2572
+ const result6 = yield conn.uploadFileToDevice(assertWriteRequest, (c, t) => {
2573
+ pcb("UPLOAD ASSERT", c, t);
2574
+ });
2575
+ if (!result6)
2576
+ return false;
2577
+ while (true) {
2578
+ const result7 = yield conn.writeDataAsync(new FactoryStatusH2DPacket(), 10000);
2579
+ if (result7 instanceof FactoryStatusReplyD2HPacket) {
2580
+ switch (result7.status) {
2581
+ case 2:
2582
+ pcb("ERASE ASSERT", result7.percent, 100);
2583
+ break;
2584
+ case 3:
2585
+ pcb("WRITE ASSERT", result7.percent, 100);
2586
+ break;
2587
+ case 4:
2588
+ pcb("VERIFY ASSERT", result7.percent, 100);
2589
+ break;
2590
+ case 8:
2591
+ pcb("FINISHING ASSERT", result7.percent, 100);
2592
+ break;
2593
+ }
2594
+ if (result7.status === 0 && result7.percent === 100)
2595
+ break;
2596
+ }
2597
+ else {
2598
+ return false;
2599
+ }
2600
+ yield sleep(500);
2601
+ }
2602
+ }
2603
+ catch (e) {
2604
+ this.state._isFileTransferring = false;
2605
+ throw e;
2606
+ }
2607
+ return true;
2608
+ });
2609
+ }
2610
+ uploadProgram(iniConfig, binFileBuf, coldFileBuf, progressCallback) {
2611
+ return __awaiter(this, void 0, void 0, function* () {
2612
+ const device = this.state._instance;
2613
+ const conn = device.connection;
2614
+ if (conn == null || !conn.isConnected)
2615
+ return;
2616
+ this.state._isFileTransferring = true;
2617
+ try {
2618
+ if (device.isV5Controller) {
2619
+ yield sleep(250);
2620
+ // V5 Controller doesn\'t appear to be connected to a V5 Brain
2621
+ if (!(yield device.refresh()))
2622
+ return;
2623
+ console.log("Transferring to download channel");
2624
+ const p1 = yield device.radio.changeChannel(exports.RadioChannelType.DOWNLOAD);
2625
+ if (!p1)
2626
+ return false;
2627
+ yield sleep(250);
2628
+ yield sleepUntilAsync(() => __awaiter(this, void 0, void 0, function* () { return (yield (conn === null || conn === void 0 ? void 0 : conn.getSystemStatus(150))) != null; }), 10000, 200);
2629
+ console.log("Transferred to download channel");
2630
+ }
2631
+ const p2 = yield conn.uploadProgramToDevice(iniConfig, binFileBuf, coldFileBuf, progressCallback);
2632
+ if (!(p2 !== null && p2 !== void 0 ? p2 : false))
2633
+ return false;
2634
+ if (device.isV5Controller) {
2635
+ // Disconnected
2636
+ if (!device.brain.isAvailable)
2637
+ return false;
2638
+ console.log("Transferring back to pit channel");
2639
+ const p3 = yield device.radio.changeChannel(exports.RadioChannelType.PIT);
2640
+ if (!p3)
2641
+ return false;
2642
+ yield sleep(250);
2643
+ yield sleepUntilAsync(() => __awaiter(this, void 0, void 0, function* () { return (yield (conn === null || conn === void 0 ? void 0 : conn.getSystemStatus(150))) != null; }), 10000, 200);
2644
+ console.log("All done");
2645
+ }
2646
+ return true;
2647
+ }
2648
+ catch (e) {
2649
+ this.state._isFileTransferring = false;
2650
+ throw e;
2651
+ }
2652
+ });
2653
+ }
2654
+ writeFile(request, progressCallback) {
2655
+ return __awaiter(this, void 0, void 0, function* () {
2656
+ this.state._isFileTransferring = true;
2657
+ const conn = this.state._instance.connection;
2658
+ if (conn == null || !conn.isConnected)
2659
+ return undefined;
2660
+ try {
2661
+ return yield conn.uploadFileToDevice(request, progressCallback);
2662
+ }
2663
+ catch (e) {
2664
+ this.state._isFileTransferring = false;
2665
+ throw e;
2666
+ }
2667
+ });
2668
+ }
2669
+ /**
2670
+ *
2671
+ * @param progressCallback Informs the progress of the download.
2672
+ * @returns array of bytes where each pixel is represented by 3 consecutive bytes (rgb).
2673
+ * This array's length is 272 width * 480 height * 3 channels = 391680 bytes.
2674
+ */
2675
+ captureScreen(progressCallback) {
2676
+ return __awaiter(this, void 0, void 0, function* () {
2677
+ // pros implementation: https://github.com/purduesigbots/pros-cli/blob/5ee18656faeb48f51d680bab4b53d5b59cc5a7d5/pros/serial/devices/vex/v5_device.py#L578
2678
+ const conn = this.state._instance.connection;
2679
+ if (conn == null || !conn.isConnected)
2680
+ return undefined;
2681
+ yield new Promise((resolve) => {
2682
+ conn.writeData(new ScreenCaptureH2DPacket(0), resolve);
2683
+ });
2684
+ const height = 272;
2685
+ const width = 480;
2686
+ const channels = 3;
2687
+ const messageWidth = 512; // brain goofiness
2688
+ const messageChannels = 4; // brain goofiness
2689
+ let buf = yield (conn === null || conn === void 0 ? void 0 : conn.downloadFileToHost({
2690
+ filename: "screen",
2691
+ vendor: exports.FileVendor.SYS,
2692
+ loadAddress: 0,
2693
+ size: messageWidth * height * messageChannels, // RGBA ig
2694
+ }, exports.FileDownloadTarget.FILE_TARGET_CBUF, progressCallback));
2695
+ if (buf == null)
2696
+ return;
2697
+ buf = buf
2698
+ // remove the extra columns
2699
+ .filter((_byte, i) => i % (messageWidth * messageChannels) < width * messageChannels)
2700
+ // remove the fake alpha channel
2701
+ .filter((_byte, i) => (i + 1) % messageChannels !== 0);
2702
+ // reverse the pixel (bgr -> rgb)
2703
+ for (let i = 0; i < buf.length; i += channels) {
2704
+ const px = buf.slice(i, i + channels).reverse();
2705
+ for (let j = 0; j < px.length; j++) {
2706
+ buf[i + j] = px[j];
2707
+ }
2708
+ }
2709
+ return buf;
2710
+ });
2711
+ }
2712
+ }
2713
+ class V5Battery {
2714
+ constructor(state) {
2715
+ this.state = state;
2716
+ }
2717
+ get batteryPercent() {
2718
+ return this.state.brain.battery.batteryPercent;
2719
+ }
2720
+ get isCharging() {
2721
+ return this.state.brain.battery.isCharging;
2722
+ }
2723
+ }
2724
+ class V5BrainButton {
2725
+ constructor(state) {
2726
+ this.state = state;
2727
+ }
2728
+ get isPressed() {
2729
+ return this.state.brain.button.isPressed;
2730
+ }
2731
+ get isDoublePressed() {
2732
+ return this.state.brain.button.isDoublePressed;
2733
+ }
2734
+ }
2735
+ class V5BrainSettings {
2736
+ constructor(state) {
2737
+ this.state = state;
2738
+ }
2739
+ get isScreenReversed() {
2740
+ return this.state.brain.settings.isScreenReversed;
2741
+ }
2742
+ get isWhiteTheme() {
2743
+ return this.state.brain.settings.isWhiteTheme;
2744
+ }
2745
+ get usingLanguage() {
2746
+ return this.state.brain.settings.usingLanguage;
2747
+ }
2748
+ }
2749
+ class V5Controller {
2750
+ constructor(state, controllerIndex) {
2751
+ this.state = state;
2752
+ this.controllerIndex = controllerIndex;
2753
+ }
2754
+ get batteryPercent() {
2755
+ return this.state.controllers[this.controllerIndex].battery;
2756
+ }
2757
+ get isMasterController() {
2758
+ return this.controllerIndex === 0;
2759
+ }
2760
+ get isAvailable() {
2761
+ return this.state.controllers[this.controllerIndex].isAvailable;
2762
+ }
2763
+ get isCharging() {
2764
+ return this.state.controllers[this.controllerIndex].isCharging;
2765
+ }
2766
+ }
2767
+ class V5SmartDevice {
2768
+ constructor(state, index) {
2769
+ this.state = state;
2770
+ this.deviceIndex = index;
2771
+ }
2772
+ getDeviceInfo() {
2773
+ return this.state.devices[this.deviceIndex];
2774
+ }
2775
+ get isAvailable() {
2776
+ return this.getDeviceInfo() !== undefined;
2777
+ }
2778
+ get port() {
2779
+ return this.deviceIndex;
2780
+ }
2781
+ get type() {
2782
+ var _a, _b;
2783
+ return (_b = (_a = this.getDeviceInfo()) === null || _a === void 0 ? void 0 : _a.type) !== null && _b !== void 0 ? _b : exports.SmartDeviceType.EMPTY;
2784
+ }
2785
+ get version() {
2786
+ var _a, _b;
2787
+ return (_b = (_a = this.getDeviceInfo()) === null || _a === void 0 ? void 0 : _a.version) !== null && _b !== void 0 ? _b : 0;
2788
+ }
2789
+ }
2790
+ class V5Radio {
2791
+ constructor(state) {
2792
+ this.state = state;
2793
+ }
2794
+ get channel() {
2795
+ return this.state.radio.channel;
2796
+ }
2797
+ get isAvailable() {
2798
+ return this.state.radio.isAvailable;
2799
+ }
2800
+ get isConnected() {
2801
+ return this.state.radio.isConnected;
2802
+ }
2803
+ get isVexNet() {
2804
+ return this.state.radio.isVexNet;
2805
+ }
2806
+ get isRadioData() {
2807
+ return this.state.radio.isRadioData;
2808
+ }
2809
+ get latency() {
2810
+ return this.state.radio.latency;
2811
+ }
2812
+ changeChannel(channel) {
2813
+ var _a;
2814
+ return __awaiter(this, void 0, void 0, function* () {
2815
+ const result = yield ((_a = this.state._instance.connection) === null || _a === void 0 ? void 0 : _a.writeDataAsync(new FileControlH2DPacket(1, channel)));
2816
+ return result instanceof FileControlReplyD2HPacket;
2817
+ });
2818
+ }
2819
+ }
2820
+ class V5SerialDevice extends VexSerialDevice {
2821
+ constructor(defaultSerial) {
2822
+ super(defaultSerial);
2823
+ this.autoReconnect = true;
2824
+ this.autoRefresh = true;
2825
+ this.pauseRefreshOnFileTransfer = true;
2826
+ this._isReconnecting = false;
2827
+ this.state = new V5SerialDeviceState(this);
2828
+ let isLastRefreshComplete = true;
2829
+ this._refreshInterval = setInterval(() => {
2830
+ if (this.autoRefresh && isLastRefreshComplete) {
2831
+ if (!this.isConnected) {
2832
+ this.state.brain.isAvailable = false;
2833
+ return;
2834
+ }
2835
+ if (!this.pauseRefreshOnFileTransfer ||
2836
+ !this.state._isFileTransferring) {
2837
+ isLastRefreshComplete = false;
2838
+ void this.refresh().finally(() => (isLastRefreshComplete = true));
2839
+ }
2840
+ }
2841
+ }, 200);
2842
+ }
2843
+ get isV5Controller() {
2844
+ return this.deviceType === exports.SerialDeviceType.V5_CONTROLLER;
2845
+ }
2846
+ get brain() {
2847
+ return new V5Brain(this.state);
2848
+ }
2849
+ get controllers() {
2850
+ return [new V5Controller(this.state, 0), new V5Controller(this.state, 1)];
2851
+ }
2852
+ get devices() {
2853
+ const rtn = [];
2854
+ for (let i = 1; i <= this.state.devices.length; i++) {
2855
+ if (this.state.devices[i] != null)
2856
+ rtn.push(new V5SmartDevice(this.state, i));
2857
+ }
2858
+ return rtn;
2859
+ }
2860
+ get isFieldControllerConnected() {
2861
+ return this.state.isFieldControllerConnected;
2862
+ }
2863
+ get matchMode() {
2864
+ return this.state.matchMode;
2865
+ }
2866
+ set matchMode(value) {
2867
+ void (() => __awaiter(this, void 0, void 0, function* () {
2868
+ var _a;
2869
+ if ((yield ((_a = this.connection) === null || _a === void 0 ? void 0 : _a.setMatchMode(value))) != null)
2870
+ this.state.matchMode = value;
2871
+ }))();
2872
+ }
2873
+ get radio() {
2874
+ return new V5Radio(this.state);
2875
+ }
2876
+ mockTouch(x, y, press) {
2877
+ var _a;
2878
+ return __awaiter(this, void 0, void 0, function* () {
2879
+ return !((yield ((_a = this.connection) === null || _a === void 0 ? void 0 : _a.mockTouch(x, y, press))) == null);
2880
+ });
2881
+ }
2882
+ connect(conn) {
2883
+ return __awaiter(this, void 0, void 0, function* () {
2884
+ if (this.isConnected)
2885
+ return true;
2886
+ if (conn != null && !conn.isConnected) {
2887
+ if ((yield conn.query1()) === null)
2888
+ return false;
2889
+ this.connection = conn;
2890
+ }
2891
+ else {
2892
+ let tryIdx = 0;
2893
+ while (true) {
2894
+ const c = new V5SerialConnection(this.defaultSerial);
2895
+ const result = yield c.open(tryIdx++, true);
2896
+ if (result === undefined)
2897
+ return false; // no port left
2898
+ if (!result) {
2899
+ // has been opened
2900
+ yield c.close();
2901
+ continue;
2902
+ }
2903
+ if ((yield c.query1()) === null) {
2904
+ // no response
2905
+ yield c.close();
2906
+ continue;
2907
+ }
2908
+ this.connection = c;
2909
+ break;
2910
+ }
2911
+ }
2912
+ if (!this.isConnected)
2913
+ return false;
2914
+ yield this.doAfterConnect();
2915
+ return true;
2916
+ });
2917
+ }
2918
+ disconnect() {
2919
+ var _a;
2920
+ return __awaiter(this, void 0, void 0, function* () {
2921
+ yield ((_a = this.connection) === null || _a === void 0 ? void 0 : _a.close());
2922
+ this.connection = undefined;
2923
+ });
2924
+ }
2925
+ dispose() {
2926
+ return __awaiter(this, void 0, void 0, function* () {
2927
+ this.autoReconnect = false;
2928
+ this.autoRefresh = false;
2929
+ clearInterval(this._refreshInterval);
2930
+ yield this.disconnect();
2931
+ });
2932
+ }
2933
+ /**
2934
+ * @param timeout defaults to 0. If timeout is 0, then it will attempt to reconnect forever
2935
+ * @returns
2936
+ */
2937
+ reconnect(timeout = 0) {
2938
+ return __awaiter(this, void 0, void 0, function* () {
2939
+ if (this.isConnected)
2940
+ return true;
2941
+ if (timeout < 0)
2942
+ return false;
2943
+ const endTime = new Date().getTime() + timeout;
2944
+ if (this._isReconnecting) {
2945
+ let successBeforeTimeout;
2946
+ do {
2947
+ successBeforeTimeout = yield sleepUntil(() => !this._isReconnecting, timeout === 0 ? 1000 : timeout);
2948
+ // eslint-disable-next-line no-unmodified-loop-condition
2949
+ } while (timeout === 0 && !successBeforeTimeout);
2950
+ if (this.isConnected)
2951
+ return true;
2952
+ if (!successBeforeTimeout)
2953
+ return false;
2954
+ }
2955
+ this._isReconnecting = true;
2956
+ // eslint-disable-next-line no-unmodified-loop-condition
2957
+ while (timeout === 0 || new Date().getTime() < endTime) {
2958
+ // console.log("try to reconnect");
2959
+ let tryIdx = 0;
2960
+ while (true) {
2961
+ const c = new V5SerialConnection(this.defaultSerial);
2962
+ const result = yield c.open(tryIdx++, false);
2963
+ if (result === undefined)
2964
+ break; // no port left
2965
+ if (!result) {
2966
+ // has been opened
2967
+ yield c.close();
2968
+ continue;
2969
+ }
2970
+ const result2 = yield c.getSystemStatus(200);
2971
+ if (result2 === null) {
2972
+ // no response
2973
+ yield c.close();
2974
+ continue;
2975
+ }
2976
+ if (this.brain.uniqueId !== 0 &&
2977
+ result2.uniqueId !== this.brain.uniqueId) {
2978
+ // uuid not match
2979
+ yield c.close();
2980
+ continue;
2981
+ }
2982
+ this.connection = c;
2983
+ break;
2984
+ }
2985
+ if (this.isConnected)
2986
+ break;
2987
+ // try again every second or when the number of ports is different
2988
+ const getPortCount = () => __awaiter(this, void 0, void 0, function* () { return (yield this.defaultSerial.getPorts()).length; });
2989
+ const portsCount = yield getPortCount();
2990
+ yield sleepUntilAsync(() => __awaiter(this, void 0, void 0, function* () { return (yield getPortCount()) !== portsCount; }), 1000);
2991
+ }
2992
+ this._isReconnecting = false;
2993
+ if (!this.isConnected)
2994
+ return false;
2995
+ void this.doAfterConnect();
2996
+ return true;
2997
+ });
2998
+ }
2999
+ doAfterConnect() {
3000
+ return __awaiter(this, void 0, void 0, function* () {
3001
+ if (this.connection == null)
3002
+ return;
3003
+ //console.log("doAfterConnect");
3004
+ this.connection.on("disconnected", (_data) => {
3005
+ if (this.autoReconnect)
3006
+ void this.reconnect();
3007
+ });
3008
+ yield this.refresh();
3009
+ });
3010
+ }
3011
+ refresh() {
3012
+ var _a, _b, _c, _d, _e, _f, _g;
3013
+ return __awaiter(this, void 0, void 0, function* () {
3014
+ const ssPacket = yield ((_a = this.connection) === null || _a === void 0 ? void 0 : _a.getSystemStatus());
3015
+ if (ssPacket == null) {
3016
+ this.state.brain.isAvailable = false;
3017
+ return false;
3018
+ }
3019
+ this.state.brain.cpu0Version = ssPacket.cpu0Version;
3020
+ this.state.brain.cpu1Version = ssPacket.cpu1Version;
3021
+ this.state.brain.systemVersion = ssPacket.systemVersion;
3022
+ const flags2 = ssPacket.sysflags[2];
3023
+ this.state.controllers[0].isCharging = (flags2 & 0b10000000) !== 0;
3024
+ this.state.matchMode =
3025
+ (flags2 & 0b00100000) !== 0
3026
+ ? "disabled"
3027
+ : (flags2 & 0b01000000) !== 0
3028
+ ? "autonomous"
3029
+ : "driver";
3030
+ this.state.isFieldControllerConnected = (flags2 & 0b00010000) !== 0;
3031
+ const flags4 = ssPacket.sysflags[4];
3032
+ this.state.brain.settings.usingLanguage = (flags4 & 0b11110000) >> 4;
3033
+ this.state.brain.settings.isWhiteTheme = (flags4 & 0b00000100) !== 0;
3034
+ this.state.brain.settings.isScreenReversed = (flags4 & 0b00000001) === 0;
3035
+ this.state.brain.uniqueId = ssPacket.uniqueId;
3036
+ const sfPacket = yield ((_b = this.connection) === null || _b === void 0 ? void 0 : _b.getSystemFlags());
3037
+ if (sfPacket == null)
3038
+ return false;
3039
+ const flags5 = sfPacket.flags; // Math.pow(2, 32 - i);
3040
+ this.state.radio.isRadioData = (flags5 & Math.pow(2, 32 - 12)) !== 0;
3041
+ this.state.brain.button.isDoublePressed =
3042
+ (flags5 & Math.pow(2, 32 - 14)) !== 0;
3043
+ this.state.brain.battery.isCharging = (flags5 & Math.pow(2, 32 - 15)) !== 0;
3044
+ this.state.brain.button.isPressed = (flags5 & Math.pow(2, 32 - 17)) !== 0;
3045
+ this.state.radio.isVexNet = (flags5 & Math.pow(2, 32 - 18)) !== 0;
3046
+ this.state.controllers[1].isAvailable =
3047
+ (flags5 & Math.pow(2, 32 - 19)) !== 0;
3048
+ this.state.radio.isConnected = (flags5 & Math.pow(2, 32 - 22)) !== 0;
3049
+ this.state.radio.isAvailable = (flags5 & Math.pow(2, 32 - 23)) !== 0;
3050
+ this.state.brain.battery.batteryPercent = (_c = sfPacket.battery) !== null && _c !== void 0 ? _c : 0;
3051
+ this.state.controllers[0].isAvailable =
3052
+ this.state.radio.isConnected || this.state.controllers[0].isCharging;
3053
+ this.state.controllers[0].battery = (_d = sfPacket.controllerBatteryPercent) !== null && _d !== void 0 ? _d : 0;
3054
+ this.state.controllers[1].battery =
3055
+ (_e = sfPacket.partnerControllerBatteryPercent) !== null && _e !== void 0 ? _e : 0;
3056
+ this.state.brain.activeProgram = sfPacket.currentProgram;
3057
+ this.state.brain.isAvailable =
3058
+ !this.isV5Controller || this.state.radio.isConnected;
3059
+ const rdPacket = yield ((_f = this.connection) === null || _f === void 0 ? void 0 : _f.getRadioStatus());
3060
+ if (rdPacket == null)
3061
+ return false;
3062
+ this.state.radio.channel = rdPacket.channel;
3063
+ this.state.radio.latency = rdPacket.timeslot;
3064
+ this.state.radio.signalQuality = rdPacket.quality;
3065
+ this.state.radio.signalStrength = rdPacket.strength;
3066
+ const dsPacket = yield ((_g = this.connection) === null || _g === void 0 ? void 0 : _g.getDeviceStatus());
3067
+ if (dsPacket == null)
3068
+ return false;
3069
+ let missingPorts = this.state.devices
3070
+ .map((d) => d === null || d === void 0 ? void 0 : d.port)
3071
+ .filter((p) => p !== undefined);
3072
+ for (let i = 0; i < dsPacket.devices.length; i++) {
3073
+ const device = dsPacket.devices[i];
3074
+ this.state.devices[device.port] = device;
3075
+ // remove device port from missing ports
3076
+ missingPorts = missingPorts.filter((p) => p !== device.port);
3077
+ }
3078
+ missingPorts.forEach((port) => {
3079
+ this.state.devices[port] = undefined;
3080
+ });
3081
+ return true;
3082
+ });
3083
+ }
3084
+ }
3085
+
3086
+ // hey this code seemed really goofy to me, so I changed it,
3087
+ // see https://github.com/LemLib/v5-serial-protocol/blob/ef8df5019a5504b5b96fc887ef1587d9ecaa84ea/src/VexIniConfig.ts
3088
+ // for unchanged code
3089
+ // -@meisZWFLZ
3090
+ class BaseIniBuilder {
3091
+ constructor() {
3092
+ this.str = "";
3093
+ }
3094
+ addLine(line) {
3095
+ this.str += line + "\n";
3096
+ }
3097
+ addComment(comment) {
3098
+ this.addLine("; " + comment);
3099
+ return this;
3100
+ }
3101
+ getContent() {
3102
+ return this.str;
3103
+ }
3104
+ }
3105
+ class IniSectionBuilder extends BaseIniBuilder {
3106
+ constructor(name, object, keyTransform = (k) => k.toString()) {
3107
+ super();
3108
+ this.name = name;
3109
+ this.object = object;
3110
+ this.keyTransform = keyTransform;
3111
+ }
3112
+ addSingleObjProperty(key, maxValueLength) {
3113
+ // if property is empty or nullish, skip it
3114
+ if (this.object[key] == null || this.object[key].toString().length === 0)
3115
+ return;
3116
+ const formattedKey = this.keyTransform(key).padEnd(12).slice(0, 12);
3117
+ const trimmedVal = this.object[key].toString().slice(0, maxValueLength);
3118
+ this.addLine(`${formattedKey} = "${trimmedVal}"`);
3119
+ }
3120
+ addObjProperty(key, maxValueLength) {
3121
+ const keys = Array.isArray(key) ? key : [key];
3122
+ for (const k of keys) {
3123
+ this.addSingleObjProperty(k, maxValueLength);
3124
+ }
3125
+ return this;
3126
+ }
3127
+ addAllObjProps(maxValueLength) {
3128
+ const keys = Object.keys(this.object);
3129
+ for (const k of keys) {
3130
+ this.addSingleObjProperty(k, maxValueLength);
3131
+ }
3132
+ return this;
3133
+ }
3134
+ }
3135
+ class IniFileBuilder extends BaseIniBuilder {
3136
+ addSection(section) {
3137
+ this.addLine(`[${section.name}]`);
3138
+ this.str += section.getContent();
3139
+ return this;
3140
+ }
3141
+ }
3142
+ class ProgramIniConfig {
3143
+ // private options: { [key: string]: string } = {};
3144
+ constructor() {
3145
+ this.baseName = "slot_1";
3146
+ this.autorun = false;
3147
+ this.project = { version: "1", ide: "Unknown", file: "none" };
3148
+ this.program = {
3149
+ version: "1",
3150
+ name: "program",
3151
+ slot: 0,
3152
+ icon: "default.bmp",
3153
+ iconalt: "",
3154
+ description: "",
3155
+ date: "",
3156
+ timezone: "0",
3157
+ };
3158
+ this.config = {}; // { port_22: "..." }
3159
+ this.controller1 = {};
3160
+ this.controller2 = {};
3161
+ this.config = {
3162
+ 22: "adi",
3163
+ };
3164
+ }
3165
+ setProgramDate(date) {
3166
+ const d = date;
3167
+ this.program.date = d.toISOString();
3168
+ const tzo = Math.abs(d.getTimezoneOffset());
3169
+ const tzh = (tzo / 60) >>> 0;
3170
+ const tzm = tzo - tzh * 60;
3171
+ this.program.timezone =
3172
+ (d.getTimezoneOffset() > 0 ? "-" : "+") +
3173
+ this.dec2(tzh) +
3174
+ ":" +
3175
+ this.dec2(tzm);
3176
+ }
3177
+ createIni() {
3178
+ if (this.program.date.length === 0) {
3179
+ this.setProgramDate(new Date());
3180
+ }
3181
+ return new IniFileBuilder()
3182
+ .addComment("")
3183
+ .addComment("VEX program ini file")
3184
+ .addComment("Generated by Vex V5 Serial Protocol Library")
3185
+ .addComment("")
3186
+ .addSection(new IniSectionBuilder("project", this.project).addObjProperty("ide", 16))
3187
+ .addComment("")
3188
+ .addSection(new IniSectionBuilder("program", this.program)
3189
+ .addObjProperty("name", 32)
3190
+ .addObjProperty("description", 256)
3191
+ .addObjProperty("icon", 16)
3192
+ .addObjProperty("iconalt", 16)
3193
+ .addObjProperty("slot", 16))
3194
+ .addComment("")
3195
+ .addSection(new IniSectionBuilder("config", this.config, (k) => "port_" + this.dec2(k)).addAllObjProps())
3196
+ .addComment("")
3197
+ .addSection(new IniSectionBuilder("controller_1", this.controller1).addAllObjProps())
3198
+ .addComment("")
3199
+ .addSection(new IniSectionBuilder("controller_2", this.controller2).addAllObjProps())
3200
+ .getContent();
3201
+ }
3202
+ dec2(value) {
3203
+ const str = ("00" + value.toString(10)).substr(-2, 2);
3204
+ return str.toUpperCase();
3205
+ }
3206
+ }
3207
+
3208
+ /* unzipit@1.4.3, license MIT */
3209
+ /* global SharedArrayBuffer, process */
3210
+
3211
+ function readBlobAsArrayBuffer(blob) {
3212
+ if (blob.arrayBuffer) {
3213
+ return blob.arrayBuffer();
3214
+ }
3215
+ return new Promise((resolve, reject) => {
3216
+ const reader = new FileReader();
3217
+ reader.addEventListener('loadend', () => {
3218
+ resolve(reader.result);
3219
+ });
3220
+ reader.addEventListener('error', reject);
3221
+ reader.readAsArrayBuffer(blob);
3222
+ });
3223
+ }
3224
+
3225
+ async function readBlobAsUint8Array(blob) {
3226
+ const arrayBuffer = await readBlobAsArrayBuffer(blob);
3227
+ return new Uint8Array(arrayBuffer);
3228
+ }
3229
+
3230
+ function isBlob(v) {
3231
+ return typeof Blob !== 'undefined' && v instanceof Blob;
3232
+ }
3233
+
3234
+ function isSharedArrayBuffer(b) {
3235
+ return typeof SharedArrayBuffer !== 'undefined' && b instanceof SharedArrayBuffer;
3236
+ }
3237
+
3238
+ const isNode =
3239
+ (typeof process !== 'undefined') &&
3240
+ process.versions &&
3241
+ (typeof process.versions.node !== 'undefined') &&
3242
+ (typeof process.versions.electron === 'undefined');
3243
+
3244
+ function isTypedArraySameAsArrayBuffer(typedArray) {
3245
+ return typedArray.byteOffset === 0 && typedArray.byteLength === typedArray.buffer.byteLength;
3246
+ }
3247
+
3248
+ class ArrayBufferReader {
3249
+ constructor(arrayBufferOrView) {
3250
+ this.typedArray = (arrayBufferOrView instanceof ArrayBuffer || isSharedArrayBuffer(arrayBufferOrView))
3251
+ ? new Uint8Array(arrayBufferOrView)
3252
+ : new Uint8Array(arrayBufferOrView.buffer, arrayBufferOrView.byteOffset, arrayBufferOrView.byteLength);
3253
+ }
3254
+ async getLength() {
3255
+ return this.typedArray.byteLength;
3256
+ }
3257
+ async read(offset, length) {
3258
+ return new Uint8Array(this.typedArray.buffer, this.typedArray.byteOffset + offset, length);
3259
+ }
3260
+ }
3261
+
3262
+ class BlobReader {
3263
+ constructor(blob) {
3264
+ this.blob = blob;
3265
+ }
3266
+ async getLength() {
3267
+ return this.blob.size;
3268
+ }
3269
+ async read(offset, length) {
3270
+ const blob = this.blob.slice(offset, offset + length);
3271
+ const arrayBuffer = await readBlobAsArrayBuffer(blob);
3272
+ return new Uint8Array(arrayBuffer);
3273
+ }
3274
+ async sliceAsBlob(offset, length, type = '') {
3275
+ return this.blob.slice(offset, offset + length, type);
3276
+ }
3277
+ }
3278
+
3279
+ class HTTPRangeReader {
3280
+ constructor(url) {
3281
+ this.url = url;
3282
+ }
3283
+ async getLength() {
3284
+ if (this.length === undefined) {
3285
+ const req = await fetch(this.url, { method: 'HEAD' });
3286
+ if (!req.ok) {
3287
+ throw new Error(`failed http request ${this.url}, status: ${req.status}: ${req.statusText}`);
3288
+ }
3289
+ this.length = parseInt(req.headers.get('content-length'));
3290
+ if (Number.isNaN(this.length)) {
3291
+ throw Error('could not get length');
3292
+ }
3293
+ }
3294
+ return this.length;
3295
+ }
3296
+ async read(offset, size) {
3297
+ if (size === 0) {
3298
+ return new Uint8Array(0);
3299
+ }
3300
+ const req = await fetch(this.url, {
3301
+ headers: {
3302
+ Range: `bytes=${offset}-${offset + size - 1}`,
3303
+ },
3304
+ });
3305
+ if (!req.ok) {
3306
+ throw new Error(`failed http request ${this.url}, status: ${req.status} offset: ${offset} size: ${size}: ${req.statusText}`);
3307
+ }
3308
+ const buffer = await req.arrayBuffer();
3309
+ return new Uint8Array(buffer);
3310
+ }
3311
+ }
3312
+
3313
+ function inflate(data, buf) {
3314
+ var u8=Uint8Array;
3315
+ if(data[0]==3 && data[1]==0) return (buf ? buf : new u8(0));
3316
+ var bitsF = _bitsF, bitsE = _bitsE, decodeTiny = _decodeTiny, get17 = _get17;
3317
+
3318
+ var noBuf = (buf==null);
3319
+ if(noBuf) buf = new u8((data.length>>>2)<<3);
3320
+
3321
+ var BFINAL=0, BTYPE=0, HLIT=0, HDIST=0, HCLEN=0, ML=0, MD=0;
3322
+ var off = 0, pos = 0;
3323
+ var lmap, dmap;
3324
+
3325
+ while(BFINAL==0) {
3326
+ BFINAL = bitsF(data, pos , 1);
3327
+ BTYPE = bitsF(data, pos+1, 2); pos+=3;
3328
+ //console.log(BFINAL, BTYPE);
3329
+
3330
+ if(BTYPE==0) {
3331
+ if((pos&7)!=0) pos+=8-(pos&7);
3332
+ var p8 = (pos>>>3)+4, len = data[p8-4]|(data[p8-3]<<8); //console.log(len);//bitsF(data, pos, 16),
3333
+ if(noBuf) buf=_check(buf, off+len);
3334
+ buf.set(new u8(data.buffer, data.byteOffset+p8, len), off);
3335
+ //for(var i=0; i<len; i++) buf[off+i] = data[p8+i];
3336
+ //for(var i=0; i<len; i++) if(buf[off+i] != data[p8+i]) throw "e";
3337
+ pos = ((p8+len)<<3); off+=len; continue;
3338
+ }
3339
+ if(noBuf) buf=_check(buf, off+(1<<17)); // really not enough in many cases (but PNG and ZIP provide buffer in advance)
3340
+ if(BTYPE==1) { lmap = U.flmap; dmap = U.fdmap; ML = (1<<9)-1; MD = (1<<5)-1; }
3341
+ if(BTYPE==2) {
3342
+ HLIT = bitsE(data, pos , 5)+257;
3343
+ HDIST = bitsE(data, pos+ 5, 5)+ 1;
3344
+ HCLEN = bitsE(data, pos+10, 4)+ 4; pos+=14;
3345
+ for(var i=0; i<38; i+=2) { U.itree[i]=0; U.itree[i+1]=0; }
3346
+ var tl = 1;
3347
+ for(var i=0; i<HCLEN; i++) { var l=bitsE(data, pos+i*3, 3); U.itree[(U.ordr[i]<<1)+1] = l; if(l>tl)tl=l; } pos+=3*HCLEN; //console.log(itree);
3348
+ makeCodes(U.itree, tl);
3349
+ codes2map(U.itree, tl, U.imap);
3350
+
3351
+ lmap = U.lmap; dmap = U.dmap;
3352
+
3353
+ pos = decodeTiny(U.imap, (1<<tl)-1, HLIT+HDIST, data, pos, U.ttree);
3354
+ var mx0 = _copyOut(U.ttree, 0, HLIT , U.ltree); ML = (1<<mx0)-1;
3355
+ var mx1 = _copyOut(U.ttree, HLIT, HDIST, U.dtree); MD = (1<<mx1)-1;
3356
+
3357
+ //var ml = decodeTiny(U.imap, (1<<tl)-1, HLIT , data, pos, U.ltree); ML = (1<<(ml>>>24))-1; pos+=(ml&0xffffff);
3358
+ makeCodes(U.ltree, mx0);
3359
+ codes2map(U.ltree, mx0, lmap);
3360
+
3361
+ //var md = decodeTiny(U.imap, (1<<tl)-1, HDIST, data, pos, U.dtree); MD = (1<<(md>>>24))-1; pos+=(md&0xffffff);
3362
+ makeCodes(U.dtree, mx1);
3363
+ codes2map(U.dtree, mx1, dmap);
3364
+ }
3365
+ //var ooff=off, opos=pos;
3366
+ while(true) {
3367
+ var code = lmap[get17(data, pos) & ML]; pos += code&15;
3368
+ var lit = code>>>4; //U.lhst[lit]++;
3369
+ if((lit>>>8)==0) { buf[off++] = lit; }
3370
+ else if(lit==256) { break; }
3371
+ else {
3372
+ var end = off+lit-254;
3373
+ if(lit>264) { var ebs = U.ldef[lit-257]; end = off + (ebs>>>3) + bitsE(data, pos, ebs&7); pos += ebs&7; }
3374
+ //dst[end-off]++;
3375
+
3376
+ var dcode = dmap[get17(data, pos) & MD]; pos += dcode&15;
3377
+ var dlit = dcode>>>4;
3378
+ var dbs = U.ddef[dlit], dst = (dbs>>>4) + bitsF(data, pos, dbs&15); pos += dbs&15;
3379
+
3380
+ //var o0 = off-dst, stp = Math.min(end-off, dst);
3381
+ //if(stp>20) while(off<end) { buf.copyWithin(off, o0, o0+stp); off+=stp; } else
3382
+ //if(end-dst<=off) buf.copyWithin(off, off-dst, end-dst); else
3383
+ //if(dst==1) buf.fill(buf[off-1], off, end); else
3384
+ if(noBuf) buf=_check(buf, off+(1<<17));
3385
+ while(off<end) { buf[off]=buf[off++-dst]; buf[off]=buf[off++-dst]; buf[off]=buf[off++-dst]; buf[off]=buf[off++-dst]; }
3386
+ off=end;
3387
+ //while(off!=end) { buf[off]=buf[off++-dst]; }
3388
+ }
3389
+ }
3390
+ //console.log(off-ooff, (pos-opos)>>>3);
3391
+ }
3392
+ //console.log(dst);
3393
+ //console.log(tlen, dlen, off-tlen+tcnt);
3394
+ return buf.length==off ? buf : buf.slice(0,off);
3395
+ }
3396
+ function _check(buf, len) {
3397
+ var bl=buf.length; if(len<=bl) return buf;
3398
+ var nbuf = new Uint8Array(Math.max(bl<<1,len)); nbuf.set(buf,0);
3399
+ //for(var i=0; i<bl; i+=4) { nbuf[i]=buf[i]; nbuf[i+1]=buf[i+1]; nbuf[i+2]=buf[i+2]; nbuf[i+3]=buf[i+3]; }
3400
+ return nbuf;
3401
+ }
3402
+
3403
+ function _decodeTiny(lmap, LL, len, data, pos, tree) {
3404
+ var bitsE = _bitsE, get17 = _get17;
3405
+ var i = 0;
3406
+ while(i<len) {
3407
+ var code = lmap[get17(data, pos)&LL]; pos+=code&15;
3408
+ var lit = code>>>4;
3409
+ if(lit<=15) { tree[i]=lit; i++; }
3410
+ else {
3411
+ var ll = 0, n = 0;
3412
+ if(lit==16) {
3413
+ n = (3 + bitsE(data, pos, 2)); pos += 2; ll = tree[i-1];
3414
+ }
3415
+ else if(lit==17) {
3416
+ n = (3 + bitsE(data, pos, 3)); pos += 3;
3417
+ }
3418
+ else if(lit==18) {
3419
+ n = (11 + bitsE(data, pos, 7)); pos += 7;
3420
+ }
3421
+ var ni = i+n;
3422
+ while(i<ni) { tree[i]=ll; i++; }
3423
+ }
3424
+ }
3425
+ return pos;
3426
+ }
3427
+ function _copyOut(src, off, len, tree) {
3428
+ var mx=0, i=0, tl=tree.length>>>1;
3429
+ while(i<len) { var v=src[i+off]; tree[(i<<1)]=0; tree[(i<<1)+1]=v; if(v>mx)mx=v; i++; }
3430
+ while(i<tl ) { tree[(i<<1)]=0; tree[(i<<1)+1]=0; i++; }
3431
+ return mx;
3432
+ }
3433
+
3434
+ function makeCodes(tree, MAX_BITS) { // code, length
3435
+ var max_code = tree.length;
3436
+ var code, bits, n, i, len;
3437
+
3438
+ var bl_count = U.bl_count; for(var i=0; i<=MAX_BITS; i++) bl_count[i]=0;
3439
+ for(i=1; i<max_code; i+=2) bl_count[tree[i]]++;
3440
+
3441
+ var next_code = U.next_code; // smallest code for each length
3442
+
3443
+ code = 0;
3444
+ bl_count[0] = 0;
3445
+ for (bits = 1; bits <= MAX_BITS; bits++) {
3446
+ code = (code + bl_count[bits-1]) << 1;
3447
+ next_code[bits] = code;
3448
+ }
3449
+
3450
+ for (n = 0; n < max_code; n+=2) {
3451
+ len = tree[n+1];
3452
+ if (len != 0) {
3453
+ tree[n] = next_code[len];
3454
+ next_code[len]++;
3455
+ }
3456
+ }
3457
+ }
3458
+ function codes2map(tree, MAX_BITS, map) {
3459
+ var max_code = tree.length;
3460
+ var r15 = U.rev15;
3461
+ for(var i=0; i<max_code; i+=2) if(tree[i+1]!=0) {
3462
+ var lit = i>>1;
3463
+ var cl = tree[i+1], val = (lit<<4)|cl; // : (0x8000 | (U.of0[lit-257]<<7) | (U.exb[lit-257]<<4) | cl);
3464
+ var rest = (MAX_BITS-cl), i0 = tree[i]<<rest, i1 = i0 + (1<<rest);
3465
+ //tree[i]=r15[i0]>>>(15-MAX_BITS);
3466
+ while(i0!=i1) {
3467
+ var p0 = r15[i0]>>>(15-MAX_BITS);
3468
+ map[p0]=val; i0++;
3469
+ }
3470
+ }
3471
+ }
3472
+ function revCodes(tree, MAX_BITS) {
3473
+ var r15 = U.rev15, imb = 15-MAX_BITS;
3474
+ for(var i=0; i<tree.length; i+=2) { var i0 = (tree[i]<<(MAX_BITS-tree[i+1])); tree[i] = r15[i0]>>>imb; }
3475
+ }
3476
+
3477
+ function _bitsE(dt, pos, length) { return ((dt[pos>>>3] | (dt[(pos>>>3)+1]<<8) )>>>(pos&7))&((1<<length)-1); }
3478
+ function _bitsF(dt, pos, length) { return ((dt[pos>>>3] | (dt[(pos>>>3)+1]<<8) | (dt[(pos>>>3)+2]<<16))>>>(pos&7))&((1<<length)-1); }
3479
+ /*
3480
+ function _get9(dt, pos) {
3481
+ return ((dt[pos>>>3] | (dt[(pos>>>3)+1]<<8))>>>(pos&7))&511;
3482
+ } */
3483
+ function _get17(dt, pos) { // return at least 17 meaningful bytes
3484
+ return (dt[pos>>>3] | (dt[(pos>>>3)+1]<<8) | (dt[(pos>>>3)+2]<<16) )>>>(pos&7);
3485
+ }
3486
+ const U = function(){
3487
+ var u16=Uint16Array, u32=Uint32Array;
3488
+ return {
3489
+ next_code : new u16(16),
3490
+ bl_count : new u16(16),
3491
+ ordr : [ 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 ],
3492
+ of0 : [3,4,5,6,7,8,9,10,11,13,15,17,19,23,27,31,35,43,51,59,67,83,99,115,131,163,195,227,258,999,999,999],
3493
+ exb : [0,0,0,0,0,0,0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 0, 0, 0],
3494
+ ldef : new u16(32),
3495
+ df0 : [1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193,257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577, 65535, 65535],
3496
+ dxb : [0,0,0,0,1,1,2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 0, 0],
3497
+ ddef : new u32(32),
3498
+ flmap: new u16( 512), fltree: [],
3499
+ fdmap: new u16( 32), fdtree: [],
3500
+ lmap : new u16(32768), ltree : [], ttree:[],
3501
+ dmap : new u16(32768), dtree : [],
3502
+ imap : new u16( 512), itree : [],
3503
+ //rev9 : new u16( 512)
3504
+ rev15: new u16(1<<15),
3505
+ lhst : new u32(286), dhst : new u32( 30), ihst : new u32(19),
3506
+ lits : new u32(15000),
3507
+ strt : new u16(1<<16),
3508
+ prev : new u16(1<<15)
3509
+ };
3510
+ } ();
3511
+
3512
+ (function(){
3513
+ var len = 1<<15;
3514
+ for(var i=0; i<len; i++) {
3515
+ var x = i;
3516
+ x = (((x & 0xaaaaaaaa) >>> 1) | ((x & 0x55555555) << 1));
3517
+ x = (((x & 0xcccccccc) >>> 2) | ((x & 0x33333333) << 2));
3518
+ x = (((x & 0xf0f0f0f0) >>> 4) | ((x & 0x0f0f0f0f) << 4));
3519
+ x = (((x & 0xff00ff00) >>> 8) | ((x & 0x00ff00ff) << 8));
3520
+ U.rev15[i] = (((x >>> 16) | (x << 16)))>>>17;
3521
+ }
3522
+
3523
+ function pushV(tgt, n, sv) { while(n--!=0) tgt.push(0,sv); }
3524
+
3525
+ for(var i=0; i<32; i++) { U.ldef[i]=(U.of0[i]<<3)|U.exb[i]; U.ddef[i]=(U.df0[i]<<4)|U.dxb[i]; }
3526
+
3527
+ pushV(U.fltree, 144, 8); pushV(U.fltree, 255-143, 9); pushV(U.fltree, 279-255, 7); pushV(U.fltree,287-279,8);
3528
+ /*
3529
+ var i = 0;
3530
+ for(; i<=143; i++) U.fltree.push(0,8);
3531
+ for(; i<=255; i++) U.fltree.push(0,9);
3532
+ for(; i<=279; i++) U.fltree.push(0,7);
3533
+ for(; i<=287; i++) U.fltree.push(0,8);
3534
+ */
3535
+ makeCodes(U.fltree, 9);
3536
+ codes2map(U.fltree, 9, U.flmap);
3537
+ revCodes (U.fltree, 9);
3538
+
3539
+ pushV(U.fdtree,32,5);
3540
+ //for(i=0;i<32; i++) U.fdtree.push(0,5);
3541
+ makeCodes(U.fdtree, 5);
3542
+ codes2map(U.fdtree, 5, U.fdmap);
3543
+ revCodes (U.fdtree, 5);
3544
+
3545
+ pushV(U.itree,19,0); pushV(U.ltree,286,0); pushV(U.dtree,30,0); pushV(U.ttree,320,0);
3546
+ /*
3547
+ for(var i=0; i< 19; i++) U.itree.push(0,0);
3548
+ for(var i=0; i<286; i++) U.ltree.push(0,0);
3549
+ for(var i=0; i< 30; i++) U.dtree.push(0,0);
3550
+ for(var i=0; i<320; i++) U.ttree.push(0,0);
3551
+ */
3552
+ })();
3553
+
3554
+ const crc = {
3555
+ table : ( function() {
3556
+ var tab = new Uint32Array(256);
3557
+ for (var n=0; n<256; n++) {
3558
+ var c = n;
3559
+ for (var k=0; k<8; k++) {
3560
+ if (c & 1) c = 0xedb88320 ^ (c >>> 1);
3561
+ else c = c >>> 1;
3562
+ }
3563
+ tab[n] = c; }
3564
+ return tab; })(),
3565
+ update : function(c, buf, off, len) {
3566
+ for (var i=0; i<len; i++) c = crc.table[(c ^ buf[off+i]) & 0xff] ^ (c >>> 8);
3567
+ return c;
3568
+ },
3569
+ crc : function(b,o,l) { return crc.update(0xffffffff,b,o,l) ^ 0xffffffff; }
3570
+ };
3571
+
3572
+ function inflateRaw(file, buf) { return inflate(file, buf); }
3573
+
3574
+ /* global module */
3575
+
3576
+ const config = {
3577
+ numWorkers: 1,
3578
+ workerURL: '',
3579
+ useWorkers: false,
3580
+ };
3581
+
3582
+ let nextId = 0;
3583
+
3584
+ // Requests are put on a queue.
3585
+ // We don't send the request to the worker until the worker
3586
+ // is finished. This probably adds a small amount of latency
3587
+ // but the issue is imagine you have 2 workers. You give worker
3588
+ // A x seconds of work to do and worker B y seconds of work to
3589
+ // do. You don't know which will finish first. If you give
3590
+ // the worker with more work to do the request then you'll
3591
+ // waste time.
3592
+
3593
+ // note: we can't check `workers.length` for deciding if
3594
+ // we've reached `config.numWorkers` because creation the worker
3595
+ // is async which means other requests to make workers might
3596
+ // come in before a worker gets added to `workers`
3597
+ let numWorkers = 0;
3598
+ let canUseWorkers = true; // gets set to false if we can't start a worker
3599
+ const workers = [];
3600
+ const availableWorkers = [];
3601
+ const waitingForWorkerQueue = [];
3602
+ const currentlyProcessingIdToRequestMap = new Map();
3603
+
3604
+ function handleResult(e) {
3605
+ makeWorkerAvailable(e.target);
3606
+ const {id, error, data} = e.data;
3607
+ const request = currentlyProcessingIdToRequestMap.get(id);
3608
+ currentlyProcessingIdToRequestMap.delete(id);
3609
+ if (error) {
3610
+ request.reject(error);
3611
+ } else {
3612
+ request.resolve(data);
3613
+ }
3614
+ }
3615
+
3616
+ // Because Firefox uses non-standard onerror to signal an error.
3617
+ function startWorker(url) {
3618
+ return new Promise((resolve, reject) => {
3619
+ const worker = new Worker(url);
3620
+ worker.onmessage = (e) => {
3621
+ if (e.data === 'start') {
3622
+ worker.onerror = undefined;
3623
+ worker.onmessage = undefined;
3624
+ resolve(worker);
3625
+ } else {
3626
+ reject(new Error(`unexpected message: ${e.data}`));
3627
+ }
3628
+ };
3629
+ worker.onerror = reject;
3630
+ });
3631
+ }
3632
+
3633
+ function dynamicRequire(mod, request) {
3634
+ return mod.require ? mod.require(request) : {};
3635
+ }
3636
+
3637
+ const workerHelper = (function() {
3638
+ if (isNode) {
3639
+ // We need to use `dynamicRequire` because `require` on it's own will be optimized by webpack.
3640
+ const {Worker} = dynamicRequire(module, 'worker_threads');
3641
+ return {
3642
+ async createWorker(url) {
3643
+ return new Worker(url);
3644
+ },
3645
+ addEventListener(worker, fn) {
3646
+ worker.on('message', (data) => {
3647
+ fn({target: worker, data});
3648
+ });
3649
+ },
3650
+ async terminate(worker) {
3651
+ await worker.terminate();
3652
+ },
3653
+ };
3654
+ } else {
3655
+ return {
3656
+ async createWorker(url) {
3657
+ // I don't understand this security issue
3658
+ // Apparently there is some iframe setting or http header
3659
+ // that prevents cross domain workers. But, I can manually
3660
+ // download the text and do it. I reported this to Chrome
3661
+ // and they said it was fine so ¯\_(ツ)_/¯
3662
+ try {
3663
+ const worker = await startWorker(url);
3664
+ return worker;
3665
+ } catch (e) {
3666
+ console.warn('could not load worker:', url);
3667
+ }
3668
+
3669
+ let text;
3670
+ try {
3671
+ const req = await fetch(url, {mode: 'cors'});
3672
+ if (!req.ok) {
3673
+ throw new Error(`could not load: ${url}`);
3674
+ }
3675
+ text = await req.text();
3676
+ url = URL.createObjectURL(new Blob([text], {type: 'application/javascript'}));
3677
+ const worker = await startWorker(url);
3678
+ config.workerURL = url; // this is a hack. What's a better way to structure this code?
3679
+ return worker;
3680
+ } catch (e) {
3681
+ console.warn('could not load worker via fetch:', url);
3682
+ }
3683
+
3684
+ if (text !== undefined) {
3685
+ try {
3686
+ url = `data:application/javascript;base64,${btoa(text)}`;
3687
+ const worker = await startWorker(url);
3688
+ config.workerURL = url;
3689
+ return worker;
3690
+ } catch (e) {
3691
+ console.warn('could not load worker via dataURI');
3692
+ }
3693
+ }
3694
+
3695
+ console.warn('workers will not be used');
3696
+ throw new Error('can not start workers');
3697
+ },
3698
+ addEventListener(worker, fn) {
3699
+ worker.addEventListener('message', fn);
3700
+ },
3701
+ async terminate(worker) {
3702
+ worker.terminate();
3703
+ },
3704
+ };
3705
+ }
3706
+ }());
3707
+
3708
+ function makeWorkerAvailable(worker) {
3709
+ availableWorkers.push(worker);
3710
+ processWaitingForWorkerQueue();
3711
+ }
3712
+
3713
+ async function getAvailableWorker() {
3714
+ if (availableWorkers.length === 0 && numWorkers < config.numWorkers) {
3715
+ ++numWorkers; // see comment at numWorkers declaration
3716
+ try {
3717
+ const worker = await workerHelper.createWorker(config.workerURL);
3718
+ workers.push(worker);
3719
+ availableWorkers.push(worker);
3720
+ workerHelper.addEventListener(worker, handleResult);
3721
+ } catch (e) {
3722
+ // set this global out-of-band (needs refactor)
3723
+ canUseWorkers = false;
3724
+ }
3725
+ }
3726
+ return availableWorkers.pop();
3727
+ }
3728
+
3729
+ // @param {Uint8Array} src
3730
+ // @param {number} uncompressedSize
3731
+ // @param {string} [type] mime-type
3732
+ // @returns {ArrayBuffer|Blob} ArrayBuffer if type is falsy or Blob otherwise.
3733
+ function inflateRawLocal(src, uncompressedSize, type, resolve) {
3734
+ const dst = new Uint8Array(uncompressedSize);
3735
+ inflateRaw(src, dst);
3736
+ resolve(type
3737
+ ? new Blob([dst], {type})
3738
+ : dst.buffer);
3739
+ }
3740
+
3741
+ async function processWaitingForWorkerQueue() {
3742
+ if (waitingForWorkerQueue.length === 0) {
3743
+ return;
3744
+ }
3745
+
3746
+ if (config.useWorkers && canUseWorkers) {
3747
+ const worker = await getAvailableWorker();
3748
+ // canUseWorkers might have been set out-of-band (need refactor)
3749
+ if (canUseWorkers) {
3750
+ if (worker) {
3751
+ if (waitingForWorkerQueue.length === 0) {
3752
+ // the queue might be empty while we awaited for a worker.
3753
+ makeWorkerAvailable(worker);
3754
+ return;
3755
+ }
3756
+ const {id, src, uncompressedSize, type, resolve, reject} = waitingForWorkerQueue.shift();
3757
+ currentlyProcessingIdToRequestMap.set(id, {id, resolve, reject});
3758
+ const transferables = [];
3759
+ // NOTE: Originally I thought you could transfer an ArrayBuffer.
3760
+ // The code on this side is often using views into the entire file
3761
+ // which means if we transferred we'd lose the entire file. That sucks
3762
+ // because it means there's an expensive copy to send the uncompressed
3763
+ // data to the worker.
3764
+ //
3765
+ // Also originally I thought we could send a Blob but we'd need to refactor
3766
+ // the code in unzipit/readEntryData as currently it reads the uncompressed
3767
+ // bytes.
3768
+ //
3769
+ //if (!isBlob(src) && !isSharedArrayBuffer(src)) {
3770
+ // transferables.push(src);
3771
+ //}
3772
+ worker.postMessage({
3773
+ type: 'inflate',
3774
+ data: {
3775
+ id,
3776
+ type,
3777
+ src,
3778
+ uncompressedSize,
3779
+ },
3780
+ }, transferables);
3781
+ }
3782
+ return;
3783
+ }
3784
+ }
3785
+
3786
+ // inflate locally
3787
+ // We loop here because what happens if many requests happen at once
3788
+ // the first N requests will try to async make a worker. Other requests
3789
+ // will then be on the queue. But if we fail to make workers then there
3790
+ // are pending requests.
3791
+ while (waitingForWorkerQueue.length) {
3792
+ const {src, uncompressedSize, type, resolve} = waitingForWorkerQueue.shift();
3793
+ let data = src;
3794
+ if (isBlob(src)) {
3795
+ data = await readBlobAsUint8Array(src);
3796
+ }
3797
+ inflateRawLocal(data, uncompressedSize, type, resolve);
3798
+ }
3799
+ }
3800
+
3801
+ function setOptions(options) {
3802
+ config.workerURL = options.workerURL || config.workerURL;
3803
+ // there's no reason to set the workerURL if you're not going to use workers
3804
+ if (options.workerURL) {
3805
+ config.useWorkers = true;
3806
+ }
3807
+ config.useWorkers = options.useWorkers !== undefined ? options.useWorkers : config.useWorkers;
3808
+ config.numWorkers = options.numWorkers || config.numWorkers;
3809
+ }
3810
+
3811
+ // It has to take non-zero time to put a large typed array in a Blob since the very
3812
+ // next instruction you could change the contents of the array. So, if you're reading
3813
+ // the zip file for images/video/audio then all you want is a Blob on which to get a URL.
3814
+ // so that operation of putting the data in a Blob should happen in the worker.
3815
+ //
3816
+ // Conversely if you want the data itself then you want an ArrayBuffer immediately
3817
+ // since the worker can transfer its ArrayBuffer zero copy.
3818
+ //
3819
+ // @param {Uint8Array|Blob} src
3820
+ // @param {number} uncompressedSize
3821
+ // @param {string} [type] falsy or mimeType string (eg: 'image/png')
3822
+ // @returns {ArrayBuffer|Blob} ArrayBuffer if type is falsy or Blob otherwise.
3823
+ function inflateRawAsync(src, uncompressedSize, type) {
3824
+ return new Promise((resolve, reject) => {
3825
+ // note: there is potential an expensive copy here. In order for the data
3826
+ // to make it into the worker we need to copy the data to the worker unless
3827
+ // it's a Blob or a SharedArrayBuffer.
3828
+ //
3829
+ // Solutions:
3830
+ //
3831
+ // 1. A minor enhancement, if `uncompressedSize` is small don't call the worker.
3832
+ //
3833
+ // might be a win period as their is overhead calling the worker
3834
+ //
3835
+ // 2. Move the entire library to the worker
3836
+ //
3837
+ // Good, Maybe faster if you pass a URL, Blob, or SharedArrayBuffer? Not sure about that
3838
+ // as those are also easy to transfer. Still slow if you pass an ArrayBuffer
3839
+ // as the ArrayBuffer has to be copied to the worker.
3840
+ //
3841
+ // I guess benchmarking is really the only thing to try.
3842
+ waitingForWorkerQueue.push({src, uncompressedSize, type, resolve, reject, id: nextId++});
3843
+ processWaitingForWorkerQueue();
3844
+ });
3845
+ }
3846
+
3847
+ function clearArray(arr) {
3848
+ arr.splice(0, arr.length);
3849
+ }
3850
+
3851
+ async function cleanup() {
3852
+ for (const worker of workers) {
3853
+ await workerHelper.terminate(worker);
3854
+ }
3855
+ clearArray(workers);
3856
+ clearArray(availableWorkers);
3857
+ clearArray(waitingForWorkerQueue);
3858
+ currentlyProcessingIdToRequestMap.clear();
3859
+ numWorkers = 0;
3860
+ canUseWorkers = true;
3861
+ }
3862
+
3863
+ /*
3864
+ class Zip {
3865
+ constructor(reader) {
3866
+ comment, // the comment for this entry
3867
+ commentBytes, // the raw comment for this entry
3868
+ }
3869
+ }
3870
+ */
3871
+
3872
+ function dosDateTimeToDate(date, time) {
3873
+ const day = date & 0x1f; // 1-31
3874
+ const month = (date >> 5 & 0xf) - 1; // 1-12, 0-11
3875
+ const year = (date >> 9 & 0x7f) + 1980; // 0-128, 1980-2108
3876
+
3877
+ const millisecond = 0;
3878
+ const second = (time & 0x1f) * 2; // 0-29, 0-58 (even numbers)
3879
+ const minute = time >> 5 & 0x3f; // 0-59
3880
+ const hour = time >> 11 & 0x1f; // 0-23
3881
+
3882
+ return new Date(year, month, day, hour, minute, second, millisecond);
3883
+ }
3884
+
3885
+ class ZipEntry {
3886
+ constructor(reader, rawEntry) {
3887
+ this._reader = reader;
3888
+ this._rawEntry = rawEntry;
3889
+ this.name = rawEntry.name;
3890
+ this.nameBytes = rawEntry.nameBytes;
3891
+ this.size = rawEntry.uncompressedSize;
3892
+ this.compressedSize = rawEntry.compressedSize;
3893
+ this.comment = rawEntry.comment;
3894
+ this.commentBytes = rawEntry.commentBytes;
3895
+ this.compressionMethod = rawEntry.compressionMethod;
3896
+ this.lastModDate = dosDateTimeToDate(rawEntry.lastModFileDate, rawEntry.lastModFileTime);
3897
+ this.isDirectory = rawEntry.uncompressedSize === 0 && rawEntry.name.endsWith('/');
3898
+ this.encrypted = !!(rawEntry.generalPurposeBitFlag & 0x1);
3899
+ this.externalFileAttributes = rawEntry.externalFileAttributes;
3900
+ this.versionMadeBy = rawEntry.versionMadeBy;
3901
+ }
3902
+ // returns a promise that returns a Blob for this entry
3903
+ async blob(type = 'application/octet-stream') {
3904
+ return await readEntryDataAsBlob(this._reader, this._rawEntry, type);
3905
+ }
3906
+ // returns a promise that returns an ArrayBuffer for this entry
3907
+ async arrayBuffer() {
3908
+ return await readEntryDataAsArrayBuffer(this._reader, this._rawEntry);
3909
+ }
3910
+ // returns text, assumes the text is valid utf8. If you want more options decode arrayBuffer yourself
3911
+ async text() {
3912
+ const buffer = await this.arrayBuffer();
3913
+ return decodeBuffer(new Uint8Array(buffer));
3914
+ }
3915
+ // returns text with JSON.parse called on it. If you want more options decode arrayBuffer yourself
3916
+ async json() {
3917
+ const text = await this.text();
3918
+ return JSON.parse(text);
3919
+ }
3920
+ }
3921
+
3922
+ const EOCDR_WITHOUT_COMMENT_SIZE = 22;
3923
+ const MAX_COMMENT_SIZE = 0xffff; // 2-byte size
3924
+ const EOCDR_SIGNATURE = 0x06054b50;
3925
+ const ZIP64_EOCDR_SIGNATURE = 0x06064b50;
3926
+
3927
+ async function readAs(reader, offset, length) {
3928
+ return await reader.read(offset, length);
3929
+ }
3930
+
3931
+ // The point of this function is we want to be able to pass the data
3932
+ // to a worker as fast as possible so when decompressing if the data
3933
+ // is already a blob and we can get a blob then get a blob.
3934
+ //
3935
+ // I'm not sure what a better way to refactor this is. We've got examples
3936
+ // of multiple readers. Ideally, for every type of reader we could ask
3937
+ // it, "give me a type that is zero copy both locally and when sent to a worker".
3938
+ //
3939
+ // The problem is the worker would also have to know the how to handle this
3940
+ // opaque type. I suppose the correct solution is to register different
3941
+ // reader handlers in the worker so BlobReader would register some
3942
+ // `handleZeroCopyType<BlobReader>`. At the moment I don't feel like
3943
+ // refactoring. As it is you just pass in an instance of the reader
3944
+ // but instead you'd have to register the reader and some how get the
3945
+ // source for the `handleZeroCopyType` handler function into the worker.
3946
+ // That sounds like a huge PITA, requiring you to put the implementation
3947
+ // in a separate file so the worker can load it or some other workaround
3948
+ // hack.
3949
+ //
3950
+ // For now this hack works even if it's not generic.
3951
+ async function readAsBlobOrTypedArray(reader, offset, length, type) {
3952
+ if (reader.sliceAsBlob) {
3953
+ return await reader.sliceAsBlob(offset, length, type);
3954
+ }
3955
+ return await reader.read(offset, length);
3956
+ }
3957
+
3958
+ const crc$1 = {
3959
+ unsigned() {
3960
+ return 0;
3961
+ },
3962
+ };
3963
+
3964
+ function getUint16LE(uint8View, offset) {
3965
+ return uint8View[offset ] +
3966
+ uint8View[offset + 1] * 0x100;
3967
+ }
3968
+
3969
+ function getUint32LE(uint8View, offset) {
3970
+ return uint8View[offset ] +
3971
+ uint8View[offset + 1] * 0x100 +
3972
+ uint8View[offset + 2] * 0x10000 +
3973
+ uint8View[offset + 3] * 0x1000000;
3974
+ }
3975
+
3976
+ function getUint64LE(uint8View, offset) {
3977
+ return getUint32LE(uint8View, offset) +
3978
+ getUint32LE(uint8View, offset + 4) * 0x100000000;
3979
+ }
3980
+
3981
+ /* eslint-disable no-irregular-whitespace */
3982
+ // const decodeCP437 = (function() {
3983
+ // const cp437 = '\u0000☺☻♥♦♣♠•◘○◙♂♀♪♫☼►◄↕‼¶§▬↨↑↓→←∟↔▲▼ !"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~⌂ÇüéâäàåçêëèïîìÄÅÉæÆôöòûùÿÖÜ¢£¥₧ƒáíóúñѪº¿⌐¬½¼¡«»░▒▓│┤╡╢╖╕╣║╗╝╜╛┐└┴┬├─┼╞╟╚╔╩╦╠═╬╧╨╤╥╙╘╒╓╫╪┘┌█▄▌▐▀αßΓπΣσµτΦΘΩδ∞φε∩≡±≥≤⌠⌡÷≈°∙·√ⁿ²■ ';
3984
+ //
3985
+ // return function(uint8view) {
3986
+ // return Array.from(uint8view).map(v => cp437[v]).join('');
3987
+ // };
3988
+ // }());
3989
+ /* eslint-enable no-irregular-whitespace */
3990
+
3991
+ const utf8Decoder = new TextDecoder();
3992
+ function decodeBuffer(uint8View, isUTF8) { /* eslint-disable-line no-unused-vars */ /* lgtm [js/superfluous-trailing-arguments] */
3993
+ if (isSharedArrayBuffer(uint8View.buffer)) {
3994
+ uint8View = new Uint8Array(uint8View);
3995
+ }
3996
+ return utf8Decoder.decode(uint8View);
3997
+ /*
3998
+ AFAICT the UTF8 flat is not set so it's 100% up to the user
3999
+ to self decode if their file is not utf8 filenames
4000
+ return isUTF8
4001
+ ? utf8Decoder.decode(uint8View)
4002
+ : decodeCP437(uint8View);
4003
+ */
4004
+ }
4005
+
4006
+ async function findEndOfCentralDirector(reader, totalLength) {
4007
+ const size = Math.min(EOCDR_WITHOUT_COMMENT_SIZE + MAX_COMMENT_SIZE, totalLength);
4008
+ const readStart = totalLength - size;
4009
+ const data = await readAs(reader, readStart, size);
4010
+ for (let i = size - EOCDR_WITHOUT_COMMENT_SIZE; i >= 0; --i) {
4011
+ if (getUint32LE(data, i) !== EOCDR_SIGNATURE) {
4012
+ continue;
4013
+ }
4014
+
4015
+ // 0 - End of central directory signature
4016
+ const eocdr = new Uint8Array(data.buffer, data.byteOffset + i, data.byteLength - i);
4017
+ // 4 - Number of this disk
4018
+ const diskNumber = getUint16LE(eocdr, 4);
4019
+ if (diskNumber !== 0) {
4020
+ throw new Error(`multi-volume zip files are not supported. This is volume: ${diskNumber}`);
4021
+ }
4022
+
4023
+ // 6 - Disk where central directory starts
4024
+ // 8 - Number of central directory records on this disk
4025
+ // 10 - Total number of central directory records
4026
+ const entryCount = getUint16LE(eocdr, 10);
4027
+ // 12 - Size of central directory (bytes)
4028
+ const centralDirectorySize = getUint32LE(eocdr, 12);
4029
+ // 16 - Offset of start of central directory, relative to start of archive
4030
+ const centralDirectoryOffset = getUint32LE(eocdr, 16);
4031
+ // 20 - Comment length
4032
+ const commentLength = getUint16LE(eocdr, 20);
4033
+ const expectedCommentLength = eocdr.length - EOCDR_WITHOUT_COMMENT_SIZE;
4034
+ if (commentLength !== expectedCommentLength) {
4035
+ throw new Error(`invalid comment length. expected: ${expectedCommentLength}, actual: ${commentLength}`);
4036
+ }
4037
+
4038
+ // 22 - Comment
4039
+ // the encoding is always cp437.
4040
+ const commentBytes = new Uint8Array(eocdr.buffer, eocdr.byteOffset + 22, commentLength);
4041
+ const comment = decodeBuffer(commentBytes);
4042
+
4043
+ if (entryCount === 0xffff || centralDirectoryOffset === 0xffffffff) {
4044
+ return await readZip64CentralDirectory(reader, readStart + i, comment, commentBytes);
4045
+ } else {
4046
+ return await readEntries(reader, centralDirectoryOffset, centralDirectorySize, entryCount, comment, commentBytes);
4047
+ }
4048
+ }
4049
+
4050
+ throw new Error('could not find end of central directory. maybe not zip file');
4051
+ }
4052
+
4053
+ const END_OF_CENTRAL_DIRECTORY_LOCATOR_SIGNATURE = 0x07064b50;
4054
+
4055
+ async function readZip64CentralDirectory(reader, offset, comment, commentBytes) {
4056
+ // ZIP64 Zip64 end of central directory locator
4057
+ const zip64EocdlOffset = offset - 20;
4058
+ const eocdl = await readAs(reader, zip64EocdlOffset, 20);
4059
+
4060
+ // 0 - zip64 end of central dir locator signature
4061
+ if (getUint32LE(eocdl, 0) !== END_OF_CENTRAL_DIRECTORY_LOCATOR_SIGNATURE) {
4062
+ throw new Error('invalid zip64 end of central directory locator signature');
4063
+ }
4064
+
4065
+ // 4 - number of the disk with the start of the zip64 end of central directory
4066
+ // 8 - relative offset of the zip64 end of central directory record
4067
+ const zip64EocdrOffset = getUint64LE(eocdl, 8);
4068
+ // 16 - total number of disks
4069
+
4070
+ // ZIP64 end of central directory record
4071
+ const zip64Eocdr = await readAs(reader, zip64EocdrOffset, 56);
4072
+
4073
+ // 0 - zip64 end of central dir signature 4 bytes (0x06064b50)
4074
+ if (getUint32LE(zip64Eocdr, 0) !== ZIP64_EOCDR_SIGNATURE) {
4075
+ throw new Error('invalid zip64 end of central directory record signature');
4076
+ }
4077
+ // 4 - size of zip64 end of central directory record 8 bytes
4078
+ // 12 - version made by 2 bytes
4079
+ // 14 - version needed to extract 2 bytes
4080
+ // 16 - number of this disk 4 bytes
4081
+ // 20 - number of the disk with the start of the central directory 4 bytes
4082
+ // 24 - total number of entries in the central directory on this disk 8 bytes
4083
+ // 32 - total number of entries in the central directory 8 bytes
4084
+ const entryCount = getUint64LE(zip64Eocdr, 32);
4085
+ // 40 - size of the central directory 8 bytes
4086
+ const centralDirectorySize = getUint64LE(zip64Eocdr, 40);
4087
+ // 48 - offset of start of central directory with respect to the starting disk number 8 bytes
4088
+ const centralDirectoryOffset = getUint64LE(zip64Eocdr, 48);
4089
+ // 56 - zip64 extensible data sector (variable size)
4090
+ return readEntries(reader, centralDirectoryOffset, centralDirectorySize, entryCount, comment, commentBytes);
4091
+ }
4092
+
4093
+ const CENTRAL_DIRECTORY_FILE_HEADER_SIGNATURE = 0x02014b50;
4094
+
4095
+ async function readEntries(reader, centralDirectoryOffset, centralDirectorySize, rawEntryCount, comment, commentBytes) {
4096
+ let readEntryCursor = 0;
4097
+ const allEntriesBuffer = await readAs(reader, centralDirectoryOffset, centralDirectorySize);
4098
+ const rawEntries = [];
4099
+
4100
+ for (let e = 0; e < rawEntryCount; ++e) {
4101
+ const buffer = allEntriesBuffer.subarray(readEntryCursor, readEntryCursor + 46);
4102
+ // 0 - Central directory file header signature
4103
+ const signature = getUint32LE(buffer, 0);
4104
+ if (signature !== CENTRAL_DIRECTORY_FILE_HEADER_SIGNATURE) {
4105
+ throw new Error(`invalid central directory file header signature: 0x${signature.toString(16)}`);
4106
+ }
4107
+ const rawEntry = {
4108
+ // 4 - Version made by
4109
+ versionMadeBy: getUint16LE(buffer, 4),
4110
+ // 6 - Version needed to extract (minimum)
4111
+ versionNeededToExtract: getUint16LE(buffer, 6),
4112
+ // 8 - General purpose bit flag
4113
+ generalPurposeBitFlag: getUint16LE(buffer, 8),
4114
+ // 10 - Compression method
4115
+ compressionMethod: getUint16LE(buffer, 10),
4116
+ // 12 - File last modification time
4117
+ lastModFileTime: getUint16LE(buffer, 12),
4118
+ // 14 - File last modification date
4119
+ lastModFileDate: getUint16LE(buffer, 14),
4120
+ // 16 - CRC-32
4121
+ crc32: getUint32LE(buffer, 16),
4122
+ // 20 - Compressed size
4123
+ compressedSize: getUint32LE(buffer, 20),
4124
+ // 24 - Uncompressed size
4125
+ uncompressedSize: getUint32LE(buffer, 24),
4126
+ // 28 - File name length (n)
4127
+ fileNameLength: getUint16LE(buffer, 28),
4128
+ // 30 - Extra field length (m)
4129
+ extraFieldLength: getUint16LE(buffer, 30),
4130
+ // 32 - File comment length (k)
4131
+ fileCommentLength: getUint16LE(buffer, 32),
4132
+ // 34 - Disk number where file starts
4133
+ // 36 - Internal file attributes
4134
+ internalFileAttributes: getUint16LE(buffer, 36),
4135
+ // 38 - External file attributes
4136
+ externalFileAttributes: getUint32LE(buffer, 38),
4137
+ // 42 - Relative offset of local file header
4138
+ relativeOffsetOfLocalHeader: getUint32LE(buffer, 42),
4139
+ };
4140
+
4141
+ if (rawEntry.generalPurposeBitFlag & 0x40) {
4142
+ throw new Error('strong encryption is not supported');
4143
+ }
4144
+
4145
+ readEntryCursor += 46;
4146
+
4147
+ const data = allEntriesBuffer.subarray(readEntryCursor, readEntryCursor + rawEntry.fileNameLength + rawEntry.extraFieldLength + rawEntry.fileCommentLength);
4148
+ rawEntry.nameBytes = data.slice(0, rawEntry.fileNameLength);
4149
+ rawEntry.name = decodeBuffer(rawEntry.nameBytes);
4150
+
4151
+ // 46+n - Extra field
4152
+ const fileCommentStart = rawEntry.fileNameLength + rawEntry.extraFieldLength;
4153
+ const extraFieldBuffer = data.slice(rawEntry.fileNameLength, fileCommentStart);
4154
+ rawEntry.extraFields = [];
4155
+ let i = 0;
4156
+ while (i < extraFieldBuffer.length - 3) {
4157
+ const headerId = getUint16LE(extraFieldBuffer, i + 0);
4158
+ const dataSize = getUint16LE(extraFieldBuffer, i + 2);
4159
+ const dataStart = i + 4;
4160
+ const dataEnd = dataStart + dataSize;
4161
+ if (dataEnd > extraFieldBuffer.length) {
4162
+ throw new Error('extra field length exceeds extra field buffer size');
4163
+ }
4164
+ rawEntry.extraFields.push({
4165
+ id: headerId,
4166
+ data: extraFieldBuffer.slice(dataStart, dataEnd),
4167
+ });
4168
+ i = dataEnd;
4169
+ }
4170
+
4171
+ // 46+n+m - File comment
4172
+ rawEntry.commentBytes = data.slice(fileCommentStart, fileCommentStart + rawEntry.fileCommentLength);
4173
+ rawEntry.comment = decodeBuffer(rawEntry.commentBytes);
4174
+
4175
+ readEntryCursor += data.length;
4176
+
4177
+ if (rawEntry.uncompressedSize === 0xffffffff ||
4178
+ rawEntry.compressedSize === 0xffffffff ||
4179
+ rawEntry.relativeOffsetOfLocalHeader === 0xffffffff) {
4180
+ // ZIP64 format
4181
+ // find the Zip64 Extended Information Extra Field
4182
+ const zip64ExtraField = rawEntry.extraFields.find(e => e.id === 0x0001);
4183
+ if (!zip64ExtraField) {
4184
+ throw new Error('expected zip64 extended information extra field');
4185
+ }
4186
+ const zip64EiefBuffer = zip64ExtraField.data;
4187
+ let index = 0;
4188
+ // 0 - Original Size 8 bytes
4189
+ if (rawEntry.uncompressedSize === 0xffffffff) {
4190
+ if (index + 8 > zip64EiefBuffer.length) {
4191
+ throw new Error('zip64 extended information extra field does not include uncompressed size');
4192
+ }
4193
+ rawEntry.uncompressedSize = getUint64LE(zip64EiefBuffer, index);
4194
+ index += 8;
4195
+ }
4196
+ // 8 - Compressed Size 8 bytes
4197
+ if (rawEntry.compressedSize === 0xffffffff) {
4198
+ if (index + 8 > zip64EiefBuffer.length) {
4199
+ throw new Error('zip64 extended information extra field does not include compressed size');
4200
+ }
4201
+ rawEntry.compressedSize = getUint64LE(zip64EiefBuffer, index);
4202
+ index += 8;
4203
+ }
4204
+ // 16 - Relative Header Offset 8 bytes
4205
+ if (rawEntry.relativeOffsetOfLocalHeader === 0xffffffff) {
4206
+ if (index + 8 > zip64EiefBuffer.length) {
4207
+ throw new Error('zip64 extended information extra field does not include relative header offset');
4208
+ }
4209
+ rawEntry.relativeOffsetOfLocalHeader = getUint64LE(zip64EiefBuffer, index);
4210
+ index += 8;
4211
+ }
4212
+ // 24 - Disk Start Number 4 bytes
4213
+ }
4214
+
4215
+ // check for Info-ZIP Unicode Path Extra Field (0x7075)
4216
+ // see https://github.com/thejoshwolfe/yauzl/issues/33
4217
+ const nameField = rawEntry.extraFields.find(e =>
4218
+ e.id === 0x7075 &&
4219
+ e.data.length >= 6 && // too short to be meaningful
4220
+ e.data[0] === 1 && // Version 1 byte version of this extra field, currently 1
4221
+ getUint32LE(e.data, 1), crc$1.unsigned(rawEntry.nameBytes)); // NameCRC32 4 bytes File Name Field CRC32 Checksum
4222
+ // > If the CRC check fails, this UTF-8 Path Extra Field should be
4223
+ // > ignored and the File Name field in the header should be used instead.
4224
+ if (nameField) {
4225
+ // UnicodeName Variable UTF-8 version of the entry File Name
4226
+ rawEntry.fileName = decodeBuffer(nameField.data.slice(5));
4227
+ }
4228
+
4229
+ // validate file size
4230
+ if (rawEntry.compressionMethod === 0) {
4231
+ let expectedCompressedSize = rawEntry.uncompressedSize;
4232
+ if ((rawEntry.generalPurposeBitFlag & 0x1) !== 0) {
4233
+ // traditional encryption prefixes the file data with a header
4234
+ expectedCompressedSize += 12;
4235
+ }
4236
+ if (rawEntry.compressedSize !== expectedCompressedSize) {
4237
+ throw new Error(`compressed size mismatch for stored file: ${rawEntry.compressedSize} != ${expectedCompressedSize}`);
4238
+ }
4239
+ }
4240
+ rawEntries.push(rawEntry);
4241
+ }
4242
+ const zip = {
4243
+ comment,
4244
+ commentBytes,
4245
+ };
4246
+ return {
4247
+ zip,
4248
+ entries: rawEntries.map(e => new ZipEntry(reader, e)),
4249
+ };
4250
+ }
4251
+
4252
+ async function readEntryDataHeader(reader, rawEntry) {
4253
+ if (rawEntry.generalPurposeBitFlag & 0x1) {
4254
+ throw new Error('encrypted entries not supported');
4255
+ }
4256
+ const buffer = await readAs(reader, rawEntry.relativeOffsetOfLocalHeader, 30);
4257
+ // note: maybe this should be passed in or cached on entry
4258
+ // as it's async so there will be at least one tick (not sure about that)
4259
+ const totalLength = await reader.getLength();
4260
+
4261
+ // 0 - Local file header signature = 0x04034b50
4262
+ const signature = getUint32LE(buffer, 0);
4263
+ if (signature !== 0x04034b50) {
4264
+ throw new Error(`invalid local file header signature: 0x${signature.toString(16)}`);
4265
+ }
4266
+
4267
+ // all this should be redundant
4268
+ // 4 - Version needed to extract (minimum)
4269
+ // 6 - General purpose bit flag
4270
+ // 8 - Compression method
4271
+ // 10 - File last modification time
4272
+ // 12 - File last modification date
4273
+ // 14 - CRC-32
4274
+ // 18 - Compressed size
4275
+ // 22 - Uncompressed size
4276
+ // 26 - File name length (n)
4277
+ const fileNameLength = getUint16LE(buffer, 26);
4278
+ // 28 - Extra field length (m)
4279
+ const extraFieldLength = getUint16LE(buffer, 28);
4280
+ // 30 - File name
4281
+ // 30+n - Extra field
4282
+ const localFileHeaderEnd = rawEntry.relativeOffsetOfLocalHeader + buffer.length + fileNameLength + extraFieldLength;
4283
+ let decompress;
4284
+ if (rawEntry.compressionMethod === 0) {
4285
+ // 0 - The file is stored (no compression)
4286
+ decompress = false;
4287
+ } else if (rawEntry.compressionMethod === 8) {
4288
+ // 8 - The file is Deflated
4289
+ decompress = true;
4290
+ } else {
4291
+ throw new Error(`unsupported compression method: ${rawEntry.compressionMethod}`);
4292
+ }
4293
+ const fileDataStart = localFileHeaderEnd;
4294
+ const fileDataEnd = fileDataStart + rawEntry.compressedSize;
4295
+ if (rawEntry.compressedSize !== 0) {
4296
+ // bounds check now, because the read streams will probably not complain loud enough.
4297
+ // since we're dealing with an unsigned offset plus an unsigned size,
4298
+ // we only have 1 thing to check for.
4299
+ if (fileDataEnd > totalLength) {
4300
+ throw new Error(`file data overflows file bounds: ${fileDataStart} + ${rawEntry.compressedSize} > ${totalLength}`);
4301
+ }
4302
+ }
4303
+ return {
4304
+ decompress,
4305
+ fileDataStart,
4306
+ };
4307
+ }
4308
+
4309
+ async function readEntryDataAsArrayBuffer(reader, rawEntry) {
4310
+ const {decompress, fileDataStart} = await readEntryDataHeader(reader, rawEntry);
4311
+ if (!decompress) {
4312
+ const dataView = await readAs(reader, fileDataStart, rawEntry.compressedSize);
4313
+ // make copy?
4314
+ //
4315
+ // 1. The source is a Blob/file. In this case we'll get back TypedArray we can just hand to the user
4316
+ // 2. The source is a TypedArray. In this case we'll get back TypedArray that is a view into a larger buffer
4317
+ // but because ultimately this is used to return an ArrayBuffer to `someEntry.arrayBuffer()`
4318
+ // we need to return copy since we need the `ArrayBuffer`, not the TypedArray to exactly match the data.
4319
+ // Note: We could add another API function `bytes()` or something that returned a `Uint8Array`
4320
+ // instead of an `ArrayBuffer`. This would let us skip a copy here. But this case only happens for uncompressed
4321
+ // data. That seems like a rare enough case that adding a new API is not worth it? Or is it? A zip of jpegs or mp3s
4322
+ // might not be compressed. For now that's a TBD.
4323
+ return isTypedArraySameAsArrayBuffer(dataView) ? dataView.buffer : dataView.slice().buffer;
4324
+ }
4325
+ // see comment in readEntryDateAsBlob
4326
+ const typedArrayOrBlob = await readAsBlobOrTypedArray(reader, fileDataStart, rawEntry.compressedSize);
4327
+ const result = await inflateRawAsync(typedArrayOrBlob, rawEntry.uncompressedSize);
4328
+ return result;
4329
+ }
4330
+
4331
+ async function readEntryDataAsBlob(reader, rawEntry, type) {
4332
+ const {decompress, fileDataStart} = await readEntryDataHeader(reader, rawEntry);
4333
+ if (!decompress) {
4334
+ const typedArrayOrBlob = await readAsBlobOrTypedArray(reader, fileDataStart, rawEntry.compressedSize, type);
4335
+ if (isBlob(typedArrayOrBlob)) {
4336
+ return typedArrayOrBlob;
4337
+ }
4338
+ return new Blob([isSharedArrayBuffer(typedArrayOrBlob.buffer) ? new Uint8Array(typedArrayOrBlob) : typedArrayOrBlob], {type});
4339
+ }
4340
+ // Here's the issue with this mess (should refactor?)
4341
+ // if the source is a blob then we really want to pass a blob to inflateRawAsync to avoid a large
4342
+ // copy if we're going to a worker.
4343
+ const typedArrayOrBlob = await readAsBlobOrTypedArray(reader, fileDataStart, rawEntry.compressedSize);
4344
+ const result = await inflateRawAsync(typedArrayOrBlob, rawEntry.uncompressedSize, type);
4345
+ return result;
4346
+ }
4347
+
4348
+ function setOptions$1(options) {
4349
+ setOptions(options);
4350
+ }
4351
+
4352
+ async function unzipRaw(source) {
4353
+ let reader;
4354
+ if (typeof Blob !== 'undefined' && source instanceof Blob) {
4355
+ reader = new BlobReader(source);
4356
+ } else if (source instanceof ArrayBuffer || (source && source.buffer && source.buffer instanceof ArrayBuffer)) {
4357
+ reader = new ArrayBufferReader(source);
4358
+ } else if (isSharedArrayBuffer(source) || isSharedArrayBuffer(source.buffer)) {
4359
+ reader = new ArrayBufferReader(source);
4360
+ } else if (typeof source === 'string') {
4361
+ const req = await fetch(source);
4362
+ if (!req.ok) {
4363
+ throw new Error(`failed http request ${source}, status: ${req.status}: ${req.statusText}`);
4364
+ }
4365
+ const blob = await req.blob();
4366
+ reader = new BlobReader(blob);
4367
+ } else if (typeof source.getLength === 'function' && typeof source.read === 'function') {
4368
+ reader = source;
4369
+ } else {
4370
+ throw new Error('unsupported source type');
4371
+ }
4372
+
4373
+ const totalLength = await reader.getLength();
4374
+
4375
+ if (totalLength > Number.MAX_SAFE_INTEGER) {
4376
+ throw new Error(`file too large. size: ${totalLength}. Only file sizes up 4503599627370496 bytes are supported`);
4377
+ }
4378
+
4379
+ return await findEndOfCentralDirector(reader, totalLength);
4380
+ }
4381
+
4382
+ // If the names are not utf8 you should use unzipitRaw
4383
+ async function unzip(source) {
4384
+ const {zip, entries} = await unzipRaw(source);
4385
+ return {
4386
+ zip,
4387
+ entries: Object.fromEntries(entries.map(v => [v.name, v])),
4388
+ };
4389
+ }
4390
+
4391
+ function cleanup$1() {
4392
+ cleanup();
4393
+ }
4394
+
4395
+ var unzipit_module = /*#__PURE__*/Object.freeze({
4396
+ __proto__: null,
4397
+ HTTPRangeReader: HTTPRangeReader,
4398
+ cleanup: cleanup$1,
4399
+ setOptions: setOptions$1,
4400
+ unzip: unzip,
4401
+ unzipRaw: unzipRaw
4402
+ });
4403
+
4404
+ exports.CrcGenerator = CrcGenerator;
4405
+ exports.DeviceBoundPacket = DeviceBoundPacket;
4406
+ exports.DisableDashH2DPacket = DisableDashH2DPacket;
4407
+ exports.DisableDashReplyD2HPacket = DisableDashReplyD2HPacket;
4408
+ exports.EnableDashH2DPacket = EnableDashH2DPacket;
4409
+ exports.EnableDashReplyD2HPacket = EnableDashReplyD2HPacket;
4410
+ exports.EraseFileH2DPacket = EraseFileH2DPacket;
4411
+ exports.EraseFileReplyD2HPacket = EraseFileReplyD2HPacket;
4412
+ exports.ExitFileTransferH2DPacket = ExitFileTransferH2DPacket;
4413
+ exports.ExitFileTransferReplyD2HPacket = ExitFileTransferReplyD2HPacket;
4414
+ exports.FactoryEnableH2DPacket = FactoryEnableH2DPacket;
4415
+ exports.FactoryEnableReplyD2HPacket = FactoryEnableReplyD2HPacket;
4416
+ exports.FactoryStatusH2DPacket = FactoryStatusH2DPacket;
4417
+ exports.FactoryStatusReplyD2HPacket = FactoryStatusReplyD2HPacket;
4418
+ exports.FileClearUpH2DPacket = FileClearUpH2DPacket;
4419
+ exports.FileClearUpReplyD2HPacket = FileClearUpReplyD2HPacket;
4420
+ exports.FileControlH2DPacket = FileControlH2DPacket;
4421
+ exports.FileControlReplyD2HPacket = FileControlReplyD2HPacket;
4422
+ exports.FileFormatH2DPacket = FileFormatH2DPacket;
4423
+ exports.FileFormatReplyD2HPacket = FileFormatReplyD2HPacket;
4424
+ exports.GetDeviceStatusH2DPacket = GetDeviceStatusH2DPacket;
4425
+ exports.GetDeviceStatusReplyD2HPacket = GetDeviceStatusReplyD2HPacket;
4426
+ exports.GetDirectoryEntryH2DPacket = GetDirectoryEntryH2DPacket;
4427
+ exports.GetDirectoryEntryReplyD2HPacket = GetDirectoryEntryReplyD2HPacket;
4428
+ exports.GetDirectoryFileCountH2DPacket = GetDirectoryFileCountH2DPacket;
4429
+ exports.GetDirectoryFileCountReplyD2HPacket = GetDirectoryFileCountReplyD2HPacket;
4430
+ exports.GetFdtStatusH2DPacket = GetFdtStatusH2DPacket;
4431
+ exports.GetFdtStatusReplyD2HPacket = GetFdtStatusReplyD2HPacket;
4432
+ exports.GetFileMetadataH2DPacket = GetFileMetadataH2DPacket;
4433
+ exports.GetFileMetadataReplyD2HPacket = GetFileMetadataReplyD2HPacket;
4434
+ exports.GetLogCountH2DPacket = GetLogCountH2DPacket;
4435
+ exports.GetLogCountReplyD2HPacket = GetLogCountReplyD2HPacket;
4436
+ exports.GetMatchStatusH2DPacket = GetMatchStatusH2DPacket;
4437
+ exports.GetProgramSlotInfoH2DPacket = GetProgramSlotInfoH2DPacket;
4438
+ exports.GetProgramSlotInfoReplyD2HPacket = GetProgramSlotInfoReplyD2HPacket;
4439
+ exports.GetRadioModeH2DPacket = GetRadioModeH2DPacket;
4440
+ exports.GetRadioStatusH2DPacket = GetRadioStatusH2DPacket;
4441
+ exports.GetRadioStatusReplyD2HPacket = GetRadioStatusReplyD2HPacket;
4442
+ exports.GetSlot1to4InfoH2DPacket = GetSlot1to4InfoH2DPacket;
4443
+ exports.GetSlot1to4InfoReplyD2HPacket = GetSlot1to4InfoReplyD2HPacket;
4444
+ exports.GetSlot5to8InfoH2DPacket = GetSlot5to8InfoH2DPacket;
4445
+ exports.GetSlot5to8InfoReplyD2HPacket = GetSlot5to8InfoReplyD2HPacket;
4446
+ exports.GetSystemFlagsH2DPacket = GetSystemFlagsH2DPacket;
4447
+ exports.GetSystemFlagsReplyD2HPacket = GetSystemFlagsReplyD2HPacket;
4448
+ exports.GetSystemStatusH2DPacket = GetSystemStatusH2DPacket;
4449
+ exports.GetSystemStatusReplyD2HPacket = GetSystemStatusReplyD2HPacket;
4450
+ exports.GetUserDataH2DPacket = GetUserDataH2DPacket;
4451
+ exports.GetUserDataReplyD2HPacket = GetUserDataReplyD2HPacket;
4452
+ exports.HostBoundPacket = HostBoundPacket;
4453
+ exports.InitFileTransferH2DPacket = InitFileTransferH2DPacket;
4454
+ exports.InitFileTransferReplyD2HPacket = InitFileTransferReplyD2HPacket;
4455
+ exports.LinkFileH2DPacket = LinkFileH2DPacket;
4456
+ exports.LinkFileReplyD2HPacket = LinkFileReplyD2HPacket;
4457
+ exports.LoadFileActionH2DPacket = LoadFileActionH2DPacket;
4458
+ exports.LoadFileActionReplyD2HPacket = LoadFileActionReplyD2HPacket;
4459
+ exports.MatchModeReplyD2HPacket = MatchModeReplyD2HPacket;
4460
+ exports.MatchStatusReplyD2HPacket = MatchStatusReplyD2HPacket;
4461
+ exports.Packet = Packet;
4462
+ exports.PacketEncoder = PacketEncoder;
4463
+ exports.PacketView = PacketView;
4464
+ exports.ProgramIniConfig = ProgramIniConfig;
4465
+ exports.Query1H2DPacket = Query1H2DPacket;
4466
+ exports.Query1ReplyD2HPacket = Query1ReplyD2HPacket;
4467
+ exports.ReadFileH2DPacket = ReadFileH2DPacket;
4468
+ exports.ReadFileReplyD2HPacket = ReadFileReplyD2HPacket;
4469
+ exports.ReadKeyValueH2DPacket = ReadKeyValueH2DPacket;
4470
+ exports.ReadKeyValueReplyD2HPacket = ReadKeyValueReplyD2HPacket;
4471
+ exports.ReadLogPageH2DPacket = ReadLogPageH2DPacket;
4472
+ exports.ReadLogPageReplyD2HPacket = ReadLogPageReplyD2HPacket;
4473
+ exports.ScreenCaptureH2DPacket = ScreenCaptureH2DPacket;
4474
+ exports.ScreenCaptureReplyD2HPacket = ScreenCaptureReplyD2HPacket;
4475
+ exports.SelectDashH2DPacket = SelectDashH2DPacket;
4476
+ exports.SelectDashReplyD2HPacket = SelectDashReplyD2HPacket;
4477
+ exports.SendDashTouchH2DPacket = SendDashTouchH2DPacket;
4478
+ exports.SendDashTouchReplyD2HPacket = SendDashTouchReplyD2HPacket;
4479
+ exports.SetFileMetadataH2DPacket = SetFileMetadataH2DPacket;
4480
+ exports.SetFileMetadataReplyD2HPacket = SetFileMetadataReplyD2HPacket;
4481
+ exports.SystemVersionH2DPacket = SystemVersionH2DPacket;
4482
+ exports.SystemVersionReplyD2HPacket = SystemVersionReplyD2HPacket;
4483
+ exports.USER_FLASH_END = USER_FLASH_END;
4484
+ exports.USER_FLASH_END_B = USER_FLASH_END_B;
4485
+ exports.USER_FLASH_END_C = USER_FLASH_END_C;
4486
+ exports.USER_FLASH_MAX_FILE_SIZE = USER_FLASH_MAX_FILE_SIZE;
4487
+ exports.USER_FLASH_START = USER_FLASH_START;
4488
+ exports.USER_FLASH_START_B = USER_FLASH_START_B;
4489
+ exports.USER_FLASH_START_C = USER_FLASH_START_C;
4490
+ exports.USER_FLASH_SYS_CODE_START = USER_FLASH_SYS_CODE_START;
4491
+ exports.USER_FLASH_USR_CODE_START = USER_FLASH_USR_CODE_START;
4492
+ exports.USER_PROG_CHUNK_SIZE = USER_PROG_CHUNK_SIZE;
4493
+ exports.UpdateMatchModeH2DPacket = UpdateMatchModeH2DPacket;
4494
+ exports.V5Battery = V5Battery;
4495
+ exports.V5Brain = V5Brain;
4496
+ exports.V5BrainButton = V5BrainButton;
4497
+ exports.V5BrainSettings = V5BrainSettings;
4498
+ exports.V5Controller = V5Controller;
4499
+ exports.V5Radio = V5Radio;
4500
+ exports.V5SerialConnection = V5SerialConnection;
4501
+ exports.V5SerialDevice = V5SerialDevice;
4502
+ exports.V5SmartDevice = V5SmartDevice;
4503
+ exports.VexEventEmitter = VexEventEmitter;
4504
+ exports.VexEventTarget = VexEventTarget;
4505
+ exports.VexFirmwareVersion = VexFirmwareVersion;
4506
+ exports.VexSerialConnection = VexSerialConnection;
4507
+ exports.VexSerialDevice = VexSerialDevice;
4508
+ exports.WriteFileH2DPacket = WriteFileH2DPacket;
4509
+ exports.WriteFileReplyD2HPacket = WriteFileReplyD2HPacket;
4510
+ exports.WriteKeyValueH2DPacket = WriteKeyValueH2DPacket;
4511
+ exports.WriteKeyValueReplyD2HPacket = WriteKeyValueReplyD2HPacket;
4512
+ exports.downloadFileFromInternet = downloadFileFromInternet;
4513
+ exports.sleep = sleep;
4514
+ exports.sleepUntil = sleepUntil;
4515
+ exports.sleepUntilAsync = sleepUntilAsync;
4516
+ //# sourceMappingURL=v5-serial-protocol.cjs.js.map