]> Piment Noir Git Repositories - e-mobility-charging-stations-simulator.git/commit
fix(ocpp): guard OCPP 1.6 UpdateFirmware deferred-timer schedule against sealed state...
authorJérôme Benoit <jerome.benoit@piment-noir.org>
Fri, 10 Jul 2026 13:09:12 +0000 (15:09 +0200)
committerGitHub <noreply@github.com>
Fri, 10 Jul 2026 13:09:12 +0000 (15:09 +0200)
commit247fef289a1786c307cecc185951e6dbc4e5d8a9
tree3604945987b1dcd39fe97c75a0cd4f57d6921119
parentef3e413db447a6293edc16255e6aa40e318b6fba
fix(ocpp): guard OCPP 1.6 UpdateFirmware deferred-timer schedule against sealed state writes (#1994)

The .on(UPDATE_FIRMWARE, ...) listener's deferred branch obtains state via
getOrCreateStationState() and then writes stationState.deferredFirmwareUpdateTimer
= setTimeout(...). After PR #1992 sealed the base-plumbing behavior,
getOrCreateStationState() returns the stopped state instead of lazy-initializing
a fresh entry once stop() has marked stationsState.get(cs)?.stopped === true. A
late UPDATE_FIRMWARE dispatch after ChargingStation.stop() runs
ocppIncomingRequestService.stop(this) at ChargingStation.ts:1273 (before
this.started = false at :1280) therefore writes a fresh Timeout onto the sealed
state.

The callback body is safe (unref'd, checkChargingStationState gate), but the
write is inconsistent with the OCPP 2.0.1 GUARD sites shipped in PR #1992
(getCertSigningRetryManager, sendSecurityEventNotification,
simulateFirmwareUpdateLifecycle, simulateLogUploadLifecycle) and leaves a Timeout
closure-referenced entry pending in Node's queue until GC reclaims the
ChargingStation.

Insert a stopped GUARD immediately after getOrCreateStationState, before
cancelDeferredFirmwareUpdate — mirroring the exact syntax of the OCPP 2.0.1
GUARD sites (bare 'return' after 'if (stationState.stopped === true) {'). The
GUARD short-circuits the schedule branch before any write reaches the sealed
state.

Add a regression test covering the post-stop() deferred-schedule path in
tests/charging-station/ocpp/1.6/OCPP16IncomingRequestService-Firmware.test.ts.

Closes #1993

Touchpoint:
- src/charging-station/ocpp/1.6/OCPP16IncomingRequestService.ts:705 — stopped GUARD

References:
- PR #1992 — source of the 'stopped' sentinel + OCPP 2.0.1 GUARD sites
- PR #1984 — source of 'deferredFirmwareUpdateTimer'

This is purely additive; no observable OCPP behavior change (the pre-existing
fire-time checkChargingStationState gate inside the setTimeout callback remains
as defense-in-depth).
src/charging-station/ocpp/1.6/OCPP16IncomingRequestService.ts
tests/charging-station/ocpp/1.6/OCPP16IncomingRequestService-Firmware.test.ts