X-Git-Url: https://git.piment-noir.org/?a=blobdiff_plain;f=src%2Fcharging-station%2Focpp%2F1.6%2FOCPP16IncomingRequestService.ts;h=8faf05cf609676ebca14249de5139edd215a3055;hb=41f3983a4f934199769f9ef1c46bfae2adc22b56;hp=66a6ee5960a95b7050a1888122e9bcef4cfe7a24;hpb=6fc0c6f3db444377c0fdea238183a14823278046;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 66a6ee59..8faf05cf 100644 --- a/src/charging-station/ocpp/1.6/OCPP16IncomingRequestService.ts +++ b/src/charging-station/ocpp/1.6/OCPP16IncomingRequestService.ts @@ -7,18 +7,13 @@ import { URL, fileURLToPath } from 'node:url'; import type { JSONSchemaType } from 'ajv'; import { Client, type FTPResponse } from 'basic-ftp'; import { + type Interval, addSeconds, differenceInSeconds, - isAfter, - isBefore, isDate, - isWithinInterval, - max, - maxTime, - min, - minTime, secondsToMilliseconds, } from 'date-fns'; +import { maxTime } from 'date-fns/constants'; import { create } from 'tar'; import { OCPP16Constants } from './OCPP16Constants'; @@ -37,8 +32,6 @@ import { OCPPError } from '../../../exception'; import { type ChangeConfigurationRequest, type ChangeConfigurationResponse, - type ClearChargingProfileRequest, - type ClearChargingProfileResponse, ErrorType, type GenericResponse, GenericStatus, @@ -47,7 +40,6 @@ import { type GetDiagnosticsRequest, type GetDiagnosticsResponse, type IncomingRequestHandler, - type JsonObject, type JsonType, OCPP16AuthorizationStatus, OCPP16AvailabilityType, @@ -60,10 +52,10 @@ import { OCPP16ChargePointStatus, type OCPP16ChargingProfile, OCPP16ChargingProfilePurposeType, - OCPP16ChargingRateUnitType, type OCPP16ChargingSchedule, - type OCPP16ChargingSchedulePeriod, type OCPP16ClearCacheRequest, + type OCPP16ClearChargingProfileRequest, + type OCPP16ClearChargingProfileResponse, type OCPP16DataTransferRequest, type OCPP16DataTransferResponse, OCPP16DataTransferVendorId, @@ -115,7 +107,6 @@ import { isNotEmptyString, isNullOrUndefined, isUndefined, - isValidTime, logger, sleep, } from '../../../utils'; @@ -124,7 +115,7 @@ import { OCPPIncomingRequestService } from '../OCPPIncomingRequestService'; const moduleName = 'OCPP16IncomingRequestService'; export class OCPP16IncomingRequestService extends OCPPIncomingRequestService { - protected jsonSchemas: Map>; + protected jsonSchemas: Map>; private incomingRequestHandlers: Map; public constructor() { @@ -202,7 +193,7 @@ export class OCPP16IncomingRequestService extends OCPPIncomingRequestService { this.handleRequestCancelReservation.bind(this) as unknown as IncomingRequestHandler, ], ]); - this.jsonSchemas = new Map>([ + this.jsonSchemas = new Map>([ [ OCPP16IncomingRequestCommand.RESET, OCPP16ServiceUtils.parseJsonSchemaFile( @@ -269,7 +260,7 @@ export class OCPP16IncomingRequestService extends OCPPIncomingRequestService { ], [ OCPP16IncomingRequestCommand.CLEAR_CHARGING_PROFILE, - OCPP16ServiceUtils.parseJsonSchemaFile( + OCPP16ServiceUtils.parseJsonSchemaFile( 'assets/json-schemas/ocpp/1.6/ClearChargingProfile.json', moduleName, 'constructor', @@ -355,7 +346,7 @@ export class OCPP16IncomingRequestService extends OCPPIncomingRequestService { ): Promise { let response: ResType; if ( - chargingStation.getOcppStrictCompliance() === true && + chargingStation.stationInfo?.ocppStrictCompliance === true && chargingStation.inPendingState() === true && (commandName === OCPP16IncomingRequestCommand.REMOTE_START_TRANSACTION || commandName === OCPP16IncomingRequestCommand.REMOTE_STOP_TRANSACTION) @@ -364,7 +355,7 @@ export class OCPP16IncomingRequestService extends OCPPIncomingRequestService { ErrorType.SECURITY_ERROR, `${commandName} cannot be issued to handle request PDU ${JSON.stringify( commandPayload, - null, + undefined, 2, )} while the charging station is in pending state on the central server`, commandName, @@ -373,7 +364,7 @@ export class OCPP16IncomingRequestService extends OCPPIncomingRequestService { } if ( chargingStation.isRegistered() === true || - (chargingStation.getOcppStrictCompliance() === false && + (chargingStation.stationInfo?.ocppStrictCompliance === false && chargingStation.inUnknownState() === true) ) { if ( @@ -390,8 +381,7 @@ export class OCPP16IncomingRequestService extends OCPPIncomingRequestService { } catch (error) { // Log logger.error( - `${chargingStation.logPrefix()} ${moduleName}.incomingRequestHandler: - Handle incoming request error:`, + `${chargingStation.logPrefix()} ${moduleName}.incomingRequestHandler: Handle incoming request error:`, error, ); throw error; @@ -402,7 +392,7 @@ export class OCPP16IncomingRequestService extends OCPPIncomingRequestService { ErrorType.NOT_IMPLEMENTED, `${commandName} is not implemented to handle request PDU ${JSON.stringify( commandPayload, - null, + undefined, 2, )}`, commandName, @@ -414,7 +404,7 @@ export class OCPP16IncomingRequestService extends OCPPIncomingRequestService { ErrorType.SECURITY_ERROR, `${commandName} cannot be issued to handle request PDU ${JSON.stringify( commandPayload, - null, + undefined, 2, )} while the charging station is not registered on the central server.`, commandName, @@ -444,8 +434,7 @@ export class OCPP16IncomingRequestService extends OCPPIncomingRequestService { ); } logger.warn( - `${chargingStation.logPrefix()} ${moduleName}.validatePayload: No JSON schema found - for command '${commandName}' PDU validation`, + `${chargingStation.logPrefix()} ${moduleName}.validatePayload: No JSON schema found for command '${commandName}' PDU validation`, ); return false; } @@ -465,8 +454,9 @@ export class OCPP16IncomingRequestService extends OCPPIncomingRequestService { `${type}Reset` as OCPP16StopTransactionReason, ).catch(Constants.EMPTY_FUNCTION); logger.info( - `${chargingStation.logPrefix()} ${type} reset command received, simulating it. The station will be - back online in ${formatDurationMilliSeconds(chargingStation.stationInfo.resetTime!)}`, + `${chargingStation.logPrefix()} ${type} reset command received, simulating it. The station will be back online in ${formatDurationMilliSeconds( + chargingStation.stationInfo.resetTime!, + )}`, ); return OCPP16Constants.OCPP_RESPONSE_ACCEPTED; } @@ -478,15 +468,12 @@ export class OCPP16IncomingRequestService extends OCPPIncomingRequestService { const { connectorId } = commandPayload; if (chargingStation.hasConnector(connectorId) === false) { logger.error( - `${chargingStation.logPrefix()} Trying to unlock a non existing - connector id ${connectorId.toString()}`, + `${chargingStation.logPrefix()} Trying to unlock a non existing connector id ${connectorId}`, ); return OCPP16Constants.OCPP_RESPONSE_UNLOCK_NOT_SUPPORTED; } if (connectorId === 0) { - logger.error( - `${chargingStation.logPrefix()} Trying to unlock connector id ${connectorId.toString()}`, - ); + logger.error(`${chargingStation.logPrefix()} Trying to unlock connector id ${connectorId}`); return OCPP16Constants.OCPP_RESPONSE_UNLOCK_NOT_SUPPORTED; } if (chargingStation.getConnectorStatus(connectorId)?.transactionStarted === true) { @@ -531,7 +518,7 @@ export class OCPP16IncomingRequestService extends OCPPIncomingRequestService { } else if (isNotEmptyArray(key) === true) { for (const k of key!) { const keyFound = getConfigurationKey(chargingStation, k, true); - if (keyFound) { + if (keyFound !== undefined) { if (isUndefined(keyFound.visible) === true) { keyFound.visible = true; } @@ -627,8 +614,7 @@ export class OCPP16IncomingRequestService extends OCPPIncomingRequestService { const { connectorId, csChargingProfiles } = commandPayload; if (chargingStation.hasConnector(connectorId) === false) { logger.error( - `${chargingStation.logPrefix()} Trying to set charging profile(s) to a - non existing connector id ${connectorId}`, + `${chargingStation.logPrefix()} Trying to set charging profile(s) to a non existing connector id ${connectorId}`, ); return OCPP16Constants.OCPP_SET_CHARGING_PROFILE_RESPONSE_REJECTED; } @@ -641,12 +627,34 @@ export class OCPP16IncomingRequestService extends OCPPIncomingRequestService { } if ( csChargingProfiles.chargingProfilePurpose === OCPP16ChargingProfilePurposeType.TX_PROFILE && - (connectorId === 0 || - chargingStation.getConnectorStatus(connectorId)?.transactionStarted === false) + connectorId === 0 + ) { + logger.error( + `${chargingStation.logPrefix()} Trying to set transaction charging profile(s) on connector ${connectorId}`, + ); + return OCPP16Constants.OCPP_SET_CHARGING_PROFILE_RESPONSE_REJECTED; + } + const connectorStatus = chargingStation.getConnectorStatus(connectorId); + if ( + csChargingProfiles.chargingProfilePurpose === OCPP16ChargingProfilePurposeType.TX_PROFILE && + connectorId > 0 && + connectorStatus?.transactionStarted === false ) { logger.error( - `${chargingStation.logPrefix()} Trying to set transaction charging profile(s) - on connector ${connectorId} without a started transaction`, + `${chargingStation.logPrefix()} Trying to set transaction charging profile(s) on connector ${connectorId} without a started transaction`, + ); + return OCPP16Constants.OCPP_SET_CHARGING_PROFILE_RESPONSE_REJECTED; + } + if ( + csChargingProfiles.chargingProfilePurpose === OCPP16ChargingProfilePurposeType.TX_PROFILE && + connectorId > 0 && + connectorStatus?.transactionStarted === true && + csChargingProfiles.transactionId !== connectorStatus?.transactionId + ) { + logger.error( + `${chargingStation.logPrefix()} Trying to set transaction charging profile(s) on connector ${connectorId} with a different transaction id ${ + csChargingProfiles.transactionId + } than the started transaction id ${connectorStatus?.transactionId}`, ); return OCPP16Constants.OCPP_SET_CHARGING_PROFILE_RESPONSE_REJECTED; } @@ -674,8 +682,7 @@ export class OCPP16IncomingRequestService extends OCPPIncomingRequestService { const { connectorId, duration, chargingRateUnit } = commandPayload; if (chargingStation.hasConnector(connectorId) === false) { logger.error( - `${chargingStation.logPrefix()} Trying to get composite schedule to a - non existing connector id ${connectorId}`, + `${chargingStation.logPrefix()} Trying to get composite schedule to a non existing connector id ${connectorId}`, ); return OCPP16Constants.OCPP_RESPONSE_REJECTED; } @@ -700,44 +707,63 @@ export class OCPP16IncomingRequestService extends OCPPIncomingRequestService { return OCPP16Constants.OCPP_RESPONSE_REJECTED; } const currentDate = new Date(); - const interval: Interval = { + const compositeScheduleInterval: Interval = { start: currentDate, end: addSeconds(currentDate, duration), }; // Get charging profiles sorted by connector id then stack level - const storedChargingProfiles: OCPP16ChargingProfile[] = getConnectorChargingProfiles( + const chargingProfiles: OCPP16ChargingProfile[] = getConnectorChargingProfiles( chargingStation, connectorId, ); - const chargingProfiles: OCPP16ChargingProfile[] = []; - for (const storedChargingProfile of storedChargingProfiles) { + let previousCompositeSchedule: OCPP16ChargingSchedule | undefined; + let compositeSchedule: OCPP16ChargingSchedule | undefined; + for (const chargingProfile of chargingProfiles) { if ( - connectorStatus?.transactionStarted && - isNullOrUndefined(storedChargingProfile.chargingSchedule?.startSchedule) + isNullOrUndefined(chargingProfile.chargingSchedule?.startSchedule) && + connectorStatus?.transactionStarted ) { logger.debug( `${chargingStation.logPrefix()} ${moduleName}.handleRequestGetCompositeSchedule: Charging profile id ${ - storedChargingProfile.chargingProfileId + chargingProfile.chargingProfileId } has no startSchedule defined. Trying to set it to the connector current transaction start date`, ); // OCPP specifies that if startSchedule is not defined, it should be relative to start of the connector transaction - storedChargingProfile.chargingSchedule.startSchedule = connectorStatus?.transactionStart; + chargingProfile.chargingSchedule.startSchedule = connectorStatus?.transactionStart; } - if (!isDate(storedChargingProfile.chargingSchedule?.startSchedule)) { + if ( + !isNullOrUndefined(chargingProfile.chargingSchedule?.startSchedule) && + !isDate(chargingProfile.chargingSchedule?.startSchedule) + ) { logger.warn( `${chargingStation.logPrefix()} ${moduleName}.handleRequestGetCompositeSchedule: Charging profile id ${ - storedChargingProfile.chargingProfileId - } startSchedule property is not a Date object. Trying to convert it to a Date object`, + chargingProfile.chargingProfileId + } startSchedule property is not a Date instance. Trying to convert it to a Date instance`, ); - storedChargingProfile.chargingSchedule.startSchedule = convertToDate( - storedChargingProfile.chargingSchedule?.startSchedule, + chargingProfile.chargingSchedule.startSchedule = convertToDate( + chargingProfile.chargingSchedule?.startSchedule, )!; } + if ( + !isNullOrUndefined(chargingProfile.chargingSchedule?.startSchedule) && + isNullOrUndefined(chargingProfile.chargingSchedule?.duration) + ) { + logger.debug( + `${chargingStation.logPrefix()} ${moduleName}.handleRequestGetCompositeSchedule: Charging profile id ${ + chargingProfile.chargingProfileId + } has no duration defined and will be set to the maximum time allowed`, + ); + // OCPP specifies that if duration is not defined, it should be infinite + chargingProfile.chargingSchedule.duration = differenceInSeconds( + maxTime, + chargingProfile.chargingSchedule.startSchedule!, + ); + } if ( !prepareChargingProfileKind( connectorStatus, - storedChargingProfile, - interval.start as Date, + chargingProfile, + compositeScheduleInterval.start as Date, chargingStation.logPrefix(), ) ) { @@ -745,173 +771,35 @@ export class OCPP16IncomingRequestService extends OCPPIncomingRequestService { } if ( !canProceedChargingProfile( - storedChargingProfile, - interval.start as Date, + chargingProfile, + compositeScheduleInterval.start as Date, chargingStation.logPrefix(), ) ) { continue; } - // Add active charging profiles into chargingProfiles array - if ( - isValidTime(storedChargingProfile.chargingSchedule?.startSchedule) && - isWithinInterval(storedChargingProfile.chargingSchedule.startSchedule!, interval) - ) { - if (isEmptyArray(chargingProfiles)) { - if ( - isAfter( - addSeconds( - storedChargingProfile.chargingSchedule.startSchedule!, - storedChargingProfile.chargingSchedule.duration!, - ), - interval.end, - ) - ) { - storedChargingProfile.chargingSchedule.chargingSchedulePeriod = - storedChargingProfile.chargingSchedule.chargingSchedulePeriod.filter( - (schedulePeriod) => - isWithinInterval( - addSeconds( - storedChargingProfile.chargingSchedule.startSchedule!, - schedulePeriod.startPeriod, - )!, - interval, - ), - ); - storedChargingProfile.chargingSchedule.duration = differenceInSeconds( - interval.end, - storedChargingProfile.chargingSchedule.startSchedule!, - ); - } - chargingProfiles.push(storedChargingProfile); - } else if (isNotEmptyArray(chargingProfiles)) { - const chargingProfilesInterval: Interval = { - start: min( - chargingProfiles.map( - (chargingProfile) => chargingProfile.chargingSchedule.startSchedule ?? maxTime, - ), - ), - end: max( - chargingProfiles.map( - (chargingProfile) => - addSeconds( - chargingProfile.chargingSchedule.startSchedule!, - chargingProfile.chargingSchedule.duration!, - ) ?? minTime, - ), - ), - }; - let addChargingProfile = false; - if ( - isBefore(interval.start, chargingProfilesInterval.start) && - isBefore( - storedChargingProfile.chargingSchedule.startSchedule!, - chargingProfilesInterval.start, - ) - ) { - // Remove charging schedule periods that are after the start of the active profiles interval - storedChargingProfile.chargingSchedule.chargingSchedulePeriod = - storedChargingProfile.chargingSchedule.chargingSchedulePeriod.filter( - (schedulePeriod) => - isWithinInterval( - addSeconds( - storedChargingProfile.chargingSchedule.startSchedule!, - schedulePeriod.startPeriod, - ), - { - start: interval.start, - end: chargingProfilesInterval.start, - }, - ), - ); - addChargingProfile = true; - } - if ( - isBefore(chargingProfilesInterval.end, interval.end) && - isAfter( - addSeconds( - storedChargingProfile.chargingSchedule.startSchedule!, - storedChargingProfile.chargingSchedule.duration!, - ), - chargingProfilesInterval.end, - ) - ) { - // Remove charging schedule periods that are before the end of the active profiles interval - // FIXME: can lead to a gap in the charging schedule: chargingProfilesInterval.end -> first matching schedulePeriod.startPeriod - storedChargingProfile.chargingSchedule.chargingSchedulePeriod = - storedChargingProfile.chargingSchedule.chargingSchedulePeriod.filter( - (schedulePeriod) => - isWithinInterval( - addSeconds( - storedChargingProfile.chargingSchedule.startSchedule!, - schedulePeriod.startPeriod, - ), - { - start: chargingProfilesInterval.end, - end: interval.end, - }, - ), - ); - addChargingProfile = true; - } - addChargingProfile && chargingProfiles.push(storedChargingProfile); - } - } - } - const compositeScheduleStart: Date = min( - chargingProfiles.map( - (chargingProfile) => chargingProfile.chargingSchedule.startSchedule ?? maxTime, - ), - ); - const compositeScheduleDuration: number = Math.max( - ...chargingProfiles.map((chargingProfile) => - isNaN(chargingProfile.chargingSchedule.duration!) - ? -Infinity - : chargingProfile.chargingSchedule.duration!, - ), - ); - const compositeSchedulePeriods: OCPP16ChargingSchedulePeriod[] = chargingProfiles - .map((chargingProfile) => chargingProfile.chargingSchedule.chargingSchedulePeriod) - .reduce( - (accumulator, value) => - accumulator.concat(value).sort((a, b) => a.startPeriod - b.startPeriod), - [], + compositeSchedule = OCPP16ServiceUtils.composeChargingSchedules( + previousCompositeSchedule, + chargingProfile.chargingSchedule, + compositeScheduleInterval, ); - const compositeSchedule: OCPP16ChargingSchedule = { - startSchedule: compositeScheduleStart, - duration: compositeScheduleDuration, - chargingRateUnit: chargingProfiles.every( - (chargingProfile) => - chargingProfile.chargingSchedule.chargingRateUnit === OCPP16ChargingRateUnitType.AMPERE, - ) - ? OCPP16ChargingRateUnitType.AMPERE - : chargingProfiles.every( - (chargingProfile) => - chargingProfile.chargingSchedule.chargingRateUnit === OCPP16ChargingRateUnitType.WATT, - ) - ? OCPP16ChargingRateUnitType.WATT - : OCPP16ChargingRateUnitType.AMPERE, - chargingSchedulePeriod: compositeSchedulePeriods, - minChargeRate: Math.min( - ...chargingProfiles.map((chargingProfile) => - isNaN(chargingProfile.chargingSchedule.minChargeRate!) - ? Infinity - : chargingProfile.chargingSchedule.minChargeRate!, - ), - ), - }; - return { - status: GenericStatus.Accepted, - scheduleStart: compositeSchedule.startSchedule!, - connectorId, - chargingSchedule: compositeSchedule, - }; + previousCompositeSchedule = compositeSchedule; + } + if (compositeSchedule) { + return { + status: GenericStatus.Accepted, + scheduleStart: compositeSchedule.startSchedule!, + connectorId, + chargingSchedule: compositeSchedule, + }; + } + return OCPP16Constants.OCPP_RESPONSE_REJECTED; } private handleRequestClearChargingProfile( chargingStation: ChargingStation, - commandPayload: ClearChargingProfileRequest, - ): ClearChargingProfileResponse { + commandPayload: OCPP16ClearChargingProfileRequest, + ): OCPP16ClearChargingProfileResponse { if ( OCPP16ServiceUtils.checkFeatureProfile( chargingStation, @@ -924,16 +812,13 @@ export class OCPP16IncomingRequestService extends OCPPIncomingRequestService { const { connectorId } = commandPayload; if (chargingStation.hasConnector(connectorId!) === false) { logger.error( - `${chargingStation.logPrefix()} Trying to clear a charging profile(s) to - a non existing connector id ${connectorId}`, + `${chargingStation.logPrefix()} Trying to clear a charging profile(s) to a non existing connector id ${connectorId}`, ); return OCPP16Constants.OCPP_CLEAR_CHARGING_PROFILE_RESPONSE_UNKNOWN; } - if ( - !isNullOrUndefined(connectorId) && - isNotEmptyArray(chargingStation.getConnectorStatus(connectorId!)?.chargingProfiles) - ) { - chargingStation.getConnectorStatus(connectorId!)!.chargingProfiles = []; + const connectorStatus = chargingStation.getConnectorStatus(connectorId!); + if (!isNullOrUndefined(connectorId) && isNotEmptyArray(connectorStatus?.chargingProfiles)) { + connectorStatus!.chargingProfiles = []; logger.debug( `${chargingStation.logPrefix()} Charging profile(s) cleared on connector id ${connectorId}`, ); @@ -943,11 +828,11 @@ export class OCPP16IncomingRequestService extends OCPPIncomingRequestService { let clearedCP = false; if (chargingStation.hasEvses) { for (const evseStatus of chargingStation.evses.values()) { - for (const connectorStatus of evseStatus.connectors.values()) { + for (const status of evseStatus.connectors.values()) { clearedCP = OCPP16ServiceUtils.clearChargingProfiles( chargingStation, commandPayload, - connectorStatus.chargingProfiles, + status.chargingProfiles, ); } } @@ -974,8 +859,7 @@ export class OCPP16IncomingRequestService extends OCPPIncomingRequestService { const { connectorId, type } = commandPayload; if (chargingStation.hasConnector(connectorId) === false) { logger.error( - `${chargingStation.logPrefix()} Trying to change the availability of a - non existing connector id ${connectorId.toString()}`, + `${chargingStation.logPrefix()} Trying to change the availability of a non existing connector id ${connectorId}`, ); return OCPP16Constants.OCPP_AVAILABILITY_RESPONSE_REJECTED; } @@ -1049,7 +933,7 @@ export class OCPP16IncomingRequestService extends OCPPIncomingRequestService { const remoteStartTransactionLogMsg = ` ${chargingStation.logPrefix()} Transaction remotely STARTED on ${ chargingStation.stationInfo.chargingStationId - }#${transactionConnectorId.toString()} for idTag '${idTag}'`; + }#${transactionConnectorId} for idTag '${idTag}'`; await OCPP16ServiceUtils.sendAndSetConnectorStatus( chargingStation, transactionConnectorId, @@ -1063,11 +947,14 @@ export class OCPP16IncomingRequestService extends OCPPIncomingRequestService { ) { // Authorization successful, start transaction if ( - this.setRemoteStartTransactionChargingProfile( - chargingStation, - transactionConnectorId, - chargingProfile!, - ) === true + (chargingProfile && + this.setRemoteStartTransactionChargingProfile( + chargingStation, + transactionConnectorId, + chargingProfile, + // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing + ) === true) || + !chargingProfile ) { connectorStatus.transactionRemoteStarted = true; if ( @@ -1098,11 +985,14 @@ export class OCPP16IncomingRequestService extends OCPPIncomingRequestService { } // No authorization check required, start transaction if ( - this.setRemoteStartTransactionChargingProfile( - chargingStation, - transactionConnectorId, - chargingProfile!, - ) === true + (chargingProfile && + this.setRemoteStartTransactionChargingProfile( + chargingStation, + transactionConnectorId, + chargingProfile, + // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing + ) === true) || + !chargingProfile ) { connectorStatus.transactionRemoteStarted = true; if ( @@ -1137,9 +1027,8 @@ export class OCPP16IncomingRequestService extends OCPPIncomingRequestService { connectorId: number, idTag: string, ): Promise { - if ( - chargingStation.getConnectorStatus(connectorId)?.status !== OCPP16ChargePointStatus.Available - ) { + const connectorStatus = chargingStation.getConnectorStatus(connectorId); + if (connectorStatus?.status !== OCPP16ChargePointStatus.Available) { await OCPP16ServiceUtils.sendAndSetConnectorStatus( chargingStation, connectorId, @@ -1147,10 +1036,7 @@ export class OCPP16IncomingRequestService extends OCPPIncomingRequestService { ); } 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.logPrefix()} Remote starting transaction REJECTED on connector id ${connectorId}, idTag '${idTag}', availability '${connectorStatus?.availability}', status '${connectorStatus?.status}'`, ); return OCPP16Constants.OCPP_RESPONSE_REJECTED; } @@ -1160,29 +1046,20 @@ export class OCPP16IncomingRequestService extends OCPPIncomingRequestService { connectorId: number, chargingProfile: OCPP16ChargingProfile, ): boolean { - if ( - chargingProfile && - chargingProfile.chargingProfilePurpose === OCPP16ChargingProfilePurposeType.TX_PROFILE - ) { + if (chargingProfile?.chargingProfilePurpose === OCPP16ChargingProfilePurposeType.TX_PROFILE) { OCPP16ServiceUtils.setChargingProfile(chargingStation, connectorId, chargingProfile); logger.debug( - `${chargingStation.logPrefix()} Charging profile(s) set at remote start transaction - on connector id ${connectorId}: %j`, + `${chargingStation.logPrefix()} Charging profile(s) set at remote start transaction on connector id ${connectorId}: %j`, chargingProfile, ); return true; - } else if ( - chargingProfile && - chargingProfile.chargingProfilePurpose !== OCPP16ChargingProfilePurposeType.TX_PROFILE - ) { - logger.warn( - `${chargingStation.logPrefix()} Not allowed to set ${ - chargingProfile.chargingProfilePurpose - } charging profile(s) at remote start transaction`, - ); - return false; } - return true; + logger.warn( + `${chargingStation.logPrefix()} Not allowed to set ${ + chargingProfile.chargingProfilePurpose + } charging profile(s) at remote start transaction`, + ); + return false; } private async handleRequestRemoteStopTransaction( @@ -1211,8 +1088,7 @@ export class OCPP16IncomingRequestService extends OCPPIncomingRequestService { } } logger.warn( - `${chargingStation.logPrefix()} Trying to remote stop a non existing transaction with id - ${transactionId.toString()}`, + `${chargingStation.logPrefix()} Trying to remote stop a non existing transaction with id ${transactionId}`, ); return OCPP16Constants.OCPP_RESPONSE_REJECTED; } @@ -1229,8 +1105,7 @@ export class OCPP16IncomingRequestService extends OCPPIncomingRequestService { ) === false ) { logger.warn( - `${chargingStation.logPrefix()} ${moduleName}.handleRequestUpdateFirmware: - Cannot simulate firmware update: feature profile not supported`, + `${chargingStation.logPrefix()} ${moduleName}.handleRequestUpdateFirmware: Cannot simulate firmware update: feature profile not supported`, ); return OCPP16Constants.OCPP_RESPONSE_EMPTY; } @@ -1240,8 +1115,7 @@ export class OCPP16IncomingRequestService extends OCPPIncomingRequestService { chargingStation.stationInfo.firmwareStatus !== OCPP16FirmwareStatus.Installed ) { logger.warn( - `${chargingStation.logPrefix()} ${moduleName}.handleRequestUpdateFirmware: - Cannot simulate firmware update: firmware update is already in progress`, + `${chargingStation.logPrefix()} ${moduleName}.handleRequestUpdateFirmware: Cannot simulate firmware update: firmware update is already in progress`, ); return OCPP16Constants.OCPP_RESPONSE_EMPTY; } @@ -1347,10 +1221,9 @@ export class OCPP16IncomingRequestService extends OCPPIncomingRequestService { if (runningTransactions > 0) { const waitTime = secondsToMilliseconds(15); logger.debug( - `${chargingStation.logPrefix()} ${moduleName}.updateFirmwareSimulation: - ${runningTransactions} transaction(s) in progress, waiting ${formatDurationMilliSeconds( - waitTime, - )} before continuing firmware update simulation`, + `${chargingStation.logPrefix()} ${moduleName}.updateFirmwareSimulation: ${runningTransactions} transaction(s) in progress, waiting ${formatDurationMilliSeconds( + waitTime, + )} before continuing firmware update simulation`, ); await sleep(waitTime); transactionsStarted = true; @@ -1433,8 +1306,7 @@ export class OCPP16IncomingRequestService extends OCPPIncomingRequestService { ) === false ) { logger.warn( - `${chargingStation.logPrefix()} ${moduleName}.handleRequestGetDiagnostics: - Cannot get diagnostics: feature profile not supported`, + `${chargingStation.logPrefix()} ${moduleName}.handleRequestGetDiagnostics: Cannot get diagnostics: feature profile not supported`, ); return OCPP16Constants.OCPP_RESPONSE_EMPTY; } @@ -1472,8 +1344,9 @@ export class OCPP16IncomingRequestService extends OCPPIncomingRequestService { }) .catch((error) => { logger.error( - `${chargingStation.logPrefix()} ${moduleName}.handleRequestGetDiagnostics: - Error while sending '${OCPP16RequestCommand.DIAGNOSTICS_STATUS_NOTIFICATION}'`, + `${chargingStation.logPrefix()} ${moduleName}.handleRequestGetDiagnostics: Error while sending '${ + OCPP16RequestCommand.DIAGNOSTICS_STATUS_NOTIFICATION + }'`, error, ); }); @@ -1496,16 +1369,16 @@ export class OCPP16IncomingRequestService extends OCPPIncomingRequestService { } throw new OCPPError( ErrorType.GENERIC_ERROR, - `Diagnostics transfer failed with error code ${accessResponse.code.toString()}${ - uploadResponse?.code && `|${uploadResponse?.code.toString()}` + `Diagnostics transfer failed with error code ${accessResponse.code}${ + uploadResponse?.code && `|${uploadResponse?.code}` }`, OCPP16IncomingRequestCommand.GET_DIAGNOSTICS, ); } throw new OCPPError( ErrorType.GENERIC_ERROR, - `Diagnostics transfer failed with error code ${accessResponse.code.toString()}${ - uploadResponse?.code && `|${uploadResponse?.code.toString()}` + `Diagnostics transfer failed with error code ${accessResponse.code}${ + uploadResponse?.code && `|${uploadResponse?.code}` }`, OCPP16IncomingRequestCommand.GET_DIAGNOSTICS, ); @@ -1589,7 +1462,7 @@ export class OCPP16IncomingRequestService extends OCPPIncomingRequestService { .requestHandler( chargingStation, OCPP16RequestCommand.HEARTBEAT, - null, + undefined, { triggerMessage: true, }, @@ -1783,8 +1656,7 @@ export class OCPP16IncomingRequestService extends OCPPIncomingRequestService { const reservation = chargingStation.getReservationBy('reservationId', reservationId); if (isUndefined(reservation)) { logger.debug( - `${chargingStation.logPrefix()} Reservation with id ${reservationId} - does not exist on charging station`, + `${chargingStation.logPrefix()} Reservation with id ${reservationId} does not exist on charging station`, ); return OCPP16Constants.OCPP_CANCEL_RESERVATION_RESPONSE_REJECTED; }