@nanolink/mirrors 1.1.74 → 1.1.76

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. package/README.md +40 -0
  2. package/dist/MirrorSync.d.ts +8 -0
  3. package/dist/MirrorSync.js +29 -1
  4. package/dist/MirrorSync.js.map +1 -1
  5. package/dist/data64.d.ts +24 -0
  6. package/dist/data64.js +71 -0
  7. package/dist/data64.js.map +1 -0
  8. package/dist/decoders.d.ts +11 -0
  9. package/dist/decoders.js +23 -0
  10. package/dist/decoders.js.map +1 -0
  11. package/dist/definitions/mirrors.d.ts +1 -0
  12. package/dist/definitions/mirrors.js +1 -0
  13. package/dist/definitions/mirrors.js.map +1 -1
  14. package/dist/definitions/opsubscriptions/contained.d.ts +1 -1
  15. package/dist/definitions/opsubscriptions/contained.js +1 -0
  16. package/dist/definitions/opsubscriptions/contained.js.map +1 -1
  17. package/dist/definitions/opsubscriptions/gpsstate.d.ts +1 -1
  18. package/dist/definitions/opsubscriptions/gpsstate.js +2 -2
  19. package/dist/definitions/opsubscriptions/index.d.ts +1 -0
  20. package/dist/definitions/opsubscriptions/index.js +1 -0
  21. package/dist/definitions/opsubscriptions/index.js.map +1 -1
  22. package/dist/definitions/opsubscriptions/lostposition.d.ts +1 -1
  23. package/dist/definitions/opsubscriptions/lostposition.js +1 -1
  24. package/dist/definitions/opsubscriptions/stateLinks.d.ts +1 -1
  25. package/dist/definitions/opsubscriptions/stateLinks.js +1 -1
  26. package/dist/definitions/opsubscriptions/stateRefLinks.d.ts +1 -1
  27. package/dist/definitions/opsubscriptions/stateRefLinks.js +1 -1
  28. package/dist/definitions/opsubscriptions/trackerstate.d.ts +1 -1
  29. package/dist/definitions/opsubscriptions/trackerstate.js +2 -2
  30. package/dist/definitions/opsubscriptions/triproutes.d.ts +1 -0
  31. package/dist/definitions/opsubscriptions/triproutes.js +12 -0
  32. package/dist/definitions/opsubscriptions/triproutes.js.map +1 -0
  33. package/dist/definitions/opsubscriptions/trips.d.ts +1 -1
  34. package/dist/definitions/opsubscriptions/trips.js +1 -1
  35. package/dist/index.d.ts +4 -0
  36. package/dist/index.js +11 -1
  37. package/dist/index.js.map +1 -1
  38. package/dist/triproute.d.ts +52 -0
  39. package/dist/triproute.js +135 -0
  40. package/dist/triproute.js.map +1 -0
  41. package/dist-compat/index.js +205 -10
  42. package/dist-compat/index.js.map +1 -1
  43. package/package.json +3 -1
