@signalk/tracks-plugin 3.0.0-beta.7 → 3.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -0
- package/dist/buildTypecheck.test.d.ts +1 -0
- package/dist/index.js +55 -27
- package/dist/index.js.map +1 -1
- package/dist/sqliteStore.d.ts +6 -0
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -6,6 +6,8 @@ Positions are recorded to a SQLite file in the plugin's data directory, at a con
|
|
|
6
6
|
resolution, so tracks survive a restart with no other plugin required. The plugin is enabled on
|
|
7
7
|
install and needs no configuration to start recording.
|
|
8
8
|
|
|
9
|
+
Requires Signal K server >= 2.33.0 for the v2 Track API; older servers get the v1 routes only.
|
|
10
|
+
|
|
9
11
|
| Setting | Behaviour |
|
|
10
12
|
| ---------------------------------------------- | ------------------------------------------------------------------------------ |
|
|
11
13
|
| Track resolution | Minimum spacing between recorded positions. |
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/dist/index.js
CHANGED
|
@@ -816,15 +816,16 @@ function createTrackProvider(deps) {
|
|
|
816
816
|
*
|
|
817
817
|
* `epsilon` implies `simplify=true`, so an explicit tolerance is honoured
|
|
818
818
|
* whether or not the flag came with it. `simplify` alone leaves the tolerance
|
|
819
|
-
* to the provider
|
|
820
|
-
*
|
|
821
|
-
*
|
|
822
|
-
*
|
|
823
|
-
* since that is the thing being computed.
|
|
819
|
+
* to the provider, and the spec asks for one "suited to the size of the box":
|
|
820
|
+
* with a `bbox` it is sized to that box, which for a chart viewer is its view,
|
|
821
|
+
* so detail follows the zoom. With no box the choice is the provider's, and
|
|
822
|
+
* the extent of the track *as thinning left it* stands in -- not the
|
|
823
|
+
* simplified extent, since that is the thing being computed. A `bbox` without
|
|
824
|
+
* `simplify` simplifies nothing.
|
|
824
825
|
*
|
|
825
|
-
* Chosen
|
|
826
|
-
*
|
|
827
|
-
*
|
|
826
|
+
* Chosen once per track rather than per segment, so every leg of one track is
|
|
827
|
+
* simplified to the same tolerance and the single reported `epsilon` describes
|
|
828
|
+
* all of them.
|
|
828
829
|
*
|
|
829
830
|
* A non-positive `epsilon` is not reachable through the API — the schema
|
|
830
831
|
* declares `exclusiveMinimum: 0`, so the server rejects it — and is treated
|
|
@@ -835,16 +836,20 @@ function createTrackProvider(deps) {
|
|
|
835
836
|
function chooseEpsilon(points, query) {
|
|
836
837
|
const explicit = query.epsilon;
|
|
837
838
|
if (explicit !== void 0 && explicit > 0) return explicit;
|
|
838
|
-
|
|
839
|
+
if (query.simplify !== true) return;
|
|
840
|
+
if (query.bbox) return extentEpsilon(query.bbox);
|
|
841
|
+
const bounds = boundsOf(points);
|
|
842
|
+
return bounds ? extentEpsilon(bounds) : void 0;
|
|
839
843
|
}
|
|
840
844
|
/**
|
|
841
|
-
* How much of
|
|
845
|
+
* How much of an extent -- the query box, or the track without one -- the
|
|
846
|
+
* automatic tolerance may deviate by.
|
|
842
847
|
*
|
|
843
|
-
* One part in a thousand
|
|
844
|
-
* SignalK/signalk-server#2504: it
|
|
845
|
-
* `simplify` without an explicit
|
|
846
|
-
*
|
|
847
|
-
* it expensive to change.
|
|
848
|
+
* One part in a thousand: across a view that is roughly one screen pixel.
|
|
849
|
+
* Provisional while the v2 API is designed in SignalK/signalk-server#2504: it
|
|
850
|
+
* is only a provider-chosen default for `simplify` without an explicit
|
|
851
|
+
* epsilon, and a client that calibrates against the exact ratio rather than
|
|
852
|
+
* reading the reported `epsilon` back would make it expensive to change.
|
|
848
853
|
*/
|
|
849
854
|
var AUTO_EPSILON_DIVISOR = 1e3;
|
|
850
855
|
/**
|
|
@@ -856,17 +861,15 @@ var AUTO_EPSILON_DIVISOR = 1e3;
|
|
|
856
861
|
*/
|
|
857
862
|
var MIN_AUTO_EPSILON = 1;
|
|
858
863
|
/**
|
|
859
|
-
* A tolerance scaled to how much ground
|
|
864
|
+
* A tolerance scaled to how much ground an extent covers.
|
|
860
865
|
*
|
|
861
|
-
* One part in a thousand of
|
|
862
|
-
* a boat holding station while keeping every turn a passage is made of
|
|
863
|
-
*
|
|
864
|
-
* and erases a marina approach
|
|
866
|
+
* One part in a thousand of its diagonal. For a track that drops the jitter of
|
|
867
|
+
* a boat holding station while keeping every turn a passage is made of; for a
|
|
868
|
+
* view it keeps what a pixel can show. A fixed metre value cannot do either —
|
|
869
|
+
* 10 m erases nothing on an ocean crossing and erases a marina approach
|
|
870
|
+
* entirely.
|
|
865
871
|
*/
|
|
866
|
-
function
|
|
867
|
-
const bounds = boundsOf(points);
|
|
868
|
-
if (!bounds) return;
|
|
869
|
-
const [west, south, east, north] = bounds;
|
|
872
|
+
function extentEpsilon([west, south, east, north]) {
|
|
870
873
|
const midLat = (south + north) / 2;
|
|
871
874
|
const height = (north - south) * M_PER_DEG;
|
|
872
875
|
const width = (east >= west ? east - west : east + 360 - west) * M_PER_DEG * Math.cos(midLat * Math.PI / 180);
|
|
@@ -12186,6 +12189,12 @@ var SqliteTrackStore = class {
|
|
|
12186
12189
|
debug;
|
|
12187
12190
|
/** Timestamp of the last position stored per context, for throttling. */
|
|
12188
12191
|
lastStored = /* @__PURE__ */ new Map();
|
|
12192
|
+
/**
|
|
12193
|
+
* The stored name per context, dated by its newest report. A name arrives
|
|
12194
|
+
* with every position, so a repeat is answered here instead of committing a
|
|
12195
|
+
* row that has not changed.
|
|
12196
|
+
*/
|
|
12197
|
+
lastName = /* @__PURE__ */ new Map();
|
|
12189
12198
|
constructor(config, debug) {
|
|
12190
12199
|
this.maxCells = config.maxCells ?? DEFAULT_MAX_CELLS;
|
|
12191
12200
|
this.segmentGap = config.segmentGap ?? DEFAULT_SEGMENT_GAP;
|
|
@@ -12347,7 +12356,16 @@ var SqliteTrackStore = class {
|
|
|
12347
12356
|
recordName(context, name, timestamp = Date.now()) {
|
|
12348
12357
|
const trimmed = name.trim();
|
|
12349
12358
|
if (trimmed === "") return;
|
|
12350
|
-
this.
|
|
12359
|
+
const seen = this.lastName.get(context);
|
|
12360
|
+
if (seen && seen.timestamp > timestamp) return;
|
|
12361
|
+
if (seen?.name === trimmed) {
|
|
12362
|
+
seen.timestamp = timestamp;
|
|
12363
|
+
return;
|
|
12364
|
+
}
|
|
12365
|
+
if (Number(this.insertName.run(context, trimmed, timestamp).changes) > 0) this.lastName.set(context, {
|
|
12366
|
+
name: trimmed,
|
|
12367
|
+
timestamp
|
|
12368
|
+
});
|
|
12351
12369
|
}
|
|
12352
12370
|
nameFor(context) {
|
|
12353
12371
|
return this.selectName.get(context)?.name;
|
|
@@ -12356,7 +12374,10 @@ var SqliteTrackStore = class {
|
|
|
12356
12374
|
const cutoff = Date.now() - maxAge;
|
|
12357
12375
|
const dropped = this.db.prepare("SELECT context FROM positions GROUP BY context HAVING MAX(timestamp) < ? AND context IS NOT ?").all(cutoff, keep ?? null);
|
|
12358
12376
|
this.db.prepare("DELETE FROM positions WHERE context IN (SELECT context FROM positions GROUP BY context HAVING MAX(timestamp) < ?) AND context IS NOT ?").run(cutoff, keep ?? null);
|
|
12359
|
-
for (const { context } of dropped)
|
|
12377
|
+
for (const { context } of dropped) {
|
|
12378
|
+
this.db.prepare("DELETE FROM names WHERE context = ?").run(context);
|
|
12379
|
+
this.lastName.delete(context);
|
|
12380
|
+
}
|
|
12360
12381
|
for (const { context } of dropped) this.lastStored.delete(context);
|
|
12361
12382
|
if (this.retention > 0) {
|
|
12362
12383
|
const oldest = Date.now() - this.retention;
|
|
@@ -12365,7 +12386,14 @@ var SqliteTrackStore = class {
|
|
|
12365
12386
|
}
|
|
12366
12387
|
}
|
|
12367
12388
|
close() {
|
|
12368
|
-
|
|
12389
|
+
try {
|
|
12390
|
+
const redate = this.db.prepare("UPDATE names SET timestamp = ? WHERE context = ? AND name = ? AND timestamp < ?");
|
|
12391
|
+
this.db.exec("BEGIN");
|
|
12392
|
+
for (const [context, { name, timestamp }] of this.lastName) redate.run(timestamp, context, name, timestamp);
|
|
12393
|
+
this.db.exec("COMMIT");
|
|
12394
|
+
} finally {
|
|
12395
|
+
this.db.close();
|
|
12396
|
+
}
|
|
12369
12397
|
}
|
|
12370
12398
|
/** Unsigned round-trip check, used by the tests. */
|
|
12371
12399
|
cellIdsFor(context) {
|