]> Piment Noir Git Repositories - e-mobility-charging-stations-simulator.git/commit
fix(cli): make high-level OCPP commands version-aware (#1801)
authorJérôme Benoit <jerome.benoit@piment-noir.org>
Wed, 22 Apr 2026 09:06:51 +0000 (11:06 +0200)
committerGitHub <noreply@github.com>
Wed, 22 Apr 2026 09:06:51 +0000 (11:06 +0200)
commit804dce720fd281de52499510cba6d8cbb01fdf0d
tree2134086c532e2943deedc16c2b93aa0ccaaf99e9
parent683476435546765d521f363f4ddb7451af268527
fix(cli): make high-level OCPP commands version-aware (#1801)

* fix(cli): make high-level transaction and authorize commands OCPP version-aware

- transaction start: detect station OCPP version, send TRANSACTION_EVENT
  with idToken/evse payload for 2.0.x or START_TRANSACTION for 1.6
- transaction stop: same version detection, send TRANSACTION_EVENT Ended
  for 2.0.x or STOP_TRANSACTION for 1.6; accept string transaction IDs
- ocpp authorize --id-tag: send idToken object for 2.0.x, idTag for 1.6;
  -p payload passthrough unchanged (low-level override)
- action.ts: extract fetchStationList helper, export resolveOcppVersion

* docs(cli): clarify prefix matching behavior in resolveOcppVersion JSDoc

* refactor(cli): use switch/case for OCPP version branching and clean up help text

* fix(cli): address audit findings for cross-version OCPP compliance

- R1: status-notification version-aware: --error-code optional, validated
  for OCPP 1.6; OCPP 2.0.x uses connectorStatus with optional --evse-id
- R2: add optional --evse-id to meter-values
- R3: skipped (callers already throw clear error for heterogeneous/no-match)
- R4: skipped (handleStopTransaction is 1.6-only, transactionId always number)
- R5: JSDoc on version-specific ProcedureName entries
- R6: comment on handleStopTransaction noting 1.6-only

* refactor(cli): consolidate version detection, fix DRY violations, and harden edge cases

- F-01: comment noting OCPP20TriggerReasonEnumType duplication
- F-02/F-04: extract resolveOcppVersionFromProgram (single fetch, returns resolved hashIds)
- F-03: export MIXED_OCPP_VERSION_ERROR constant
- F-05: default evse.id to 1, add --evse-id to transaction start
- F-06: document -p limitation in help text
- F-07: remove idTag ?? '' dead code
- F-08: remove redundant === id check
- F-09: add test for ambiguous prefix with homogeneous versions
- F-10: rewrite handleStopTransaction comment

* style: remove unnecessary duplication comments in ui/common enums

* refactor(cli): use commander conflicts() for mutually exclusive options

ocpp authorize: --id-tag and -p/--payload are now declared as mutually
exclusive via Option.conflicts(). Commander enforces this at parse time.

* fix(cli): resolve audit findings — BUG-01, DRY-01, DEAD-01, ROBUST-01, PERF-01

- BUG-01: use resolvedHashIds (not raw hashIds) in resolveOcppVersionFromProgram
- DRY-01: extract resolveShortHashIdsFromList pure helper, used by both
  resolveShortHashIds and resolveOcppVersionFromProgram
- DEAD-01/DOC-01: remove unused resolveOcppVersion, update JSDoc references
- ROBUST-01: seqNo 1 for transaction stop (start uses 0)
- PERF-01: resolveOcppVersionFromProgram returns config, runAction accepts
  preloadedConfig to skip redundant loadConfig call

* chore: refine .gitignore

Signed-off-by: Jérôme Benoit <jerome.benoit@sap.com>
* fix(cli): simplify OCPP 2.0.x transaction payloads to match builder options

- transaction start: send flat OCPP20TransactionEventOptions (connectorId,
  evseId, idToken) instead of wire-format fields (seqNo, timestamp,
  transactionInfo nesting, evse structure)
- transaction stop: send flat transactionId instead of nested
  transactionInfo, remove hardcoded seqNo/timestamp/triggerReason
- Remove evseId ?? 1 default (let builder resolve from connectorId)
- Remove unused imports (randomUUID, OCPP20TriggerReasonEnumType)
- Fix meter-values --evse-id misleading help text
- Add test for mixed matching/non-matching hashIds

Addresses review comments from hyperspace-insights and Copilot,
cross-validated with audit v2 findings BUG-01, BUG-02, BUG-03.

* fix(cli): harmonize all OCPP commands with version-aware conflicts pattern

- Add early NO_STATIONS_ERROR check in resolveOcppVersionFromProgram
- Refactor status-notification, meter-values, transaction start/stop to
  use .addOption/.conflicts() pattern matching authorize's design
- Make meter-values version-aware: OCPP 1.6 sends connectorId, OCPP 2.0
  sends evseId, passthrough mode sends only routing fields
- Fix --evse-id help text in transaction start (was claiming false default)
- Fix pre-existing jsdoc/require-throws-type lint warning

* fix(cli): add connectorId to transaction stop for OCPP 2.0.x and harmonize evseId conflicts

- Add --connector-id option to transaction stop (defaults to 1) so
  buildTransactionEvent resolves the correct connector on multi-connector
  stations
- Convert all --evse-id options to .addOption/.conflicts('payload') for
  consistent UX with other semantic options
- Add evseId to reverse .conflicts() lists on -p/--payload options

* fix(cli): update JSDoc and comments to match current behavior

- Update resolveOcppVersionFromProgram JSDoc: returns OCPPVersion (not
  undefined), add @throws documentation for all error cases
- Update MIN_FULL_HASH_LENGTH comment: now validates existence, not just
  skips resolution

* fix(cli): route version-detection errors through formatter for --json mode

Add handleActionErrors wrapper that catches errors from version
detection, option validation, and hash-ID resolution before runAction,
routing them through the same formatter used by runAction. Without this,
errors in --json mode were output as plain text instead of structured
JSON.

* Apply suggestion from @jerome-benoit

* refactor(cli): extract shared error formatter and clean up exports

- Extract formatError() from duplicated catch blocks in
  handleActionErrors and runAction
- Align authorize error message with the pattern used by all other
  commands ('X is required when -p/--payload is not provided')
- Remove unnecessary exports from 3 internal-only error constants
  (NO_STATIONS_ERROR, MIXED_OCPP_VERSION_ERROR, UNKNOWN_OCPP_VERSION_ERROR)

* fix(cli): standardize option help texts and remove redundancy

- Standardize EVSE ID help text to 'EVSE ID (OCPP 2.0.x; derived from
  connector ID if omitted)' across meter-values, status-notification,
  and transaction start
- Simplify error-code help text from 'OCPP 1.6 only; required for 1.6'
  to 'OCPP 1.6' (the constraint is already enforced at runtime)

* docs(cli): document version-aware commands and new OCPP 2.0.x options

- Add --evse-id to meter-values, status-notification, transaction start
- Add --connector-id to transaction stop (required for OCPP 2.0.x)
- Mark --error-code as optional (OCPP 1.6 only)
- Mark --vendor-id as optional in data-transfer
- Document -p/--payload support for transaction commands
- Add Version-aware commands section with OCPP 1.6 vs 2.0.x mapping
- Update both README.md and SKILL.md consistently

* docs(cli): fix pre-existing documentation gaps in README and SKILL.md

- Add missing station add options: --persistent-config, --ocpp-strict
- Add missing station delete --delete-config example in SKILL.md
- Add missing atg stop --connector-ids in SKILL.md
- Fix meter-values: both --connector-id and --evse-id are optional
  (at least one required)
- Fix ATG --connector-ids notation: <id,...> instead of <ids...>
- Add hashId prefix matching note to SKILL.md

* fix(cli): harmonize user-facing strings and fix documentation accuracy

Code:
- Harmonize 'station(s)' terminology (drop 'charging' prefix in
  station.ts descriptions to match all other command files)
- Fix NO_STATIONS_ERROR to use consistent 'stations' wording
- Fix data-transfer --data description: free-form string, not JSON only
- Fix transaction unsupported version error: direct users to
  'ocpp transaction-event -p' instead of generic '-p' which forces 1.6

Docs (README + SKILL.md):
- Fix merge claim: -p conflicts with typed options on most commands,
  only data-transfer allows merge
- Add meter-values 'at least one required' constraint note
- Add --connector-id required for transaction stop on OCPP 2.0.x in
  version-aware table
- Fix data-transfer --data placeholder from <json> to <data>

* refactor(cli): extract duplicated unsupported version error in transaction.ts

Extract inline error string into a local const within
createTransactionCommands to avoid duplication across the start and
stop default switch branches.

* fix(cli): correct meter-values payload for OCPP 2.0.x stations

The OCPP 2.0.x MeterValues JSON schema does not allow connectorId as a
property. The previous implementation conditionally included connectorId
in the payload for OCPP 2.0.x, which caused schema validation failures
in the simulator ("additionalProperty: connectorId — must NOT have
additional properties").

For OCPP 2.0.x, evseId is the only valid EVSE identifier in a
MeterValues request. The fix now requires --evse-id for OCPP 2.0.x
stations and sends only evseId in the payload. If only --connector-id
is supplied against a 2.0.x station, a clear error message guides the
user to use --evse-id instead. The --connector-id help text is also
updated to indicate it is OCPP 1.6 only for this command.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* docs(cli): align meter-values documentation with evseId-only OCPP 2.0.x fix

Update README and SKILL.md to reflect that meter-values requires
--evse-id for OCPP 2.0.x (connectorId is not a valid MeterValues
field in 2.0.x). Show separate OCPP 1.6 and 2.0.x usage lines.

* fix(cli): harmonize meter-values help texts and error message

- Drop 'only' from --connector-id help: '(OCPP 1.6)' matches
  --error-code pattern in status-notification
- Drop 'required' from --evse-id help: '(OCPP 2.0.x)' matches
  version-only pattern used for version-exclusive options
- Remove verbose parenthetical from evseId error message to match
  the terse pattern used by all other version-specific errors

* fix(cli): use SCREAMING_CASE for error constant and add missing exit code

- Rename unsupportedVersionError to UNSUPPORTED_VERSION_ERROR in
  transaction.ts to match the naming convention used by all error
  constants in action.ts
- Add exit code 143 (SIGTERM) to SKILL.md exit codes table

* fix(cli): complete resolveOcppVersionFromList JSDoc for unknown versions

Add 'or all versions are unknown' to the @returns description to
document that the function also returns undefined when all targeted
stations have ocppVersion: undefined (Set {undefined}, size 1).

* fix(cli): align error constant naming and fix README station list comment

- Rename UNSUPPORTED_VERSION_ERROR to UNSUPPORTED_OCPP_VERSION_ERROR in
  transaction.ts to match the naming convention with OCPP_ prefix used
  by the exported constant in action.ts
- Fix README inline comment: 'List all stations' to match station.ts
  description (was still 'List all charging stations')

---------

Signed-off-by: Jérôme Benoit <jerome.benoit@sap.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
.gitignore
src/types/UIProtocol.ts
ui/cli/README.md
ui/cli/skills/evse-simulator/SKILL.md
ui/cli/src/commands/action.ts
ui/cli/src/commands/ocpp.ts
ui/cli/src/commands/station.ts
ui/cli/src/commands/transaction.ts
ui/cli/tests/action.test.ts [new file with mode: 0644]
ui/common/src/types/ChargingStationType.ts