@@ -0,0 +1,52 @@
1
+ import type { ReadonlyMapView } from './DelegateMap';
2
+ /** One position of a trip's route; `speed` is null when the device reported none. */
3
+ export interface RoutePoint {
4
+ stamp: number;
5
+ longitude: number;
6
+ latitude: number;
7
+ speed: number | null;
8
+ }
9
+ /**
10
+ * One chunk of the route of one trip, keyed `<vid>/<tripStart>/<chunk>`,
11
+ * as the `tripRoutes` mirror holds it.
12
+ */
13
+ export interface TripRouteItem {
14
+ id: string;
15
+ trackerVID: string;
16
+ tripStart: number;
17
+ chunk: number;
18
+ points: RoutePoint[];
19
+ opVersion: string;
20
+ deleted: boolean;
21
+ }
22
+ export interface TripRouteKey {
23
+ trackerVID: string;
24
+ tripStart: number;
25
+ chunk: number;
26
+ }
27
+ /** The mirror key of a chunk: `<vid>/<tripStart>/<chunk>`. */
28
+ export declare function tripRouteKey(trackerVID: string, tripStart: number, chunk: number): string;
29
+ /** The parts of a mirror key, or null when it is not a trip route key. */
30
+ export declare function parseTripRouteKey(id: string): TripRouteKey | null;
31
+ /**
32
+ * The route of one trip: the points of its contiguous chunks from 0, in
33
+ * order, stopping at the first chunk the mirror does not hold.
34
+ */
35
+ export declare function tripRoute(mirror: ReadonlyMapView<string, any>, trackerVID: string, tripStart: number): RoutePoint[];
36
+ /**
37
+ * Reads a zigzag varint (Go's binary.Varint): LEB128 unsigned, then
38
+ * even -> n/2, odd -> -(n+1)/2.
39
+ */
40
+ export declare function readVarint(bytes: Uint8Array, offset: number): {
41
+ value: number;
42
+ offset: number;
43
+ };
44
+ /**
45
+ * Decodes a statetriproute record. The value is `[version: 12][count: u16]`
46
+ * and, with a count above 0, the first point absolute (stamp int64 LE,
47
+ * longitude and latitude int32 LE at 1e-7 degrees, speed uint16 LE at
48
+ * 0.1 km/h, 65535 for none) followed by every further point as four zigzag
49
+ * varints: the deltas of the stamp, the longitude, the latitude and the
50
+ * speed, in the same units. The key is `<vid>/<tripStart>/<chunk>`.
51
+ */
52
+ export declare function decodeTripRouteRecord(key: string, value: Uint8Array): TripRouteItem;
@@ -0,0 +1,135 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.tripRouteKey = tripRouteKey;
4
+ exports.parseTripRouteKey = parseTripRouteKey;
5
+ exports.tripRoute = tripRoute;
6
+ exports.readVarint = readVarint;
7
+ exports.decodeTripRouteRecord = decodeTripRouteRecord;
8
+ const decoders_1 = require("./decoders");
9
+ const KEY = /^([^/]+)\/(-?\d+)\/(\d+)$/;
10
+ const ROUTE_SPEED_NONE = 65535;
11
+ const ROUTE_COORD_UNIT = 1e7;
12
+ const ROUTE_SPEED_UNIT = 10;
13
+ const HEX = '0123456789abcdef';
14
+ /** The mirror key of a chunk: `<vid>/<tripStart>/<chunk>`. */
15
+ function tripRouteKey(trackerVID, tripStart, chunk) {
16
+ return `${trackerVID}/${tripStart}/${chunk}`;
17
+ }
18
+ /** The parts of a mirror key, or null when it is not a trip route key. */
19
+ function parseTripRouteKey(id) {
20
+ const m = KEY.exec(id);
21
+ if (!m)
22
+ return null;
23
+ return { trackerVID: m[1], tripStart: Number(m[2]), chunk: Number(m[3]) };
24
+ }
25
+ /**
26
+ * The route of one trip: the points of its contiguous chunks from 0, in
27
+ * order, stopping at the first chunk the mirror does not hold.
28
+ */
29
+ function tripRoute(mirror, trackerVID, tripStart) {
30
+ const points = [];
31
+ for (let chunk = 0;; chunk++) {
32
+ const item = mirror.get(tripRouteKey(trackerVID, tripStart, chunk));
33
+ if (!item || !Array.isArray(item.points))
34
+ break;
35
+ for (const p of item.points)
36
+ points.push(p);
37
+ }
38
+ return points;
39
+ }
40
+ function hex(bytes, start, end) {
41
+ let s = '';
42
+ for (let i = start; i < end; i++)
43
+ s += HEX[bytes[i] >> 4] + HEX[bytes[i] & 15];
44
+ return s;
45
+ }
46
+ /** int64 LE as a number: two uint32 halves, lo + hi * 2^32 (hi signed). */
47
+ function int64(view, offset) {
48
+ return view.getInt32(offset + 4, true) * 4294967296 + view.getUint32(offset, true);
49
+ }
50
+ /**
51
+ * Reads a zigzag varint (Go's binary.Varint): LEB128 unsigned, then
52
+ * even -> n/2, odd -> -(n+1)/2.
53
+ */
54
+ function readVarint(bytes, offset) {
55
+ let result = 0;
56
+ let scale = 1;
57
+ let at = offset;
58
+ for (;;) {
59
+ if (at >= bytes.length)
60
+ throw new Error('truncated statetriproute varint');
61
+ const byte = bytes[at++];
62
+ result += (byte & 0x7f) * scale;
63
+ if ((byte & 0x80) === 0)
64
+ break;
65
+ scale *= 128;
66
+ if (scale > Math.pow(2, 56))
67
+ throw new Error('statetriproute varint too long');
68
+ }
69
+ const signed = result % 2 === 0 ? result / 2 : -(result + 1) / 2;
70
+ return { value: signed, offset: at };
71
+ }
72
+ function routePoint(stamp, lon, lat, speed) {
73
+ return {
74
+ stamp,
75
+ longitude: lon / ROUTE_COORD_UNIT,
76
+ latitude: lat / ROUTE_COORD_UNIT,
77
+ speed: speed === ROUTE_SPEED_NONE ? null : speed / ROUTE_SPEED_UNIT,
78
+ };
79
+ }
80
+ /**
81
+ * Decodes a statetriproute record. The value is `[version: 12][count: u16]`
82
+ * and, with a count above 0, the first point absolute (stamp int64 LE,
83
+ * longitude and latitude int32 LE at 1e-7 degrees, speed uint16 LE at
84
+ * 0.1 km/h, 65535 for none) followed by every further point as four zigzag
85
+ * varints: the deltas of the stamp, the longitude, the latitude and the
86
+ * speed, in the same units. The key is `<vid>/<tripStart>/<chunk>`.
87
+ */
88
+ function decodeTripRouteRecord(key, value) {
89
+ const parsed = parseTripRouteKey(key);
90
+ if (!parsed)
91
+ throw new Error(`invalid statetriproute key: ${key}`);
92
+ if (value.length < 14)
93
+ throw new Error(`statetriproute record too short: ${value.length}`);
94
+ const view = new DataView(value.buffer, value.byteOffset, value.byteLength);
95
+ const count = view.getUint16(12, true);
96
+ const points = [];
97
+ let offset = 14;
98
+ if (count > 0) {
99
+ if (value.length < 32)
100
+ throw new Error('truncated statetriproute first point');
101
+ let stamp = int64(view, 14);
102
+ let lon = view.getInt32(22, true);
103
+ let lat = view.getInt32(26, true);
104
+ let speed = view.getUint16(30, true);
105
+ points.push(routePoint(stamp, lon, lat, speed));
106
+ offset = 32;
107
+ for (let i = 1; i < count; i++) {
108
+ const dStamp = readVarint(value, offset);
109
+ const dLon = readVarint(value, dStamp.offset);
110
+ const dLat = readVarint(value, dLon.offset);
111
+ const dSpeed = readVarint(value, dLat.offset);
112
+ offset = dSpeed.offset;
113
+ stamp += dStamp.value;
114
+ lon += dLon.value;
115
+ lat += dLat.value;
116
+ speed += dSpeed.value;
117
+ if (speed < 0 || speed > ROUTE_SPEED_NONE)
118
+ throw new Error(`statetriproute point ${i} speed out of range`);
119
+ points.push(routePoint(stamp, lon, lat, speed));
120
+ }
121
+ }
122
+ if (offset !== value.length)
123
+ throw new Error(`statetriproute has ${value.length - offset} trailing bytes`);
124
+ return {
125
+ id: key,
126
+ trackerVID: parsed.trackerVID,
127
+ tripStart: parsed.tripStart,
128
+ chunk: parsed.chunk,
129
+ points,
130
+ opVersion: hex(value, 0, 12),
131
+ deleted: false,
132
+ };
133
+ }
134
+ (0, decoders_1.registerDecoder)('tripRoutes', decodeTripRouteRecord);
135
+ //# sourceMappingURL=triproute.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"triproute.js","sourceRoot":"","sources":["../src/triproute.ts"],"names":[],"mappings":"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"}
@@ -71,13 +71,75 @@ __export(index_exports, {
71
71
  SubscriptionClient: () => SubscriptionClient_default,
72
72
  Subscriptions: () => Subscriptions,
73
73
  TempSubscriptions: () => TempSubscriptions2,
74
+ decodeTripRouteRecord: () => decodeTripRouteRecord,
74
75
  draftMirrors: () => draftMirrors,
75
- exposedMirrors: () => exposedMirrors
76
+ exposedMirrors: () => exposedMirrors,
77
+ getDecoder: () => getDecoder,
78
+ parseTripRouteKey: () => parseTripRouteKey,
79
+ registerDecoder: () => registerDecoder,
80
+ tripRoute: () => tripRoute,
81
+ tripRouteKey: () => tripRouteKey
76
82
  });
