From 0a6d389a54f3f656c3d3024587059e9befabd514 Mon Sep 17 00:00:00 2001 From: =?utf8?q?J=C3=A9r=C3=B4me=20Benoit?= Date: Wed, 29 Oct 2025 23:02:33 +0100 Subject: [PATCH] fix(ocpp20): align TxStartPoint/TxStopPoint defaults and enumerations with OCPP 2.0.1 errata --- .../ocpp/2.0/OCPP20VariableRegistry.ts | 25 ++++++++++++++++--- .../ocpp/2.0/OCPP20VariableManager.test.ts | 18 +++++++++++-- 2 files changed, 37 insertions(+), 6 deletions(-) diff --git a/src/charging-station/ocpp/2.0/OCPP20VariableRegistry.ts b/src/charging-station/ocpp/2.0/OCPP20VariableRegistry.ts index d0dec097..7bc7aa2a 100644 --- a/src/charging-station/ocpp/2.0/OCPP20VariableRegistry.ts +++ b/src/charging-station/ocpp/2.0/OCPP20VariableRegistry.ts @@ -844,9 +844,18 @@ export const VARIABLE_REGISTRY: Record = { )]: { component: OCPP20ComponentName.TxCtrlr as string, dataType: DataEnumType.MemberList, - defaultValue: 'CablePluggedIn,EnergyTransfer', + // Spec-aligned default (exclude EnergyTransfer & DataSigned due to measurement skew and signed data optionality) + defaultValue: 'Authorized,EVConnected', description: 'Trigger conditions for starting a transaction.', - enumeration: ['CablePluggedIn', 'EnergyTransfer', 'Authorized', 'PowerPathClosed'], + // Spec-aligned enumeration per errata: Authorized, EVConnected, PowerPathClosed, EnergyTransfer, ParkingBayOccupancy plus DataSigned (start only) + enumeration: [ + 'Authorized', + 'EVConnected', + 'PowerPathClosed', + 'EnergyTransfer', + 'ParkingBayOccupancy', + 'DataSigned', + ], mutability: MutabilityEnumType.ReadWrite, persistence: PersistenceEnumType.Persistent, supportedAttributes: [AttributeEnumType.Actual], @@ -856,9 +865,17 @@ export const VARIABLE_REGISTRY: Record = { { component: OCPP20ComponentName.TxCtrlr as string, dataType: DataEnumType.MemberList, - defaultValue: 'EVSEIdle,CableUnplugged', + // Spec-aligned default stop triggers (exclude Authorized by default to avoid id re-presentation auto-stop) + defaultValue: 'EVConnected,PowerPathClosed', description: 'Trigger conditions for ending a transaction.', - enumeration: ['EVSEIdle', 'CableUnplugged', 'Deauthorized', 'PowerPathOpened'], + // Spec-aligned enumeration per errata: Authorized, EVConnected, PowerPathClosed, EnergyTransfer, ParkingBayOccupancy (DataSigned excluded as invalid stop point) + enumeration: [ + 'Authorized', + 'EVConnected', + 'PowerPathClosed', + 'EnergyTransfer', + 'ParkingBayOccupancy', + ], mutability: MutabilityEnumType.ReadWrite, persistence: PersistenceEnumType.Persistent, supportedAttributes: [AttributeEnumType.Actual], diff --git a/tests/charging-station/ocpp/2.0/OCPP20VariableManager.test.ts b/tests/charging-station/ocpp/2.0/OCPP20VariableManager.test.ts index 8a1fe78a..3c9d8e79 100644 --- a/tests/charging-station/ocpp/2.0/OCPP20VariableManager.test.ts +++ b/tests/charging-station/ocpp/2.0/OCPP20VariableManager.test.ts @@ -1202,12 +1202,12 @@ await describe('OCPP20VariableManager test suite', async () => { variable: { name: OCPP20RequiredVariableName.TimeSource }, }, { - attributeValue: 'CablePluggedIn,EnergyTransfer,Authorized', + attributeValue: 'Authorized,EVConnected,PowerPathClosed', component: { name: OCPP20ComponentName.TxCtrlr }, variable: { name: OCPP20RequiredVariableName.TxStartPoint }, }, { - attributeValue: 'EVSEIdle,CableUnplugged', // keep same + attributeValue: 'EVConnected,PowerPathClosed', // updated default component: { name: OCPP20ComponentName.TxCtrlr }, variable: { name: OCPP20RequiredVariableName.TxStopPoint }, }, @@ -1286,6 +1286,20 @@ await describe('OCPP20VariableManager test suite', async () => { }) }) + await it('Should reject DataSigned in TxStopPoint list value', () => { + const manager = OCPP20VariableManager.getInstance() + const res = manager.setVariables(mockChargingStation, [ + { + attributeValue: 'Authorized,EVConnected,DataSigned', // DataSigned invalid for stop point enumeration + component: { name: OCPP20ComponentName.TxCtrlr }, + variable: { name: OCPP20RequiredVariableName.TxStopPoint }, + }, + ])[0] + expect(res.attributeStatus).toBe(SetVariableStatusEnumType.Rejected) + expect(res.attributeStatusInfo?.reasonCode).toBe(ReasonCodeEnumType.InvalidValue) + expect(res.attributeStatusInfo?.additionalInfo).toContain('Member not in enumeration') + }) + await describe('Unsupported MinSet/MaxSet attribute tests', async () => { const manager = OCPP20VariableManager.getInstance() const station = createChargingStation({ -- 2.53.0