-import { AuthorizationStatus, StartTransactionRequest, StartTransactionResponse, StopTransactionReason, StopTransactionRequest, StopTransactionResponse } from '../types/ocpp/1.6/Transaction';
+import { AuthorizationStatus, AuthorizeRequest, AuthorizeResponse, StartTransactionRequest, StartTransactionResponse, StopTransactionReason, StopTransactionRequest, StopTransactionResponse } from '../types/ocpp/1.6/Transaction';
import { AvailabilityType, BootNotificationRequest, ChangeAvailabilityRequest, ChangeConfigurationRequest, GetConfigurationRequest, HeartbeatRequest, IncomingRequestCommand, RemoteStartTransactionRequest, RemoteStopTransactionRequest, RequestCommand, ResetRequest, SetChargingProfileRequest, StatusNotificationRequest, UnlockConnectorRequest } from '../types/ocpp/1.6/Requests';
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';
}
_getStationName(stationTemplate: ChargingStationTemplate): string {
- return stationTemplate.fixedName ? stationTemplate.baseName : stationTemplate.baseName + '-' + ('000000000' + this._index.toString()).substr(('000000000' + this._index.toString()).length - 4);
+ // In case of multiple instances: add instance index to charging station id
+ let instanceIndex = process.env.CF_INSTANCE_INDEX ? process.env.CF_INSTANCE_INDEX : 0;
+ instanceIndex = instanceIndex > 0 ? instanceIndex : '';
+
+ const idSuffix = Configuration.getChargingStationIdSuffix();
+
+ return stationTemplate.fixedName ? stationTemplate.baseName : stationTemplate.baseName + '-' + instanceIndex + ('000000000' + this._index.toString()).substr(('000000000' + this._index.toString()).length - 4) + idSuffix;
}
_buildStationInfo(): ChargingStationInfo {
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;
}
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);
}
_startAuthorizationFileMonitoring(): void {
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
- fs.watchFile(this._getAuthorizationFile(), (current, previous) => {
+ fs.watch(this._getAuthorizationFile()).on("change", e => {
try {
logger.debug(this._logPrefix() + ' Authorization file ' + this._getAuthorizationFile() + ' have changed, reload');
// Initialize _authorizedTags
}
_startStationTemplateFileMonitoring(): void {
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
- fs.watchFile(this._stationTemplateFile, (current, previous) => {
+ fs.watch(this._stationTemplateFile).on("change", e => {
try {
logger.debug(this._logPrefix() + ' Template file ' + this._stationTemplateFile + ' have changed, reload');
// Initialize
this._initialize();
+ // Stop the ATG
if (!this._stationInfo.AutomaticTransactionGenerator.enable &&
this._automaticTransactionGeneration) {
this._automaticTransactionGeneration.stop().catch(() => { });
}
+ // Start the ATG
+ if (this._stationInfo.AutomaticTransactionGenerator.enable) {
+ if (!this._automaticTransactionGeneration) {
+ this._automaticTransactionGeneration = new AutomaticTransactionGenerator(this);
+ }
+ if (this._automaticTransactionGeneration.timeToStop) {
+ this._automaticTransactionGeneration.start();
+ }
+ }
// FIXME?: restart heartbeat and WebSocket ping when their interval values have changed
} catch (error) {
logger.error(this._logPrefix() + ' Charging station template file monitoring error: %j', error);
}
}, 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`);
}
}
}
}
+ async sendAuthorize(idTag?: string): Promise<AuthorizeResponse> {
+ try {
+ const payload: AuthorizeRequest = {
+ ...!Utils.isUndefined(idTag) ? { idTag } : { idTag: Constants.TRANSACTION_DEFAULT_IDTAG },
+ };
+ return await this.sendMessage(Utils.generateUUID(), payload, MessageType.CALL_MESSAGE, RequestCommand.AUTHORIZE) as AuthorizeResponse;
+ } catch (error) {
+ this.handleRequestError(RequestCommand.AUTHORIZE, error);
+ }
+ }
+
async sendStartTransaction(connectorId: number, idTag?: string): Promise<StartTransactionResponse> {
try {
const payload: StartTransactionRequest = {
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--;
}
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)) {
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;
async handleRequestRemoteStartTransaction(commandPayload: RemoteStartTransactionRequest): Promise<DefaultResponse> {
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<DefaultResponse> {