77
83
  module.exports = __toCommonJS(index_exports);
78
84
 
79
85
  // src/MirrorSync.ts
80
86
  var import_eventemitter3 = __toESM(require("eventemitter3"));
87
+
88
+ // src/data64.ts
89
+ function base64ToBytes(data64) {
90
+ if (typeof Buffer !== "undefined" && typeof Buffer.from === "function") {
91
+ const buf = Buffer.from(data64, "base64");
92
+ return new Uint8Array(buf.buffer, buf.byteOffset, buf.byteLength);
93
+ }
94
+ if (typeof atob !== "function") throw new Error("data64: no base64 decoder available");
95
+ const binary = atob(data64);
96
+ const out = new Uint8Array(binary.length);
97
+ for (let i = 0; i < binary.length; i++) out[i] = binary.charCodeAt(i);
98
+ return out;
99
+ }
100
+ function utf8(bytes) {
101
+ if (typeof TextDecoder !== "undefined") return new TextDecoder().decode(bytes);
102
+ if (typeof Buffer !== "undefined") return Buffer.from(bytes.buffer, bytes.byteOffset, bytes.byteLength).toString("utf8");
103
+ let s = "";
104
+ for (let i = 0; i < bytes.length; i++) s += String.fromCharCode(bytes[i]);
105
+ return s;
106
+ }
107
+ function readFrames(bytes) {
108
+ const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
109
+ const frames = [];
110
+ let at = 0;
111
+ while (at < bytes.length) {
112
+ if (at + 2 > bytes.length) throw new Error(`data64: truncated key length at ${at}`);
113
+ const keyLength = view.getUint16(at, true);
114
+ at += 2;
115
+ if (at + keyLength + 2 > bytes.length) throw new Error(`data64: truncated key at ${at}`);
116
+ const key = utf8(bytes.subarray(at, at + keyLength));
117
+ at += keyLength;
118
+ const valueLength = view.getUint16(at, true);
119
+ at += 2;
120
+ if (at + valueLength > bytes.length) throw new Error(`data64: truncated value for '${key}' at ${at}`);
121
+ frames.push({ key, value: bytes.subarray(at, at + valueLength) });
122
+ at += valueLength;
123
+ }
124
+ return frames;
125
+ }
126
+ function decodeData64Frames(data64) {
127
+ return readFrames(base64ToBytes(data64));
128
+ }
129
+
130
+ // src/decoders.ts
131
+ var decoders = /* @__PURE__ */ new Map();
132
+ function registerDecoder(rootField, decoder) {
133
+ decoders.set(rootField, decoder);
134
+ }
135
+ function getDecoder(rootField) {
136
+ return decoders.get(rootField);
137
+ }
138
+ function decodeData64(data64, decoder) {
139
+ return decodeData64Frames(data64).map((f) => decoder(f.key, f.value));
140
+ }
141
+
142
+ // src/MirrorSync.ts
81
143
  var MirrorSync = class extends import_eventemitter3.default {
82
144
  constructor(client, options) {
83
145
  super();
@@ -250,7 +312,11 @@ var MirrorSync = class extends import_eventemitter3.default {
250
312
  break;
251
313
  }
252
314
  case "UPDATED" /* UPDATED */:
253
- this.applyUpdated(msg.data);
315
+ if (msg.data !== void 0 && msg.data !== null) this.applyUpdated(msg.data);
316
+ if (typeof msg.data64 === "string") {
317
+ const items = this.decodeData64(firstKey, msg.data64);
318
+ if (items) this.applyUpdated(items);
319
+ }
254
320
  break;
255
321
  case "DELETED" /* DELETED */:
256
322
  this.applyDeleted(msg.deleteId, msg.deleteVersion, msg.deleteOpVersion);
@@ -292,6 +358,26 @@ var MirrorSync = class extends import_eventemitter3.default {
292
358
  this.subscribeInternal(this.currentVersion, this.currentOpVersion);
293
359
  }, 0);
294
360
  }
