Skip to content

fix(tanks): seed tankVolume2 capacity from the data tree#266

Open
msallin wants to merge 2 commits into
SignalK:masterfrom
msallin:claude/condescending-goldstine-136e57
Open

fix(tanks): seed tankVolume2 capacity from the data tree#266
msallin wants to merge 2 commits into
SignalK:masterfrom
msallin:claude/condescending-goldstine-136e57

Conversation

@msallin

@msallin msallin commented May 25, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • Fixes tankVolume2 never emitting currentVolume when capacity comes from defaults.json (or any static source that doesn't push deltas through the streambundle to late subscribers).
  • Seeds the capacity slot from app.getSelfPath at factory time via the existing defaults array; streamed capacity from a tank sender still supersedes the seed.
  • Hardens input guards (Number.isFinite(x) && x > 0) so a misconfigured negative or zero capacity doesn't emit nonsense volumes.
  • Adds integration coverage for both the seeded-from-tree and streamed-capacity paths, and a regression test that proves the unblock end-to-end.

Why

The signalk-server streambundle applies defaults.json values at server boot but does not replay those deltas to plugins that subscribe later. tankVolume2 uses Bacon's combine over [currentLevel, capacity], so a defaults-only capacity leaves the combined stream blocked forever waiting on a capacity delta that never arrives. Users see the checkbox enabled in the plugin config but no output for the tank.

The plugin's calculation framework already supports per-input seeding via the optional defaults array on a Calculation (consumed in src/index.ts via Bacon's .toProperty(seed)); eight other calcs already use it. This change adopts the same mechanism for capacity, with the seed read from the data tree at start. Bacon's toProperty semantics let any subsequent real capacity delta override the seed, so tank-sender plugins and mid-runtime recalibration paths are preserved.

Title also cleaned up: dropped the dangling "Uses " fragment that was clearly a truncated template, and aligned the format with tankVolume.ts.

Test plan

  • npm test — 323 passing (was 319; +4 new tests: 2 unit boundary cases incl. the multi-tank seeding regression, 2 integration tests covering the seeded-from-tree and streamed-capacity paths).
  • npm run typecheck — clean.
  • npm run prettier:check — clean.
  • Live smoke test on a SignalK server with a tank whose capacity lives in defaults.json: confirm tanks.<inst>.currentVolume starts emitting on the next currentLevel delta after enabling tankVolume2.

When a tank's capacity comes from defaults.json, the streambundle
applies it at server boot but doesn't replay the delta to plugins
that subscribe later. The combined stream over [currentLevel,
capacity] blocks forever waiting on capacity and no currentVolume
emits.

Read capacity once via app.getSelfPath at factory time (after
plugin.start, so defaults are already in the tree) and seed the
capacity slot via the `defaults` array already consumed by
index.ts. Bacon's toProperty semantics let a real streamed
capacity delta supersede the seed, so tank senders still work
unchanged.

Also tightens the input guards to reject negative, zero, and
non-finite capacities (so a misconfigured defaults.json doesn't
emit nonsense volumes), aligns the title format with tankVolume.ts,
and adds an integration test that pushes only currentLevel against
a seeded capacity to pin the regression.
@msallin msallin added the fix label May 25, 2026
Keep the two real-world cases the seed covers (defaults.json static
capacity, and a tank sender's streamed capacity) and drop the
implementation walkthrough.
@msallin

msallin commented Jun 6, 2026

Copy link
Copy Markdown
Collaborator Author

@tkurki may I have your opinion here? My case is that the tank capacity comes from defaults.json.
It feels like such things should "just" work... Probably we should do it in another way as I did here?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant