signalk-czone 0.3.0-beta.10 → 0.3.0-beta.12

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/CHANGELOG.md CHANGED
@@ -1,5 +1,16 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.3.0-beta.12
4
+
5
+ - Keeps the connection indicator disconnected when circuit-list REST refreshes succeed but the live WebSocket is down; shows connecting/reconnecting status and the snapshot time.
6
+
7
+ ## 0.3.0-beta.11
8
+
9
+ - Uses the npm `latest` tag for default installation and App Store updates while retaining the BETA version and listing labels.
10
+
11
+ - Routes circuit current to known physical output owners instead of groups referencing those outputs, restoring Starlink current and correcting Port Fresh Water Pump and Meitaki Nav. AIS attribution.
12
+ - Preserves existing current mappings when output ownership is ambiguous and adds regression coverage across all six ZCF fixtures.
13
+
3
14
  ## 0.3.0-beta.10
4
15
 
5
16
  - Adds opt-in circuit current trends with preset and custom chart periods, CSV storage, summaries and retention settings.
package/README.md CHANGED
@@ -208,15 +208,15 @@ Once this beta is published and available in your App Store:
208
208
  3. Open **Server → Plugin Config → CZone** and use **Upload and install ZCF** to upload your vessel's `.zcf` configuration.
209
209
  4. Enable the plugin after configuration, then check the **Diagnostics** tab and published currents before testing controls.
210
210
 
211
- The plugin is disabled by default until explicitly enabled. Availability of beta versions in the App Store depends on the server version and publication channel.
211
+ The plugin is disabled by default until explicitly enabled. Tested releases use the npm `latest` tag for default installation and Signal K App Store discovery; the version and listing retain their BETA labels.
212
212
 
213
- ### Explicit npm beta installation
213
+ ### Explicit npm installation
214
214
 
215
215
  After npm publication, run this as the Signal K service user from the server's configuration directory (normally `~/.signalk`, or the directory configured by `SIGNALK_NODE_CONFIG_DIR`):
216
216
 
217
217
  ```bash
218
218
  cd ~/.signalk
219
- npm install signalk-czone@beta --omit=dev --ignore-scripts
219
+ npm install signalk-czone@latest --omit=dev --ignore-scripts
220
220
  ```
221
221
 
222
222
  Restart Signal K and follow the configuration steps above. For Docker or appliance installations, use the corresponding container/configuration directory and restart method.