361
+ /**
362
+ * Decodes a `data64` frame through the decoder registered for the root
363
+ * field. No decoder, or a record that does not decode: emits 'error' and
364
+ * returns undefined so the frame is skipped; never throws.
365
+ */
366
+ decodeData64(rootField, data64) {
367
+ const decoder = getDecoder(rootField);
368
+ if (!decoder) {
369
+ this.l("no data64 decoder", { rootField });
370
+ this.emit("error", new Error(`No data64 decoder registered for root field '${rootField}'`));
371
+ return void 0;
372
+ }
373
+ try {
374
+ return decodeData64(data64, decoder);
375
+ } catch (err) {
376
+ this.l("data64 decode failed", { rootField, err });
377
+ this.emit("error", err);
378
+ return void 0;
379
+ }
380
+ }
295
381
  normalizeItems(data) {
296
382
  if (!data) return [];
297
383
  return Array.isArray(data) ? data : [data];
@@ -2558,12 +2644,13 @@ var contained = `subscription contained($opVersion: String) {
2558
2644
  opVersion
2559
2645
  }
2560
2646
  deleteId
2647
+ deleteOpVersion
2561
2648
  }
2562
2649
  }`;
2563
2650
 
2564
2651
  // src/definitions/opsubscriptions/gpsstate.ts
2565
2652
  var gpsState = `subscription gpsState($opVersion: String) {
2566
- stateGPSBulk(opVersion: $opVersion) {
2653
+ stateGPSBulk(opversion: $opVersion) {
2567
2654
  type
2568
2655
  data {
2569
2656
  id
@@ -2577,7 +2664,7 @@ var gpsState = `subscription gpsState($opVersion: String) {
2577
2664
  opVersion
2578
2665
  }
2579
2666
  deleteId
2580
- deleteVersion
2667
+ deleteOpVersion
2581
2668
  }
