X-Git-Url: https://git.piment-noir.org/?a=blobdiff_plain;ds=sidebyside;f=src%2Fcharging-station%2FChargingStation.ts;h=6870c1f79f2802fec10f002bff3a2fe560090a21;hb=84d4e562327afa2613b07540de63fe39ed838d8c;hp=cdf87cddc903cb173abd3492dfacf1bfdf8057db;hpb=5b0e583fa396c09bd7bcfce6acf6d69c96ef0610;p=e-mobility-charging-stations-simulator.git diff --git a/src/charging-station/ChargingStation.ts b/src/charging-station/ChargingStation.ts index cdf87cdd..6870c1f7 100644 --- a/src/charging-station/ChargingStation.ts +++ b/src/charging-station/ChargingStation.ts @@ -3,7 +3,7 @@ import { AvailabilityType, BootNotificationRequest, ChangeAvailabilityRequest, C import { BootNotificationResponse, ChangeAvailabilityResponse, ChangeConfigurationResponse, DefaultResponse, GetConfigurationResponse, HeartbeatResponse, RegistrationStatus, SetChargingProfileResponse, StatusNotificationResponse, UnlockConnectorResponse } from '../types/ocpp/1.6/RequestResponses'; import { ChargingProfile, ChargingProfilePurposeType } from '../types/ocpp/1.6/ChargingProfile'; import ChargingStationConfiguration, { ConfigurationKey } from '../types/ChargingStationConfiguration'; -import ChargingStationTemplate, { PowerOutType } from '../types/ChargingStationTemplate'; +import ChargingStationTemplate, { PowerOutType, VoltageOut } from '../types/ChargingStationTemplate'; import Connectors, { Connector } from '../types/Connectors'; import { MeterValue, MeterValueLocation, MeterValueMeasurand, MeterValuePhase, MeterValueUnit, MeterValuesRequest, MeterValuesResponse, SampledValue } from '../types/ocpp/1.6/MeterValues'; import { PerformanceObserver, performance } from 'perf_hooks'; @@ -304,6 +304,10 @@ export default class ChargingStation { return this.getConnector(id).availability === AvailabilityType.OPERATIVE; } + _isChargingStationAvailable(): boolean { + return this.getConnector(0).availability === AvailabilityType.OPERATIVE; + } + _getTemplateMaxNumberOfConnectors(): number { return Object.keys(this._stationInfo.Connectors).length; } @@ -331,10 +335,10 @@ export default class ChargingStation { let defaultVoltageOut: number; switch (this._getPowerOutType()) { case PowerOutType.AC: - defaultVoltageOut = 230; + defaultVoltageOut = VoltageOut.VOLTAGE_230; break; case PowerOutType.DC: - defaultVoltageOut = 400; + defaultVoltageOut = VoltageOut.VOLTAGE_400; break; default: logger.error(errMsg); @@ -576,7 +580,7 @@ export default class ChargingStation { } }, interval); } else { - logger.error(`${this._logPrefix()} Charging station MeterValueSampleInterval configuration set to ${Utils.milliSecondsToHHMMSS(interval)}, not sending MeterValues`); + logger.error(`${this._logPrefix()} Charging station ${StandardParametersKey.MeterValueSampleInterval} configuration set to ${Utils.milliSecondsToHHMMSS(interval)}, not sending MeterValues`); } } @@ -661,7 +665,7 @@ export default class ChargingStation { this._bootNotificationResponse = await this.sendBootNotification(); if (!this._isRegistered()) { registrationRetryCount++; - await Utils.sleep(this._bootNotificationResponse.interval * 1000); + await Utils.sleep(this._bootNotificationResponse?.interval ? this._bootNotificationResponse.interval * 1000 : Constants.OCPP_DEFAULT_BOOT_NOTIFICATION_INTERVAL); } } while (!this._isRegistered() && (registrationRetryCount <= this._getRegistrationMaxRetries() || this._getRegistrationMaxRetries() === -1)); } @@ -714,7 +718,7 @@ export default class ChargingStation { } async onMessage(messageEvent: MessageEvent): Promise { - let [messageType, messageId, commandName, commandPayload, errorDetails]: IncomingRequest = [0, '', '' as IncomingRequestCommand, '', {}]; + let [messageType, messageId, commandName, commandPayload, errorDetails]: IncomingRequest = [0, '', '' as IncomingRequestCommand, {}, {}]; let responseCallback: (payload?: Record | string, requestPayload?: Record) => void; let rejectCallback: (error: OCPPError) => void; let requestPayload: Record; @@ -746,7 +750,7 @@ export default class ChargingStation { throw new Error(`Response request for unknown message id ${messageId}`); } delete this._requests[messageId]; - responseCallback(commandName.toString(), requestPayload); + responseCallback(commandName, requestPayload); break; // Error Message case MessageType.CALL_ERROR_MESSAGE: @@ -874,7 +878,7 @@ export default class ChargingStation { } // Yes: Send Message this._wsConnection.send(messageToSend); - } else { + } else if (commandName !== RequestCommand.BOOT_NOTIFICATION) { let dups = false; // Handle dups in buffer for (const message of this._messageQueue) { @@ -901,7 +905,7 @@ export default class ChargingStation { } // Function that will receive the request's response - async function responseCallback(payload, requestPayload): Promise { + async function responseCallback(payload: Record | string, requestPayload: Record): Promise { if (self.getEnableStatistics()) { self._statistics.addMessage(commandName, messageType); } @@ -925,7 +929,7 @@ export default class ChargingStation { }); } - async handleResponse(commandName: RequestCommand, payload: Record, requestPayload: Record): Promise { + async handleResponse(commandName: RequestCommand, payload: Record | string, requestPayload: Record): Promise { const responseCallbackFn = 'handleResponse' + commandName; if (typeof this[responseCallbackFn] === 'function') { await this[responseCallbackFn](payload, requestPayload); @@ -1013,7 +1017,11 @@ export default class ChargingStation { return; } if (payload.idTagInfo?.status === AuthorizationStatus.ACCEPTED) { - await this.sendStatusNotification(transactionConnectorId, ChargePointStatus.AVAILABLE); + if (!this._isChargingStationAvailable() || !this._isConnectorAvailable(transactionConnectorId)) { + await this.sendStatusNotification(transactionConnectorId, ChargePointStatus.UNAVAILABLE); + } else { + await this.sendStatusNotification(transactionConnectorId, ChargePointStatus.AVAILABLE); + } if (this._stationInfo.powerSharedByConnectors) { this._stationInfo.powerDivider--; } @@ -1036,7 +1044,7 @@ export default class ChargingStation { logger.debug(this._logPrefix() + ' Heartbeat response received: %j to Heartbeat request: %j', payload, requestPayload); } - async handleRequest(messageId: string, commandName: IncomingRequestCommand, commandPayload: Record | string): Promise { + async handleRequest(messageId: string, commandName: IncomingRequestCommand, commandPayload: Record): Promise { let response; // Call if (typeof this['handleRequest' + commandName] === 'function') { @@ -1230,7 +1238,6 @@ export default class ChargingStation { return Constants.OCPP_CHARGING_PROFILE_RESPONSE_ACCEPTED; } - // FIXME: Handle properly the transaction started case handleRequestChangeAvailability(commandPayload: ChangeAvailabilityRequest): ChangeAvailabilityResponse { const connectorId: number = commandPayload.connectorId; if (!this.getConnector(connectorId)) { @@ -1245,13 +1252,12 @@ export default class ChargingStation { response = Constants.OCPP_AVAILABILITY_RESPONSE_SCHEDULED; } this.getConnector(Utils.convertToInt(connector)).availability = commandPayload.type; - void this.sendStatusNotification(Utils.convertToInt(connector), chargePointStatus); + response === Constants.OCPP_AVAILABILITY_RESPONSE_ACCEPTED && this.sendStatusNotification(Utils.convertToInt(connector), chargePointStatus); } return response; } else if (connectorId > 0 && (this.getConnector(0).availability === AvailabilityType.OPERATIVE || (this.getConnector(0).availability === AvailabilityType.INOPERATIVE && commandPayload.type === AvailabilityType.INOPERATIVE))) { if (this.getConnector(connectorId)?.transactionStarted) { this.getConnector(connectorId).availability = commandPayload.type; - void this.sendStatusNotification(connectorId, chargePointStatus); return Constants.OCPP_AVAILABILITY_RESPONSE_SCHEDULED; } this.getConnector(connectorId).availability = commandPayload.type; @@ -1263,23 +1269,27 @@ export default class ChargingStation { async handleRequestRemoteStartTransaction(commandPayload: RemoteStartTransactionRequest): Promise { const transactionConnectorID: number = commandPayload.connectorId ? commandPayload.connectorId : 1; - if (this._getAuthorizeRemoteTxRequests() && this._getLocalAuthListEnabled() && this.hasAuthorizedTags()) { - // Check if authorized - if (this._authorizedTags.find((value) => value === commandPayload.idTag)) { - await this.sendStatusNotification(transactionConnectorID, ChargePointStatus.PREPARING); - // Authorization successful start transaction - await this.sendStartTransaction(transactionConnectorID, commandPayload.idTag); - logger.debug(this._logPrefix() + ' Transaction remotely STARTED on ' + this._stationInfo.name + '#' + transactionConnectorID.toString() + ' for idTag ' + commandPayload.idTag); - return Constants.OCPP_RESPONSE_ACCEPTED; + if (this._isChargingStationAvailable() && this._isConnectorAvailable(transactionConnectorID)) { + if (this._getAuthorizeRemoteTxRequests() && this._getLocalAuthListEnabled() && this.hasAuthorizedTags()) { + // Check if authorized + if (this._authorizedTags.find((value) => value === commandPayload.idTag)) { + await this.sendStatusNotification(transactionConnectorID, ChargePointStatus.PREPARING); + // Authorization successful start transaction + await this.sendStartTransaction(transactionConnectorID, commandPayload.idTag); + logger.debug(this._logPrefix() + ' Transaction remotely STARTED on ' + this._stationInfo.name + '#' + transactionConnectorID.toString() + ' for idTag ' + commandPayload.idTag); + return Constants.OCPP_RESPONSE_ACCEPTED; + } + logger.error(this._logPrefix() + ' Remote starting transaction REJECTED on connector Id ' + transactionConnectorID.toString() + ', idTag ' + commandPayload.idTag); + return Constants.OCPP_RESPONSE_REJECTED; } - logger.error(this._logPrefix() + ' Remote starting transaction REJECTED, idTag ' + commandPayload.idTag); - return Constants.OCPP_RESPONSE_REJECTED; + await this.sendStatusNotification(transactionConnectorID, ChargePointStatus.PREPARING); + // No local authorization check required => start transaction + await this.sendStartTransaction(transactionConnectorID, commandPayload.idTag); + logger.debug(this._logPrefix() + ' Transaction remotely STARTED on ' + this._stationInfo.name + '#' + transactionConnectorID.toString() + ' for idTag ' + commandPayload.idTag); + return Constants.OCPP_RESPONSE_ACCEPTED; } - await this.sendStatusNotification(transactionConnectorID, ChargePointStatus.PREPARING); - // No local authorization check required => start transaction - await this.sendStartTransaction(transactionConnectorID, commandPayload.idTag); - logger.debug(this._logPrefix() + ' Transaction remotely STARTED on ' + this._stationInfo.name + '#' + transactionConnectorID.toString() + ' for idTag ' + commandPayload.idTag); - return Constants.OCPP_RESPONSE_ACCEPTED; + logger.error(this._logPrefix() + ' Remote starting transaction REJECTED on unavailable connector Id ' + transactionConnectorID.toString() + ', idTag ' + commandPayload.idTag); + return Constants.OCPP_RESPONSE_REJECTED; } async handleRequestRemoteStopTransaction(commandPayload: RemoteStopTransactionRequest): Promise {