]> Piment Noir Git Repositories - e-mobility-charging-stations-simulator.git/commit
feat(ui): add OCPP 2.0.x command support to Web UI (#1734)
authorJérôme Benoit <jerome.benoit@piment-noir.org>
Wed, 18 Mar 2026 13:34:49 +0000 (14:34 +0100)
committerGitHub <noreply@github.com>
Wed, 18 Mar 2026 13:34:49 +0000 (14:34 +0100)
commit4aeb171dbb5cd2f9122452c1e45759e843d6ddb1
treeb18b72512191ca2fb99133a58c69bc40d699da85
parentec24a90ee8c9c91e27b385c77c7903ccd5420342
feat(ui): add OCPP 2.0.x command support to Web UI (#1734)

* feat(ui): add OCPP 2.0.x types and sync ProcedureName enum

- Add OCPP 2.0.x-specific procedures to ProcedureName enum:
  TRANSACTION_EVENT, GET_15118_EV_CERTIFICATE, GET_CERTIFICATE_STATUS,
  LOG_STATUS_NOTIFICATION, NOTIFY_CUSTOMER_INFORMATION, NOTIFY_REPORT,
  SECURITY_EVENT_NOTIFICATION, SIGN_CERTIFICATE

- Add OCPP 2.0.x type definitions:
  - OCPP20IdTokenEnumType (8 values)
  - OCPP20TransactionEventEnumType (Ended, Started, Updated)
  - OCPP20IdTokenType interface
  - OCPP20TransactionEventRequest interface

- Update ConnectorStatus.transactionId to support both number (OCPP 1.6)
  and string/UUID (OCPP 2.0.x)

Wave 1 complete.

* feat(ui): add UIClient transaction methods with OCPP version support

- Add transactionEvent() method for OCPP 2.0.x TransactionEvent requests
- Add isOCPP20x() static helper for version detection
- Add startTransactionForVersion() helper that routes to appropriate
  method based on OCPP version (1.6 vs 2.0.x)
- Add stopTransactionForVersion() helper for version-aware stop
- Add comprehensive unit tests (16 tests passing)

Wave 2 complete.

* feat(ui): add version-aware StartTransaction form with OCPP 2.0.x support

- Modify StartTransaction.vue to detect OCPP version from station info
- Show connector ID for OCPP 1.6, EVSE ID input for OCPP 2.0.x
- Hide Authorize checkbox for OCPP 2.0.x stations (v-if)
- Use startTransactionForVersion() helper for version-aware API calls
- Add loading state while fetching station info
- Show appropriate form fields based on OCPP version
- All 16 tests passing

Wave 3 complete.

* fix(webui): use enums instead of string literals for OCPP 2.0.x types

- Replace 'ISO14443' string with OCPP20IdTokenEnumType.ISO14443

- Fix test mocks to use Protocol.UI and ResponseStatus.SUCCESS enums

- Export OCPP20IdTokenEnumType from types index

* style(webui): fix import ordering in UIClient.ts

* [autofix.ci] apply automated fixes

* chore: remove tsbuildinfo and add to gitignore

* fix(webui): address PR review comments

- Add ResponseStatus import and use enum instead of string

- Use UIClient.isOCPP20x() helper instead of manual comparison

- Remove redundant showAuthorize computed, use !isOCPP20x directly

- Fix authorizeIdTag checkbox binding (remove true-value/false-value)

- Initialize evseId from props.connectorId

- Separate error handling for authorize vs startTransaction

- Add validation for transactionId type in stopTransactionForVersion

* [autofix.ci] apply automated fixes

* chore: move tsbuildinfo gitignore to ui/web subdirectory

- Remove *.tsbuildinfo from root .gitignore

- Add *.tsbuildinfo to ui/web/.gitignore with proper comment

* ci(webui): add TypeScript type checking to CI

- Add vue-tsc dev dependency to ui/web

- Add typecheck script to package.json

- Add typecheck step to build-dashboard job in CI

* fix(webui): fix vue-tsc typecheck and improve Vue.js best practices

- Break recursive JsonObject/JsonType chain causing TS2589 in vue-tsc
- Fix CSConnector to use stopTransactionForVersion with ocppVersion prop
- Replace getCurrentInstance() anti-pattern with useToast()/useRouter()
- Make isOCPP20x a computed instead of manually-synced ref
- Deduplicate handleStartTransaction (remove ~30 lines of duplication)
- Add null guards for watch() on potentially undefined global refs

* [autofix.ci] apply automated fixes

* refactor(webui): align namespace with simulator and improve API design

- Merge startTransactionForVersion/stopTransactionForVersion into
  startTransaction/stopTransaction with optional ocppVersion param
- Make transactionEvent private (implementation detail, not public API)
- Revert UITransactionEventPayload to OCPP20TransactionEventRequest
  to match backend naming convention
- Pass ocppVersion via route param instead of re-fetching all stations
- Remove convertToBoolean no-op and loading state
- Flip negated v-if condition for SonarCloud compliance
- Factor test setup, remove duplicate coverage, add missing test case
- Net result: -90 lines, cleaner API surface

* [autofix.ci] apply automated fixes

* refactor(webui): move tests from __tests__ to tests/unit for consistency

Align test file location with existing project convention (tests/unit/)
instead of Jest-style __tests__ directory.

* feat(webui): integrate OCPP 2.0 EVSE 3-tier model across web UI

- Add OCPP20EVSEType matching spec EVSEType {id, connectorId?}
- Replace flat evseId with proper evse object in TransactionEventRequest
- CSData: preserve EVSE→Connector mapping instead of flattening
- CSConnector: display 'evseId/connectorId' for OCPP 2.0 stations
- Route: pass evseId and ocppVersion as query params (not sentinels)
- StartTransaction: read EVSE context from query, display EVSE/Connector
- UIClient.startTransaction: accept evseId, build spec-compliant evse object
- Tests: exhaustive decision tree coverage (18 tests, all branches)

* [autofix.ci] apply automated fixes

* refactor(webui): improve API elegance and fix cross-version concerns

- Refactor startTransaction/stopTransaction to use named options object
  instead of positional params for better readability and grouping
- Fix ToggleButton ID collision: include evseId for multi-EVSE uniqueness
- Normalize idTag validation as cross-version concern (empty→undefined)
- Rename getConnectorStatuses→getConnectorEntries to match semantics
- Extract toggleButtonId as computed to avoid string duplication

* feat: entry-based serialization for EVSE/Connector/ATG data

Introduce ConnectorEntry, EvseEntry, and ATGStatusEntry types at the
UI serialization boundary to preserve Map keys (evseId, connectorId)
that were previously lost during Map-to-Array conversion.

Backend:
- Add buildConnectorEntries/buildEvseEntries using .entries()
- Keep buildConnectorsStatus/buildEvsesStatus unchanged for config persistence
- Remove EvseStatusWorkerType and OutputFormat enum
- ATG statuses serialized with connectorId at the UI boundary only
- ConnectorStatus and EvseStatus types remain pure (no identity fields)

Frontend:
- CSData uses explicit IDs from Entry types (no more index-based mapping)
- ATG status lookup by connectorId instead of array index
- Filter connector 0 in both OCPP 1.6 and 2.0 paths
- Both connectors and evses optional in ChargingStationData

* [autofix.ci] apply automated fixes

* fix(webui): use data presence instead of protocol version for EVSE display

EVSE/Connector display depends on whether the station has EVSEs (data),
not on the OCPP version (protocol). A station could use EVSEs regardless
of OCPP version.

* refactor: extract buildATGStatusEntries for consistent Entry builder pattern

Align ATG status serialization with ConnectorEntry/EvseEntry pattern:
dedicated builder function instead of inline transformation.

* refactor: harmonize Entry naming pattern across codebase

Rename ATGStatusEntry/buildATGStatusEntries to ATGEntry/buildATGEntries
to match ConnectorEntry/EvseEntry naming convention.

* refactor: define ATGConfiguration type and harmonize across workspaces

Extract inline ATG type into named ATGConfiguration interface, matching
the ATG*/Connector*/Evse* Entry pattern in both backend and frontend.

* test: add missing Entry builder tests and non-sequential ID coverage

- Add buildATGEntries tests (entries with IDs, non-sequential, no ATG, no status)
- Add non-sequential connector ID test for buildConnectorEntries (keys 0,3,7)
- Add non-sequential evseId/connectorId test for buildEvseEntries (3/2,5)
- These tests verify the core invariant of the Entry pattern: Map keys are
  preserved regardless of their sequence

* refactor: organize tests by concern and replace throw with graceful failure

- Group backend tests: config persistence builders then UI Entry builders
- Replace throw Error in stopTransaction with ResponsePayload FAILURE
  to avoid unhandled rejections in UI components

* docs: harmonize quality gate ordering (typecheck before lint) across codebase

Align CI workflows, READMEs, and copilot-instructions to consistently
run typecheck before lint in all three sub-projects.

* refactor(ocpp2): centralize TransactionEvent payload building

- requestStopTransaction delegates to sendTransactionEvent instead of
  building the OCPP payload inline, eliminating duplication
- All TransactionEvent paths now converge through sendTransactionEvent
  → buildTransactionEvent as the single payload construction point
- handleTransactionEvent (UI) dispatches Started/Ended to proper flows
  with connector state initialization and lifecycle management
- Remove unused imports (secondsToMilliseconds, Constants)

---------

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
27 files changed:
.github/copilot-instructions.md
.github/workflows/ci.yml
pnpm-lock.yaml
src/charging-station/broadcast-channel/ChargingStationWorkerBroadcastChannel.ts
src/charging-station/ocpp/2.0/OCPP20IncomingRequestService.ts
src/charging-station/ocpp/2.0/OCPP20ServiceUtils.ts
src/types/ChargingStationWorker.ts
src/types/index.ts
src/utils/ChargingStationConfigurationUtils.ts
src/utils/MessageChannelUtils.ts
src/utils/index.ts
tests/ocpp-server/README.md
tests/utils/ChargingStationConfigurationUtils.test.ts
ui/web/.gitignore
ui/web/README.md
ui/web/package.json
ui/web/src/components/actions/AddChargingStations.vue
ui/web/src/components/actions/StartTransaction.vue
ui/web/src/components/charging-stations/CSConnector.vue
ui/web/src/components/charging-stations/CSData.vue
ui/web/src/composables/UIClient.ts
ui/web/src/types/ChargingStationType.ts
ui/web/src/types/JsonType.ts
ui/web/src/types/UIProtocol.ts
ui/web/src/types/index.ts
ui/web/src/views/ChargingStationsView.vue
ui/web/tests/unit/UIClient.test.ts [new file with mode: 0644]