2582
2669
  }`;
2583
2670
 
@@ -2595,7 +2682,7 @@ var lostposition = `subscription lostPosition($opVersion: String) {
2595
2682
  opVersion
2596
2683
  }
2597
2684
  deleteId
2598
- deleteVersion
2685
+ deleteOpVersion
2599
2686
  }
2600
2687
  }`;
2601
2688
 
@@ -2614,7 +2701,7 @@ var stateLinks = `subscription stateLink($opVersion: String) {
2614
2701
  closed
2615
2702
  }
2616
2703
  deleteId
2617
- deleteVersion
2704
+ deleteOpVersion
2618
2705
  }
2619
2706
  }`;
2620
2707
 
@@ -2631,13 +2718,13 @@ var stateRefLinks = `subscription stateReflink($opVersion: String) {
2631
2718
  opVersion
2632
2719
  }
2633
2720
  deleteId
2634
- deleteVersion
2721
+ deleteOpVersion
2635
2722
  }
2636
2723
  }`;
2637
2724
 
2638
2725
  // src/definitions/opsubscriptions/trackerstate.ts
2639
2726
  var trackerState = `subscription trackerState($opVersion: String) {
2640
- trackerStateBulk(opVersion: $opVersion) {
2727
+ trackerStateBulk(opversion: $opVersion) {
2641
2728
  type
2642
2729
  data {
2643
2730
  id
@@ -2650,7 +2737,17 @@ var trackerState = `subscription trackerState($opVersion: String) {
2650
2737
  opVersion
2651
2738
  }
2652
2739
  deleteId
2653
- deleteVersion
2740
+ deleteOpVersion
2741
+ }
2742
+ }`;
2743
+
2744
+ // src/definitions/opsubscriptions/triproutes.ts
2745
+ var tripRoutes = `subscription tripRoutes($opVersion: String, $trackerVIDs: [String!]) {
2746
+ tripRoutes(opversion: $opVersion, trackerVIDs: $trackerVIDs) {
2747
+ type
2748
+ data64
2749
+ deleteId
2750
+ deleteOpVersion
2654
2751
  }
2655
2752
  }`;
2656
2753
 
@@ -2678,7 +2775,7 @@ var trips2 = `subscription stateTrips($opVersion: String) {
2678
2775
  opVersion
2679
2776
  }
2680
2777
  deleteId
2681
- deleteVersion
2778
+ deleteOpVersion
2682
2779
  }
2683
2780
  }`;
2684
2781
 
@@ -2840,6 +2937,7 @@ var OpSubscriptions = {
2840
2937
  stateLinks,
2841
2938
  stateRefLinks,
2842
2939
  trackerState,
2940
+ tripRoutes,
2843
2941
  trips3: trips2
2844
2942
  };
2845
2943
  var RequiredMirrors = {
@@ -3202,6 +3300,103 @@ function draftMirrors() {
3202
3300
  );
3203
3301
  }
3204
3302
 
3303
+ // src/triproute.ts
3304
+ var KEY = /^([^/]+)\/(-?\d+)\/(\d+)$/;
3305
+ var ROUTE_SPEED_NONE = 65535;
3306
+ var ROUTE_COORD_UNIT = 1e7;
3307
+ var ROUTE_SPEED_UNIT = 10;
3308
+ var HEX = "0123456789abcdef";
3309
+ function tripRouteKey(trackerVID, tripStart, chunk) {
3310
+ return `${trackerVID}/${tripStart}/${chunk}`;
3311
+ }
3312
+ function parseTripRouteKey(id) {
3313
+ const m = KEY.exec(id);
3314
+ if (!m) return null;
3315
+ return { trackerVID: m[1], tripStart: Number(m[2]), chunk: Number(m[3]) };
3316
+ }
3317
+ function tripRoute(mirror, trackerVID, tripStart) {
3318
+ const points = [];
3319
+ for (let chunk = 0; ; chunk++) {
3320
+ const item = mirror.get(tripRouteKey(trackerVID, tripStart, chunk));
3321
+ if (!item || !Array.isArray(item.points)) break;
3322
+ for (const p of item.points) points.push(p);
3323
+ }
3324
+ return points;
3325
+ }
3326
+ function hex(bytes, start, end) {
3327
+ let s = "";
3328
+ for (let i = start; i < end; i++) s += HEX[bytes[i] >> 4] + HEX[bytes[i] & 15];
3329
+ return s;
3330
+ }
3331
+ function int64(view, offset) {
3332
+ return view.getInt32(offset + 4, true) * 4294967296 + view.getUint32(offset, true);
3333
+ }
3334
+ function readVarint(bytes, offset) {
3335
+ let result = 0;
3336
+ let scale = 1;
3337
+ let at = offset;
3338
+ for (; ; ) {
3339
+ if (at >= bytes.length) throw new Error("truncated statetriproute varint");
3340
+ const byte = bytes[at++];
3341
+ result += (byte & 127) * scale;
3342
+ if ((byte & 128) === 0) break;
3343
+ scale *= 128;
3344
+ if (scale > 2 ** 56) throw new Error("statetriproute varint too long");
3345
+ }
3346
+ const signed = result % 2 === 0 ? result / 2 : -(result + 1) / 2;
3347
+ return { value: signed, offset: at };
3348
+ }
3349
+ function routePoint(stamp, lon, lat, speed) {
3350
+ return {
3351
+ stamp,
3352
+ longitude: lon / ROUTE_COORD_UNIT,
3353
+ latitude: lat / ROUTE_COORD_UNIT,
3354
+ speed: speed === ROUTE_SPEED_NONE ? null : speed / ROUTE_SPEED_UNIT
3355
+ };
3356
+ }
3357
+ function decodeTripRouteRecord(key, value) {
3358
+ const parsed = parseTripRouteKey(key);
3359
+ if (!parsed) throw new Error(`invalid statetriproute key: ${key}`);
3360
+ if (value.length < 14) throw new Error(`statetriproute record too short: ${value.length}`);
3361
+ const view = new DataView(value.buffer, value.byteOffset, value.byteLength);
3362
+ const count = view.getUint16(12, true);
3363
+ const points = [];
3364
+ let offset = 14;
3365
+ if (count > 0) {
3366
+ if (value.length < 32) throw new Error("truncated statetriproute first point");
3367
+ let stamp = int64(view, 14);
3368
+ let lon = view.getInt32(22, true);
3369
+ let lat = view.getInt32(26, true);
3370
+ let speed = view.getUint16(30, true);
3371
+ points.push(routePoint(stamp, lon, lat, speed));
3372
+ offset = 32;
3373
+ for (let i = 1; i < count; i++) {
3374
+ const dStamp = readVarint(value, offset);
3375
+ const dLon = readVarint(value, dStamp.offset);
3376
+ const dLat = readVarint(value, dLon.offset);
3377
+ const dSpeed = readVarint(value, dLat.offset);
3378
+ offset = dSpeed.offset;
3379
+ stamp += dStamp.value;
3380
+ lon += dLon.value;
3381
+ lat += dLat.value;
3382
+ speed += dSpeed.value;
3383
+ if (speed < 0 || speed > ROUTE_SPEED_NONE) throw new Error(`statetriproute point ${i} speed out of range`);
3384
+ points.push(routePoint(stamp, lon, lat, speed));
3385
+ }
3386
+ }
3387
+ if (offset !== value.length) throw new Error(`statetriproute has ${value.length - offset} trailing bytes`);
3388
+ return {
3389
+ id: key,
3390
+ trackerVID: parsed.trackerVID,
3391
+ tripStart: parsed.tripStart,
3392
+ chunk: parsed.chunk,
3393
+ points,
3394
+ opVersion: hex(value, 0, 12),
3395
+ deleted: false
3396
+ };
3397
+ }
3398
+ registerDecoder("tripRoutes", decodeTripRouteRecord);
3399
+
3205
3400
  // src/index.ts
3206
3401
  var Connection = class extends SubscriptionClient_default {
3207
3402
  constructor() {