| mainVoltageMeterValues | true/false | true | boolean | include charging stations main voltage MeterValues on three phased charging stations |
| phaseLineToLineVoltageMeterValues | true/false | true | boolean | include charging stations line to line voltage MeterValues on three phased charging stations |
| customValueLimitationMeterValues | true/false | true | boolean | enable limitation on custom fluctuated value in MeterValues |
-| commandsSupport | | {<br />"incomingCommands": {},<br />"outgoingCommands": {}<br />} | {<br /> incomingCommands: Record<IncomingRequestCommand, boolean>;<br />outgoingCommands?: Record<RequestCommand, boolean>;<br />} | Configuration section for OCPP commands support. Empty section or subsections means all implemented commands are supported |
+| commandsSupport | | {<br />"incomingCommands": {},<br />"outgoingCommands": {}<br />} | {<br /> incomingCommands: Record<IncomingRequestCommand, boolean>;<br />outgoingCommands?: Record<RequestCommand, boolean>;<br />} | Configuration section for OCPP commands support. Empty section or subsections means all implemented OCPP commands are supported |
+| messageTriggerSupport | | {} | Record<MessageTrigger, boolean> | Configuration section for OCPP commands trigger support. Empty section means all implemented OCPP trigger commands are supported |
| Configuration | | | ChargingStationConfiguration | charging stations OCPP parameters configuration section |
| AutomaticTransactionGenerator | | | AutomaticTransactionGenerator | charging stations ATG configuration section |
| Connectors | | | Connectors | charging stations connectors configuration section |
"TriggerMessage": false
}
},
+ "messageTriggerSupport": {
+ "BootNotification": true,
+ "Heartbeat": true,
+ "StatusNotification": false
+ },
"Configuration": {
"configurationKey": [
{
DiagnosticsStatusNotificationRequest,
GetConfigurationRequest,
GetDiagnosticsRequest,
- MessageTrigger,
OCPP16AvailabilityType,
OCPP16BootNotificationRequest,
OCPP16ClearCacheRequest,
OCPP16HeartbeatRequest,
OCPP16IncomingRequestCommand,
+ OCPP16MessageTrigger,
OCPP16RequestCommand,
OCPP16StatusNotificationRequest,
OCPP16TriggerMessageRequest,
commandPayload: UnlockConnectorRequest
): Promise<UnlockConnectorResponse> {
const connectorId = commandPayload.connectorId;
+ if (chargingStation.connectors.has(connectorId) === false) {
+ logger.error(
+ `${chargingStation.logPrefix()} Trying to unlock a non existing connector Id ${connectorId.toString()}`
+ );
+ return Constants.OCPP_RESPONSE_UNLOCK_NOT_SUPPORTED;
+ }
if (connectorId === 0) {
logger.error(
- chargingStation.logPrefix() + ' Trying to unlock connector ' + connectorId.toString()
+ chargingStation.logPrefix() + ' Trying to unlock connector Id ' + connectorId.toString()
);
return Constants.OCPP_RESPONSE_UNLOCK_NOT_SUPPORTED;
}
commandPayload: ChangeAvailabilityRequest
): Promise<ChangeAvailabilityResponse> {
const connectorId: number = commandPayload.connectorId;
- if (!chargingStation.getConnectorStatus(connectorId)) {
+ if (chargingStation.connectors.has(connectorId) === false) {
logger.error(
`${chargingStation.logPrefix()} Trying to change the availability of a non existing connector Id ${connectorId.toString()}`
);
chargingStation,
OCPP16SupportedFeatureProfiles.RemoteTrigger,
OCPP16IncomingRequestCommand.TRIGGER_MESSAGE
+ ) ||
+ !OCPP16ServiceUtils.isMessageTriggerSupported(
+ chargingStation,
+ commandPayload.requestedMessage
)
) {
return Constants.OCPP_TRIGGER_MESSAGE_RESPONSE_NOT_IMPLEMENTED;
}
- // TODO: factor out the check on connector id
- if (commandPayload?.connectorId < 0) {
- logger.warn(
- `${chargingStation.logPrefix()} ${
- OCPP16IncomingRequestCommand.TRIGGER_MESSAGE
- } incoming request received with invalid connectorId ${commandPayload.connectorId}`
- );
+ if (
+ OCPP16ServiceUtils.isConnectorIdValid(
+ chargingStation,
+ OCPP16IncomingRequestCommand.TRIGGER_MESSAGE,
+ commandPayload.connectorId
+ )
+ ) {
return Constants.OCPP_TRIGGER_MESSAGE_RESPONSE_REJECTED;
}
try {
switch (commandPayload.requestedMessage) {
- case MessageTrigger.BootNotification:
+ case OCPP16MessageTrigger.BootNotification:
setTimeout(() => {
chargingStation.ocppRequestService
.requestHandler<OCPP16BootNotificationRequest, OCPP16BootNotificationResponse>(
});
}, Constants.OCPP_TRIGGER_MESSAGE_DELAY);
return Constants.OCPP_TRIGGER_MESSAGE_RESPONSE_ACCEPTED;
- case MessageTrigger.Heartbeat:
+ case OCPP16MessageTrigger.Heartbeat:
setTimeout(() => {
chargingStation.ocppRequestService
.requestHandler<OCPP16HeartbeatRequest, OCPP16HeartbeatResponse>(
});
}, Constants.OCPP_TRIGGER_MESSAGE_DELAY);
return Constants.OCPP_TRIGGER_MESSAGE_RESPONSE_ACCEPTED;
- case MessageTrigger.StatusNotification:
+ case OCPP16MessageTrigger.StatusNotification:
setTimeout(() => {
if (commandPayload?.connectorId) {
chargingStation.ocppRequestService
import { StandardParametersKey } from '../../types/ocpp/Configuration';
import { ErrorType } from '../../types/ocpp/ErrorType';
import { MeterValueMeasurand, type MeterValuePhase } from '../../types/ocpp/MeterValues';
-import { IncomingRequestCommand, RequestCommand } from '../../types/ocpp/Requests';
+import { IncomingRequestCommand, MessageTrigger, RequestCommand } from '../../types/ocpp/Requests';
import Constants from '../../utils/Constants';
import logger from '../../utils/Logger';
import Utils from '../../utils/Utils';
return false;
}
+ public static isMessageTriggerSupported(
+ chargingStation: ChargingStation,
+ messageTrigger: MessageTrigger
+ ): boolean {
+ const isMessageTrigger = Object.values(MessageTrigger).includes(messageTrigger);
+ if (isMessageTrigger === true && !chargingStation.stationInfo?.messageTriggerSupport) {
+ return true;
+ } else if (isMessageTrigger === true && chargingStation.stationInfo?.messageTriggerSupport) {
+ return chargingStation.stationInfo?.messageTriggerSupport[messageTrigger] ?? false;
+ }
+ logger.error(
+ `${chargingStation.logPrefix()} Unknown incoming OCPP message trigger '${messageTrigger}'`
+ );
+ return false;
+ }
+
+ public static isConnectorIdValid(
+ chargingStation: ChargingStation,
+ ocppCommand: IncomingRequestCommand,
+ connectorId: number
+ ): boolean {
+ if (connectorId < 0) {
+ logger.error(
+ `${chargingStation.logPrefix()} ${ocppCommand} incoming request received with invalid connectorId ${connectorId}`
+ );
+ return false;
+ }
+ return true;
+ }
+
protected static getSampledValueTemplate(
chargingStation: ChargingStation,
connectorId: number,
import type { ConnectorStatus } from './ConnectorStatus';
import type { OCPPProtocol } from './ocpp/OCPPProtocol';
import type { OCPPVersion } from './ocpp/OCPPVersion';
-import type { IncomingRequestCommand, RequestCommand } from './ocpp/Requests';
+import type { IncomingRequestCommand, MessageTrigger, RequestCommand } from './ocpp/Requests';
export enum CurrentType {
AC = 'AC',
phaseLineToLineVoltageMeterValues?: boolean;
customValueLimitationMeterValues?: boolean;
commandsSupport?: CommandsSupport;
+ messageTriggerSupport?: Record<MessageTrigger, boolean>;
Configuration?: ChargingStationOcppConfiguration;
AutomaticTransactionGenerator?: AutomaticTransactionGeneratorConfiguration;
Connectors: Record<string, ConnectorStatus>;
status: OCPP16DiagnosticsStatus;
}
-export enum MessageTrigger {
+export enum OCPP16MessageTrigger {
BootNotification = 'BootNotification',
DiagnosticsStatusNotification = 'DiagnosticsStatusNotification',
FirmwareStatusNotification = 'FirmwareStatusNotification',
}
export interface OCPP16TriggerMessageRequest extends JsonObject {
- requestedMessage: MessageTrigger;
+ requestedMessage: OCPP16MessageTrigger;
connectorId?: number;
}
OCPP16BootNotificationRequest,
OCPP16HeartbeatRequest,
OCPP16IncomingRequestCommand,
+ OCPP16MessageTrigger,
OCPP16RequestCommand,
OCPP16StatusNotificationRequest,
} from './1.6/Requests';
JsonType
];
+export type MessageTrigger = OCPP16MessageTrigger;
+
+export const MessageTrigger = {
+ ...OCPP16MessageTrigger,
+};
+
export type BootNotificationRequest = OCPP16BootNotificationRequest;
export type HeartbeatRequest = OCPP16HeartbeatRequest;
phaseLineToLineVoltageMeterValues?: boolean;
customValueLimitationMeterValues?: boolean;
commandsSupport?: CommandsSupport;
+ messageTriggerSupport?: Record<MessageTrigger, boolean>;
};
export enum OCPP16IncomingRequestCommand {
interval: number;
}
+export enum OCPP16MessageTrigger {
+ BootNotification = 'BootNotification',
+ DiagnosticsStatusNotification = 'DiagnosticsStatusNotification',
+ FirmwareStatusNotification = 'FirmwareStatusNotification',
+ Heartbeat = 'Heartbeat',
+ MeterValues = 'MeterValues',
+ StatusNotification = 'StatusNotification',
+}
+
+export type MessageTrigger = OCPP16MessageTrigger;
+
+export const MessageTrigger = {
+ ...OCPP16MessageTrigger,
+};
+
type CommandsSupport = {
incomingCommands: Record<IncomingRequestCommand, boolean>;
outgoingCommands?: Record<RequestCommand, boolean>;