From: Rishabh Vaish Date: Sun, 5 Apr 2026 15:08:24 +0000 (-0700) Subject: fix(ocpp): check connector availability in RemoteStartTransaction auto-selection... X-Git-Tag: ocpp-server@v4.3.1~2 X-Git-Url: https://git.piment-noir.org/?a=commitdiff_plain;h=2249b13016a22022a2e0b0838d7ba01fa53ecf7c;p=e-mobility-charging-stations-simulator.git fix(ocpp): check connector availability in RemoteStartTransaction auto-selection (#1774) * fix(ocpp): check connector availability in RemoteStartTransaction auto-selection The OCPP 1.6 RemoteStartTransaction handler's connector auto-selection (when connectorId is omitted) only checked transactionStarted and reservation status but not administrative availability. This meant an Inoperative connector could be selected, causing the request to be rejected even when other Operative connectors were free. Added isConnectorAvailable() check to the auto-selection loop, matching the behavior already present in the OCPP 2.0 selectAvailableEvse(). * [autofix.ci] apply automated fixes * Update tests/charging-station/ocpp/1.6/OCPP16IncomingRequestService-RemoteStartTransaction.test.ts * Apply suggestion from @jerome-benoit --------- Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> Co-authored-by: Jérôme Benoit --- diff --git a/src/charging-station/ocpp/1.6/OCPP16IncomingRequestService.ts b/src/charging-station/ocpp/1.6/OCPP16IncomingRequestService.ts index e3f16aa7..3718e774 100644 --- a/src/charging-station/ocpp/1.6/OCPP16IncomingRequestService.ts +++ b/src/charging-station/ocpp/1.6/OCPP16IncomingRequestService.ts @@ -1228,6 +1228,7 @@ export class OCPP16IncomingRequestService extends OCPPIncomingRequestService { connectorId++ ) { if ( + chargingStation.isConnectorAvailable(connectorId) && chargingStation.getConnectorStatus(connectorId)?.transactionStarted === false && !OCPP16ServiceUtils.hasReservation(chargingStation, connectorId, commandPayload.idTag) ) { diff --git a/tests/charging-station/ocpp/1.6/OCPP16IncomingRequestService-RemoteStartTransaction.test.ts b/tests/charging-station/ocpp/1.6/OCPP16IncomingRequestService-RemoteStartTransaction.test.ts index 40dd71d6..bcf40e75 100644 --- a/tests/charging-station/ocpp/1.6/OCPP16IncomingRequestService-RemoteStartTransaction.test.ts +++ b/tests/charging-station/ocpp/1.6/OCPP16IncomingRequestService-RemoteStartTransaction.test.ts @@ -155,6 +155,57 @@ await describe('OCPP16IncomingRequestService — RemoteStartTransaction', async assert.strictEqual(response.status, GenericStatus.Rejected) }) + // @spec §5.11 — Auto-select skips Inoperative connectors + await it('should skip inoperative connectors during auto-selection without connectorId', async () => { + // Arrange + const { station, testableService } = testContext + + // Set connector 1 to Inoperative + const connector1Status = station.getConnectorStatus(1) + if (connector1Status != null) { + connector1Status.availability = AvailabilityType.Inoperative + } + + const request: RemoteStartTransactionRequest = { + idTag: TEST_ID_TAG, + } + + // Act + const response = await testableService.handleRequestRemoteStartTransaction(station, request) + + // Assert — should select connector 2 (which is Operative) and accept + assert.strictEqual(response.status, GenericStatus.Accepted) + assert.strictEqual( + request.connectorId, + 2, + 'should auto-select connector 2 since connector 1 is Inoperative' + ) + }) + + // @spec §5.11 — All connectors Inoperative, no connectorId specified + await it('should reject remote start transaction when all connectors are inoperative and no connectorId specified', async () => { + // Arrange + const { station, testableService } = testContext + + // Set all connectors to Inoperative + for (let connectorId = 1; connectorId <= station.getNumberOfConnectors(); connectorId++) { + const connectorStatus = station.getConnectorStatus(connectorId) + if (connectorStatus != null) { + connectorStatus.availability = AvailabilityType.Inoperative + } + } + + const request: RemoteStartTransactionRequest = { + idTag: TEST_ID_TAG, + } + + // Act + const response = await testableService.handleRequestRemoteStartTransaction(station, request) + + // Assert + assert.strictEqual(response.status, GenericStatus.Rejected) + }) + // @spec §5.11 — Non-existing connector await it('should reject remote start transaction with non-existing connectorId', async () => { // Arrange