From 4ecff7ce6e87af51f1ff04e95641aee2270fbdb0 Mon Sep 17 00:00:00 2001 From: =?utf8?q?J=C3=A9r=C3=B4me=20Benoit?= Date: Mon, 17 Apr 2023 23:48:42 +0200 Subject: [PATCH] feat: check status notification transition in OCPP 1.6 stack MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Signed-off-by: Jérôme Benoit --- .../ocpp/1.6/OCPP16Constants.ts | 116 ++++++++++++++++++ .../ocpp/1.6/OCPP16IncomingRequestService.ts | 102 +++++---------- .../ocpp/1.6/OCPP16ResponseService.ts | 57 +++------ .../ocpp/1.6/OCPP16ServiceUtils.ts | 55 ++++++++- src/charging-station/ocpp/OCPPConstants.ts | 2 +- src/charging-station/ocpp/internal.ts | 1 + src/types/ocpp/1.6/ChargePointStatus.ts | 1 - 7 files changed, 224 insertions(+), 110 deletions(-) create mode 100644 src/charging-station/ocpp/1.6/OCPP16Constants.ts diff --git a/src/charging-station/ocpp/1.6/OCPP16Constants.ts b/src/charging-station/ocpp/1.6/OCPP16Constants.ts new file mode 100644 index 00000000..b0fb1ef8 --- /dev/null +++ b/src/charging-station/ocpp/1.6/OCPP16Constants.ts @@ -0,0 +1,116 @@ +import { OCPP16ChargePointStatus } from '../../../types'; +import { OCPPConstants } from '../internal'; + +export class OCPP16Constants extends OCPPConstants { + static readonly OCPP16ChargePointStatusChargingStationTransition = new Set< + [OCPP16ChargePointStatus | undefined, OCPP16ChargePointStatus | undefined] + >([ + [undefined, OCPP16ChargePointStatus.Available], + // [OCPP16ChargePointStatus.Available, OCPP16ChargePointStatus.Available], + [OCPP16ChargePointStatus.Available, OCPP16ChargePointStatus.Unavailable], + [OCPP16ChargePointStatus.Available, OCPP16ChargePointStatus.Faulted], + [undefined, OCPP16ChargePointStatus.Unavailable], + [OCPP16ChargePointStatus.Unavailable, OCPP16ChargePointStatus.Available], + // [OCPP16ChargePointStatus.Unavailable, OCPP16ChargePointStatus.Unavailable], + [OCPP16ChargePointStatus.Unavailable, OCPP16ChargePointStatus.Faulted], + [undefined, OCPP16ChargePointStatus.Faulted], + [OCPP16ChargePointStatus.Faulted, OCPP16ChargePointStatus.Available], + [OCPP16ChargePointStatus.Faulted, OCPP16ChargePointStatus.Unavailable], + // [OCPP16ChargePointStatus.Faulted, OCPP16ChargePointStatus.Faulted], + ]); + + static readonly OCPP16ChargePointStatusConnectorTransition = new Set< + [OCPP16ChargePointStatus | undefined, OCPP16ChargePointStatus | undefined] + >([ + [undefined, OCPP16ChargePointStatus.Available], + // [OCPP16ChargePointStatus.Available, OCPP16ChargePointStatus.Available], + [OCPP16ChargePointStatus.Available, OCPP16ChargePointStatus.Preparing], + [OCPP16ChargePointStatus.Available, OCPP16ChargePointStatus.Charging], + [OCPP16ChargePointStatus.Available, OCPP16ChargePointStatus.SuspendedEV], + [OCPP16ChargePointStatus.Available, OCPP16ChargePointStatus.SuspendedEVSE], + // [OCPP16ChargePointStatus.Available, OCPP16ChargePointStatus.Finishing], + [OCPP16ChargePointStatus.Available, OCPP16ChargePointStatus.Reserved], + [OCPP16ChargePointStatus.Available, OCPP16ChargePointStatus.Unavailable], + [OCPP16ChargePointStatus.Available, OCPP16ChargePointStatus.Faulted], + // [undefined, OCPP16ChargePointStatus.Preparing], + [OCPP16ChargePointStatus.Preparing, OCPP16ChargePointStatus.Available], + // [OCPP16ChargePointStatus.Preparing, OCPP16ChargePointStatus.Preparing], + [OCPP16ChargePointStatus.Preparing, OCPP16ChargePointStatus.Charging], + [OCPP16ChargePointStatus.Preparing, OCPP16ChargePointStatus.SuspendedEV], + [OCPP16ChargePointStatus.Preparing, OCPP16ChargePointStatus.SuspendedEVSE], + [OCPP16ChargePointStatus.Preparing, OCPP16ChargePointStatus.Finishing], + // [OCPP16ChargePointStatus.Preparing, OCPP16ChargePointStatus.Reserved], + // [OCPP16ChargePointStatus.Preparing, OCPP16ChargePointStatus.Unavailable], + [OCPP16ChargePointStatus.Preparing, OCPP16ChargePointStatus.Faulted], + // [undefined, OCPP16ChargePointStatus.Charging], + [OCPP16ChargePointStatus.Charging, OCPP16ChargePointStatus.Available], + // [OCPP16ChargePointStatus.Charging, OCPP16ChargePointStatus.Preparing], + // [OCPP16ChargePointStatus.Charging, OCPP16ChargePointStatus.Charging], + [OCPP16ChargePointStatus.Charging, OCPP16ChargePointStatus.SuspendedEV], + [OCPP16ChargePointStatus.Charging, OCPP16ChargePointStatus.SuspendedEVSE], + [OCPP16ChargePointStatus.Charging, OCPP16ChargePointStatus.Finishing], + // [OCPP16ChargePointStatus.Charging, OCPP16ChargePointStatus.Reserved], + [OCPP16ChargePointStatus.Charging, OCPP16ChargePointStatus.Unavailable], + [OCPP16ChargePointStatus.Charging, OCPP16ChargePointStatus.Faulted], + // [undefined, OCPP16ChargePointStatus.SuspendedEV], + [OCPP16ChargePointStatus.SuspendedEV, OCPP16ChargePointStatus.Available], + // [OCPP16ChargePointStatus.SuspendedEV, OCPP16ChargePointStatus.Preparing], + [OCPP16ChargePointStatus.SuspendedEV, OCPP16ChargePointStatus.Charging], + // [OCPP16ChargePointStatus.SuspendedEV, OCPP16ChargePointStatus.SuspendedEV], + [OCPP16ChargePointStatus.SuspendedEV, OCPP16ChargePointStatus.SuspendedEVSE], + [OCPP16ChargePointStatus.SuspendedEV, OCPP16ChargePointStatus.Finishing], + // [OCPP16ChargePointStatus.SuspendedEV, OCPP16ChargePointStatus.Reserved], + [OCPP16ChargePointStatus.SuspendedEV, OCPP16ChargePointStatus.Unavailable], + [OCPP16ChargePointStatus.SuspendedEV, OCPP16ChargePointStatus.Faulted], + // [undefined, OCPP16ChargePointStatus.SuspendedEVSE], + [OCPP16ChargePointStatus.SuspendedEVSE, OCPP16ChargePointStatus.Available], + // [OCPP16ChargePointStatus.SuspendedEVSE, OCPP16ChargePointStatus.Preparing], + [OCPP16ChargePointStatus.SuspendedEVSE, OCPP16ChargePointStatus.Charging], + [OCPP16ChargePointStatus.SuspendedEVSE, OCPP16ChargePointStatus.SuspendedEV], + // [OCPP16ChargePointStatus.SuspendedEVSE, OCPP16ChargePointStatus.SuspendedEVSE], + [OCPP16ChargePointStatus.SuspendedEVSE, OCPP16ChargePointStatus.Finishing], + // [OCPP16ChargePointStatus.SuspendedEVSE, OCPP16ChargePointStatus.Reserved], + [OCPP16ChargePointStatus.SuspendedEVSE, OCPP16ChargePointStatus.Unavailable], + [OCPP16ChargePointStatus.SuspendedEVSE, OCPP16ChargePointStatus.Faulted], + // [undefined, OCPP16ChargePointStatus.Finishing], + [OCPP16ChargePointStatus.Finishing, OCPP16ChargePointStatus.Available], + [OCPP16ChargePointStatus.Finishing, OCPP16ChargePointStatus.Preparing], + // [OCPP16ChargePointStatus.Finishing, OCPP16ChargePointStatus.Charging], + // [OCPP16ChargePointStatus.Finishing, OCPP16ChargePointStatus.SuspendedEV], + // [OCPP16ChargePointStatus.Finishing, OCPP16ChargePointStatus.SuspendedEVSE], + // [OCPP16ChargePointStatus.Finishing, OCPP16ChargePointStatus.Finishing], + // [OCPP16ChargePointStatus.Finishing, OCPP16ChargePointStatus.Reserved], + [OCPP16ChargePointStatus.Finishing, OCPP16ChargePointStatus.Unavailable], + [OCPP16ChargePointStatus.Finishing, OCPP16ChargePointStatus.Faulted], + // [undefined, OCPP16ChargePointStatus.Reserved], + [OCPP16ChargePointStatus.Reserved, OCPP16ChargePointStatus.Available], + [OCPP16ChargePointStatus.Reserved, OCPP16ChargePointStatus.Preparing], + // [OCPP16ChargePointStatus.Reserved, OCPP16ChargePointStatus.Charging], + // [OCPP16ChargePointStatus.Reserved, OCPP16ChargePointStatus.SuspendedEV], + // [OCPP16ChargePointStatus.Reserved, OCPP16ChargePointStatus.SuspendedEVSE], + // [OCPP16ChargePointStatus.Reserved, OCPP16ChargePointStatus.Finishing], + // [OCPP16ChargePointStatus.Reserved, OCPP16ChargePointStatus.Reserved], + [OCPP16ChargePointStatus.Reserved, OCPP16ChargePointStatus.Unavailable], + [OCPP16ChargePointStatus.Reserved, OCPP16ChargePointStatus.Faulted], + [undefined, OCPP16ChargePointStatus.Unavailable], + [OCPP16ChargePointStatus.Unavailable, OCPP16ChargePointStatus.Available], + [OCPP16ChargePointStatus.Unavailable, OCPP16ChargePointStatus.Preparing], + [OCPP16ChargePointStatus.Unavailable, OCPP16ChargePointStatus.Charging], + [OCPP16ChargePointStatus.Unavailable, OCPP16ChargePointStatus.SuspendedEV], + [OCPP16ChargePointStatus.Unavailable, OCPP16ChargePointStatus.SuspendedEVSE], + // [OCPP16ChargePointStatus.Unavailable, OCPP16ChargePointStatus.Finishing], + // [OCPP16ChargePointStatus.Unavailable, OCPP16ChargePointStatus.Reserved], + // [OCPP16ChargePointStatus.Unavailable, OCPP16ChargePointStatus.Unavailable], + [OCPP16ChargePointStatus.Unavailable, OCPP16ChargePointStatus.Faulted], + [undefined, OCPP16ChargePointStatus.Faulted], + [OCPP16ChargePointStatus.Faulted, OCPP16ChargePointStatus.Available], + [OCPP16ChargePointStatus.Faulted, OCPP16ChargePointStatus.Preparing], + [OCPP16ChargePointStatus.Faulted, OCPP16ChargePointStatus.Charging], + [OCPP16ChargePointStatus.Faulted, OCPP16ChargePointStatus.SuspendedEV], + [OCPP16ChargePointStatus.Faulted, OCPP16ChargePointStatus.SuspendedEVSE], + [OCPP16ChargePointStatus.Faulted, OCPP16ChargePointStatus.Finishing], + [OCPP16ChargePointStatus.Faulted, OCPP16ChargePointStatus.Reserved], + [OCPP16ChargePointStatus.Faulted, OCPP16ChargePointStatus.Unavailable], + // [OCPP16ChargePointStatus.Faulted, OCPP16ChargePointStatus.Faulted], + ]); +} diff --git a/src/charging-station/ocpp/1.6/OCPP16IncomingRequestService.ts b/src/charging-station/ocpp/1.6/OCPP16IncomingRequestService.ts index a3aced78..49ed8c92 100644 --- a/src/charging-station/ocpp/1.6/OCPP16IncomingRequestService.ts +++ b/src/charging-station/ocpp/1.6/OCPP16IncomingRequestService.ts @@ -416,15 +416,11 @@ export class OCPP16IncomingRequestService extends OCPPIncomingRequestService { } return OCPPConstants.OCPP_RESPONSE_UNLOCK_FAILED; } - await chargingStation.ocppRequestService.requestHandler< - OCPP16StatusNotificationRequest, - OCPP16StatusNotificationResponse - >(chargingStation, OCPP16RequestCommand.STATUS_NOTIFICATION, { + await OCPP16ServiceUtils.sendAndSetConnectorStatus( + chargingStation, connectorId, - status: OCPP16ChargePointStatus.Available, - errorCode: OCPP16ChargePointErrorCode.NO_ERROR, - }); - chargingStation.getConnectorStatus(connectorId).status = OCPP16ChargePointStatus.Available; + OCPP16ChargePointStatus.Available + ); return OCPPConstants.OCPP_RESPONSE_UNLOCKED; } @@ -744,15 +740,11 @@ export class OCPP16IncomingRequestService extends OCPPIncomingRequestService { } chargingStation.getConnectorStatus(id).availability = commandPayload.type; if (response === OCPPConstants.OCPP_AVAILABILITY_RESPONSE_ACCEPTED) { - await chargingStation.ocppRequestService.requestHandler< - OCPP16StatusNotificationRequest, - OCPP16StatusNotificationResponse - >(chargingStation, OCPP16RequestCommand.STATUS_NOTIFICATION, { - connectorId: id, - status: chargePointStatus, - errorCode: OCPP16ChargePointErrorCode.NO_ERROR, - }); - chargingStation.getConnectorStatus(id).status = chargePointStatus; + await OCPP16ServiceUtils.sendAndSetConnectorStatus( + chargingStation, + id, + chargePointStatus + ); } } return response; @@ -767,15 +759,11 @@ export class OCPP16IncomingRequestService extends OCPPIncomingRequestService { return OCPPConstants.OCPP_AVAILABILITY_RESPONSE_SCHEDULED; } chargingStation.getConnectorStatus(connectorId).availability = commandPayload.type; - await chargingStation.ocppRequestService.requestHandler< - OCPP16StatusNotificationRequest, - OCPP16StatusNotificationResponse - >(chargingStation, OCPP16RequestCommand.STATUS_NOTIFICATION, { + await OCPP16ServiceUtils.sendAndSetConnectorStatus( + chargingStation, connectorId, - status: chargePointStatus, - errorCode: OCPP16ChargePointErrorCode.NO_ERROR, - }); - chargingStation.getConnectorStatus(connectorId).status = chargePointStatus; + chargePointStatus + ); return OCPPConstants.OCPP_AVAILABILITY_RESPONSE_ACCEPTED; } return OCPPConstants.OCPP_AVAILABILITY_RESPONSE_REJECTED; @@ -790,16 +778,12 @@ export class OCPP16IncomingRequestService extends OCPPIncomingRequestService { const remoteStartTransactionLogMsg = `${chargingStation.logPrefix()} Transaction remotely STARTED on ${ chargingStation.stationInfo.chargingStationId }#${transactionConnectorId.toString()} for idTag '${commandPayload.idTag}'`; - await chargingStation.ocppRequestService.requestHandler< - OCPP16StatusNotificationRequest, - OCPP16StatusNotificationResponse - >(chargingStation, OCPP16RequestCommand.STATUS_NOTIFICATION, { - connectorId: transactionConnectorId, - status: OCPP16ChargePointStatus.Preparing, - errorCode: OCPP16ChargePointErrorCode.NO_ERROR, - }); + await OCPP16ServiceUtils.sendAndSetConnectorStatus( + chargingStation, + transactionConnectorId, + OCPP16ChargePointStatus.Preparing + ); const connectorStatus = chargingStation.getConnectorStatus(transactionConnectorId); - connectorStatus.status = OCPP16ChargePointStatus.Preparing; if ( chargingStation.isChargingStationAvailable() === true && chargingStation.isConnectorAvailable(transactionConnectorId) === true @@ -934,15 +918,11 @@ export class OCPP16IncomingRequestService extends OCPPIncomingRequestService { if ( chargingStation.getConnectorStatus(connectorId)?.status !== OCPP16ChargePointStatus.Available ) { - await chargingStation.ocppRequestService.requestHandler< - OCPP16StatusNotificationRequest, - OCPP16StatusNotificationResponse - >(chargingStation, OCPP16RequestCommand.STATUS_NOTIFICATION, { + await OCPP16ServiceUtils.sendAndSetConnectorStatus( + chargingStation, connectorId, - status: OCPP16ChargePointStatus.Available, - errorCode: OCPP16ChargePointErrorCode.NO_ERROR, - }); - chargingStation.getConnectorStatus(connectorId).status = OCPP16ChargePointStatus.Available; + OCPP16ChargePointStatus.Available + ); } logger.warn( `${chargingStation.logPrefix()} Remote starting transaction REJECTED on connector Id ${connectorId.toString()}, idTag '${idTag}', availability '${ @@ -986,15 +966,11 @@ export class OCPP16IncomingRequestService extends OCPPIncomingRequestService { connectorId > 0 && chargingStation.getConnectorStatus(connectorId)?.transactionId === transactionId ) { - await chargingStation.ocppRequestService.requestHandler< - OCPP16StatusNotificationRequest, - OCPP16StatusNotificationResponse - >(chargingStation, OCPP16RequestCommand.STATUS_NOTIFICATION, { + await OCPP16ServiceUtils.sendAndSetConnectorStatus( + chargingStation, connectorId, - status: OCPP16ChargePointStatus.Finishing, - errorCode: OCPP16ChargePointErrorCode.NO_ERROR, - }); - chargingStation.getConnectorStatus(connectorId).status = OCPP16ChargePointStatus.Finishing; + OCPP16ChargePointStatus.Finishing + ); const stopResponse = await chargingStation.stopTransactionOnConnector( connectorId, OCPP16StopTransactionReason.REMOTE @@ -1071,16 +1047,11 @@ export class OCPP16IncomingRequestService extends OCPPIncomingRequestService { connectorId > 0 && chargingStation.getConnectorStatus(connectorId)?.transactionStarted === false ) { - await chargingStation.ocppRequestService.requestHandler< - OCPP16StatusNotificationRequest, - OCPP16StatusNotificationResponse - >(chargingStation, OCPP16RequestCommand.STATUS_NOTIFICATION, { + await OCPP16ServiceUtils.sendAndSetConnectorStatus( + chargingStation, connectorId, - status: OCPP16ChargePointStatus.Unavailable, - errorCode: OCPP16ChargePointErrorCode.NO_ERROR, - }); - chargingStation.getConnectorStatus(connectorId).status = - OCPP16ChargePointStatus.Unavailable; + OCPP16ChargePointStatus.Unavailable + ); } } await chargingStation.ocppRequestService.requestHandler< @@ -1142,16 +1113,11 @@ export class OCPP16IncomingRequestService extends OCPPIncomingRequestService { chargingStation.getConnectorStatus(connectorId)?.status !== OCPP16ChargePointStatus.Unavailable ) { - await chargingStation.ocppRequestService.requestHandler< - OCPP16StatusNotificationRequest, - OCPP16StatusNotificationResponse - >(chargingStation, OCPP16RequestCommand.STATUS_NOTIFICATION, { + await OCPP16ServiceUtils.sendAndSetConnectorStatus( + chargingStation, connectorId, - status: OCPP16ChargePointStatus.Unavailable, - errorCode: OCPP16ChargePointErrorCode.NO_ERROR, - }); - chargingStation.getConnectorStatus(connectorId).status = - OCPP16ChargePointStatus.Unavailable; + OCPP16ChargePointStatus.Unavailable + ); } } transactionsStarted = false; diff --git a/src/charging-station/ocpp/1.6/OCPP16ResponseService.ts b/src/charging-station/ocpp/1.6/OCPP16ResponseService.ts index 2a86135d..36eecc57 100644 --- a/src/charging-station/ocpp/1.6/OCPP16ResponseService.ts +++ b/src/charging-station/ocpp/1.6/OCPP16ResponseService.ts @@ -17,9 +17,7 @@ import { OCPP16AuthorizationStatus, type OCPP16AuthorizeRequest, type OCPP16AuthorizeResponse, - type OCPP16BootNotificationRequest, type OCPP16BootNotificationResponse, - OCPP16ChargePointErrorCode, OCPP16ChargePointStatus, type OCPP16DataTransferResponse, type OCPP16DiagnosticsStatusNotificationResponse, @@ -33,7 +31,6 @@ import { OCPP16StandardParametersKey, type OCPP16StartTransactionRequest, type OCPP16StartTransactionResponse, - type OCPP16StatusNotificationRequest, type OCPP16StatusNotificationResponse, type OCPP16StopTransactionRequest, type OCPP16StopTransactionResponse, @@ -558,15 +555,11 @@ export class OCPP16ResponseService extends OCPPResponseService { transactionId: payload.transactionId, meterValue: [chargingStation.getConnectorStatus(connectorId).transactionBeginMeterValue], })); - await chargingStation.ocppRequestService.requestHandler< - OCPP16StatusNotificationRequest, - OCPP16StatusNotificationResponse - >(chargingStation, OCPP16RequestCommand.STATUS_NOTIFICATION, { + await OCPP16ServiceUtils.sendAndSetConnectorStatus( + chargingStation, connectorId, - status: OCPP16ChargePointStatus.Charging, - errorCode: OCPP16ChargePointErrorCode.NO_ERROR, - }); - chargingStation.getConnectorStatus(connectorId).status = OCPP16ChargePointStatus.Charging; + OCPP16ChargePointStatus.Charging + ); logger.info( `${chargingStation.logPrefix()} Transaction ${payload.transactionId.toString()} STARTED on ${ chargingStation.stationInfo.chargingStationId @@ -604,15 +597,11 @@ export class OCPP16ResponseService extends OCPPResponseService { if ( chargingStation.getConnectorStatus(connectorId)?.status !== OCPP16ChargePointStatus.Available ) { - await chargingStation.ocppRequestService.requestHandler< - OCPP16StatusNotificationRequest, - OCPP16StatusNotificationResponse - >(chargingStation, OCPP16RequestCommand.STATUS_NOTIFICATION, { + await OCPP16ServiceUtils.sendAndSetConnectorStatus( + chargingStation, connectorId, - status: OCPP16ChargePointStatus.Available, - errorCode: OCPP16ChargePointErrorCode.NO_ERROR, - }); - chargingStation.getConnectorStatus(connectorId).status = OCPP16ChargePointStatus.Available; + OCPP16ChargePointStatus.Available + ); } } @@ -651,27 +640,17 @@ export class OCPP16ResponseService extends OCPPResponseService { chargingStation.isChargingStationAvailable() === false || chargingStation.isConnectorAvailable(transactionConnectorId) === false ) { - await chargingStation.ocppRequestService.requestHandler< - OCPP16StatusNotificationRequest, - OCPP16StatusNotificationResponse - >(chargingStation, OCPP16RequestCommand.STATUS_NOTIFICATION, { - connectorId: transactionConnectorId, - status: OCPP16ChargePointStatus.Unavailable, - errorCode: OCPP16ChargePointErrorCode.NO_ERROR, - }); - chargingStation.getConnectorStatus(transactionConnectorId).status = - OCPP16ChargePointStatus.Unavailable; + await OCPP16ServiceUtils.sendAndSetConnectorStatus( + chargingStation, + transactionConnectorId, + OCPP16ChargePointStatus.Unavailable + ); } else { - await chargingStation.ocppRequestService.requestHandler< - OCPP16BootNotificationRequest, - OCPP16BootNotificationResponse - >(chargingStation, OCPP16RequestCommand.STATUS_NOTIFICATION, { - connectorId: transactionConnectorId, - status: OCPP16ChargePointStatus.Available, - errorCode: OCPP16ChargePointErrorCode.NO_ERROR, - }); - chargingStation.getConnectorStatus(transactionConnectorId).status = - OCPP16ChargePointStatus.Available; + await OCPP16ServiceUtils.sendAndSetConnectorStatus( + chargingStation, + transactionConnectorId, + OCPP16ChargePointStatus.Available + ); } if (chargingStation.stationInfo.powerSharedByConnectors) { chargingStation.powerDivider--; diff --git a/src/charging-station/ocpp/1.6/OCPP16ServiceUtils.ts b/src/charging-station/ocpp/1.6/OCPP16ServiceUtils.ts index 932d4515..47c711af 100644 --- a/src/charging-station/ocpp/1.6/OCPP16ServiceUtils.ts +++ b/src/charging-station/ocpp/1.6/OCPP16ServiceUtils.ts @@ -16,6 +16,8 @@ import { MeterValueContext, MeterValueLocation, MeterValueUnit, + OCPP16ChargePointErrorCode, + type OCPP16ChargePointStatus, type OCPP16ChargingProfile, type OCPP16IncomingRequestCommand, type OCPP16MeterValue, @@ -24,13 +26,15 @@ import { OCPP16RequestCommand, type OCPP16SampledValue, OCPP16StandardParametersKey, + type OCPP16StatusNotificationRequest, + type OCPP16StatusNotificationResponse, type OCPP16SupportedFeatureProfiles, OCPPVersion, type SampledValueTemplate, Voltage, } from '../../../types'; import { ACElectricUtils, Constants, DCElectricUtils, Utils, logger } from '../../../utils'; -import { OCPPServiceUtils } from '../internal'; +import { OCPP16Constants, OCPPServiceUtils } from '../internal'; export class OCPP16ServiceUtils extends OCPPServiceUtils { public static checkFeatureProfile( @@ -840,6 +844,55 @@ export class OCPP16ServiceUtils extends OCPPServiceUtils { ); } + public static async sendAndSetConnectorStatus( + chargingStation: ChargingStation, + connectorId: number, + status: OCPP16ChargePointStatus, + errorCode: OCPP16ChargePointErrorCode = OCPP16ChargePointErrorCode.NO_ERROR + ) { + OCPP16ServiceUtils.checkConnectorStatusTransition(chargingStation, connectorId, status); + await chargingStation.ocppRequestService.requestHandler< + OCPP16StatusNotificationRequest, + OCPP16StatusNotificationResponse + >(chargingStation, OCPP16RequestCommand.STATUS_NOTIFICATION, { + connectorId, + status, + errorCode, + }); + chargingStation.getConnectorStatus(connectorId).status = status; + } + + private static checkConnectorStatusTransition( + chargingStation: ChargingStation, + connectorId: number, + status: OCPP16ChargePointStatus + ): void { + if ( + connectorId === 0 && + !OCPP16Constants.OCPP16ChargePointStatusChargingStationTransition.has([ + chargingStation.getConnectorStatus(connectorId).status as OCPP16ChargePointStatus, + status, + ]) + ) { + logger.warn( + `${chargingStation.logPrefix()} Connector ${connectorId} status transition from ${ + chargingStation.getConnectorStatus(connectorId).status + } to ${status} is not allowed` + ); + } else if ( + !OCPP16Constants.OCPP16ChargePointStatusConnectorTransition.has([ + chargingStation.getConnectorStatus(connectorId).status as OCPP16ChargePointStatus, + status, + ]) + ) { + logger.warn( + `${chargingStation.logPrefix()} Connector ${connectorId} status transition from ${ + chargingStation.getConnectorStatus(connectorId).status + } to ${status} is not allowed` + ); + } + } + private static buildSampledValue( sampledValueTemplate: SampledValueTemplate, value: number, diff --git a/src/charging-station/ocpp/OCPPConstants.ts b/src/charging-station/ocpp/OCPPConstants.ts index c8b110e4..2da93455 100644 --- a/src/charging-station/ocpp/OCPPConstants.ts +++ b/src/charging-station/ocpp/OCPPConstants.ts @@ -89,7 +89,7 @@ export class OCPPConstants { status: DataTransferStatus.REJECTED, }); - private constructor() { + protected constructor() { // This is intentional } } diff --git a/src/charging-station/ocpp/internal.ts b/src/charging-station/ocpp/internal.ts index c8755707..c7f0fe72 100644 --- a/src/charging-station/ocpp/internal.ts +++ b/src/charging-station/ocpp/internal.ts @@ -1,3 +1,4 @@ +export * from './1.6/OCPP16Constants'; export * from './1.6/OCPP16IncomingRequestService'; export * from './1.6/OCPP16RequestService'; export * from './1.6/OCPP16ResponseService'; diff --git a/src/types/ocpp/1.6/ChargePointStatus.ts b/src/types/ocpp/1.6/ChargePointStatus.ts index d7a197ae..4cef943e 100644 --- a/src/types/ocpp/1.6/ChargePointStatus.ts +++ b/src/types/ocpp/1.6/ChargePointStatus.ts @@ -2,7 +2,6 @@ export enum OCPP16ChargePointStatus { Available = 'Available', Preparing = 'Preparing', Charging = 'Charging', - Occupied = 'Occupied', SuspendedEVSE = 'SuspendedEVSE', SuspendedEV = 'SuspendedEV', Finishing = 'Finishing', -- 2.34.1