From f938317f2902366a85a8f76de55ee51f1d4a662a Mon Sep 17 00:00:00 2001 From: =?utf8?q?J=C3=A9r=C3=B4me=20Benoit?= Date: Fri, 12 Jan 2024 17:45:03 +0100 Subject: [PATCH] refactor: cleanup nullish values handling MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Signed-off-by: Jérôme Benoit --- src/charging-station/ChargingStation.ts | 56 +++++++++-------- src/charging-station/Helpers.ts | 14 +++-- .../ChargingStationWorkerBroadcastChannel.ts | 3 +- .../ocpp/1.6/OCPP16IncomingRequestService.ts | 62 +++++++++---------- .../ocpp/1.6/OCPP16RequestService.ts | 3 +- .../ocpp/1.6/OCPP16ResponseService.ts | 49 +++++++-------- src/charging-station/ocpp/OCPPServiceUtils.ts | 19 +++--- 7 files changed, 104 insertions(+), 102 deletions(-) diff --git a/src/charging-station/ChargingStation.ts b/src/charging-station/ChargingStation.ts index 1f2b1d78..47ffecf2 100644 --- a/src/charging-station/ChargingStation.ts +++ b/src/charging-station/ChargingStation.ts @@ -427,8 +427,10 @@ export class ChargingStation extends EventEmitter { return numberOfRunningTransactions } - public getConnectorIdByTransactionId (transactionId: number): number | undefined { - if (this.hasEvses) { + public getConnectorIdByTransactionId (transactionId: number | undefined): number | undefined { + if (transactionId == null) { + return undefined + } else if (this.hasEvses) { for (const evseStatus of this.evses.values()) { for (const [connectorId, connectorStatus] of evseStatus.connectors) { if (connectorStatus.transactionId === transactionId) { @@ -446,19 +448,18 @@ export class ChargingStation extends EventEmitter { } public getEnergyActiveImportRegisterByTransactionId ( - transactionId: number, + transactionId: number | undefined, rounded = false ): number { return this.getEnergyActiveImportRegister( // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - this.getConnectorStatus(this.getConnectorIdByTransactionId(transactionId)!)!, + this.getConnectorStatus(this.getConnectorIdByTransactionId(transactionId)!), rounded ) } public getEnergyActiveImportRegisterByConnectorId (connectorId: number, rounded = false): number { - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - return this.getEnergyActiveImportRegister(this.getConnectorStatus(connectorId)!, rounded) + return this.getEnergyActiveImportRegister(this.getConnectorStatus(connectorId), rounded) } public getAuthorizeRemoteTxRequests (): boolean { @@ -561,21 +562,22 @@ export class ChargingStation extends EventEmitter { logger.error(`${this.logPrefix()} Trying to start MeterValues on connector id ${connectorId}`) return } - if (this.getConnectorStatus(connectorId) == null) { + const connectorStatus = this.getConnectorStatus(connectorId) + if (connectorStatus == null) { logger.error( `${this.logPrefix()} Trying to start MeterValues on non existing connector id ${connectorId}` ) return } - if (this.getConnectorStatus(connectorId)?.transactionStarted === false) { + if (connectorStatus.transactionStarted === false) { logger.error( `${this.logPrefix()} Trying to start MeterValues on connector id ${connectorId} with no transaction started` ) return } else if ( - this.getConnectorStatus(connectorId)?.transactionStarted === true && - this.getConnectorStatus(connectorId)?.transactionId == null + connectorStatus.transactionStarted === true && + connectorStatus.transactionId == null ) { logger.error( `${this.logPrefix()} Trying to start MeterValues on connector id ${connectorId} with no transaction id` @@ -583,13 +585,12 @@ export class ChargingStation extends EventEmitter { return } if (interval > 0) { - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - this.getConnectorStatus(connectorId)!.transactionSetInterval = setInterval(() => { + connectorStatus.transactionSetInterval = setInterval(() => { const meterValue = buildMeterValue( this, connectorId, // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - this.getConnectorStatus(connectorId)!.transactionId!, + connectorStatus.transactionId!, interval ) this.ocppRequestService @@ -598,7 +599,7 @@ export class ChargingStation extends EventEmitter { RequestCommand.METER_VALUES, { connectorId, - transactionId: this.getConnectorStatus(connectorId)?.transactionId, + transactionId: connectorStatus.transactionId, meterValue: [meterValue] } ) @@ -619,8 +620,9 @@ export class ChargingStation extends EventEmitter { } public stopMeterValues (connectorId: number): void { - if (this.getConnectorStatus(connectorId)?.transactionSetInterval != null) { - clearInterval(this.getConnectorStatus(connectorId)?.transactionSetInterval) + const connectorStatus = this.getConnectorStatus(connectorId) + if (connectorStatus?.transactionSetInterval != null) { + clearInterval(connectorStatus.transactionSetInterval) } } @@ -859,8 +861,7 @@ export class ChargingStation extends EventEmitter { connectorId: number, reason?: StopTransactionReason ): Promise { - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - const transactionId = this.getConnectorStatus(connectorId)!.transactionId! + const transactionId = this.getConnectorStatus(connectorId)?.transactionId if ( this.stationInfo?.beginEndMeterValues === true && this.stationInfo.ocppStrictCompliance === true && @@ -2018,20 +2019,25 @@ export class ChargingStation extends EventEmitter { logger.error(`${this.logPrefix()} WebSocket error:`, error) } - private getEnergyActiveImportRegister (connectorStatus: ConnectorStatus, rounded = false): number { + private getEnergyActiveImportRegister ( + connectorStatus: ConnectorStatus | undefined, + rounded = false + ): number { if (this.stationInfo?.meteringPerTransaction === true) { return ( (rounded - ? // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - Math.round(connectorStatus.transactionEnergyActiveImportRegisterValue!) - : connectorStatus.transactionEnergyActiveImportRegisterValue) ?? 0 + ? connectorStatus?.transactionEnergyActiveImportRegisterValue != null + ? Math.round(connectorStatus.transactionEnergyActiveImportRegisterValue) + : undefined + : connectorStatus?.transactionEnergyActiveImportRegisterValue) ?? 0 ) } return ( (rounded - ? // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - Math.round(connectorStatus.energyActiveImportRegisterValue!) - : connectorStatus.energyActiveImportRegisterValue) ?? 0 + ? connectorStatus?.energyActiveImportRegisterValue != null + ? Math.round(connectorStatus.energyActiveImportRegisterValue) + : undefined + : connectorStatus?.energyActiveImportRegisterValue) ?? 0 ) } diff --git a/src/charging-station/Helpers.ts b/src/charging-station/Helpers.ts index d8ef4a32..bb736f3f 100644 --- a/src/charging-station/Helpers.ts +++ b/src/charging-station/Helpers.ts @@ -367,7 +367,10 @@ export const initializeConnectorsMapStatus = ( } } -export const resetConnectorStatus = (connectorStatus: ConnectorStatus): void => { +export const resetConnectorStatus = (connectorStatus: ConnectorStatus | undefined): void => { + if (connectorStatus == null) { + return + } connectorStatus.chargingProfiles = connectorStatus.transactionId != null && isNotEmptyArray(connectorStatus.chargingProfiles) ? connectorStatus.chargingProfiles?.filter( @@ -795,8 +798,7 @@ const getLimitFromChargingProfiles = ( ): ChargingProfilesLimit | undefined => { const debugLogMsg = `${logPrefix} ${moduleName}.getLimitFromChargingProfiles: Matching charging profile found for power limitation: %j` const currentDate = new Date() - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - const connectorStatus = chargingStation.getConnectorStatus(connectorId)! + const connectorStatus = chargingStation.getConnectorStatus(connectorId) for (const chargingProfile of chargingProfiles) { const chargingSchedule = chargingProfile.chargingSchedule if (chargingSchedule.startSchedule == null) { @@ -804,7 +806,7 @@ const getLimitFromChargingProfiles = ( `${logPrefix} ${moduleName}.getLimitFromChargingProfiles: Charging profile id ${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 - chargingSchedule.startSchedule = connectorStatus.transactionStart + chargingSchedule.startSchedule = connectorStatus?.transactionStart } if (!isDate(chargingSchedule.startSchedule)) { logger.warn( @@ -915,7 +917,7 @@ const getLimitFromChargingProfiles = ( } export const prepareChargingProfileKind = ( - connectorStatus: ConnectorStatus, + connectorStatus: ConnectorStatus | undefined, chargingProfile: ChargingProfile, currentDate: string | number | Date, logPrefix: string @@ -934,7 +936,7 @@ export const prepareChargingProfileKind = ( ) delete chargingProfile.chargingSchedule.startSchedule } - if (connectorStatus.transactionStarted === true) { + if (connectorStatus?.transactionStarted === true) { chargingProfile.chargingSchedule.startSchedule = connectorStatus.transactionStart } // FIXME: Handle relative charging profile duration diff --git a/src/charging-station/broadcast-channel/ChargingStationWorkerBroadcastChannel.ts b/src/charging-station/broadcast-channel/ChargingStationWorkerBroadcastChannel.ts index 24074186..b82587c4 100644 --- a/src/charging-station/broadcast-channel/ChargingStationWorkerBroadcastChannel.ts +++ b/src/charging-station/broadcast-channel/ChargingStationWorkerBroadcastChannel.ts @@ -129,8 +129,7 @@ export class ChargingStationWorkerBroadcastChannel extends WorkerBroadcastChanne RequestCommand.STOP_TRANSACTION, { meterStop: this.chargingStation.getEnergyActiveImportRegisterByTransactionId( - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - requestPayload!.transactionId!, + requestPayload?.transactionId, true ), ...requestPayload diff --git a/src/charging-station/ocpp/1.6/OCPP16IncomingRequestService.ts b/src/charging-station/ocpp/1.6/OCPP16IncomingRequestService.ts index 64d836d5..3e371e82 100644 --- a/src/charging-station/ocpp/1.6/OCPP16IncomingRequestService.ts +++ b/src/charging-station/ocpp/1.6/OCPP16IncomingRequestService.ts @@ -691,10 +691,9 @@ export class OCPP16IncomingRequestService extends OCPPIncomingRequestService { `${chargingStation.logPrefix()} Get composite schedule with a specified rate unit is not yet supported, no conversion will be done` ) } - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - const connectorStatus = chargingStation.getConnectorStatus(connectorId)! + const connectorStatus = chargingStation.getConnectorStatus(connectorId) if ( - isEmptyArray(connectorStatus.chargingProfiles) && + isEmptyArray(connectorStatus?.chargingProfiles) && isEmptyArray(chargingStation.getConnectorStatus(0)?.chargingProfiles) ) { return OCPP16Constants.OCPP_RESPONSE_REJECTED @@ -719,7 +718,7 @@ export class OCPP16IncomingRequestService extends OCPPIncomingRequestService { } 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 - chargingProfile.chargingSchedule.startSchedule = connectorStatus.transactionStart + chargingProfile.chargingSchedule.startSchedule = connectorStatus?.transactionStart } if (!isDate(chargingProfile.chargingSchedule.startSchedule)) { logger.warn( @@ -857,7 +856,7 @@ export class OCPP16IncomingRequestService extends OCPPIncomingRequestService { ? OCPP16ChargePointStatus.Available : OCPP16ChargePointStatus.Unavailable if (connectorId === 0) { - let response: OCPP16ChangeAvailabilityResponse + let response: OCPP16ChangeAvailabilityResponse | undefined if (chargingStation.hasEvses) { for (const evseStatus of chargingStation.evses.values()) { response = await OCPP16ServiceUtils.changeAvailability( @@ -1455,31 +1454,9 @@ export class OCPP16IncomingRequestService extends OCPPIncomingRequestService { } ) .catch(Constants.EMPTY_FUNCTION) - } else { - if (chargingStation.hasEvses) { - for (const evseStatus of chargingStation.evses.values()) { - for (const [id, connectorStatus] of evseStatus.connectors) { - chargingStation.ocppRequestService - .requestHandler< - OCPP16StatusNotificationRequest, - OCPP16StatusNotificationResponse - >( - chargingStation, - OCPP16RequestCommand.STATUS_NOTIFICATION, - { - connectorId: id, - errorCode: OCPP16ChargePointErrorCode.NO_ERROR, - status: connectorStatus.status - }, - { - triggerMessage: true - } - ) - .catch(Constants.EMPTY_FUNCTION) - } - } - } else { - for (const id of chargingStation.connectors.keys()) { + } else if (chargingStation.hasEvses) { + for (const evseStatus of chargingStation.evses.values()) { + for (const [id, connectorStatus] of evseStatus.connectors) { chargingStation.ocppRequestService .requestHandler< OCPP16StatusNotificationRequest, @@ -1490,7 +1467,7 @@ export class OCPP16IncomingRequestService extends OCPPIncomingRequestService { { connectorId: id, errorCode: OCPP16ChargePointErrorCode.NO_ERROR, - status: chargingStation.getConnectorStatus(id)?.status + status: connectorStatus.status }, { triggerMessage: true @@ -1499,6 +1476,26 @@ export class OCPP16IncomingRequestService extends OCPPIncomingRequestService { .catch(Constants.EMPTY_FUNCTION) } } + } else { + for (const [id, connectorStatus] of chargingStation.connectors) { + chargingStation.ocppRequestService + .requestHandler< + OCPP16StatusNotificationRequest, + OCPP16StatusNotificationResponse + >( + chargingStation, + OCPP16RequestCommand.STATUS_NOTIFICATION, + { + connectorId: id, + errorCode: OCPP16ChargePointErrorCode.NO_ERROR, + status: connectorStatus.status + }, + { + triggerMessage: true + } + ) + .catch(Constants.EMPTY_FUNCTION) + } } }, OCPP16Constants.OCPP_TRIGGER_MESSAGE_DELAY) return OCPP16Constants.OCPP_TRIGGER_MESSAGE_RESPONSE_ACCEPTED @@ -1563,8 +1560,7 @@ export class OCPP16IncomingRequestService extends OCPPIncomingRequestService { return OCPP16Constants.OCPP_RESERVATION_RESPONSE_REJECTED } await removeExpiredReservations(chargingStation) - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - switch (chargingStation.getConnectorStatus(connectorId)!.status) { + switch (chargingStation.getConnectorStatus(connectorId)?.status) { case OCPP16ChargePointStatus.Faulted: response = OCPP16Constants.OCPP_RESERVATION_RESPONSE_FAULTED break diff --git a/src/charging-station/ocpp/1.6/OCPP16RequestService.ts b/src/charging-station/ocpp/1.6/OCPP16RequestService.ts index 124ffba1..415254d1 100644 --- a/src/charging-station/ocpp/1.6/OCPP16RequestService.ts +++ b/src/charging-station/ocpp/1.6/OCPP16RequestService.ts @@ -201,10 +201,9 @@ export class OCPP16RequestService extends OCPPRequestService { } as unknown as Request case OCPP16RequestCommand.STOP_TRANSACTION: chargingStation.stationInfo?.transactionDataMeterValues === true && - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion (connectorId = chargingStation.getConnectorIdByTransactionId( commandParams.transactionId as number - )!) + )) energyActiveImportRegister = chargingStation.getEnergyActiveImportRegisterByTransactionId( commandParams.transactionId as number, true diff --git a/src/charging-station/ocpp/1.6/OCPP16ResponseService.ts b/src/charging-station/ocpp/1.6/OCPP16ResponseService.ts index 3f311ba5..7c2c041d 100644 --- a/src/charging-station/ocpp/1.6/OCPP16ResponseService.ts +++ b/src/charging-station/ocpp/1.6/OCPP16ResponseService.ts @@ -460,29 +460,30 @@ export class OCPP16ResponseService extends OCPPResponseService { } } } - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - const authorizeConnectorStatus = chargingStation.getConnectorStatus(authorizeConnectorId!) - const authorizeConnectorIdDefined = authorizeConnectorId != null - if (payload.idTagInfo.status === OCPP16AuthorizationStatus.ACCEPTED) { - if (authorizeConnectorIdDefined) { - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - authorizeConnectorStatus!.idTagAuthorized = true + if (authorizeConnectorId != null) { + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + const authorizeConnectorStatus = chargingStation.getConnectorStatus(authorizeConnectorId)! + if (payload.idTagInfo.status === OCPP16AuthorizationStatus.ACCEPTED) { + authorizeConnectorStatus.idTagAuthorized = true + logger.debug( + `${chargingStation.logPrefix()} idTag '${ + requestPayload.idTag + }' accepted on connector id ${authorizeConnectorId}` + ) + } else { + authorizeConnectorStatus.idTagAuthorized = false + delete authorizeConnectorStatus.authorizeIdTag + logger.debug( + `${chargingStation.logPrefix()} idTag '${requestPayload.idTag}' rejected with status '${ + payload.idTagInfo.status + }` + ) } - logger.debug( - `${chargingStation.logPrefix()} idTag '${requestPayload.idTag}' accepted${ - authorizeConnectorIdDefined ? ` on connector id ${authorizeConnectorId}` : '' - }` - ) } else { - if (authorizeConnectorIdDefined) { - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - authorizeConnectorStatus!.idTagAuthorized = false - delete authorizeConnectorStatus?.authorizeIdTag - } - logger.debug( - `${chargingStation.logPrefix()} idTag '${requestPayload.idTag}' rejected with status '${ - payload.idTagInfo.status - }'${authorizeConnectorIdDefined ? ` on connector id ${authorizeConnectorId}` : ''}` + logger.error( + `${chargingStation.logPrefix()} idTag '${ + requestPayload.idTag + }' has no authorize request pending` ) } } @@ -699,8 +700,7 @@ export class OCPP16ResponseService extends OCPPResponseService { connectorId: number ): Promise { const connectorStatus = chargingStation.getConnectorStatus(connectorId) - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - resetConnectorStatus(connectorStatus!) + resetConnectorStatus(connectorStatus) chargingStation.stopMeterValues(connectorId) if (connectorStatus?.status !== OCPP16ChargePointStatus.Available) { await OCPP16ServiceUtils.sendAndSetConnectorStatus( @@ -764,8 +764,7 @@ export class OCPP16ResponseService extends OCPPResponseService { // eslint-disable-next-line @typescript-eslint/no-non-null-assertion chargingStation.powerDivider!-- } - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - resetConnectorStatus(chargingStation.getConnectorStatus(transactionConnectorId)!) + resetConnectorStatus(chargingStation.getConnectorStatus(transactionConnectorId)) chargingStation.stopMeterValues(transactionConnectorId) const logMsg = `${chargingStation.logPrefix()} Transaction with id ${ requestPayload.transactionId diff --git a/src/charging-station/ocpp/OCPPServiceUtils.ts b/src/charging-station/ocpp/OCPPServiceUtils.ts index e73caca4..414b0a8f 100644 --- a/src/charging-station/ocpp/OCPPServiceUtils.ts +++ b/src/charging-station/ocpp/OCPPServiceUtils.ts @@ -120,9 +120,12 @@ export const isIdTagAuthorized = async ( `${chargingStation.logPrefix()} The charging station expects to authorize RFID tags but nor local authorization nor remote authorization are enabled. Misbehavior may occur` ) } - if (chargingStation.getLocalAuthListEnabled() && isIdTagLocalAuthorized(chargingStation, idTag)) { - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - const connectorStatus = chargingStation.getConnectorStatus(connectorId)! + const connectorStatus = chargingStation.getConnectorStatus(connectorId) + if ( + connectorStatus != null && + chargingStation.getLocalAuthListEnabled() && + isIdTagLocalAuthorized(chargingStation, idTag) + ) { connectorStatus.localAuthorizeIdTag = idTag connectorStatus.idTagLocalAuthorized = true return true @@ -196,8 +199,7 @@ const checkConnectorStatusTransition = ( connectorId: number, status: ConnectorStatusEnum ): boolean => { - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - const fromStatus = chargingStation.getConnectorStatus(connectorId)!.status + const fromStatus = chargingStation.getConnectorStatus(connectorId)?.status let transitionAllowed = false switch (chargingStation.stationInfo?.ocppVersion) { case OCPPVersion.VERSION_16: @@ -238,10 +240,9 @@ const checkConnectorStatusTransition = ( logger.warn( `${chargingStation.logPrefix()} OCPP ${ chargingStation.stationInfo.ocppVersion - } connector id ${connectorId} status transition from '${ - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - chargingStation.getConnectorStatus(connectorId)!.status - }' to '${status}' is not allowed` + } connector id ${connectorId} status transition from '${chargingStation.getConnectorStatus( + connectorId + )?.status}' to '${status}' is not allowed` ) } return transitionAllowed -- 2.34.1