]> Piment Noir Git Repositories - e-mobility-charging-stations-simulator.git/commit
feat(ocpp16): wire signed meter values into trigger + broadcast paths (issue #1936...
authorJérôme Benoit <jerome.benoit@piment-noir.org>
Fri, 3 Jul 2026 21:26:23 +0000 (23:26 +0200)
committerGitHub <noreply@github.com>
Fri, 3 Jul 2026 21:26:23 +0000 (23:26 +0200)
commit4b421f2e44ce695ca51e3cfea5691230be1b2bee
treefe49886b6f1dc9f1f23131526dfe92578cd1b838
parentf03e7f35b77d8d68523325982650d5cd749c2e89
feat(ocpp16): wire signed meter values into trigger + broadcast paths (issue #1936 d) (#1945)

* feat(ocpp16): wire signed meter values into trigger + broadcast paths (issue #1936 d)

OCPP 1.6 Signed Meter Values whitepaper v1.0 requires that when
SampledDataSignReadings + SampledDataSignUpdatedReadings are enabled
and a signing key is configured, a paired SignedData SampledValue
accompanies the Raw SampledValue in every Sample.Periodic-context
MeterValue. The periodic loop (OCPP16ServiceUtils.startUpdatedMeterValues)
already applies POST-HOC signing after buildMeterValue returns, so
periodic MeterValues are signed today.

Two callsites were missing the signing wrapper:
1. OCPP 1.6 TriggerMessage(MeterValues) handler in
   OCPP16IncomingRequestService.ts (both the specific-connectorId
   branch and the broadcast-to-all-connectors branch).
2. Worker broadcast channel in
   ChargingStationWorkerBroadcastChannel.handleMeterValues
   (cross-version handler; signing is 1.6-only per the whitepaper).

Both paths silently emitted unsigned Raw values instead of the
whitepaper-mandated paired SignedData SampledValue when signing was
enabled.

Fix: consolidate the signing block from startUpdatedMeterValues into
a new public static helper OCPP16ServiceUtils.appendSignedUpdatedReadings
that mutates the MeterValue in place. The helper is a no-op when
signing is disabled or the connector's signing config is missing.
Apply the helper at the three missing callsites and refactor
startUpdatedMeterValues to call it too.

Test invariant fail: 0, skipped: 6 preserved (2895 pass / 2901 total).

Spec citation: OCA Application Note 'Signed Meter Values for OCPP 1.6'
v1.0 §3.2.1 (paired SignedData SampledValue).

Closes issue #1936 item (d).

* docs(ocpp16): apply round-1 review fixes on signed MV wire-up (issue #1936 d)

Address cross-validated R1 findings:

- Naming coherence in TriggerMessage broadcast-to-all branch: rename
  loop-local variables from abbreviated 'id'/'cs'/'txId'/'mv' to
  full 'connectorId'/'connectorStatus'/'transactionId'/'meterValue'
  to match the specific-connector sibling branch style. Per AGENTS.md
  naming coherence: two adjacent branches doing the same thing with
  different name styles is the 'synonym creates ambiguity' pattern.

- Rewrite the broadcast channel guard comment to correctly attribute
  the '!isOcpp2' skip. Previous wording claimed 'the whitepaper is OCPP
  1.6 specific', but the whitepaper §4 explicitly covers OCPP 2.x. The
  actual reason for the skip is that OCPP 2.0.x signing is applied
  inline inside buildMeterValue via the versioned dispatcher's signing
  hook, so post-hoc wrapping is the 1.6 pattern only.

- Tighten the appendSignedUpdatedReadings @description to drop
  refactor-history narrative ('Consolidates the signing block used by
  every trigger/broadcast path...'). Replace with operational spec
  citing whitepaper §3.3.6 SampledDataSignUpdatedReadings and the
  mutation contract on connectorStatus.publicKeySentInTransaction
  (per PublicKeyWithSignedMeterValue = OncePerTransaction).

* fix(ocpp16): harden signed MV helper and thread reading context (issue #1936 d)

Enforce the transactionStarted invariant inside `appendSignedUpdatedReadings` so callsites
with looser guards cannot leak signed emissions past `resetConnectorTransactionStatus`.

Accept an optional reading `context` parameter (default `Sample.Periodic`);
`TriggerMessage(MeterValues)` callsites pass `Trigger` per OCPP 1.6 Core Table 30 so the
signed payload's context field matches its emission source.

Downgrade the `readSigningConfigForConnector` disabled-state log from `warn` to `debug`;
the helper is a hot-path probe whose `undefined` return already conveys the disabled state
to callers.

Test invariant `fail: 0, skipped: 6` preserved (2925 pass / 2931 total).
src/charging-station/broadcast-channel/ChargingStationWorkerBroadcastChannel.ts
src/charging-station/ocpp/1.6/OCPP16IncomingRequestService.ts
src/charging-station/ocpp/1.6/OCPP16ServiceUtils.ts