signalk-garmin-keypad-plugin 1.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.codex +0 -0
- package/.github/workflows/publish.yml +42 -0
- package/README.md +69 -0
- package/dist/index.d.ts +45 -0
- package/dist/index.js +395 -0
- package/dist/n2k.d.ts +19 -0
- package/dist/n2k.js +143 -0
- package/dist/pgns.d.ts +169 -0
- package/dist/pgns.js +454 -0
- package/dist/protocol.d.ts +22 -0
- package/dist/protocol.js +55 -0
- package/index.js +1 -0
- package/package.json +32 -0
- package/public/183.js +1 -0
- package/public/main.js +1 -0
- package/public/remoteEntry.js +1 -0
- package/resources/demo.png +0 -0
- package/tsconfig.json +13 -0
package/dist/pgns.js
ADDED
|
@@ -0,0 +1,454 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// Garmin GNX Keypad PGN definitions for canboatjs v3
|
|
3
|
+
//
|
|
4
|
+
// PGN 61184 — Button events (select/save preset, page nav)
|
|
5
|
+
// PGN 126720 — Property commands (display, sleep) and heartbeat
|
|
6
|
+
//
|
|
7
|
+
// Field types use LOOKUP+MANUFACTURER_CODE (not MANUFACTURER) for toPgn encoding.
|
|
8
|
+
module.exports = {
|
|
9
|
+
PGNs: [
|
|
10
|
+
// =========================================================
|
|
11
|
+
// PGN 61184 — Select Preset (Short Press)
|
|
12
|
+
// =========================================================
|
|
13
|
+
{
|
|
14
|
+
PGN: 61184,
|
|
15
|
+
Id: 'garminGnxKeypadSelectPreset',
|
|
16
|
+
Description: 'Garmin GNX Keypad Select Preset',
|
|
17
|
+
Type: 'Single',
|
|
18
|
+
Complete: true,
|
|
19
|
+
Length: 7,
|
|
20
|
+
Fields: [
|
|
21
|
+
{
|
|
22
|
+
Order: 1,
|
|
23
|
+
Id: 'manufacturerCode',
|
|
24
|
+
Name: 'Manufacturer Code',
|
|
25
|
+
BitLength: 11,
|
|
26
|
+
BitOffset: 0,
|
|
27
|
+
BitStart: 0,
|
|
28
|
+
Match: 229,
|
|
29
|
+
FieldType: 'LOOKUP',
|
|
30
|
+
LookupEnumeration: 'MANUFACTURER_CODE',
|
|
31
|
+
Signed: false
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
Order: 2,
|
|
35
|
+
Id: 'reserved',
|
|
36
|
+
Name: 'Reserved',
|
|
37
|
+
BitLength: 2,
|
|
38
|
+
BitOffset: 11,
|
|
39
|
+
BitStart: 3,
|
|
40
|
+
FieldType: 'RESERVED'
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
Order: 3,
|
|
44
|
+
Id: 'industryCode',
|
|
45
|
+
Name: 'Industry Code',
|
|
46
|
+
BitLength: 3,
|
|
47
|
+
BitOffset: 13,
|
|
48
|
+
BitStart: 5,
|
|
49
|
+
Match: 4,
|
|
50
|
+
FieldType: 'LOOKUP',
|
|
51
|
+
LookupEnumeration: 'INDUSTRY_CODE',
|
|
52
|
+
Signed: false
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
Order: 4,
|
|
56
|
+
Id: 'command',
|
|
57
|
+
Name: 'Command',
|
|
58
|
+
BitLength: 8,
|
|
59
|
+
BitOffset: 16,
|
|
60
|
+
BitStart: 0,
|
|
61
|
+
FieldType: 'NUMBER',
|
|
62
|
+
Resolution: 1,
|
|
63
|
+
Signed: false,
|
|
64
|
+
Match: 0x84
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
Order: 5,
|
|
68
|
+
Id: 'productId',
|
|
69
|
+
Name: 'Product ID',
|
|
70
|
+
BitLength: 8,
|
|
71
|
+
BitOffset: 24,
|
|
72
|
+
BitStart: 0,
|
|
73
|
+
FieldType: 'NUMBER',
|
|
74
|
+
Resolution: 1,
|
|
75
|
+
Signed: false
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
Order: 6,
|
|
79
|
+
Id: 'unknown1',
|
|
80
|
+
Name: 'Unknown 1',
|
|
81
|
+
BitLength: 8,
|
|
82
|
+
BitOffset: 32,
|
|
83
|
+
BitStart: 0,
|
|
84
|
+
FieldType: 'NUMBER',
|
|
85
|
+
Resolution: 1,
|
|
86
|
+
Signed: false
|
|
87
|
+
},
|
|
88
|
+
{
|
|
89
|
+
Order: 7,
|
|
90
|
+
Id: 'unknown2',
|
|
91
|
+
Name: 'Unknown 2',
|
|
92
|
+
BitLength: 8,
|
|
93
|
+
BitOffset: 40,
|
|
94
|
+
BitStart: 0,
|
|
95
|
+
FieldType: 'NUMBER',
|
|
96
|
+
Resolution: 1,
|
|
97
|
+
Signed: false
|
|
98
|
+
},
|
|
99
|
+
{
|
|
100
|
+
Order: 8,
|
|
101
|
+
Id: 'presetIndex',
|
|
102
|
+
Name: 'Preset Index',
|
|
103
|
+
BitLength: 8,
|
|
104
|
+
BitOffset: 48,
|
|
105
|
+
BitStart: 0,
|
|
106
|
+
FieldType: 'NUMBER',
|
|
107
|
+
Resolution: 1,
|
|
108
|
+
Signed: false
|
|
109
|
+
}
|
|
110
|
+
]
|
|
111
|
+
},
|
|
112
|
+
// =========================================================
|
|
113
|
+
// PGN 61184 — Save Preset (Long Press)
|
|
114
|
+
// =========================================================
|
|
115
|
+
{
|
|
116
|
+
PGN: 61184,
|
|
117
|
+
Id: 'garminGnxKeypadSavePreset',
|
|
118
|
+
Description: 'Garmin GNX Keypad Save Preset',
|
|
119
|
+
Type: 'Single',
|
|
120
|
+
Complete: true,
|
|
121
|
+
Length: 7,
|
|
122
|
+
Fields: [
|
|
123
|
+
{
|
|
124
|
+
Order: 1,
|
|
125
|
+
Id: 'manufacturerCode',
|
|
126
|
+
Name: 'Manufacturer Code',
|
|
127
|
+
BitLength: 11,
|
|
128
|
+
BitOffset: 0,
|
|
129
|
+
BitStart: 0,
|
|
130
|
+
Match: 229,
|
|
131
|
+
FieldType: 'LOOKUP',
|
|
132
|
+
LookupEnumeration: 'MANUFACTURER_CODE',
|
|
133
|
+
Signed: false
|
|
134
|
+
},
|
|
135
|
+
{
|
|
136
|
+
Order: 2,
|
|
137
|
+
Id: 'reserved',
|
|
138
|
+
Name: 'Reserved',
|
|
139
|
+
BitLength: 2,
|
|
140
|
+
BitOffset: 11,
|
|
141
|
+
BitStart: 3,
|
|
142
|
+
FieldType: 'RESERVED'
|
|
143
|
+
},
|
|
144
|
+
{
|
|
145
|
+
Order: 3,
|
|
146
|
+
Id: 'industryCode',
|
|
147
|
+
Name: 'Industry Code',
|
|
148
|
+
BitLength: 3,
|
|
149
|
+
BitOffset: 13,
|
|
150
|
+
BitStart: 5,
|
|
151
|
+
Match: 4,
|
|
152
|
+
FieldType: 'LOOKUP',
|
|
153
|
+
LookupEnumeration: 'INDUSTRY_CODE',
|
|
154
|
+
Signed: false
|
|
155
|
+
},
|
|
156
|
+
{
|
|
157
|
+
Order: 4,
|
|
158
|
+
Id: 'command',
|
|
159
|
+
Name: 'Command',
|
|
160
|
+
BitLength: 8,
|
|
161
|
+
BitOffset: 16,
|
|
162
|
+
BitStart: 0,
|
|
163
|
+
FieldType: 'NUMBER',
|
|
164
|
+
Resolution: 1,
|
|
165
|
+
Signed: false,
|
|
166
|
+
Match: 0x85
|
|
167
|
+
},
|
|
168
|
+
{
|
|
169
|
+
Order: 5,
|
|
170
|
+
Id: 'productId',
|
|
171
|
+
Name: 'Product ID',
|
|
172
|
+
BitLength: 8,
|
|
173
|
+
BitOffset: 24,
|
|
174
|
+
BitStart: 0,
|
|
175
|
+
FieldType: 'NUMBER',
|
|
176
|
+
Resolution: 1,
|
|
177
|
+
Signed: false
|
|
178
|
+
},
|
|
179
|
+
{
|
|
180
|
+
Order: 6,
|
|
181
|
+
Id: 'unknown1',
|
|
182
|
+
Name: 'Unknown 1',
|
|
183
|
+
BitLength: 8,
|
|
184
|
+
BitOffset: 32,
|
|
185
|
+
BitStart: 0,
|
|
186
|
+
FieldType: 'NUMBER',
|
|
187
|
+
Resolution: 1,
|
|
188
|
+
Signed: false
|
|
189
|
+
},
|
|
190
|
+
{
|
|
191
|
+
Order: 7,
|
|
192
|
+
Id: 'unknown2',
|
|
193
|
+
Name: 'Unknown 2',
|
|
194
|
+
BitLength: 8,
|
|
195
|
+
BitOffset: 40,
|
|
196
|
+
BitStart: 0,
|
|
197
|
+
FieldType: 'NUMBER',
|
|
198
|
+
Resolution: 1,
|
|
199
|
+
Signed: false
|
|
200
|
+
},
|
|
201
|
+
{
|
|
202
|
+
Order: 8,
|
|
203
|
+
Id: 'presetIndex',
|
|
204
|
+
Name: 'Preset Index',
|
|
205
|
+
BitLength: 8,
|
|
206
|
+
BitOffset: 48,
|
|
207
|
+
BitStart: 0,
|
|
208
|
+
FieldType: 'NUMBER',
|
|
209
|
+
Resolution: 1,
|
|
210
|
+
Signed: false
|
|
211
|
+
}
|
|
212
|
+
]
|
|
213
|
+
},
|
|
214
|
+
// =========================================================
|
|
215
|
+
// PGN 61184 — Page Navigation
|
|
216
|
+
// =========================================================
|
|
217
|
+
{
|
|
218
|
+
PGN: 61184,
|
|
219
|
+
Id: 'garminGnxKeypadPageNav',
|
|
220
|
+
Description: 'Garmin GNX Keypad Page Navigation',
|
|
221
|
+
Type: 'Single',
|
|
222
|
+
Complete: true,
|
|
223
|
+
Length: 7,
|
|
224
|
+
Fields: [
|
|
225
|
+
{
|
|
226
|
+
Order: 1,
|
|
227
|
+
Id: 'manufacturerCode',
|
|
228
|
+
Name: 'Manufacturer Code',
|
|
229
|
+
BitLength: 11,
|
|
230
|
+
BitOffset: 0,
|
|
231
|
+
BitStart: 0,
|
|
232
|
+
Match: 229,
|
|
233
|
+
FieldType: 'LOOKUP',
|
|
234
|
+
LookupEnumeration: 'MANUFACTURER_CODE',
|
|
235
|
+
Signed: false
|
|
236
|
+
},
|
|
237
|
+
{
|
|
238
|
+
Order: 2,
|
|
239
|
+
Id: 'reserved',
|
|
240
|
+
Name: 'Reserved',
|
|
241
|
+
BitLength: 2,
|
|
242
|
+
BitOffset: 11,
|
|
243
|
+
BitStart: 3,
|
|
244
|
+
FieldType: 'RESERVED'
|
|
245
|
+
},
|
|
246
|
+
{
|
|
247
|
+
Order: 3,
|
|
248
|
+
Id: 'industryCode',
|
|
249
|
+
Name: 'Industry Code',
|
|
250
|
+
BitLength: 3,
|
|
251
|
+
BitOffset: 13,
|
|
252
|
+
BitStart: 5,
|
|
253
|
+
Match: 4,
|
|
254
|
+
FieldType: 'LOOKUP',
|
|
255
|
+
LookupEnumeration: 'INDUSTRY_CODE',
|
|
256
|
+
Signed: false
|
|
257
|
+
},
|
|
258
|
+
{
|
|
259
|
+
Order: 4,
|
|
260
|
+
Id: 'command',
|
|
261
|
+
Name: 'Command',
|
|
262
|
+
BitLength: 8,
|
|
263
|
+
BitOffset: 16,
|
|
264
|
+
BitStart: 0,
|
|
265
|
+
FieldType: 'NUMBER',
|
|
266
|
+
Resolution: 1,
|
|
267
|
+
Signed: false,
|
|
268
|
+
Match: 0x49
|
|
269
|
+
},
|
|
270
|
+
{
|
|
271
|
+
Order: 5,
|
|
272
|
+
Id: 'productId',
|
|
273
|
+
Name: 'Product ID',
|
|
274
|
+
BitLength: 8,
|
|
275
|
+
BitOffset: 24,
|
|
276
|
+
BitStart: 0,
|
|
277
|
+
FieldType: 'NUMBER',
|
|
278
|
+
Resolution: 1,
|
|
279
|
+
Signed: false
|
|
280
|
+
},
|
|
281
|
+
{
|
|
282
|
+
Order: 6,
|
|
283
|
+
Id: 'unknown1',
|
|
284
|
+
Name: 'Unknown 1',
|
|
285
|
+
BitLength: 8,
|
|
286
|
+
BitOffset: 32,
|
|
287
|
+
BitStart: 0,
|
|
288
|
+
FieldType: 'NUMBER',
|
|
289
|
+
Resolution: 1,
|
|
290
|
+
Signed: false
|
|
291
|
+
},
|
|
292
|
+
{
|
|
293
|
+
Order: 7,
|
|
294
|
+
Id: 'unknown2',
|
|
295
|
+
Name: 'Unknown 2',
|
|
296
|
+
BitLength: 8,
|
|
297
|
+
BitOffset: 40,
|
|
298
|
+
BitStart: 0,
|
|
299
|
+
FieldType: 'NUMBER',
|
|
300
|
+
Resolution: 1,
|
|
301
|
+
Signed: false
|
|
302
|
+
},
|
|
303
|
+
{
|
|
304
|
+
Order: 8,
|
|
305
|
+
Id: 'direction',
|
|
306
|
+
Name: 'Direction',
|
|
307
|
+
BitLength: 8,
|
|
308
|
+
BitOffset: 48,
|
|
309
|
+
BitStart: 0,
|
|
310
|
+
FieldType: 'NUMBER',
|
|
311
|
+
Resolution: 1,
|
|
312
|
+
Signed: false
|
|
313
|
+
}
|
|
314
|
+
]
|
|
315
|
+
},
|
|
316
|
+
// =========================================================
|
|
317
|
+
// PGN 126720 — Property Command (display, sleep)
|
|
318
|
+
// Byte 2 = 0xe5 distinguishes from heartbeat and race timer
|
|
319
|
+
// =========================================================
|
|
320
|
+
{
|
|
321
|
+
PGN: 126720,
|
|
322
|
+
Id: 'garminGnxKeypadPropertyCommand',
|
|
323
|
+
Description: 'Garmin GNX Keypad Property Command',
|
|
324
|
+
Type: 'Fast',
|
|
325
|
+
Complete: false,
|
|
326
|
+
Fields: [
|
|
327
|
+
{
|
|
328
|
+
Order: 1,
|
|
329
|
+
Id: 'manufacturerCode',
|
|
330
|
+
Name: 'Manufacturer Code',
|
|
331
|
+
BitLength: 11,
|
|
332
|
+
BitOffset: 0,
|
|
333
|
+
BitStart: 0,
|
|
334
|
+
Match: 229,
|
|
335
|
+
FieldType: 'LOOKUP',
|
|
336
|
+
LookupEnumeration: 'MANUFACTURER_CODE',
|
|
337
|
+
Signed: false
|
|
338
|
+
},
|
|
339
|
+
{
|
|
340
|
+
Order: 2,
|
|
341
|
+
Id: 'reserved',
|
|
342
|
+
Name: 'Reserved',
|
|
343
|
+
BitLength: 2,
|
|
344
|
+
BitOffset: 11,
|
|
345
|
+
BitStart: 3,
|
|
346
|
+
FieldType: 'RESERVED'
|
|
347
|
+
},
|
|
348
|
+
{
|
|
349
|
+
Order: 3,
|
|
350
|
+
Id: 'industryCode',
|
|
351
|
+
Name: 'Industry Code',
|
|
352
|
+
BitLength: 3,
|
|
353
|
+
BitOffset: 13,
|
|
354
|
+
BitStart: 5,
|
|
355
|
+
Match: 4,
|
|
356
|
+
FieldType: 'LOOKUP',
|
|
357
|
+
LookupEnumeration: 'INDUSTRY_CODE',
|
|
358
|
+
Signed: false
|
|
359
|
+
},
|
|
360
|
+
{
|
|
361
|
+
Order: 4,
|
|
362
|
+
Id: 'command',
|
|
363
|
+
Name: 'Command',
|
|
364
|
+
BitLength: 8,
|
|
365
|
+
BitOffset: 16,
|
|
366
|
+
BitStart: 0,
|
|
367
|
+
FieldType: 'NUMBER',
|
|
368
|
+
Resolution: 1,
|
|
369
|
+
Signed: false,
|
|
370
|
+
Match: 0xe5
|
|
371
|
+
},
|
|
372
|
+
{
|
|
373
|
+
Order: 5,
|
|
374
|
+
Id: 'payload',
|
|
375
|
+
Name: 'Payload',
|
|
376
|
+
BitLength: 384,
|
|
377
|
+
BitOffset: 24,
|
|
378
|
+
BitStart: 0,
|
|
379
|
+
FieldType: 'Binary data',
|
|
380
|
+
Signed: false
|
|
381
|
+
}
|
|
382
|
+
]
|
|
383
|
+
},
|
|
384
|
+
// =========================================================
|
|
385
|
+
// PGN 126720 — Heartbeat Ping
|
|
386
|
+
// Byte 2 = 0xe7 distinguishes from property commands
|
|
387
|
+
// =========================================================
|
|
388
|
+
{
|
|
389
|
+
PGN: 126720,
|
|
390
|
+
Id: 'garminGnxKeypadHeartbeat',
|
|
391
|
+
Description: 'Garmin GNX Keypad Heartbeat',
|
|
392
|
+
Type: 'Fast',
|
|
393
|
+
Complete: true,
|
|
394
|
+
Length: 17,
|
|
395
|
+
Fields: [
|
|
396
|
+
{
|
|
397
|
+
Order: 1,
|
|
398
|
+
Id: 'manufacturerCode',
|
|
399
|
+
Name: 'Manufacturer Code',
|
|
400
|
+
BitLength: 11,
|
|
401
|
+
BitOffset: 0,
|
|
402
|
+
BitStart: 0,
|
|
403
|
+
Match: 229,
|
|
404
|
+
FieldType: 'LOOKUP',
|
|
405
|
+
LookupEnumeration: 'MANUFACTURER_CODE',
|
|
406
|
+
Signed: false
|
|
407
|
+
},
|
|
408
|
+
{
|
|
409
|
+
Order: 2,
|
|
410
|
+
Id: 'reserved',
|
|
411
|
+
Name: 'Reserved',
|
|
412
|
+
BitLength: 2,
|
|
413
|
+
BitOffset: 11,
|
|
414
|
+
BitStart: 3,
|
|
415
|
+
FieldType: 'RESERVED'
|
|
416
|
+
},
|
|
417
|
+
{
|
|
418
|
+
Order: 3,
|
|
419
|
+
Id: 'industryCode',
|
|
420
|
+
Name: 'Industry Code',
|
|
421
|
+
BitLength: 3,
|
|
422
|
+
BitOffset: 13,
|
|
423
|
+
BitStart: 5,
|
|
424
|
+
Match: 4,
|
|
425
|
+
FieldType: 'LOOKUP',
|
|
426
|
+
LookupEnumeration: 'INDUSTRY_CODE',
|
|
427
|
+
Signed: false
|
|
428
|
+
},
|
|
429
|
+
{
|
|
430
|
+
Order: 4,
|
|
431
|
+
Id: 'command',
|
|
432
|
+
Name: 'Command',
|
|
433
|
+
BitLength: 8,
|
|
434
|
+
BitOffset: 16,
|
|
435
|
+
BitStart: 0,
|
|
436
|
+
FieldType: 'NUMBER',
|
|
437
|
+
Resolution: 1,
|
|
438
|
+
Signed: false,
|
|
439
|
+
Match: 0xe7
|
|
440
|
+
},
|
|
441
|
+
{
|
|
442
|
+
Order: 5,
|
|
443
|
+
Id: 'payload',
|
|
444
|
+
Name: 'Payload',
|
|
445
|
+
BitLength: 112,
|
|
446
|
+
BitOffset: 24,
|
|
447
|
+
BitStart: 0,
|
|
448
|
+
FieldType: 'Binary data',
|
|
449
|
+
Signed: false
|
|
450
|
+
}
|
|
451
|
+
]
|
|
452
|
+
}
|
|
453
|
+
]
|
|
454
|
+
};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
export declare const PLUGIN_ID = "signalk-garmin-keypad";
|
|
3
|
+
export declare const PGN_SINGLE = 61184;
|
|
4
|
+
export declare const PGN_FAST = 126720;
|
|
5
|
+
export declare const CMD_SELECT_PRESET = 132;
|
|
6
|
+
export declare const CMD_SAVE_PRESET = 133;
|
|
7
|
+
export declare const CMD_PAGE_NAV = 73;
|
|
8
|
+
export declare const PRODUCT_ID = 23;
|
|
9
|
+
export declare const UNK1 = 2;
|
|
10
|
+
export declare const UNK2 = 2;
|
|
11
|
+
export declare const PROP_SLEEP = "gnx_sleep_mode_id";
|
|
12
|
+
export declare const PROP_DISPLAY = "gnx_selected_disp";
|
|
13
|
+
export declare const PROP_DISP_CNT = "gnx_disp_cnt";
|
|
14
|
+
export declare const SLEEP = 0;
|
|
15
|
+
export declare const WAKE = 1;
|
|
16
|
+
export declare const DEFAULT_SRC = 0;
|
|
17
|
+
export declare const DEFAULT_DST = 255;
|
|
18
|
+
export declare const DEFAULT_PRIO = 7;
|
|
19
|
+
export declare const DEFAULT_GROUP_ID: Buffer;
|
|
20
|
+
export declare function buildPropertyHeader(groupId: Buffer): Buffer;
|
|
21
|
+
export declare function parseGroupId(hexStr: string): Buffer;
|
|
22
|
+
export declare const PROPERTY_SEPARATOR: Buffer;
|
package/dist/protocol.js
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.PROPERTY_SEPARATOR = exports.parseGroupId = exports.buildPropertyHeader = exports.DEFAULT_GROUP_ID = exports.DEFAULT_PRIO = exports.DEFAULT_DST = exports.DEFAULT_SRC = exports.WAKE = exports.SLEEP = exports.PROP_DISP_CNT = exports.PROP_DISPLAY = exports.PROP_SLEEP = exports.UNK2 = exports.UNK1 = exports.PRODUCT_ID = exports.CMD_PAGE_NAV = exports.CMD_SAVE_PRESET = exports.CMD_SELECT_PRESET = exports.PGN_FAST = exports.PGN_SINGLE = exports.PLUGIN_ID = void 0;
|
|
4
|
+
exports.PLUGIN_ID = 'signalk-garmin-keypad';
|
|
5
|
+
// PGN numbers
|
|
6
|
+
exports.PGN_SINGLE = 61184;
|
|
7
|
+
exports.PGN_FAST = 126720;
|
|
8
|
+
// PGN 61184 command bytes
|
|
9
|
+
exports.CMD_SELECT_PRESET = 0x84;
|
|
10
|
+
exports.CMD_SAVE_PRESET = 0x85;
|
|
11
|
+
exports.CMD_PAGE_NAV = 0x49;
|
|
12
|
+
// Device identification bytes (constant in all PGN 61184 messages)
|
|
13
|
+
exports.PRODUCT_ID = 0x17;
|
|
14
|
+
exports.UNK1 = 0x02;
|
|
15
|
+
exports.UNK2 = 0x02;
|
|
16
|
+
// PGN 126720 property names
|
|
17
|
+
exports.PROP_SLEEP = 'gnx_sleep_mode_id';
|
|
18
|
+
exports.PROP_DISPLAY = 'gnx_selected_disp';
|
|
19
|
+
exports.PROP_DISP_CNT = 'gnx_disp_cnt';
|
|
20
|
+
// Sleep/wake values
|
|
21
|
+
exports.SLEEP = 0;
|
|
22
|
+
exports.WAKE = 1;
|
|
23
|
+
// N2K defaults
|
|
24
|
+
exports.DEFAULT_SRC = 0;
|
|
25
|
+
exports.DEFAULT_DST = 255;
|
|
26
|
+
exports.DEFAULT_PRIO = 7;
|
|
27
|
+
// Default GNX group ID — the 4-byte binding token shared by all devices in a group.
|
|
28
|
+
// Configured during Garmin group setup; persists in device NVM. Any keypad emulation
|
|
29
|
+
// must use the group ID that matches the target display group.
|
|
30
|
+
// Bytes 10-13 of any PGN 126720 0xe5 or 0xe7 message on the GNX bus.
|
|
31
|
+
const DEFAULT_GROUP_ID_HEX = '80d99efc';
|
|
32
|
+
exports.DEFAULT_GROUP_ID = Buffer.from(DEFAULT_GROUP_ID_HEX, 'hex');
|
|
33
|
+
// Property command header layout (14 bytes total):
|
|
34
|
+
// [0] 0xe5 — command byte (consumed by canboatjs PGN Match, NOT in Payload)
|
|
35
|
+
// [1-3] 08 0a 0a — protocol version
|
|
36
|
+
// [4-7] 05 01 03 0d — shared device field
|
|
37
|
+
// [8-11] [groupId] — GROUP ID: 4-byte binding token for this GNX group
|
|
38
|
+
// [12-13] 08 1f — message subtype (property commands)
|
|
39
|
+
function buildPropertyHeader(groupId) {
|
|
40
|
+
return Buffer.from([
|
|
41
|
+
0xe5, 0x08, 0x0a, 0x0a, 0x05, 0x01,
|
|
42
|
+
0x03, 0x0d, groupId[0], groupId[1], groupId[2], groupId[3],
|
|
43
|
+
0x08, 0x1f
|
|
44
|
+
]);
|
|
45
|
+
}
|
|
46
|
+
exports.buildPropertyHeader = buildPropertyHeader;
|
|
47
|
+
function parseGroupId(hexStr) {
|
|
48
|
+
const cleaned = hexStr.replace(/[^0-9a-fA-F]/g, '');
|
|
49
|
+
if (cleaned.length !== 8) {
|
|
50
|
+
throw new Error(`groupId must be exactly 4 bytes (8 hex digits), got: "${hexStr}"`);
|
|
51
|
+
}
|
|
52
|
+
return Buffer.from(cleaned, 'hex');
|
|
53
|
+
}
|
|
54
|
+
exports.parseGroupId = parseGroupId;
|
|
55
|
+
exports.PROPERTY_SEPARATOR = Buffer.from([0x23, 0x09, 0x01]);
|
package/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
module.exports = require('./dist/').default
|
package/package.json
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "signalk-garmin-keypad-plugin",
|
|
3
|
+
"version": "1.0.2",
|
|
4
|
+
"description": "Signal K plugin for GNX Keypad control on NMEA 2000",
|
|
5
|
+
"main": "index.js",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"build": "tsc && npm run build:webapp",
|
|
8
|
+
"build:plugin": "tsc",
|
|
9
|
+
"build:webapp": "cd webapp && npm run build",
|
|
10
|
+
"watch": "tsc -w",
|
|
11
|
+
"test": "tsc && mocha --exit"
|
|
12
|
+
},
|
|
13
|
+
"keywords": [
|
|
14
|
+
"signalk-node-server-plugin",
|
|
15
|
+
"signalk-category-nmea-2000",
|
|
16
|
+
"signalk-embeddable-webapp"
|
|
17
|
+
],
|
|
18
|
+
"signalk": {
|
|
19
|
+
"displayName": "GNX Keypad"
|
|
20
|
+
},
|
|
21
|
+
"license": "Apache-2.0",
|
|
22
|
+
"dependencies": {
|
|
23
|
+
"@signalk/server-api": "^1.39.0"
|
|
24
|
+
},
|
|
25
|
+
"devDependencies": {
|
|
26
|
+
"@canboat/canboatjs": "^3.3.0",
|
|
27
|
+
"@types/node": "^14.14.10",
|
|
28
|
+
"chai": "^4.1.2",
|
|
29
|
+
"mocha": "^11.7.5",
|
|
30
|
+
"typescript": "^4.1.2"
|
|
31
|
+
}
|
|
32
|
+
}
|
package/public/183.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";(self.webpackChunksignalk_garmin_keypad_webapp=self.webpackChunksignalk_garmin_keypad_webapp||[]).push([[183],{439(e,n,t){t.d(n,{A:()=>c});var r=t(601),a=t.n(r),o=t(314),i=t.n(o)()(a());i.push([e.id,"/* GNX Keypad — dark theme matching the physical device */\n\n.keypad-container {\n display: flex;\n justify-content: center;\n align-items: center;\n min-height: 100%;\n padding: 20px;\n box-sizing: border-box;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n color: #d0d0d0;\n}\n\n.keypad-body {\n width: 260px;\n background: #1a1a1a;\n border-radius: 20px;\n padding: 20px 16px;\n box-shadow:\n 0 4px 24px rgba(0, 0, 0, 0.5),\n inset 0 1px 0 rgba(255, 255, 255, 0.04);\n display: flex;\n flex-direction: column;\n gap: 14px;\n}\n\n.keypad-loading {\n color: #888;\n padding: 40px;\n text-align: center;\n}\n\n/* Status bar */\n.status-bar {\n display: flex;\n align-items: center;\n gap: 8px;\n font-size: 12px;\n color: #888;\n padding: 0 4px;\n min-height: 20px;\n}\n\n.status-label {\n flex: 1;\n font-weight: 700;\n font-size: 15px;\n}\n\n.feedback {\n color: #82b1ff;\n font-size: 11px;\n animation: fadeIn 0.15s ease;\n}\n\n.error {\n color: #ff5252;\n font-size: 11px;\n}\n\n@keyframes fadeIn {\n from { opacity: 0; }\n to { opacity: 1; }\n}\n\n/* Generic button */\n.keypad-btn {\n background: #2a2a2a;\n border: 1px solid #3a3a3a;\n color: #d0d0d0;\n cursor: pointer;\n font-family: inherit;\n font-size: 14px;\n transition: all 0.15s ease;\n user-select: none;\n -webkit-user-select: none;\n touch-action: manipulation;\n}\n\n.keypad-btn:hover {\n background: #333;\n border-color: #4a4a4a;\n}\n\n.keypad-btn:active {\n background: #222;\n transform: scale(0.96);\n}\n\n/* Power row */\n.power-row {\n display: flex;\n align-items: center;\n justify-content: flex-end;\n padding: 0 25px;\n margin-bottom: 32px;\n}\n\n.power-btn {\n width: 48px;\n height: 48px;\n border-radius: 50%;\n display: flex;\n align-items: center;\n justify-content: center;\n background: #2a2a2a;\n}\n\n.power-btn:hover {\n background: #383838;\n}\n\n/* Preset grid */\n.preset-grid {\n display: grid;\n grid-template-columns: 1fr 1fr;\n gap: 10px;\n padding: 0 10px;\n margin-bottom: 32px;\n}\n\n.preset-btn {\n width: 100%;\n aspect-ratio: 1;\n border-radius: 50%;\n font-size: 20px;\n font-weight: 600;\n display: flex;\n align-items: center;\n justify-content: center;\n max-width: 80px;\n max-height: 80px;\n margin: 0 auto;\n}\n\n.preset-btn.long-press {\n background: #7a5c00 !important;\n border-color: #b8860b !important;\n color: #ffd54f !important;\n box-shadow: 0 0 12px rgba(255, 193, 7, 0.3);\n}\n\n/* Control rows (display selector, page nav) */\n.control-row {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 8px;\n padding: 0 10px;\n}\n\n/* Arrow buttons */\n.arrow-btn {\n width: 62px;\n height: 53px;\n border-radius: 11px;\n display: flex;\n align-items: center;\n justify-content: center;\n}\n\n/* Center icon in control rows */\n.row-icon {\n width: 62px;\n height: 53px;\n display: flex;\n align-items: center;\n justify-content: center;\n color: #666;\n}\n\n\n",""]);const c=i},314(e){e.exports=function(e){var n=[];return n.toString=function(){return this.map(function(n){var t="",r=void 0!==n[5];return n[4]&&(t+="@supports (".concat(n[4],") {")),n[2]&&(t+="@media ".concat(n[2]," {")),r&&(t+="@layer".concat(n[5].length>0?" ".concat(n[5]):""," {")),t+=e(n),r&&(t+="}"),n[2]&&(t+="}"),n[4]&&(t+="}"),t}).join("")},n.i=function(e,t,r,a,o){"string"==typeof e&&(e=[[null,e,void 0]]);var i={};if(r)for(var c=0;c<this.length;c++){var s=this[c][0];null!=s&&(i[s]=!0)}for(var l=0;l<e.length;l++){var d=[].concat(e[l]);r&&i[d[0]]||(void 0!==o&&(void 0===d[5]||(d[1]="@layer".concat(d[5].length>0?" ".concat(d[5]):""," {").concat(d[1],"}")),d[5]=o),t&&(d[2]?(d[1]="@media ".concat(d[2]," {").concat(d[1],"}"),d[2]=t):d[2]=t),a&&(d[4]?(d[1]="@supports (".concat(d[4],") {").concat(d[1],"}"),d[4]=a):d[4]="".concat(a)),n.push(d))}},n}},601(e){e.exports=function(e){return e[1]}},72(e){var n=[];function t(e){for(var t=-1,r=0;r<n.length;r++)if(n[r].identifier===e){t=r;break}return t}function r(e,r){for(var o={},i=[],c=0;c<e.length;c++){var s=e[c],l=r.base?s[0]+r.base:s[0],d=o[l]||0,p="".concat(l," ").concat(d);o[l]=d+1;var u=t(p),f={css:s[1],media:s[2],sourceMap:s[3],supports:s[4],layer:s[5]};if(-1!==u)n[u].references++,n[u].updater(f);else{var m=a(f,r);r.byIndex=c,n.splice(c,0,{identifier:p,updater:m,references:1})}i.push(p)}return i}function a(e,n){var t=n.domAPI(n);return t.update(e),function(n){if(n){if(n.css===e.css&&n.media===e.media&&n.sourceMap===e.sourceMap&&n.supports===e.supports&&n.layer===e.layer)return;t.update(e=n)}else t.remove()}}e.exports=function(e,a){var o=r(e=e||[],a=a||{});return function(e){e=e||[];for(var i=0;i<o.length;i++){var c=t(o[i]);n[c].references--}for(var s=r(e,a),l=0;l<o.length;l++){var d=t(o[l]);0===n[d].references&&(n[d].updater(),n.splice(d,1))}o=s}}},659(e){var n={};e.exports=function(e,t){var r=function(e){if(void 0===n[e]){var t=document.querySelector(e);if(window.HTMLIFrameElement&&t instanceof window.HTMLIFrameElement)try{t=t.contentDocument.head}catch(e){t=null}n[e]=t}return n[e]}(e);if(!r)throw new Error("Couldn't find a style target. This probably means that the value for the 'insert' parameter is invalid.");r.appendChild(t)}},540(e){e.exports=function(e){var n=document.createElement("style");return e.setAttributes(n,e.attributes),e.insert(n,e.options),n}},56(e,n,t){e.exports=function(e){var n=t.nc;n&&e.setAttribute("nonce",n)}},825(e){e.exports=function(e){if("undefined"==typeof document)return{update:function(){},remove:function(){}};var n=e.insertStyleElement(e);return{update:function(t){!function(e,n,t){var r="";t.supports&&(r+="@supports (".concat(t.supports,") {")),t.media&&(r+="@media ".concat(t.media," {"));var a=void 0!==t.layer;a&&(r+="@layer".concat(t.layer.length>0?" ".concat(t.layer):""," {")),r+=t.css,a&&(r+="}"),t.media&&(r+="}"),t.supports&&(r+="}");var o=t.sourceMap;o&&"undefined"!=typeof btoa&&(r+="\n/*# sourceMappingURL=data:application/json;base64,".concat(btoa(unescape(encodeURIComponent(JSON.stringify(o))))," */")),n.styleTagTransform(r,e,n.options)}(n,e,t)},remove:function(){!function(e){if(null===e.parentNode)return!1;e.parentNode.removeChild(e)}(n)}}}},113(e){e.exports=function(e,n){if(n.styleSheet)n.styleSheet.cssText=e;else{for(;n.firstChild;)n.removeChild(n.firstChild);n.appendChild(document.createTextNode(e))}}},183(e,n,t){t.r(n),t.d(n,{default:()=>E});var r=t(403),a=t.n(r);const o="/plugins/signalk-garmin-keypad";async function i(e,n){const t=await fetch(`${o}${e}`,{method:"POST",headers:{"Content-Type":"application/json"},credentials:"include",body:JSON.stringify(n)});if(!t.ok){const e=await t.json();throw new Error(e.error||"Request failed")}}var c=t(72),s=t.n(c),l=t(825),d=t.n(l),p=t(659),u=t.n(p),f=t(56),m=t.n(f),h=t(540),y=t.n(h),g=t(113),x=t.n(g),b=t(439),v={};function w({index:e,onSelect:n,onSave:t}){const[o,i]=(0,r.useState)(!1),c=(0,r.useRef)(null);return a().createElement("button",{className:"keypad-btn preset-btn "+(o?"long-press":""),onPointerDown:()=>{i(!1),c.current=setTimeout(()=>{i(!0),t()},500)},onPointerUp:()=>{c.current&&(clearTimeout(c.current),c.current=null),o||n(),i(!1)},onPointerLeave:()=>{c.current&&(clearTimeout(c.current),c.current=null),i(!1)}},e+1)}function k(){const[e,n]=(0,r.useState)(null),[t,c]=(0,r.useState)(null),[s,l]=(0,r.useState)(null),d=e=>{l(e),setTimeout(()=>l(null),1e3)},p=e=>{const n=e instanceof Error?e.message:"Unknown error";c(n),setTimeout(()=>c(null),3e3)},u=(0,r.useCallback)(async()=>{try{const e=await async function(){return(await fetch(`${o}/state`,{credentials:"include"})).json()}();n(e),c(null)}catch(e){p(e)}},[]);(0,r.useEffect)(()=>{u();const e=setInterval(u,5e3);return()=>clearInterval(e)},[u]);const f=async e=>{try{const t=await async function(e){const n=await fetch(`${o}/display/cycle`,{method:"POST",headers:{"Content-Type":"application/json"},credentials:"include",body:JSON.stringify({direction:e})});if(!n.ok){const e=await n.json();throw new Error(e.error||"Request failed")}return n.json()}(e);n(e=>e?{...e,activeDisplay:t.displayIndex}:e),d(`Display ${t.displayIndex+1}`)}catch(e){p(e)}},m=async e=>{try{await async function(e){await i("/page",{direction:e})}(e),d(`Page ${e}`)}catch(e){p(e)}};return e?a().createElement("div",{className:"keypad-container"},a().createElement("div",{className:"keypad-body"},a().createElement("div",{className:"status-bar"},a().createElement("span",{className:"status-label"},"GNX Keypad"),s&&a().createElement("span",{className:"feedback"},s),t&&a().createElement("span",{className:"error"},t)),a().createElement("div",{className:"power-row"},a().createElement("button",{className:"keypad-btn power-btn",onClick:()=>{(async e=>{try{await async function(e){await i("/power",{action:e})}(e),n(n=>n?{...n,sleeping:"sleep"===e}:n),d("sleep"===e?"Sleep":"Wake")}catch(e){p(e)}})(e?.sleeping?"wake":"sleep")}},a().createElement("svg",{viewBox:"0 0 24 24",width:"20",height:"20"},a().createElement("line",{x1:"12",y1:"3",x2:"12",y2:"12",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round"}),a().createElement("path",{d:"M6.3 7.7a8 8 0 1 0 11.4 0",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round"})))),a().createElement("div",{className:"preset-grid"},[0,1,2,3].map(e=>a().createElement(w,{key:e,index:e,onSelect:()=>(async e=>{try{await async function(e){await i("/preset/select",{index:e})}(e),d(`Preset ${e+1}`)}catch(e){p(e)}})(e),onSave:()=>(async e=>{try{await async function(e){await i("/preset/save",{index:e})}(e),d(`Saved preset ${e+1}`)}catch(e){p(e)}})(e)}))),a().createElement("div",{className:"control-row display-row"},a().createElement("button",{className:"keypad-btn arrow-btn",onClick:()=>f("up")},a().createElement("svg",{viewBox:"0 0 24 24",width:"25",height:"25"},a().createElement("path",{d:"M12 8l-6 6h12z",fill:"currentColor"}))),a().createElement("div",{className:"row-icon"},a().createElement("svg",{viewBox:"0 0 24 24",width:"28",height:"28"},a().createElement("rect",{x:"2",y:"3",width:"20",height:"14",rx:"2",fill:"none",stroke:"currentColor",strokeWidth:"2"}),a().createElement("line",{x1:"8",y1:"21",x2:"16",y2:"21",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round"}),a().createElement("line",{x1:"12",y1:"17",x2:"12",y2:"21",stroke:"currentColor",strokeWidth:"2"}))),a().createElement("button",{className:"keypad-btn arrow-btn",onClick:()=>f("down")},a().createElement("svg",{viewBox:"0 0 24 24",width:"25",height:"25"},a().createElement("path",{d:"M12 16l6-6H6z",fill:"currentColor"})))),a().createElement("div",{className:"control-row page-row"},a().createElement("button",{className:"keypad-btn arrow-btn",onClick:()=>m("next")},a().createElement("svg",{viewBox:"0 0 24 24",width:"25",height:"25"},a().createElement("path",{d:"M12 8l-6 6h12z",fill:"currentColor"}))),a().createElement("div",{className:"row-icon"},a().createElement("svg",{viewBox:"0 0 24 24",width:"28",height:"28"},a().createElement("path",{d:"M6 2h9l5 5v15H6z",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinejoin:"round"}),a().createElement("path",{d:"M15 2v5h5",fill:"none",stroke:"currentColor",strokeWidth:"2"}))),a().createElement("button",{className:"keypad-btn arrow-btn",onClick:()=>m("previous")},a().createElement("svg",{viewBox:"0 0 24 24",width:"25",height:"25"},a().createElement("path",{d:"M12 16l6-6H6z",fill:"currentColor"})))))):a().createElement("div",{className:"keypad-container"},a().createElement("div",{className:"keypad-loading"},"Loading..."))}function E(){return a().createElement(k,null)}v.styleTagTransform=x(),v.setAttributes=m(),v.insert=u().bind(null,"head"),v.domAPI=d(),v.insertStyleElement=y(),s()(b.A,v),b.A&&b.A.locals&&b.A.locals}}]);
|
package/public/main.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
(()=>{"use strict";var r={221(){}},t={};function e(o){var n=t[o];if(void 0!==n)return n.exports;var a=t[o]={exports:{}};return r[o](a,a.exports,e),a.exports}e.m=r,e.c=t,e.o=(r,t)=>Object.prototype.hasOwnProperty.call(r,t),(()=>{e.S={};var r={},t={};e.I=(o,n)=>{n||(n=[]);var a=t[o];if(a||(a=t[o]={}),!(n.indexOf(a)>=0)){if(n.push(a),r[o])return r[o];e.o(e.S,o)||(e.S[o]={}),e.S[o];var s=[];return r[o]=s.length?Promise.all(s).then(()=>r[o]=1):1}}})(),e(221)})();
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
var signalk_garmin_keypad;(()=>{"use strict";var e,r,t,a,n,o,i,l,u,d,s,p,f,c,h,v={254(e,r,t){var a={"./AppPanel":()=>t.e(183).then(()=>()=>t(183))},n=(e,r)=>(t.R=r,r=t.o(a,e)?a[e]():Promise.resolve().then(()=>{throw new Error('Module "'+e+'" does not exist in container.')}),t.R=void 0,r),o=(e,r)=>{if(t.S){var a="default",n=t.S[a];if(n&&n!==e)throw new Error("Container initialization failed as it has already been initialized with a different share scope");return t.S[a]=e,t.I(a,r)}};t.d(r,{get:()=>n,init:()=>o})}},g={};function m(e){var r=g[e];if(void 0!==r)return r.exports;var t=g[e]={id:e,exports:{}};return v[e](t,t.exports,m),t.exports}m.m=v,m.c=g,m.n=e=>{var r=e&&e.__esModule?()=>e.default:()=>e;return m.d(r,{a:r}),r},m.d=(e,r)=>{for(var t in r)m.o(r,t)&&!m.o(e,t)&&Object.defineProperty(e,t,{enumerable:!0,get:r[t]})},m.f={},m.e=e=>Promise.all(Object.keys(m.f).reduce((r,t)=>(m.f[t](e,r),r),[])),m.u=e=>e+".js",m.o=(e,r)=>Object.prototype.hasOwnProperty.call(e,r),e={},r="signalk-garmin-keypad-webapp:",m.l=(t,a,n,o)=>{if(e[t])e[t].push(a);else{var i,l;if(void 0!==n)for(var u=document.getElementsByTagName("script"),d=0;d<u.length;d++){var s=u[d];if(s.getAttribute("src")==t||s.getAttribute("data-webpack")==r+n){i=s;break}}i||(l=!0,(i=document.createElement("script")).charset="utf-8",m.nc&&i.setAttribute("nonce",m.nc),i.setAttribute("data-webpack",r+n),i.src=t),e[t]=[a];var p=(r,a)=>{i.onerror=i.onload=null,clearTimeout(f);var n=e[t];if(delete e[t],i.parentNode&&i.parentNode.removeChild(i),n&&n.forEach(e=>e(a)),r)return r(a)},f=setTimeout(p.bind(null,void 0,{type:"timeout",target:i}),12e4);i.onerror=p.bind(null,i.onerror),i.onload=p.bind(null,i.onload),l&&document.head.appendChild(i)}},m.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},(()=>{m.S={};var e={},r={};m.I=(t,a)=>{a||(a=[]);var n=r[t];if(n||(n=r[t]={}),!(a.indexOf(n)>=0)){if(a.push(n),e[t])return e[t];m.o(m.S,t)||(m.S[t]={}),m.S[t];var o=[];return e[t]=o.length?Promise.all(o).then(()=>e[t]=1):1}}})(),m.p="/signalk-garmin-keypad/",t=e=>{var r=e=>e.split(".").map(e=>+e==e?+e:e),t=/^([^-+]+)?(?:-([^+]+))?(?:\+(.+))?$/.exec(e),a=t[1]?r(t[1]):[];return t[2]&&(a.length++,a.push.apply(a,r(t[2]))),t[3]&&(a.push([]),a.push.apply(a,r(t[3]))),a},a=(e,r)=>{e=t(e),r=t(r);for(var a=0;;){if(a>=e.length)return a<r.length&&"u"!=(typeof r[a])[0];var n=e[a],o=(typeof n)[0];if(a>=r.length)return"u"==o;var i=r[a],l=(typeof i)[0];if(o!=l)return"o"==o&&"n"==l||"s"==l||"u"==o;if("o"!=o&&"u"!=o&&n!=i)return n<i;a++}},n=(e,r)=>e&&m.o(e,r),o=e=>(e.loaded=1,e.get()),i=e=>Object.keys(e).reduce((r,t)=>(e[t].eager&&(r[t]=e[t]),r),{}),l=(e,r,t)=>{var n=t?i(e[r]):e[r];return Object.keys(n).reduce((e,r)=>!e||!n[e].loaded&&a(e,r)?r:e,0)},u=e=>{throw new Error(e)},d=(e,r,t)=>t?t():((e,r)=>u("Shared module "+r+" doesn't exist in shared scope "+e))(e,r),s=(e=>function(r,t,a,n,o){var i=m.I(r);return i&&i.then&&!a?i.then(e.bind(e,r,m.S[r],t,!1,n,o)):e(r,m.S[r],t,a,n)})((e,r,t,a,i)=>{if(!n(r,t))return d(e,t,i);var u=l(r,t,a);return o(r[t][u])}),p={},f={403:()=>s("default","react",!1)},c={183:[403]},h={},m.f.consumes=(e,r)=>{m.o(c,e)&&c[e].forEach(e=>{if(m.o(p,e))return r.push(p[e]);if(!h[e]){var t=r=>{p[e]=0,m.m[e]=t=>{delete m.c[e],t.exports=r()}};h[e]=!0;var a=r=>{delete p[e],m.m[e]=t=>{throw delete m.c[e],r}};try{var n=f[e]();n.then?r.push(p[e]=n.then(t).catch(a)):t(n)}catch(e){a(e)}}})},(()=>{var e={802:0};m.f.j=(r,t)=>{var a=m.o(e,r)?e[r]:void 0;if(0!==a)if(a)t.push(a[2]);else{var n=new Promise((t,n)=>a=e[r]=[t,n]);t.push(a[2]=n);var o=m.p+m.u(r),i=new Error;m.l(o,t=>{if(m.o(e,r)&&(0!==(a=e[r])&&(e[r]=void 0),a)){var n=t&&("load"===t.type?"missing":t.type),o=t&&t.target&&t.target.src;i.message="Loading chunk "+r+" failed.\n("+n+": "+o+")",i.name="ChunkLoadError",i.type=n,i.request=o,a[1](i)}},"chunk-"+r,r)}};var r=(r,t)=>{var a,n,[o,i,l]=t,u=0;if(o.some(r=>0!==e[r])){for(a in i)m.o(i,a)&&(m.m[a]=i[a]);l&&l(m)}for(r&&r(t);u<o.length;u++)n=o[u],m.o(e,n)&&e[n]&&e[n][0](),e[n]=0},t=self.webpackChunksignalk_garmin_keypad_webapp=self.webpackChunksignalk_garmin_keypad_webapp||[];t.forEach(r.bind(null,0)),t.push=r.bind(null,t.push.bind(t))})(),m.nc=void 0;var b=m(254);signalk_garmin_keypad=b})();
|
|
Binary file
|
package/tsconfig.json
ADDED