"space-unary-ops": "error",
"spaced-comment": ["error", "always"],
"switch-colon-spacing": "error",
- "arrow-body-style": ["error", "as-needed"],
- "arrow-parens": ["error", "as-needed"],
+ "arrow-parens": ["error", "always"],
"arrow-spacing": "error",
"no-duplicate-imports": "error",
"no-var": "error",
{
"printWidth": 100,
- "arrowParens": "avoid",
"singleQuote": true
}
logger.info(
`${this.logPrefix(connectorId)} transaction ${this.chargingStation
.getConnectorStatus(connectorId)
- .transactionId.toString()} started and will stop in ${Utils.formatDurationMilliSeconds(
+ ?.transactionId?.toString()} started and will stop in ${Utils.formatDurationMilliSeconds(
waitTrxEnd
)}`
);
private setStartConnectorStatus(connectorId: number): void {
this.connectorsStatus.get(connectorId).skippedConsecutiveTransactions = 0;
const previousRunDuration =
- this?.connectorsStatus.get(connectorId)?.startDate &&
- this?.connectorsStatus.get(connectorId)?.lastRunDate
+ this.connectorsStatus.get(connectorId)?.startDate &&
+ this.connectorsStatus.get(connectorId)?.lastRunDate
? this.connectorsStatus.get(connectorId).lastRunDate.getTime() -
this.connectorsStatus.get(connectorId).startDate.getTime()
: 0;
private workerImplementation: WorkerAbstract<ChargingStationWorkerData> | null;
private readonly uiServer!: AbstractUIServer;
private readonly storage!: Storage;
- private numberOfChargingStationTemplates!: number;
+ private numberOfChargingStationTemplates!: number | undefined;
private numberOfChargingStations!: number;
private numberOfStartedChargingStations!: number;
private readonly version: string = version;
await this.workerImplementation?.start();
this.uiServer?.start();
const stationTemplateUrls = Configuration.getStationTemplateUrls();
- this.numberOfChargingStationTemplates = stationTemplateUrls.length;
+ this.numberOfChargingStationTemplates = stationTemplateUrls?.length;
// Start ChargingStation object in worker thread
if (!Utils.isEmptyArray(stationTemplateUrls)) {
for (const stationTemplateUrl of stationTemplateUrls) {
stationTemplateUrl.file
),
};
- await this.workerImplementation.addElement(workerData);
+ await this.workerImplementation?.addElement(workerData);
++this.numberOfChargingStations;
}
public starting: boolean;
public authorizedTagsCache: AuthorizedTagsCache;
public automaticTransactionGenerator!: AutomaticTransactionGenerator;
- public ocppConfiguration!: ChargingStationOcppConfiguration;
- public wsConnection!: WebSocket;
+ public ocppConfiguration!: ChargingStationOcppConfiguration | null;
+ public wsConnection!: WebSocket | null;
public readonly connectors: Map<number, ConnectorStatus>;
public readonly requests: Map<string, CachedRequest>;
public performanceStatistics!: PerformanceStatistics;
private configuredSupervisionUrlIndex!: number;
private wsConnectionRestarted: boolean;
private autoReconnectRetryCount: number;
- private templateFileWatcher!: fs.FSWatcher;
+ private templateFileWatcher!: fs.FSWatcher | undefined;
private readonly sharedLRUCache: SharedLRUCache;
private webSocketPingSetInterval!: NodeJS.Timeout;
private readonly chargingStationWorkerBroadcastChannel: ChargingStationWorkerBroadcastChannel;
? ChargingStationConfigurationUtils.getConfigurationKey(
this,
this.getSupervisionUrlOcppKey()
- ).value
+ )?.value
: this.configuredSupervisionUrl.href
}/${this.stationInfo.chargingStationId}`
);
}
public getCurrentOutType(stationInfo?: ChargingStationInfo): CurrentType {
- return (stationInfo ?? this.stationInfo).currentOutType ?? CurrentType.AC;
+ return (stationInfo ?? this.stationInfo)?.currentOutType ?? CurrentType.AC;
}
public getOcppStrictCompliance(): boolean {
let connectorAmperageLimitationPowerLimit: number;
if (
!Utils.isNullOrUndefined(this.getAmperageLimitation()) &&
- this.getAmperageLimitation() < this.stationInfo.maximumAmperage
+ this.getAmperageLimitation() < this.stationInfo?.maximumAmperage
) {
connectorAmperageLimitationPowerLimit =
(this.getCurrentOutType() === CurrentType.AC
connectorId > 0 &&
this.getConnectorStatus(connectorId)?.transactionId === transactionId
) {
- return this.getConnectorStatus(connectorId).transactionIdTag;
+ return this.getConnectorStatus(connectorId)?.transactionIdTag;
}
}
}
this.heartbeatSetInterval = setInterval(() => {
this.ocppRequestService
.requestHandler<HeartbeatRequest, HeartbeatResponse>(this, RequestCommand.HEARTBEAT)
- .catch(error => {
+ .catch((error) => {
logger.error(
`${this.logPrefix()} Error while sending '${RequestCommand.HEARTBEAT}':`,
error
RequestCommand.METER_VALUES,
{
connectorId,
- transactionId: this.getConnectorStatus(connectorId).transactionId,
+ transactionId: this.getConnectorStatus(connectorId)?.transactionId,
meterValue: [meterValue],
}
)
- .catch(error => {
+ .catch((error) => {
logger.error(
`${this.logPrefix()} Error while sending '${RequestCommand.METER_VALUES}':`,
error
this.performanceStatistics.stop();
}
this.sharedLRUCache.deleteChargingStationConfiguration(this.configurationFileHash);
- this.templateFileWatcher.close();
+ this.templateFileWatcher?.close();
this.sharedLRUCache.deleteChargingStationTemplate(this.stationInfo?.templateHash);
this.bootNotificationResponse = undefined;
this.started = false;
parentPort?.postMessage(MessageChannelUtils.buildUpdatedMessage(this));
}
- public hasFeatureProfile(featureProfile: SupportedFeatureProfiles): boolean {
+ public hasFeatureProfile(featureProfile: SupportedFeatureProfiles): boolean | undefined {
return ChargingStationConfigurationUtils.getConfigurationKey(
this,
StandardParametersKey.SupportedFeatureProfiles
- )?.value.includes(featureProfile);
+ )?.value?.includes(featureProfile);
}
public bufferMessage(message: string): void {
public closeWSConnection(): void {
if (this.isWebSocketConnectionOpened() === true) {
- this.wsConnection.close();
+ this.wsConnection?.close();
this.wsConnection = null;
}
}
connectorId: number,
reason = StopTransactionReason.NONE
): Promise<StopTransactionResponse> {
- const transactionId = this.getConnectorStatus(connectorId).transactionId;
+ const transactionId = this.getConnectorStatus(connectorId)?.transactionId;
if (
this.getBeginEndMeterValues() === true &&
this.getOcppStrictCompliance() === true &&
private flushMessageBuffer(): void {
if (this.messageBuffer.size > 0) {
- this.messageBuffer.forEach(message => {
+ this.messageBuffer.forEach((message) => {
let beginId: string;
let commandName: RequestCommand;
const [messageType] = JSON.parse(message) as OutgoingRequest | Response | ErrorResponse;
[, , commandName] = JSON.parse(message) as OutgoingRequest;
beginId = PerformanceStatistics.beginMeasure(commandName);
}
- this.wsConnection.send(message);
+ this.wsConnection?.send(message);
isRequest && PerformanceStatistics.endMeasure(commandName, beginId);
logger.debug(
`${this.logPrefix()} >> Buffered ${OCPPServiceUtils.getMessageTypeString(
return this.stationInfo.supervisionUrlOcppKey ?? VendorDefaultParametersKey.ConnectionUrl;
}
- private getTemplateFromFile(): ChargingStationTemplate | null {
- let template: ChargingStationTemplate = null;
+ private getTemplateFromFile(): ChargingStationTemplate | undefined {
+ let template: ChargingStationTemplate;
try {
if (this.sharedLRUCache.hasChargingStationTemplate(this.stationInfo?.templateHash)) {
template = this.sharedLRUCache.getChargingStationTemplate(this.stationInfo.templateHash);
}
private getStationInfoFromTemplate(): ChargingStationInfo {
- const stationTemplate: ChargingStationTemplate = this.getTemplateFromFile();
+ const stationTemplate: ChargingStationTemplate | undefined = this.getTemplateFromFile();
if (Utils.isNullOrUndefined(stationTemplate)) {
const errorMsg = `Failed to read charging station template file ${this.templateFile}`;
logger.error(`${this.logPrefix()} ${errorMsg}`);
this.index,
stationTemplate
);
- stationInfo.ocppVersion = stationTemplate.ocppVersion ?? OCPPVersion.VERSION_16;
+ stationInfo.ocppVersion = stationTemplate?.ocppVersion ?? OCPPVersion.VERSION_16;
ChargingStationUtils.createSerialNumber(stationTemplate, stationInfo);
- if (!Utils.isEmptyArray(stationTemplate.power)) {
- stationTemplate.power = stationTemplate.power as number[];
+ if (!Utils.isEmptyArray(stationTemplate?.power)) {
+ stationTemplate.power = stationTemplate?.power as number[];
const powerArrayRandomIndex = Math.floor(Utils.secureRandom() * stationTemplate.power.length);
stationInfo.maximumPower =
- stationTemplate.powerUnit === PowerUnits.KILO_WATT
+ stationTemplate?.powerUnit === PowerUnits.KILO_WATT
? stationTemplate.power[powerArrayRandomIndex] * 1000
: stationTemplate.power[powerArrayRandomIndex];
} else {
stationTemplate.power = stationTemplate.power as number;
stationInfo.maximumPower =
- stationTemplate.powerUnit === PowerUnits.KILO_WATT
+ stationTemplate?.powerUnit === PowerUnits.KILO_WATT
? stationTemplate.power * 1000
: stationTemplate.power;
}
stationInfo.firmwareVersionPattern =
- stationTemplate.firmwareVersionPattern ?? Constants.SEMVER_PATTERN;
+ stationTemplate?.firmwareVersionPattern ?? Constants.SEMVER_PATTERN;
if (
stationInfo.firmwareVersion &&
new RegExp(stationInfo.firmwareVersionPattern).test(stationInfo.firmwareVersion) === false
{
reset: true,
},
- stationTemplate.firmwareUpgrade ?? {}
+ stationTemplate?.firmwareUpgrade ?? {}
);
- stationInfo.resetTime = stationTemplate.resetTime
+ stationInfo.resetTime = stationTemplate?.resetTime
? stationTemplate.resetTime * 1000
: Constants.CHARGING_STATION_DEFAULT_RESET_TIME;
const configuredMaxConnectors =
}
private getStationInfoFromFile(): ChargingStationInfo | null {
- let stationInfo: ChargingStationInfo = null;
+ let stationInfo: ChargingStationInfo | null = null;
this.getStationInfoPersistentConfiguration() &&
(stationInfo = this.getConfigurationFromFile()?.stationInfo ?? null);
stationInfo && ChargingStationUtils.createStationInfoHash(stationInfo);
private getStationInfo(): ChargingStationInfo {
const stationInfoFromTemplate: ChargingStationInfo = this.getStationInfoFromTemplate();
- const stationInfoFromFile: ChargingStationInfo = this.getStationInfoFromFile();
+ const stationInfoFromFile: ChargingStationInfo | null = this.getStationInfoFromFile();
// Priority: charging station info from template > charging station info from configuration file > charging station info attribute
if (stationInfoFromFile?.templateHash === stationInfoFromTemplate.templateHash) {
if (this.stationInfo?.infoHash === stationInfoFromFile?.infoHash) {
const patternGroup: number =
this.stationInfo.firmwareUpgrade?.versionUpgrade?.patternGroup ??
this.stationInfo.firmwareVersion.split('.').length;
- const match = this.stationInfo.firmwareVersion
- .match(new RegExp(this.stationInfo.firmwareVersionPattern))
- .slice(1, patternGroup + 1);
+ const match = this.stationInfo?.firmwareVersion
+ ?.match(new RegExp(this.stationInfo.firmwareVersionPattern))
+ ?.slice(1, patternGroup + 1);
const patchLevelIndex = match.length - 1;
match[patchLevelIndex] = (
Utils.convertToInt(match[patchLevelIndex]) + versionStep
).toString();
- this.stationInfo.firmwareVersion = match.join('.');
+ this.stationInfo.firmwareVersion = match?.join('.');
}
}
ChargingStationConfigurationUtils.getConfigurationKey(
this,
StandardParametersKey.SupportedFeatureProfiles
- )?.value.includes(SupportedFeatureProfiles.LocalAuthListManagement)
+ )?.value?.includes(SupportedFeatureProfiles.LocalAuthListManagement)
) {
ChargingStationConfigurationUtils.addConfigurationKey(
this,
}
// Initialize transaction attributes on connectors
for (const connectorId of this.connectors.keys()) {
- if (connectorId > 0 && this.getConnectorStatus(connectorId).transactionStarted === true) {
+ if (connectorId > 0 && this.getConnectorStatus(connectorId)?.transactionStarted === true) {
logger.warn(
`${this.logPrefix()} Connector ${connectorId} at initialization has a transaction started: ${
- this.getConnectorStatus(connectorId).transactionId
+ this.getConnectorStatus(connectorId)?.transactionId
}`
);
}
if (
connectorId > 0 &&
- (this.getConnectorStatus(connectorId).transactionStarted === undefined ||
- this.getConnectorStatus(connectorId).transactionStarted === null)
+ (this.getConnectorStatus(connectorId)?.transactionStarted === undefined ||
+ this.getConnectorStatus(connectorId)?.transactionStarted === null)
) {
this.initializeConnectorStatus(connectorId);
}
}
private getConfigurationFromFile(): ChargingStationConfiguration | null {
- let configuration: ChargingStationConfiguration = null;
+ let configuration: ChargingStationConfiguration | null = null;
if (this.configurationFile && fs.existsSync(this.configurationFile)) {
try {
if (this.sharedLRUCache.hasChargingStationConfiguration(this.configurationFileHash)) {
}
private getOcppConfigurationFromFile(): ChargingStationOcppConfiguration | null {
- let configuration: ChargingStationConfiguration = null;
+ let configuration: ChargingStationConfiguration | null = null;
if (this.getOcppPersistentConfiguration() === true) {
const configurationFromFile = this.getConfigurationFromFile();
configuration = configurationFromFile?.configurationKey && configurationFromFile;
}
private getOcppConfiguration(): ChargingStationOcppConfiguration | null {
- let ocppConfiguration: ChargingStationOcppConfiguration = this.getOcppConfigurationFromFile();
+ let ocppConfiguration: ChargingStationOcppConfiguration | null =
+ this.getOcppConfigurationFromFile();
if (!ocppConfiguration) {
ocppConfiguration = this.getOcppConfigurationFromTemplate();
}
throw new OCPPError(
ErrorType.INTERNAL_ERROR,
`Response for unknown message id ${messageId}`,
- null,
+ undefined,
commandPayload
);
}
throw new OCPPError(
ErrorType.PROTOCOL_ERROR,
`Cached request for message id ${messageId} response is not an array`,
- null,
+ undefined,
cachedRequest as unknown as JsonType
);
}
throw new OCPPError(
ErrorType.INTERNAL_ERROR,
`Error response for unknown message id ${messageId}`,
- null,
+ undefined,
{ errorType, errorMessage, errorDetails }
);
}
throw new OCPPError(
ErrorType.PROTOCOL_ERROR,
`Cached request for message id ${messageId} error response is not an array`,
- null,
+ undefined,
cachedRequest as unknown as JsonType
);
}
}
// -1 for unlimited, 0 for disabling
- private getAutoReconnectMaxRetries(): number {
+ private getAutoReconnectMaxRetries(): number | undefined {
if (!Utils.isUndefined(this.stationInfo.autoReconnectMaxRetries)) {
return this.stationInfo.autoReconnectMaxRetries;
}
}
// 0 for disabling
- private getRegistrationMaxRetries(): number {
+ private getRegistrationMaxRetries(): number | undefined {
if (!Utils.isUndefined(this.stationInfo.registrationMaxRetries)) {
return this.stationInfo.registrationMaxRetries;
}
ChargingStationConfigurationUtils.getConfigurationKey(
this,
this.stationInfo.amperageLimitationOcppKey
- ).value
+ )?.value
) / ChargingStationUtils.getAmperageLimitationUnitDivider(this.stationInfo)
);
}
this.startHeartbeat();
// Initialize connectors status
for (const connectorId of this.connectors.keys()) {
- let connectorStatus: ConnectorStatusEnum;
+ let connectorStatus: ConnectorStatusEnum | undefined;
if (connectorId === 0) {
continue;
} else if (
this.getConnectorStatus(connectorId)?.bootStatus
) {
// Set boot status in template at startup
- connectorStatus = this.getConnectorStatus(connectorId).bootStatus;
+ connectorStatus = this.getConnectorStatus(connectorId)?.bootStatus;
} else if (this.getConnectorStatus(connectorId)?.status) {
// Set previous status at startup
- connectorStatus = this.getConnectorStatus(connectorId).status;
+ connectorStatus = this.getConnectorStatus(connectorId)?.status;
} else {
// Set default status
connectorStatus = ConnectorStatusEnum.AVAILABLE;
ConnectorStatusEnum.UNAVAILABLE
)
);
- this.getConnectorStatus(connectorId).status = null;
+ this.getConnectorStatus(connectorId).status = undefined;
}
}
}
ChargingStationConfigurationUtils.getConfigurationKey(
this,
StandardParametersKey.WebSocketPingInterval
- ).value
+ )?.value
)
: 0;
if (webSocketPingInterval > 0 && !this.webSocketPingSetInterval) {
this.webSocketPingSetInterval = setInterval(() => {
if (this.isWebSocketConnectionOpened() === true) {
- this.wsConnection.ping();
+ this.wsConnection?.ping();
}
}, webSocketPingInterval * 1000);
logger.info(
}
private getConfiguredSupervisionUrl(): URL {
- const supervisionUrls = this.stationInfo.supervisionUrls ?? Configuration.getSupervisionUrls();
+ const supervisionUrls = this.stationInfo?.supervisionUrls ?? Configuration.getSupervisionUrls();
if (!Utils.isEmptyArray(supervisionUrls)) {
switch (Configuration.getSupervisionUrlDistribution()) {
case SupervisionUrlDistribution.ROUND_ROBIN:
private terminateWSConnection(): void {
if (this.isWebSocketConnectionOpened() === true) {
- this.wsConnection.terminate();
+ this.wsConnection?.terminate();
this.wsConnection = null;
}
}
private stopMeterValues(connectorId: number) {
if (this.getConnectorStatus(connectorId)?.transactionSetInterval) {
- clearInterval(this.getConnectorStatus(connectorId).transactionSetInterval);
+ clearInterval(this.getConnectorStatus(connectorId)?.transactionSetInterval);
}
}
key: string | StandardParametersKey,
caseInsensitive = false
): ConfigurationKey | undefined {
- return chargingStation.ocppConfiguration.configurationKey?.find(configElement => {
+ return chargingStation.ocppConfiguration?.configurationKey?.find((configElement) => {
if (caseInsensitive) {
return configElement.key.toLowerCase() === key.toLowerCase();
}
keyFound = undefined;
}
if (!keyFound) {
- chargingStation.ocppConfiguration.configurationKey?.push({
+ chargingStation.ocppConfiguration?.configurationKey?.push({
key,
readonly: options.readonly,
value,
params?.caseInsensitive
);
if (keyFound) {
- const deletedConfigurationKey = chargingStation.ocppConfiguration.configurationKey.splice(
+ const deletedConfigurationKey = chargingStation.ocppConfiguration?.configurationKey?.splice(
chargingStation.ocppConfiguration.configurationKey.indexOf(keyFound),
1
);
[
BroadcastChannelProcedureName.START_AUTOMATIC_TRANSACTION_GENERATOR,
(requestPayload?: BroadcastChannelRequestPayload) =>
- this.chargingStation.startAutomaticTransactionGenerator(requestPayload.connectorIds),
+ this.chargingStation.startAutomaticTransactionGenerator(requestPayload?.connectorIds),
],
[
BroadcastChannelProcedureName.STOP_AUTOMATIC_TRANSACTION_GENERATOR,
(requestPayload?: BroadcastChannelRequestPayload) =>
- this.chargingStation.stopAutomaticTransactionGenerator(requestPayload.connectorIds),
+ this.chargingStation.stopAutomaticTransactionGenerator(requestPayload?.connectorIds),
],
[
BroadcastChannelProcedureName.START_TRANSACTION,
if (
commandResponse === undefined ||
commandResponse === null ||
- Utils.isEmptyObject(commandResponse as CommandResponse)
+ Utils.isEmptyObject(commandResponse)
) {
responsePayload = {
hashId: this.chargingStation.stationInfo.hashId,
responsePayload = this.commandResponseToResponsePayload(
command,
requestPayload,
- commandResponse as CommandResponse
+ commandResponse
);
}
} catch (error) {
this.responses.get(uuid)?.responsesReceived <= this.responses.get(uuid)?.responsesExpected
) {
this.responses.get(uuid).responsesReceived++;
- this.responses.get(uuid).responses.push(responsePayload);
+ this.responses.get(uuid)?.responses.push(responsePayload);
}
if (
this.responses.get(uuid)?.responsesReceived === this.responses.get(uuid)?.responsesExpected
return hashId;
}
})
- .filter(hashId => hashId !== undefined),
+ .filter((hashId) => hashId !== undefined),
...(responsesStatus === ResponseStatus.FAILURE && {
hashIdsFailed: this.responses
.get(uuid)
return hashId;
}
})
- .filter(hashId => hashId !== undefined),
+ .filter((hashId) => hashId !== undefined),
}),
...(responsesStatus === ResponseStatus.FAILURE && {
responsesFailed: this.responses
.get(uuid)
- ?.responses.map(response => {
+ ?.responses.map((response) => {
if (response.status === ResponseStatus.FAILURE) {
return response;
}
})
- .filter(response => response !== undefined),
+ .filter((response) => response !== undefined),
}),
};
}
return OCPPConstants.OCPP_CLEAR_CHARGING_PROFILE_RESPONSE_UNKNOWN;
}
const connectorStatus = chargingStation.getConnectorStatus(commandPayload.connectorId);
- if (commandPayload.connectorId && !Utils.isEmptyArray(connectorStatus.chargingProfiles)) {
+ if (commandPayload.connectorId && !Utils.isEmptyArray(connectorStatus?.chargingProfiles)) {
connectorStatus.chargingProfiles = [];
logger.debug(
`${chargingStation.logPrefix()} Charging profile(s) cleared on connector id ${
if (!commandPayload.connectorId) {
let clearedCP = false;
for (const connectorId of chargingStation.connectors.keys()) {
- if (!Utils.isEmptyArray(chargingStation.getConnectorStatus(connectorId).chargingProfiles)) {
+ if (
+ !Utils.isEmptyArray(chargingStation.getConnectorStatus(connectorId)?.chargingProfiles)
+ ) {
chargingStation
.getConnectorStatus(connectorId)
- .chargingProfiles?.forEach((chargingProfile: OCPP16ChargingProfile, index: number) => {
+ ?.chargingProfiles?.forEach((chargingProfile: OCPP16ChargingProfile, index: number) => {
let clearCurrentCP = false;
if (chargingProfile.chargingProfileId === commandPayload.id) {
clearCurrentCP = true;
clearCurrentCP = true;
}
if (clearCurrentCP) {
- connectorStatus.chargingProfiles.splice(index, 1);
+ connectorStatus?.chargingProfiles?.splice(index, 1);
logger.debug(
`${chargingStation.logPrefix()} Matching charging profile(s) cleared: %j`,
chargingProfile
.getAuthorizedTags(
ChargingStationUtils.getAuthorizationFile(chargingStation.stationInfo)
)
- .find(idTag => idTag === commandPayload.idTag)
+ ?.find((idTag) => idTag === commandPayload.idTag)
) {
connectorStatus.localAuthorizeIdTag = commandPayload.idTag;
connectorStatus.idTagLocalAuthorized = true;
idTag: string
): Promise<GenericResponse> {
if (
- chargingStation.getConnectorStatus(connectorId).status !== OCPP16ChargePointStatus.AVAILABLE
+ chargingStation.getConnectorStatus(connectorId)?.status !== OCPP16ChargePointStatus.AVAILABLE
) {
await chargingStation.ocppRequestService.requestHandler<
OCPP16StatusNotificationRequest,
}
logger.warn(
`${chargingStation.logPrefix()} Remote starting transaction REJECTED on connector Id ${connectorId.toString()}, idTag '${idTag}', availability '${
- chargingStation.getConnectorStatus(connectorId).availability
- }', status '${chargingStation.getConnectorStatus(connectorId).status}'`
+ chargingStation.getConnectorStatus(connectorId)?.availability
+ }', status '${chargingStation.getConnectorStatus(connectorId)?.status}'`
);
return OCPPConstants.OCPP_RESPONSE_REJECTED;
}
}
const retrieveDate = Utils.convertToDate(commandPayload.retrieveDate);
const now = Date.now();
- if (retrieveDate.getTime() <= now) {
+ if (retrieveDate?.getTime() <= now) {
this.asyncResource
.runInAsyncScope(
this.updateFirmware.bind(this) as (
this.updateFirmware(chargingStation).catch(() => {
/* Intentional */
});
- }, retrieveDate.getTime() - now);
+ }, retrieveDate?.getTime() - now);
}
return OCPPConstants.OCPP_RESPONSE_EMPTY;
}
for (const connectorId of chargingStation.connectors.keys()) {
if (
connectorId > 0 &&
- chargingStation.getConnectorStatus(connectorId).transactionStarted === false
+ chargingStation.getConnectorStatus(connectorId)?.transactionStarted === false
) {
await chargingStation.ocppRequestService.requestHandler<
OCPP16StatusNotificationRequest,
try {
const logFiles = fs
.readdirSync(path.resolve(path.dirname(fileURLToPath(import.meta.url)), '../../../../'))
- .filter(file => file.endsWith('.log'))
- .map(file => path.join('./', file));
+ .filter((file) => file.endsWith('.log'))
+ .map((file) => path.join('./', file));
const diagnosticsArchive = `${chargingStation.stationInfo.chargingStationId}_logs.tar.gz`;
tar.create({ gzip: true }, logFiles).pipe(fs.createWriteStream(diagnosticsArchive));
ftpClient = new Client();
});
let uploadResponse: FTPResponse;
if (accessResponse.code === 220) {
- ftpClient.trackProgress(info => {
+ ftpClient.trackProgress((info) => {
logger.info(
`${chargingStation.logPrefix()} ${
info.bytes / 1024
>(chargingStation, OCPP16RequestCommand.DIAGNOSTICS_STATUS_NOTIFICATION, {
status: OCPP16DiagnosticsStatus.Uploading,
})
- .catch(error => {
+ .catch((error) => {
logger.error(
`${chargingStation.logPrefix()} ${moduleName}.handleRequestGetDiagnostics: Error while sending '${
OCPP16RequestCommand.DIAGNOSTICS_STATUS_NOTIFICATION
chargingStation.bootNotificationRequest,
{ skipBufferingOnError: true, triggerMessage: true }
)
- .then(response => {
+ .then((response) => {
chargingStation.bootNotificationResponse = response;
})
.catch(() => {
{
connectorId: commandPayload.connectorId,
errorCode: OCPP16ChargePointErrorCode.NO_ERROR,
- status: chargingStation.getConnectorStatus(commandPayload.connectorId).status,
+ status: chargingStation.getConnectorStatus(commandPayload.connectorId)?.status,
},
{
triggerMessage: true,
{
connectorId,
errorCode: OCPP16ChargePointErrorCode.NO_ERROR,
- status: chargingStation.getConnectorStatus(connectorId).status,
+ status: chargingStation.getConnectorStatus(connectorId)?.status,
},
{
triggerMessage: true,
break;
}
}
- if (!transactionConnectorId) {
+ if (Utils.isNullOrUndefined(transactionConnectorId)) {
logger.error(
`${chargingStation.logPrefix()} Trying to start a transaction on a non existing connector Id ${connectorId.toString()}`
);
return;
}
if (
- chargingStation.getConnectorStatus(connectorId).transactionRemoteStarted === true &&
+ chargingStation.getConnectorStatus(connectorId)?.transactionRemoteStarted === true &&
chargingStation.getAuthorizeRemoteTxRequests() === true &&
chargingStation.getLocalAuthListEnabled() === true &&
chargingStation.hasAuthorizedTags() &&
- chargingStation.getConnectorStatus(connectorId).idTagLocalAuthorized === false
+ chargingStation.getConnectorStatus(connectorId)?.idTagLocalAuthorized === false
) {
logger.error(
`${chargingStation.logPrefix()} Trying to start a transaction with a not local authorized idTag ${
- chargingStation.getConnectorStatus(connectorId).localAuthorizeIdTag
+ chargingStation.getConnectorStatus(connectorId)?.localAuthorizeIdTag
} on connector Id ${connectorId.toString()}`
);
await this.resetConnectorOnStartTransactionError(chargingStation, connectorId);
return;
}
if (
- chargingStation.getConnectorStatus(connectorId).transactionRemoteStarted === true &&
+ chargingStation.getConnectorStatus(connectorId)?.transactionRemoteStarted === true &&
chargingStation.getAuthorizeRemoteTxRequests() === true &&
chargingStation.getMustAuthorizeAtRemoteStart() === true &&
- chargingStation.getConnectorStatus(connectorId).idTagLocalAuthorized === false &&
- chargingStation.getConnectorStatus(connectorId).idTagAuthorized === false
+ chargingStation.getConnectorStatus(connectorId)?.idTagLocalAuthorized === false &&
+ chargingStation.getConnectorStatus(connectorId)?.idTagAuthorized === false
) {
logger.error(
`${chargingStation.logPrefix()} Trying to start a transaction with a not authorized idTag ${
- chargingStation.getConnectorStatus(connectorId).authorizeIdTag
+ chargingStation.getConnectorStatus(connectorId)?.authorizeIdTag
} on connector Id ${connectorId.toString()}`
);
await this.resetConnectorOnStartTransactionError(chargingStation, connectorId);
return;
}
if (
- chargingStation.getConnectorStatus(connectorId).idTagAuthorized &&
- chargingStation.getConnectorStatus(connectorId).authorizeIdTag !== requestPayload.idTag
+ chargingStation.getConnectorStatus(connectorId)?.idTagAuthorized &&
+ chargingStation.getConnectorStatus(connectorId)?.authorizeIdTag !== requestPayload.idTag
) {
logger.error(
`${chargingStation.logPrefix()} Trying to start a transaction with an idTag ${
requestPayload.idTag
} different from the authorize request one ${
- chargingStation.getConnectorStatus(connectorId).authorizeIdTag
+ chargingStation.getConnectorStatus(connectorId)?.authorizeIdTag
} on connector Id ${connectorId.toString()}`
);
await this.resetConnectorOnStartTransactionError(chargingStation, connectorId);
return;
}
if (
- chargingStation.getConnectorStatus(connectorId).idTagLocalAuthorized &&
- chargingStation.getConnectorStatus(connectorId).localAuthorizeIdTag !== requestPayload.idTag
+ chargingStation.getConnectorStatus(connectorId)?.idTagLocalAuthorized &&
+ chargingStation.getConnectorStatus(connectorId)?.localAuthorizeIdTag !== requestPayload.idTag
) {
logger.error(
`${chargingStation.logPrefix()} Trying to start a transaction with an idTag ${
requestPayload.idTag
} different from the local authorized one ${
- chargingStation.getConnectorStatus(connectorId).localAuthorizeIdTag
+ chargingStation.getConnectorStatus(connectorId)?.localAuthorizeIdTag
} on connector Id ${connectorId.toString()}`
);
await this.resetConnectorOnStartTransactionError(chargingStation, connectorId);
): Promise<void> {
chargingStation.resetConnectorStatus(connectorId);
if (
- chargingStation.getConnectorStatus(connectorId).status !== OCPP16ChargePointStatus.AVAILABLE
+ chargingStation.getConnectorStatus(connectorId)?.status !== OCPP16ChargePointStatus.AVAILABLE
) {
await chargingStation.ocppRequestService.requestHandler<
OCPP16StatusNotificationRequest,
`${chargingStation.logPrefix()} MeterValues measurand ${
meterValue.sampledValue[sampledValuesIndex].measurand ??
OCPP16MeterValueMeasurand.ENERGY_ACTIVE_IMPORT_REGISTER
- }: connectorId ${connectorId}, transaction ${connector.transactionId}, value: ${
+ }: connectorId ${connectorId}, transaction ${connector?.transactionId}, value: ${
meterValue.sampledValue[sampledValuesIndex].value
}/100`
);
OCPP16ServiceUtils.buildSampledValue(
voltagePhaseLineToNeutralSampledValueTemplate ?? voltageSampledValueTemplate,
voltagePhaseLineToNeutralMeasurandValue ?? voltageMeasurandValue,
- null,
+ undefined,
phaseLineToNeutralValue as OCPP16MeterValuePhase
)
);
OCPP16ServiceUtils.buildSampledValue(
voltagePhaseLineToLineSampledValueTemplate ?? voltageSampledValueTemplate,
voltagePhaseLineToLineMeasurandValue ?? defaultVoltagePhaseLineToLineMeasurandValue,
- null,
+ undefined,
phaseLineToLineValue as OCPP16MeterValuePhase
)
);
`${chargingStation.logPrefix()} MeterValues measurand ${
meterValue.sampledValue[sampledValuesIndex].measurand ??
OCPP16MeterValueMeasurand.ENERGY_ACTIVE_IMPORT_REGISTER
- }: connectorId ${connectorId}, transaction ${connector.transactionId}, value: ${
+ }: connectorId ${connectorId}, transaction ${connector?.transactionId}, value: ${
meterValue.sampledValue[sampledValuesIndex].value
}/${connectorMaximumPowerRounded}`
);
(powerPerPhaseSampledValueTemplates[`L${phase}`] as SampledValueTemplate) ??
powerSampledValueTemplate,
powerMeasurandValues[`L${phase}`] as number,
- null,
+ undefined,
phaseValue as OCPP16MeterValuePhase
)
);
OCPP16MeterValueMeasurand.ENERGY_ACTIVE_IMPORT_REGISTER
}: phase ${
meterValue.sampledValue[sampledValuesPerPhaseIndex].phase
- }, connectorId ${connectorId}, transaction ${connector.transactionId}, value: ${
+ }, connectorId ${connectorId}, transaction ${connector?.transactionId}, value: ${
meterValue.sampledValue[sampledValuesPerPhaseIndex].value
}/${connectorMaximumPowerPerPhaseRounded}`
);
`${chargingStation.logPrefix()} MeterValues measurand ${
meterValue.sampledValue[sampledValuesIndex].measurand ??
OCPP16MeterValueMeasurand.ENERGY_ACTIVE_IMPORT_REGISTER
- }: connectorId ${connectorId}, transaction ${connector.transactionId}, value: ${
+ }: connectorId ${connectorId}, transaction ${connector?.transactionId}, value: ${
meterValue.sampledValue[sampledValuesIndex].value
}/${connectorMaximumAmperage}`
);
(currentPerPhaseSampledValueTemplates[phaseValue] as SampledValueTemplate) ??
currentSampledValueTemplate,
currentMeasurandValues[phaseValue] as number,
- null,
+ undefined,
phaseValue as OCPP16MeterValuePhase
)
);
OCPP16MeterValueMeasurand.ENERGY_ACTIVE_IMPORT_REGISTER
}: phase ${
meterValue.sampledValue[sampledValuesPerPhaseIndex].phase
- }, connectorId ${connectorId}, transaction ${connector.transactionId}, value: ${
+ }, connectorId ${connectorId}, transaction ${connector?.transactionId}, value: ${
meterValue.sampledValue[sampledValuesPerPhaseIndex].value
}/${connectorMaximumAmperage}`
);
meterValue.sampledValue[sampledValuesIndex].measurand ??
OCPP16MeterValueMeasurand.ENERGY_ACTIVE_IMPORT_REGISTER
}: connectorId ${connectorId}, transaction ${
- connector.transactionId
+ connector?.transactionId
}, value: ${energyValueRounded}/${connectorMaximumEnergyRounded}, duration: ${Utils.roundTo(
interval / (3600 * 1000),
4
connectorId: number,
cp: OCPP16ChargingProfile
): void {
- if (Utils.isNullOrUndefined(chargingStation.getConnectorStatus(connectorId).chargingProfiles)) {
+ if (
+ Utils.isNullOrUndefined(chargingStation.getConnectorStatus(connectorId)?.chargingProfiles)
+ ) {
logger.error(
`${chargingStation.logPrefix()} Trying to set a charging profile on connectorId ${connectorId} with an uninitialized charging profiles array attribute, applying deferred initialization`
);
chargingStation.getConnectorStatus(connectorId).chargingProfiles = [];
}
- if (Array.isArray(chargingStation.getConnectorStatus(connectorId).chargingProfiles) === false) {
+ if (
+ Array.isArray(chargingStation.getConnectorStatus(connectorId)?.chargingProfiles) === false
+ ) {
logger.error(
`${chargingStation.logPrefix()} Trying to set a charging profile on connectorId ${connectorId} with an improper attribute type for the charging profiles array, applying proper type initialization`
);
chargingStation.getConnectorStatus(connectorId).chargingProfiles = [];
}
let cpReplaced = false;
- if (!Utils.isEmptyArray(chargingStation.getConnectorStatus(connectorId).chargingProfiles)) {
+ if (!Utils.isEmptyArray(chargingStation.getConnectorStatus(connectorId)?.chargingProfiles)) {
chargingStation
.getConnectorStatus(connectorId)
- .chargingProfiles?.forEach((chargingProfile: OCPP16ChargingProfile, index: number) => {
+ ?.chargingProfiles?.forEach((chargingProfile: OCPP16ChargingProfile, index: number) => {
if (
chargingProfile.chargingProfileId === cp.chargingProfileId ||
(chargingProfile.stackLevel === cp.stackLevel &&
}
});
}
- !cpReplaced && chargingStation.getConnectorStatus(connectorId).chargingProfiles?.push(cp);
+ !cpReplaced && chargingStation.getConnectorStatus(connectorId)?.chargingProfiles?.push(cp);
}
private static buildSampledValue(
messageId: string,
messagePayload: JsonType,
commandName: IncomingRequestCommand
- ): Promise<ResponseType> {
+ ): Promise<ResponseType | undefined> {
try {
// Send response message
return await this.internalSendMessage(
messageId: string,
messagePayload: JsonType | OCPPError,
messageType: MessageType,
- commandName?: RequestCommand | IncomingRequestCommand,
+ commandName: RequestCommand | IncomingRequestCommand,
params: RequestParams = {
skipBufferingOnError: false,
triggerMessage: false,
if (wsOpened) {
const beginId = PerformanceStatistics.beginMeasure(commandName);
try {
- chargingStation.wsConnection.send(messageToSend);
+ chargingStation.wsConnection?.send(messageToSend);
logger.debug(
`${chargingStation.logPrefix()} >> Command '${commandName}' sent ${OCPPServiceUtils.getMessageTypeString(
messageType
.then(() => {
resolve(payload);
})
- .catch(error => {
+ .catch((error) => {
reject(error);
})
.finally(() => {
messageId: string,
messagePayload: JsonType | OCPPError,
messageType: MessageType,
- commandName?: RequestCommand | IncomingRequestCommand,
- responseCallback?: ResponseCallback,
- errorCallback?: ErrorCallback
+ commandName: RequestCommand | IncomingRequestCommand,
+ responseCallback: ResponseCallback,
+ errorCallback: ErrorCallback
): string {
let messageToSend: string;
// Type of message
ChargingStationConfigurationUtils.getConfigurationKey(
chargingStation,
StandardParametersKey.MeterValuesSampledData
- )?.value.includes(measurand) === false
+ )?.value?.includes(measurand) === false
) {
logger.debug(
`${chargingStation.logPrefix()} Trying to get MeterValues measurand '${measurand}' ${onPhaseStr}in template on connectorId ${connectorId} not found in '${
return;
}
const sampledValueTemplates: SampledValueTemplate[] =
- chargingStation.getConnectorStatus(connectorId).MeterValues;
+ chargingStation.getConnectorStatus(connectorId)?.MeterValues;
for (
let index = 0;
Utils.isEmptyArray(sampledValueTemplates) === false && index < sampledValueTemplates.length;
ChargingStationConfigurationUtils.getConfigurationKey(
chargingStation,
StandardParametersKey.MeterValuesSampledData
- )?.value.includes(measurand) === true
+ )?.value?.includes(measurand) === true
) {
return sampledValueTemplates[index];
} else if (
ChargingStationConfigurationUtils.getConfigurationKey(
chargingStation,
StandardParametersKey.MeterValuesSampledData
- )?.value.includes(measurand) === true
+ )?.value?.includes(measurand) === true
) {
return sampledValueTemplates[index];
} else if (
}
private requestListener(req: IncomingMessage, res: ServerResponse): void {
- this.authenticate(req, err => {
+ this.authenticate(req, (err) => {
if (err) {
res
.writeHead(StatusCodes.UNAUTHORIZED, {
throw new BaseError(`Unsupported UI protocol version: '${fullProtocol}'`);
}
this.registerProtocolVersionUIService(version);
- req.on('error', error => {
+ req.on('error', (error) => {
logger.error(
`${this.logPrefix(moduleName, 'requestListener.req.onerror')} Error on HTTP request:`,
error
if (req.method === 'POST') {
const bodyBuffer = [];
req
- .on('data', chunk => {
+ .on('data', (chunk) => {
bodyBuffer.push(chunk);
})
.on('end', () => {
}
const [, version] = UIServerUtils.getProtocolAndVersion(ws.protocol);
this.registerProtocolVersionUIService(version);
- ws.on('message', rawData => {
+ ws.on('message', (rawData) => {
const request = this.validateRawDataRequest(rawData);
if (request === false) {
ws.close(WebSocketCloseEventStatusCode.CLOSE_INVALID_PAYLOAD);
/* Error caught by AbstractUIService */
});
});
- ws.on('error', error => {
+ ws.on('error', (error) => {
logger.error(`${this.logPrefix(moduleName, 'start.ws.onerror')} WebSocket error:`, error);
});
ws.on('close', (code, reason) => {
this.httpServer.on(
'upgrade',
(req: IncomingMessage, socket: internal.Duplex, head: Buffer): void => {
- this.authenticate(req, err => {
+ this.authenticate(req, (err) => {
if (err) {
socket.write(`HTTP/1.1 ${StatusCodes.UNAUTHORIZED} Unauthorized\r\n\r\n`);
socket.destroy();
): void {
if (!Utils.isEmptyArray(payload.hashIds)) {
payload.hashIds = payload.hashIds
- .map(hashId => {
+ .map((hashId) => {
if (this.uiServer.chargingStations.has(hashId) === true) {
return hashId;
}
)} Charging station with hashId '${hashId}' not found`
);
})
- .filter(hashId => hashId !== undefined);
+ .filter((hashId) => hashId !== undefined);
}
const expectedNumberOfResponses = !Utils.isEmptyArray(payload.hashIds)
? payload.hashIds.length
}
private initializePerformanceObserver(): void {
- this.performanceObserver = new PerformanceObserver(performanceObserverList => {
+ this.performanceObserver = new PerformanceObserver((performanceObserverList) => {
const lastPerformanceEntry = performanceObserverList.getEntries()[0];
// logger.debug(
// `${this.logPrefix()} '${lastPerformanceEntry.name}' performance entry: %j`,
);
} else {
logger.info(
- `${this.logPrefix()} log interval is set to ${Configuration.getLogStatisticsInterval().toString()}. Not logging statistics`
+ `${this.logPrefix()} log interval is set to ${Configuration.getLogStatisticsInterval()?.toString()}. Not logging statistics`
);
}
}
this.statistics.statisticsData.get(entryName).avgTimeMeasurement =
this.statistics.statisticsData.get(entryName).totalTimeMeasurement /
this.statistics.statisticsData.get(entryName).countTimeMeasurement;
- Array.isArray(this.statistics.statisticsData.get(entryName).timeMeasurementSeries) === true
+ Array.isArray(this.statistics.statisticsData.get(entryName)?.timeMeasurementSeries) === true
? this.statistics.statisticsData
.get(entryName)
- .timeMeasurementSeries.push({ timestamp: entry.startTime, value: entry.duration })
+ ?.timeMeasurementSeries?.push({ timestamp: entry.startTime, value: entry.duration })
: (this.statistics.statisticsData.get(entryName).timeMeasurementSeries =
new CircularArray<TimeSeries>(DEFAULT_CIRCULAR_ARRAY_SIZE, {
timestamp: entry.startTime,
}
private extractTimeSeriesValues(timeSeries: CircularArray<TimeSeries>): number[] {
- return timeSeries.map(timeSeriesItem => timeSeriesItem.value);
+ return timeSeries.map((timeSeriesItem) => timeSeriesItem.value);
}
private logPrefix(): string {
this.checkPerformanceRecordsFile();
lockfile
.lock(this.dbName, { stale: 5000, retries: 3 })
- .then(async release => {
+ .then(async (release) => {
try {
const fileData = fs.readFileSync(this.dbName, 'utf8');
const performanceRecords: Statistics[] = fileData
try {
this.checkDBConnection();
await this.client
- .db(this.dbName)
+ ?.db(this.dbName)
.collection<Statistics>(Constants.PERFORMANCE_RECORDS_TABLE)
.insertOne(performanceStatistics);
} catch (error) {
Bootstrap.getInstance()
.start()
- .catch(error => {
+ .catch((error) => {
console.error(chalk.red(error));
});
uiServerConfiguration = merge(uiServerConfiguration, Configuration.getConfig()?.uiServer);
}
if (Configuration.isCFEnvironment() === true) {
- delete uiServerConfiguration.options.host;
+ delete uiServerConfiguration.options?.host;
uiServerConfiguration.options.port = parseInt(process.env.PORT);
}
return uiServerConfiguration;
// Nullify to force configuration file reading
Configuration.configuration = null;
if (!Configuration.isUndefined(Configuration.configurationChangeCallback)) {
- Configuration.configurationChangeCallback().catch(error => {
+ Configuration.configurationChangeCallback().catch((error) => {
throw typeof error === 'string' ? new Error(error) : error;
});
}
}
public static async sleep(milliSeconds: number): Promise<NodeJS.Timeout> {
- return new Promise(resolve => setTimeout(resolve as () => void, milliSeconds));
+ return new Promise((resolve) => setTimeout(resolve as () => void, milliSeconds));
}
public static formatDurationMilliSeconds(duration: number): string {
}
public static isUndefined(value: unknown): boolean {
- return typeof value === 'undefined';
+ return value === undefined;
}
public static isNullOrUndefined(value: unknown): boolean {
protected readonly workerScript: string;
protected readonly workerOptions: WorkerOptions;
public abstract readonly size: number;
- public abstract readonly maxElementsPerWorker: number | null;
+ public abstract readonly maxElementsPerWorker: number | undefined;
/**
* `WorkerAbstract` constructor.
return this.pool.workers.length;
}
- get maxElementsPerWorker(): number | null {
- return null;
+ get maxElementsPerWorker(): number | undefined {
+ return undefined;
}
/**
return this.workerSet.size;
}
- get maxElementsPerWorker(): number | null {
+ get maxElementsPerWorker(): number | undefined {
return this.workerOptions.elementsPerWorker;
}
).bind(this) as MessageHandler<Worker>
);
worker.on('error', WorkerUtils.defaultErrorHandler.bind(this) as (err: Error) => void);
- worker.on('exit', code => {
+ worker.on('exit', (code) => {
WorkerUtils.defaultExitHandler(code);
this.workerSet.delete(this.getWorkerSetElementByWorker(worker));
});
return this.pool.workers.length;
}
- get maxElementsPerWorker(): number | null {
- return null;
+ get maxElementsPerWorker(): number | undefined {
+ return undefined;
}
/**
config.uiServer.protocol
);
this._ws.onmessage = this.responseHandler.bind(this);
- this._ws.onerror = errorEvent => {
+ this._ws.onerror = (errorEvent) => {
console.error('WebSocket error: ', errorEvent);
};
- this._ws.onclose = closeEvent => {
+ this._ws.onclose = (closeEvent) => {
console.info('WebSocket closed: ', closeEvent);
};
}