From 802cfa135dad14f8b15401685c3429395cb3e6e1 Mon Sep 17 00:00:00 2001 From: =?utf8?q?J=C3=A9r=C3=B4me=20Benoit?= Date: Sun, 5 Sep 2021 19:47:12 +0200 Subject: [PATCH] Add support for OCPP 1.6 TriggerMessage command MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Signed-off-by: Jérôme Benoit --- README.md | 2 +- src/charging-station/ChargingStation.ts | 4 +++ .../ocpp/1.6/OCPP16IncomingRequestService.ts | 27 +++++++++++++++++-- src/types/ocpp/1.6/Requests.ts | 19 +++++++++++-- src/types/ocpp/1.6/Responses.ts | 10 +++++++ src/types/ocpp/Responses.ts | 8 +++++- src/utils/Constants.ts | 6 ++++- 7 files changed, 69 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 1bbe4dd9..95c44eb9 100644 --- a/README.md +++ b/README.md @@ -231,7 +231,7 @@ make SUBMODULES_INIT=false #### Remote Trigger Profile -- :x: TriggerMessage +- :white_check_mark: TriggerMessage ## OCPP-J standard parameters supported diff --git a/src/charging-station/ChargingStation.ts b/src/charging-station/ChargingStation.ts index fb146eaf..e3dd077d 100644 --- a/src/charging-station/ChargingStation.ts +++ b/src/charging-station/ChargingStation.ts @@ -78,6 +78,10 @@ export default class ChargingStation { return Utils.logPrefix(` ${this.stationInfo.chargingStationId} |`); } + public getBootNotificationRequest(): BootNotificationRequest { + return this.bootNotificationRequest; + } + public getRandomTagId(): string { const index = Math.floor(Math.random() * this.authorizedTags.length); return this.authorizedTags[index]; diff --git a/src/charging-station/ocpp/1.6/OCPP16IncomingRequestService.ts b/src/charging-station/ocpp/1.6/OCPP16IncomingRequestService.ts index 1d93726d..541a27fb 100644 --- a/src/charging-station/ocpp/1.6/OCPP16IncomingRequestService.ts +++ b/src/charging-station/ocpp/1.6/OCPP16IncomingRequestService.ts @@ -2,8 +2,8 @@ import * as url from 'url'; -import { ChangeAvailabilityRequest, ChangeConfigurationRequest, ClearChargingProfileRequest, GetConfigurationRequest, GetDiagnosticsRequest, OCPP16AvailabilityType, OCPP16IncomingRequestCommand, RemoteStartTransactionRequest, RemoteStopTransactionRequest, ResetRequest, SetChargingProfileRequest, UnlockConnectorRequest } from '../../../types/ocpp/1.6/Requests'; -import { ChangeAvailabilityResponse, ChangeConfigurationResponse, ClearChargingProfileResponse, GetConfigurationResponse, GetDiagnosticsResponse, SetChargingProfileResponse, UnlockConnectorResponse } from '../../../types/ocpp/1.6/Responses'; +import { ChangeAvailabilityRequest, ChangeConfigurationRequest, ClearChargingProfileRequest, GetConfigurationRequest, GetDiagnosticsRequest, MessageTrigger, OCPP16AvailabilityType, OCPP16IncomingRequestCommand, OCPP16TriggerMessageRequest, RemoteStartTransactionRequest, RemoteStopTransactionRequest, ResetRequest, SetChargingProfileRequest, UnlockConnectorRequest } from '../../../types/ocpp/1.6/Requests'; +import { ChangeAvailabilityResponse, ChangeConfigurationResponse, ClearChargingProfileResponse, GetConfigurationResponse, GetDiagnosticsResponse, OCPP16TriggerMessageResponse, SetChargingProfileResponse, UnlockConnectorResponse } from '../../../types/ocpp/1.6/Responses'; import { ChargingProfilePurposeType, OCPP16ChargingProfile } from '../../../types/ocpp/1.6/ChargingProfile'; import { Client, FTPResponse } from 'basic-ftp'; import { IncomingRequestCommand, RequestCommand } from '../../../types/ocpp/Requests'; @@ -399,4 +399,27 @@ export default class OCPP16IncomingRequestService extends OCPPIncomingRequestSer return Constants.OCPP_RESPONSE_EMPTY; } } + + private handleRequestTriggerMessage(commandPayload: OCPP16TriggerMessageRequest): OCPP16TriggerMessageResponse { + try { + switch (commandPayload.requestedMessage) { + case MessageTrigger.BootNotification: + setTimeout(() => { + this.chargingStation.ocppRequestService.sendBootNotification(this.chargingStation.getBootNotificationRequest().chargePointModel, + this.chargingStation.getBootNotificationRequest().chargePointVendor, this.chargingStation.getBootNotificationRequest().chargeBoxSerialNumber, + this.chargingStation.getBootNotificationRequest().firmwareVersion).catch(() => {}); + }, Constants.OCPP_TRIGGER_MESSAGE_DELAY); + return Constants.OCPP_TRIGGER_MESSAGE_RESPONSE_ACCEPTED; + case MessageTrigger.Heartbeat: + setTimeout(() => { + this.chargingStation.ocppRequestService.sendHeartbeat().catch(() => {}); + }, Constants.OCPP_TRIGGER_MESSAGE_DELAY); + return Constants.OCPP_TRIGGER_MESSAGE_RESPONSE_ACCEPTED; + default: + return Constants.OCPP_TRIGGER_MESSAGE_RESPONSE_NOT_IMPLEMENTED; + } + } catch (error) { + return this.handleIncomingRequestError(IncomingRequestCommand.TRIGGER_MESSAGE, error, Constants.OCPP_TRIGGER_MESSAGE_RESPONSE_REJECTED) as OCPP16TriggerMessageResponse; + } + } } diff --git a/src/types/ocpp/1.6/Requests.ts b/src/types/ocpp/1.6/Requests.ts index 873d41a0..860f4b06 100644 --- a/src/types/ocpp/1.6/Requests.ts +++ b/src/types/ocpp/1.6/Requests.ts @@ -14,7 +14,7 @@ export enum OCPP16RequestCommand { START_TRANSACTION = 'StartTransaction', STOP_TRANSACTION = 'StopTransaction', METER_VALUES = 'MeterValues', - DIAGNOSTICS_STATUS_NOTIFICATION= 'DiagnosticsStatusNotification' + DIAGNOSTICS_STATUS_NOTIFICATION = 'DiagnosticsStatusNotification' } export enum OCPP16IncomingRequestCommand { @@ -28,7 +28,8 @@ export enum OCPP16IncomingRequestCommand { CLEAR_CHARGING_PROFILE = 'ClearChargingProfile', REMOTE_START_TRANSACTION = 'RemoteStartTransaction', REMOTE_STOP_TRANSACTION = 'RemoteStopTransaction', - GET_DIAGNOSTICS = 'GetDiagnostics' + GET_DIAGNOSTICS = 'GetDiagnostics', + TRIGGER_MESSAGE = 'TriggerMessage' } // eslint-disable-next-line @typescript-eslint/no-empty-interface @@ -121,3 +122,17 @@ export interface GetDiagnosticsRequest { export interface DiagnosticsStatusNotificationRequest { status: OCPP16DiagnosticsStatus } + +export enum MessageTrigger { + BootNotification = 'BootNotification', + DiagnosticsStatusNotification = 'DiagnosticsStatusNotification', + FirmwareStatusNotification = 'FirmwareStatusNotification', + Heartbeat = 'Heartbeat', + MeterValues = 'MeterValues', + StatusNotification = 'StatusNotification' +} + +export interface OCPP16TriggerMessageRequest { + requestedMessage: MessageTrigger; + connectorId?: number +} diff --git a/src/types/ocpp/1.6/Responses.ts b/src/types/ocpp/1.6/Responses.ts index 68df3e91..cf0a84ef 100644 --- a/src/types/ocpp/1.6/Responses.ts +++ b/src/types/ocpp/1.6/Responses.ts @@ -80,3 +80,13 @@ export interface GetDiagnosticsResponse { // eslint-disable-next-line @typescript-eslint/no-empty-interface export interface DiagnosticsStatusNotificationResponse {} + +export enum OCPP16TriggerMessageStatus { + ACCEPTED = 'Accepted', + REJECTED = 'Rejected', + NOT_IMPLEMENTED = 'NotImplemented' +} + +export interface OCPP16TriggerMessageResponse { + status: OCPP16TriggerMessageStatus +} diff --git a/src/types/ocpp/Responses.ts b/src/types/ocpp/Responses.ts index a09da33b..77497074 100644 --- a/src/types/ocpp/Responses.ts +++ b/src/types/ocpp/Responses.ts @@ -1,4 +1,4 @@ -import { OCPP16AvailabilityStatus, OCPP16BootNotificationResponse, OCPP16ChargingProfileStatus, OCPP16ClearChargingProfileStatus, OCPP16ConfigurationStatus, OCPP16RegistrationStatus, OCPP16UnlockStatus } from './1.6/Responses'; +import { OCPP16AvailabilityStatus, OCPP16BootNotificationResponse, OCPP16ChargingProfileStatus, OCPP16ClearChargingProfileStatus, OCPP16ConfigurationStatus, OCPP16RegistrationStatus, OCPP16TriggerMessageStatus, OCPP16UnlockStatus } from './1.6/Responses'; export type BootNotificationResponse = OCPP16BootNotificationResponse; @@ -46,3 +46,9 @@ export type UnlockStatus = OCPP16UnlockStatus; export const UnlockStatus = { ...OCPP16UnlockStatus }; + +export type TriggerMessageStatus = OCPP16TriggerMessageStatus; + +export const TriggerMessageStatus = { + ...OCPP16TriggerMessageStatus +}; diff --git a/src/utils/Constants.ts b/src/utils/Constants.ts index c83340e4..593aa42a 100644 --- a/src/utils/Constants.ts +++ b/src/utils/Constants.ts @@ -1,4 +1,4 @@ -import { AvailabilityStatus, ChargingProfileStatus, ClearChargingProfileStatus, ConfigurationStatus, DefaultStatus, UnlockStatus } from '../types/ocpp/Responses'; +import { AvailabilityStatus, ChargingProfileStatus, ClearChargingProfileStatus, ConfigurationStatus, DefaultStatus, TriggerMessageStatus, UnlockStatus } from '../types/ocpp/Responses'; import { MeterValueMeasurand } from '../types/ocpp/MeterValues'; @@ -21,9 +21,13 @@ export default class Constants { static readonly OCPP_AVAILABILITY_RESPONSE_ACCEPTED = Object.freeze({ status: AvailabilityStatus.ACCEPTED }); static readonly OCPP_AVAILABILITY_RESPONSE_REJECTED = Object.freeze({ status: AvailabilityStatus.REJECTED }); static readonly OCPP_AVAILABILITY_RESPONSE_SCHEDULED = Object.freeze({ status: AvailabilityStatus.SCHEDULED }); + static readonly OCPP_TRIGGER_MESSAGE_RESPONSE_ACCEPTED = Object.freeze({ status: TriggerMessageStatus.ACCEPTED }); + static readonly OCPP_TRIGGER_MESSAGE_RESPONSE_REJECTED = Object.freeze({ status: TriggerMessageStatus.REJECTED }); + static readonly OCPP_TRIGGER_MESSAGE_RESPONSE_NOT_IMPLEMENTED = Object.freeze({ status: TriggerMessageStatus.NOT_IMPLEMENTED }); static readonly OCPP_DEFAULT_BOOT_NOTIFICATION_INTERVAL = 60000; // Ms static readonly OCPP_ERROR_TIMEOUT = 60000; // Ms + static readonly OCPP_TRIGGER_MESSAGE_DELAY = 2000; // Ms static readonly CHARGING_STATION_DEFAULT_RESET_TIME = 60000; // Ms static readonly CHARGING_STATION_ATG_WAIT_TIME = 2000; // Ms -- 2.34.1