@@ -225,9 +225,9 @@ For installation from a maintainer-provided npm tarball, run `npm install /path/
225
225
 
226
226
  ### Publishing (maintainers)
227
227
 
228
- Publish `signalk-czone-zcf@0.1.0-beta.1` first. Then run `npm install`, `npm test`, and `npm pack --dry-run` in this repository, verify the runtime files and App Store assets, and run `npm publish --tag beta` after npm authentication.
228
+ Publish `signalk-czone-zcf@0.1.0-beta.1` first. Then run `npm install`, `npm test`, and `npm pack --dry-run` in this repository, verify the runtime files and App Store assets, and run `npm publish --tag latest` after npm authentication.
229
229
 
230
- The package defaults to the `beta` tag. Promoting a beta to `latest` for default installs is a separate release decision.
230
+ The package defaults to `latest`, including versions named `-beta.N`. The GitHub publishing workflow runs when `package.json` or the workflow changes on `main`: it tests and packs the release, publishes it if the version is new, and sets and verifies the `latest` tag. If the version already exists, the workflow promotes that existing version without republishing its contents.
231
231
 
232
232
  ### Beta feedback
233
233
 
package/index.js CHANGED
@@ -559,11 +559,8 @@ module.exports = function (app) {
559
559
  if (!mapping || !Array.isArray(mapping.circuits)) return null
560
560
  if (pgn === CURRENT_PGN_AC && Number(module) !== 0xF8) return null
561
561
  if (pgn === CURRENT_PGN_DC && Number(module) === 0x28) return null
562
- return mapping.circuits.find(c =>
563
- Number(c.module) === Number(module) &&
564
- Number(c.page) === Number(page) &&
565
- Number(c.slot) === Number(slot)
566
- ) || null
562
+ return zcf.lookup(mapping, module, page, slot,
563
+ pgn === CURRENT_PGN_CONTROL_X_PLUS ? CURRENT_PGN_DC : pgn)
567
564
  }
568
565
 
569
566
  function publishSettingsRevision () {
package/lib/zcf.js CHANGED
@@ -64,6 +64,14 @@ function enrichRuntimeModel (mapping) {
64
64
  mapping.currentMappings = mapping.circuits
65
65
  .map(circuit => {
66
66
  if (Number(circuit.module) === 0x28) return null
67
+ // Group/virtual circuits can reference another circuit's primary load.
68
+ // Prefer a known owner, preserving existing resolution where ownership
69
+ // is ambiguous (for example multiple controls for the same load).
70
+ if (Array.isArray(circuit.ownOutputs) && !circuit.ownOutputs.length &&
71
+ mapping.circuits.some(owner => Array.isArray(owner.ownOutputs) &&
72
+ owner.ownOutputs.some(output =>
73
+ output.module === circuit.module && output.channel === circuit.channel
74
+ ))) return null
67
75
  return {
68
76
  ...circuit,
69
77
  pgn: Number(circuit.module) === 0xF8 ? CURRENT_PGN_AC : CURRENT_PGN_DC,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "signalk-czone",
3
- "version": "0.3.0-beta.10",
3
+ "version": "0.3.0-beta.12",
4
4
  "description": "BETA: Signal K CZone monitoring and control using dynamically parsed ZCF configuration and NMEA 2000",
5
5
  "main": "index.js",
6
6
  "keywords": [
@@ -57,6 +57,6 @@
57
57
  },
58
58
  "publishConfig": {
59
59
  "access": "public",
60
- "tag": "beta"
60
+ "tag": "latest"
61
61
  }
62
62
  }
package/public/index.html CHANGED
@@ -293,7 +293,7 @@
293
293
  ];
294
294
  const topLevelCategories = new Set(['AC', 'DC', 'Favorites']);
295
295
  let circuits = [], status = {}, modes = [], activeMode = null, vesselName = '', view = 'all', category = null, query = '', sort = 'name', socket = null;
296
- let socketReconnectTimer = null, watchdogTimer = null, lastSocketUpdateAt = 0, socketConnected = false;
296
+ let socketReconnectTimer = null, watchdogTimer = null, lastSocketUpdateAt = 0, socketConnected = false, socketEverOpen = false;
297
297
  const WS_WATCHDOG_MS = 120000;
298
298
  const COMMAND_CONFIRM_MS = 15000;
299
299
  const COMMAND_RECONCILE_DELAY_MS = 200;
@@ -565,8 +565,16 @@
565
565
  console.debug('[CZone UI] REST refresh', reason, { circuits: incoming.length, modes: Array.isArray(data.modes) ? data.modes.length : 0, sendingEnabled: data.sendingEnabled === true, nmeaReady: data.nmeaReady === true });
566
566
  mergeRest(data);
567
567
  if (incoming.length === 0) throw new Error('CZone plugin returned an empty circuit list');
568
- document.querySelector('#connection').classList.add('ok');
569
- document.querySelector('#connection').innerHTML = '<i></i><span>Connected · live circuit data</span>';
568
+ // "Connected" only while the live feed is up. This read is a one-off
569
+ // (first load, or the watchdog's reconciliation): with the feed down
570
+ // the page would otherwise say Connected while nothing on it moves.
571
+ const conn = document.querySelector('#connection');
572
+ conn.classList.toggle('ok', socketConnected);
573
+ conn.innerHTML = socketConnected
574
+ ? '<i></i><span>Connected · live circuit data</span>'
575
+ : socketEverOpen
576
+ ? `<i></i><span>Live updates lost · reconnecting… (circuits as of ${new Date().toLocaleTimeString([], { hour: '2-digit', minute: '2-digit', second: '2-digit' })})</span>`
577
+ : '<i></i><span>Circuits loaded · connecting live updates…</span>';
570
578
  render();
571
579
  return true;
572
580
  } catch (e) {
@@ -1018,6 +1026,7 @@
1018
1026
  socket = new WebSocket(SK);
1019
1027
  socket.onopen = () => {
1020
1028
  socketConnected = true;
1029
+ socketEverOpen = true;
1021
1030
  lastSocketUpdateAt = Date.now();
1022
1031
  updateSocketIndicator('Connected · WebSocket live', true);
1023
1032
  sendSubscriptions();
@@ -1046,7 +1055,7 @@
1046
1055
  };
1047
1056
  socket.onclose = () => {
1048
1057
  socketConnected = false;
1049
- updateSocketIndicator('Reconnecting to Signal K…', false);
1058
+ updateSocketIndicator(socketEverOpen ? 'Live updates lost · reconnecting…' : 'Connecting live updates…', false);
1050
1059
  console.warn('[CZone WS] closed; reconnecting');
1051
1060
  clearTimeout(socketReconnectTimer);
1052
1061
  socketReconnectTimer = setTimeout(connectSocket, 3000);