fix(ocpp2): align MeterValues implementation with OCPP 2.0.1 spec (#1744)
* fix(ocpp2): use AlignedDataInterval for standalone MeterValues
Add getAlignedDataInterval() helper to OCPP20ServiceUtils that reads
AlignedDataCtrlr.Interval from the variable registry (default 900s).
Replace getTxUpdatedInterval() with getAlignedDataInterval() in the
broadcast channel handleMeterValues OCPP 2.0 branch. Standalone
MeterValuesRequest is non-transaction data per OCPP 2.0.1 spec and
should use the aligned data interval, not the tx-updated interval.
* fix(ocpp2): include meter value in TransactionEvent Started
Add buildTransactionBeginMeterValues() to OCPP20ServiceUtils following
the buildFinalMeterValues() pattern. Builds an OCPP20MeterValue with
Transaction.Begin context and Energy.Active.Import.Register measurand.
Wire it into both TransactionEvent(Started) call sites:
- OCPPServiceUtils.startTransactionOnConnector (ATG/broadcast channel)
- OCPP20IncomingRequestService RequestStartTransaction event listener
This aligns OCPP 2.0 with the OCPP 1.6 beginEndMeterValues behavior
per OCPP 2.0.1 spec SampledDataTxStartedMeasurands requirement.
* test(ocpp2): add tests for buildTransactionBeginMeterValues
Test Transaction.Begin context, energy register value, default to 0
when undefined, and empty array when energy is negative.
* refactor(ocpp2): address PR review comments
- Extract buildEnergyMeterValues private helper to eliminate DRY
violation between buildTransactionBeginMeterValues and
buildFinalMeterValues
- Add AlignedDataInterval to OCPP20RequiredVariableName enum replacing
raw string literal in getAlignedDataInterval
- Clarify zero-energy test name to document that 0 Wh is a valid
Transaction.Begin reading
- Add meterValue assertions to RequestStartTransaction test verifying
Transaction.Begin context and Energy.Active.Import.Register measurand
* refactor(ocpp2): extract readVariableAsIntervalMs to eliminate DRY
getAlignedDataInterval and getTxUpdatedInterval were structurally
identical. Extract the shared variable-reading logic into a private
readVariableAsIntervalMs helper that accepts component name, variable
name, and default seconds. Both public methods become one-liner
delegates.
* refactor(ocpp2): extract terminateTransaction and resolveActiveTransaction
requestDeauthorizeTransaction and requestStopTransaction shared
identical transaction termination logic (build final meter values,
send TransactionEvent Ended, stop periodic, reset connector status).
Extract resolveActiveTransaction for the shared precondition check
and transactionId string resolution, and terminateTransaction for
the shared Ended event + cleanup workflow. Both public methods now
focus only on their unique behavior.
* fix(test): use enum constants instead of string literals in RequestStartTransaction test
Replace 'Transaction.Begin' and 'Energy.Active.Import.Register' string
literals with OCPP20ReadingContextEnumType.TRANSACTION_BEGIN and
OCPP20MeasurandEnumType.ENERGY_ACTIVE_IMPORT_REGISTER to match
codebase conventions.
* refactor(test): replace string literals with enum constants in OCPP 2.0 tests
Replace hardcoded string literals with their corresponding OCPP 2.0.1
enum values across test files for type safety and consistency:
requestDeauthorizeTransaction mocks returned { status: 'Accepted' }
but OCPP20TransactionEventResponse has no status field. Replace with
properly typed empty response objects since the return value is not
asserted in these tests.
* refactor(ocpp2): align method names with OCPP 2.0.1 spec terminology
The spec uses Started/Updated/Ended for TransactionEvent types, not
Begin/Final.
* refactor(test): replace 'Operative' string literal with enum constants
Use OCPP20OperationalStatusEnumType.Operative in OCPP 2.0 test files
and the cross-version AvailabilityType.Operative in MessageChannelUtils
test to match ConnectorStatus.availability typed field.