X-Git-Url: https://git.piment-noir.org/?a=blobdiff_plain;f=src%2Fcharging-station%2Focpp%2F1.6%2FOCPP16IncomingRequestService.ts;h=999e1ceafaf9a703d81bcf2890e69eec728e3c0a;hb=411894569d4a0333a4e38e911a178520a69448cd;hp=8b23eddd1e0820c118a8b8242aaa31f413fe7353;hpb=b768993dd4636df8276b0ea47158dd9bdc9a997b;p=e-mobility-charging-stations-simulator.git diff --git a/src/charging-station/ocpp/1.6/OCPP16IncomingRequestService.ts b/src/charging-station/ocpp/1.6/OCPP16IncomingRequestService.ts index 8b23eddd..999e1cea 100644 --- a/src/charging-station/ocpp/1.6/OCPP16IncomingRequestService.ts +++ b/src/charging-station/ocpp/1.6/OCPP16IncomingRequestService.ts @@ -23,6 +23,7 @@ import { type ClearChargingProfileResponse, ErrorType, type GenericResponse, + GenericStatus, type GetConfigurationRequest, type GetConfigurationResponse, type GetDiagnosticsRequest, @@ -40,6 +41,7 @@ import { OCPP16ChargePointStatus, type OCPP16ChargingProfile, OCPP16ChargingProfilePurposeType, + type OCPP16ChargingSchedule, type OCPP16ClearCacheRequest, type OCPP16DataTransferRequest, type OCPP16DataTransferResponse, @@ -51,6 +53,8 @@ import { OCPP16FirmwareStatus, type OCPP16FirmwareStatusNotificationRequest, type OCPP16FirmwareStatusNotificationResponse, + type OCPP16GetCompositeScheduleRequest, + type OCPP16GetCompositeScheduleResponse, type OCPP16HeartbeatRequest, type OCPP16HeartbeatResponse, OCPP16IncomingRequestCommand, @@ -103,6 +107,10 @@ export class OCPP16IncomingRequestService extends OCPPIncomingRequestService { OCPP16IncomingRequestCommand.CHANGE_CONFIGURATION, this.handleRequestChangeConfiguration.bind(this), ], + [ + OCPP16IncomingRequestCommand.GET_COMPOSITE_SCHEDULE, + this.handleRequestGetCompositeSchedule.bind(this), + ], [ OCPP16IncomingRequestCommand.SET_CHARGING_PROFILE, this.handleRequestSetChargingProfile.bind(this), @@ -177,6 +185,14 @@ export class OCPP16IncomingRequestService extends OCPPIncomingRequestService { 'constructor' ), ], + [ + OCPP16IncomingRequestCommand.GET_COMPOSITE_SCHEDULE, + OCPP16ServiceUtils.parseJsonSchemaFile( + '../../../assets/json-schemas/ocpp/1.6/GetCompositeSchedule.json', + moduleName, + 'constructor' + ), + ], [ OCPP16IncomingRequestCommand.SET_CHARGING_PROFILE, OCPP16ServiceUtils.parseJsonSchemaFile( @@ -568,6 +584,56 @@ export class OCPP16IncomingRequestService extends OCPPIncomingRequestService { return OCPPConstants.OCPP_SET_CHARGING_PROFILE_RESPONSE_ACCEPTED; } + private handleRequestGetCompositeSchedule( + chargingStation: ChargingStation, + commandPayload: OCPP16GetCompositeScheduleRequest + ): OCPP16GetCompositeScheduleResponse { + if ( + OCPP16ServiceUtils.checkFeatureProfile( + chargingStation, + OCPP16SupportedFeatureProfiles.SmartCharging, + OCPP16IncomingRequestCommand.CLEAR_CHARGING_PROFILE + ) === false + ) { + return OCPPConstants.OCPP_RESPONSE_REJECTED; + } + if (chargingStation.connectors.has(commandPayload.connectorId) === false) { + logger.error( + `${chargingStation.logPrefix()} Trying to get composite schedule to a non existing connector Id ${ + commandPayload.connectorId + }` + ); + return OCPPConstants.OCPP_RESPONSE_REJECTED; + } + if ( + Utils.isEmptyArray( + chargingStation.getConnectorStatus(commandPayload.connectorId)?.chargingProfiles + ) + ) { + return OCPPConstants.OCPP_RESPONSE_REJECTED; + } + const startDate = new Date(); + const endDate = new Date(startDate.getTime() + commandPayload.duration * 1000); + let compositeSchedule: OCPP16ChargingSchedule; + for (const chargingProfile of chargingStation.getConnectorStatus(commandPayload.connectorId) + .chargingProfiles) { + // FIXME: build the composite schedule including the local power limit, the stack level, the charging rate unit, etc. + if ( + chargingProfile.chargingSchedule?.startSchedule >= startDate && + chargingProfile.chargingSchedule?.startSchedule <= endDate + ) { + compositeSchedule = chargingProfile.chargingSchedule; + break; + } + } + return { + status: GenericStatus.Accepted, + scheduleStart: compositeSchedule?.startSchedule, + connectorId: commandPayload.connectorId, + chargingSchedule: compositeSchedule, + }; + } + private handleRequestClearChargingProfile( chargingStation: ChargingStation, commandPayload: ClearChargingProfileRequest @@ -730,18 +796,19 @@ export class OCPP16IncomingRequestService extends OCPPIncomingRequestService { }); const connectorStatus = chargingStation.getConnectorStatus(transactionConnectorId); connectorStatus.status = OCPP16ChargePointStatus.Preparing; - if (chargingStation.isChargingStationAvailable() === true) { + if ( + chargingStation.isChargingStationAvailable() === true && + chargingStation.isConnectorAvailable(transactionConnectorId) === true + ) { // Check if authorized if (chargingStation.getAuthorizeRemoteTxRequests() === true) { let authorized = false; if ( chargingStation.getLocalAuthListEnabled() === true && - chargingStation.hasAuthorizedTags() === true && + chargingStation.hasIdTags() === true && Utils.isNotEmptyString( - chargingStation.authorizedTagsCache - .getAuthorizedTags( - ChargingStationUtils.getAuthorizationFile(chargingStation.stationInfo) - ) + chargingStation.idTagsCache + .getIdTags(ChargingStationUtils.getIdTagsFile(chargingStation.stationInfo)) ?.find((idTag) => idTag === commandPayload.idTag) ) ) { @@ -969,7 +1036,7 @@ export class OCPP16IncomingRequestService extends OCPPIncomingRequestService { const now = Date.now(); if (retrieveDate?.getTime() <= now) { this.runInAsyncScope( - this.updateFirmware.bind(this) as ( + this.updateFirmwareSimulation.bind(this) as ( this: OCPP16IncomingRequestService, ...args: any[] ) => Promise, @@ -978,18 +1045,23 @@ export class OCPP16IncomingRequestService extends OCPPIncomingRequestService { ).catch(Constants.EMPTY_FUNCTION); } else { setTimeout(() => { - this.updateFirmware(chargingStation).catch(Constants.EMPTY_FUNCTION); + this.updateFirmwareSimulation(chargingStation).catch(Constants.EMPTY_FUNCTION); }, retrieveDate?.getTime() - now); } return OCPPConstants.OCPP_RESPONSE_EMPTY; } - private async updateFirmware( + private async updateFirmwareSimulation( chargingStation: ChargingStation, maxDelay = 30, minDelay = 15 ): Promise { - chargingStation.stopAutomaticTransactionGenerator(); + if ( + ChargingStationUtils.checkChargingStation(chargingStation, chargingStation.logPrefix()) === + false + ) { + return; + } for (const connectorId of chargingStation.connectors.keys()) { if ( connectorId > 0 && @@ -1037,7 +1109,58 @@ export class OCPP16IncomingRequestService extends OCPPIncomingRequestService { status: OCPP16FirmwareStatus.Downloaded, }); chargingStation.stationInfo.firmwareStatus = OCPP16FirmwareStatus.Downloaded; - await Utils.sleep(Utils.getRandomInteger(maxDelay, minDelay) * 1000); + let wasTransactionsStarted = false; + let transactionsStarted: boolean; + do { + let trxCount = 0; + for (const connectorId of chargingStation.connectors.keys()) { + if ( + connectorId > 0 && + chargingStation.getConnectorStatus(connectorId)?.transactionStarted === true + ) { + trxCount++; + } + } + if (trxCount > 0) { + const waitTime = 15 * 1000; + logger.debug( + `${chargingStation.logPrefix()} ${moduleName}.updateFirmwareSimulation: ${trxCount} transaction(s) in progress, waiting ${ + waitTime / 1000 + } seconds before continuing firmware update simulation` + ); + await Utils.sleep(waitTime); + transactionsStarted = true; + wasTransactionsStarted = true; + } else { + for (const connectorId of chargingStation.connectors.keys()) { + if ( + connectorId > 0 && + chargingStation.getConnectorStatus(connectorId)?.status !== + OCPP16ChargePointStatus.Unavailable + ) { + await chargingStation.ocppRequestService.requestHandler< + OCPP16StatusNotificationRequest, + OCPP16StatusNotificationResponse + >(chargingStation, OCPP16RequestCommand.STATUS_NOTIFICATION, { + connectorId, + status: OCPP16ChargePointStatus.Unavailable, + errorCode: OCPP16ChargePointErrorCode.NO_ERROR, + }); + chargingStation.getConnectorStatus(connectorId).status = + OCPP16ChargePointStatus.Unavailable; + } + } + transactionsStarted = false; + } + } while (transactionsStarted); + !wasTransactionsStarted && + (await Utils.sleep(Utils.getRandomInteger(maxDelay, minDelay) * 1000)); + if ( + ChargingStationUtils.checkChargingStation(chargingStation, chargingStation.logPrefix()) === + false + ) { + return; + } await chargingStation.ocppRequestService.requestHandler< OCPP16FirmwareStatusNotificationRequest, OCPP16FirmwareStatusNotificationResponse