* 3. Request routed to appropriate handler method
* 4. Business logic executed with charging station state management
* 5. Response payload validated and sent back to Central System
- * @see {@link validatePayload} Request payload validation method
+ * @see {@link validateIncomingRequestPayload} Request payload validation method
* @see {@link handleRequestRemoteStartTransaction} Example request handler
*/
])
this.payloadValidatorFunctions = OCPP16ServiceUtils.createPayloadValidatorMap(
OCPP16ServiceUtils.createIncomingRequestPayloadConfigs(),
- OCPP16ServiceUtils.createIncomingRequestPayloadOptions(moduleName, 'constructor'),
+ OCPP16ServiceUtils.createPayloadOptions(moduleName, 'constructor'),
this.ajv
)
// Handle incoming request events
}
}
)
- this.validatePayload = this.validatePayload.bind(this)
}
// eslint-disable-next-line @typescript-eslint/no-unnecessary-type-parameters
OCPP16ServiceUtils.isIncomingRequestCommandSupported(chargingStation, commandName)
) {
try {
- this.validatePayload(chargingStation, commandName, commandPayload)
+ this.validateIncomingRequestPayload(chargingStation, commandName, commandPayload)
// Call the method to build the response
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const incomingRequestHandler = this.incomingRequestHandlers.get(commandName)!
await chargingStation.reset(OCPP16StopTransactionReason.REBOOT)
}
}
-
- /**
- * Validates incoming OCPP 1.6 request payload against JSON schema
- * @param chargingStation - The charging station instance processing the request
- * @param commandName - OCPP 1.6 command name to validate against
- * @param commandPayload - JSON payload to validate
- * @returns True if payload validation succeeds, false otherwise
- */
- private validatePayload (
- chargingStation: ChargingStation,
- commandName: OCPP16IncomingRequestCommand,
- commandPayload: JsonType
- ): boolean {
- if (this.payloadValidatorFunctions.has(commandName)) {
- return this.validateIncomingRequestPayload(chargingStation, commandName, commandPayload)
- }
- logger.warn(
- `${chargingStation.logPrefix()} ${moduleName}.validatePayload: No JSON schema validation function found for command '${commandName}' PDU validation`
- )
- return false
- }
}
super(OCPPVersion.VERSION_16, ocppResponseService)
this.payloadValidatorFunctions = OCPP16ServiceUtils.createPayloadValidatorMap(
OCPP16ServiceUtils.createRequestPayloadConfigs(),
- OCPP16ServiceUtils.createRequestPayloadOptions(moduleName, 'constructor'),
+ OCPP16ServiceUtils.createPayloadOptions(moduleName, 'constructor'),
this.ajv
)
this.buildRequestPayload = this.buildRequestPayload.bind(this)
* 3. Response routed to appropriate handler based on original request type
* 4. Charging station state updated based on response content
* 5. Any follow-up actions triggered (transactions, status changes, etc.)
- * @see {@link validatePayload} Response payload validation method
+ * @see {@link validateResponsePayload} Response payload validation method
* @see {@link handleResponse} Response processing methods
*/
])
this.payloadValidatorFunctions = OCPP16ServiceUtils.createPayloadValidatorMap(
OCPP16ServiceUtils.createResponsePayloadConfigs(),
- OCPP16ServiceUtils.createResponsePayloadOptions(moduleName, 'constructor'),
+ OCPP16ServiceUtils.createPayloadOptions(moduleName, 'constructor'),
this.ajv
)
this.incomingRequestResponsePayloadValidateFunctions =
OCPP16ServiceUtils.createPayloadValidatorMap(
OCPP16ServiceUtils.createIncomingRequestResponsePayloadConfigs(),
- OCPP16ServiceUtils.createIncomingRequestResponsePayloadOptions(moduleName, 'constructor'),
+ OCPP16ServiceUtils.createPayloadOptions(moduleName, 'constructor'),
this.ajvIncomingRequest
)
- this.validatePayload = this.validatePayload.bind(this)
}
// eslint-disable-next-line @typescript-eslint/no-unnecessary-type-parameters
OCPP16ServiceUtils.isRequestCommandSupported(chargingStation, commandName)
) {
try {
- this.validatePayload(chargingStation, commandName, payload)
+ this.validateResponsePayload(chargingStation, commandName, payload)
logger.debug(
`${chargingStation.logPrefix()} ${moduleName}.responseHandler: Handling '${commandName}' response`
)
resetConnectorStatus(connectorStatus)
await OCPP16ServiceUtils.restoreConnectorStatus(chargingStation, connectorId, connectorStatus)
}
-
- /**
- * Validates incoming OCPP 1.6 response payload against JSON schema
- * @param chargingStation - The charging station instance receiving the response
- * @param commandName - OCPP 1.6 command name to validate against
- * @param payload - JSON response payload to validate
- * @returns True if payload validation succeeds, false otherwise
- */
- private validatePayload (
- chargingStation: ChargingStation,
- commandName: OCPP16RequestCommand,
- payload: JsonType
- ): boolean {
- if (this.payloadValidatorFunctions.has(commandName)) {
- logger.debug(
- `${chargingStation.logPrefix()} ${moduleName}.validatePayload: Validating '${commandName}' response payload`
- )
- const isValid = this.validateResponsePayload(chargingStation, commandName, payload)
- if (!isValid) {
- logger.warn(
- `${chargingStation.logPrefix()} ${moduleName}.validatePayload: '${commandName}' response payload validation failed`
- )
- } else {
- logger.debug(
- `${chargingStation.logPrefix()} ${moduleName}.validatePayload: '${commandName}' response payload validation successful`
- )
- }
- return isValid
- }
- logger.warn(
- `${chargingStation.logPrefix()} ${moduleName}.validatePayload: No JSON schema validation function found for command '${commandName}' PDU validation`
- )
- return false
- }
}
const moduleName = 'OCPP16ServiceUtils'
export class OCPP16ServiceUtils extends OCPPServiceUtils {
+ private static readonly incomingRequestSchemaNames: readonly [
+ OCPP16IncomingRequestCommand,
+ string
+ ][] = [
+ [OCPP16IncomingRequestCommand.CANCEL_RESERVATION, 'CancelReservation'],
+ [OCPP16IncomingRequestCommand.CHANGE_AVAILABILITY, 'ChangeAvailability'],
+ [OCPP16IncomingRequestCommand.CHANGE_CONFIGURATION, 'ChangeConfiguration'],
+ [OCPP16IncomingRequestCommand.CLEAR_CACHE, 'ClearCache'],
+ [OCPP16IncomingRequestCommand.CLEAR_CHARGING_PROFILE, 'ClearChargingProfile'],
+ [OCPP16IncomingRequestCommand.DATA_TRANSFER, 'DataTransfer'],
+ [OCPP16IncomingRequestCommand.GET_COMPOSITE_SCHEDULE, 'GetCompositeSchedule'],
+ [OCPP16IncomingRequestCommand.GET_CONFIGURATION, 'GetConfiguration'],
+ [OCPP16IncomingRequestCommand.GET_DIAGNOSTICS, 'GetDiagnostics'],
+ [OCPP16IncomingRequestCommand.REMOTE_START_TRANSACTION, 'RemoteStartTransaction'],
+ [OCPP16IncomingRequestCommand.REMOTE_STOP_TRANSACTION, 'RemoteStopTransaction'],
+ [OCPP16IncomingRequestCommand.RESERVE_NOW, 'ReserveNow'],
+ [OCPP16IncomingRequestCommand.RESET, 'Reset'],
+ [OCPP16IncomingRequestCommand.SET_CHARGING_PROFILE, 'SetChargingProfile'],
+ [OCPP16IncomingRequestCommand.TRIGGER_MESSAGE, 'TriggerMessage'],
+ [OCPP16IncomingRequestCommand.UNLOCK_CONNECTOR, 'UnlockConnector'],
+ [OCPP16IncomingRequestCommand.UPDATE_FIRMWARE, 'UpdateFirmware'],
+ ]
+
+ private static readonly outgoingRequestSchemaNames: readonly [OCPP16RequestCommand, string][] = [
+ [OCPP16RequestCommand.AUTHORIZE, 'Authorize'],
+ [OCPP16RequestCommand.BOOT_NOTIFICATION, 'BootNotification'],
+ [OCPP16RequestCommand.DATA_TRANSFER, 'DataTransfer'],
+ [OCPP16RequestCommand.DIAGNOSTICS_STATUS_NOTIFICATION, 'DiagnosticsStatusNotification'],
+ [OCPP16RequestCommand.FIRMWARE_STATUS_NOTIFICATION, 'FirmwareStatusNotification'],
+ [OCPP16RequestCommand.HEARTBEAT, 'Heartbeat'],
+ [OCPP16RequestCommand.METER_VALUES, 'MeterValues'],
+ [OCPP16RequestCommand.START_TRANSACTION, 'StartTransaction'],
+ [OCPP16RequestCommand.STATUS_NOTIFICATION, 'StatusNotification'],
+ [OCPP16RequestCommand.STOP_TRANSACTION, 'StopTransaction'],
+ ]
+
public static buildTransactionBeginMeterValue (
chargingStation: ChargingStation,
connectorId: number,
public static createIncomingRequestPayloadConfigs = (): [
OCPP16IncomingRequestCommand,
{ schemaPath: string }
- ][] => [
- [
- OCPP16IncomingRequestCommand.CANCEL_RESERVATION,
- OCPP16ServiceUtils.PayloadValidatorConfig('CancelReservation.json'),
- ],
- [
- OCPP16IncomingRequestCommand.CHANGE_AVAILABILITY,
- OCPP16ServiceUtils.PayloadValidatorConfig('ChangeAvailability.json'),
- ],
- [
- OCPP16IncomingRequestCommand.CHANGE_CONFIGURATION,
- OCPP16ServiceUtils.PayloadValidatorConfig('ChangeConfiguration.json'),
- ],
- [
- OCPP16IncomingRequestCommand.CLEAR_CACHE,
- OCPP16ServiceUtils.PayloadValidatorConfig('ClearCache.json'),
- ],
- [
- OCPP16IncomingRequestCommand.CLEAR_CHARGING_PROFILE,
- OCPP16ServiceUtils.PayloadValidatorConfig('ClearChargingProfile.json'),
- ],
- [
- OCPP16IncomingRequestCommand.DATA_TRANSFER,
- OCPP16ServiceUtils.PayloadValidatorConfig('DataTransfer.json'),
- ],
- [
- OCPP16IncomingRequestCommand.GET_COMPOSITE_SCHEDULE,
- OCPP16ServiceUtils.PayloadValidatorConfig('GetCompositeSchedule.json'),
- ],
- [
- OCPP16IncomingRequestCommand.GET_CONFIGURATION,
- OCPP16ServiceUtils.PayloadValidatorConfig('GetConfiguration.json'),
- ],
- [
- OCPP16IncomingRequestCommand.GET_DIAGNOSTICS,
- OCPP16ServiceUtils.PayloadValidatorConfig('GetDiagnostics.json'),
- ],
- [
- OCPP16IncomingRequestCommand.REMOTE_START_TRANSACTION,
- OCPP16ServiceUtils.PayloadValidatorConfig('RemoteStartTransaction.json'),
- ],
- [
- OCPP16IncomingRequestCommand.REMOTE_STOP_TRANSACTION,
- OCPP16ServiceUtils.PayloadValidatorConfig('RemoteStopTransaction.json'),
- ],
- [
- OCPP16IncomingRequestCommand.RESERVE_NOW,
- OCPP16ServiceUtils.PayloadValidatorConfig('ReserveNow.json'),
- ],
- [OCPP16IncomingRequestCommand.RESET, OCPP16ServiceUtils.PayloadValidatorConfig('Reset.json')],
- [
- OCPP16IncomingRequestCommand.SET_CHARGING_PROFILE,
- OCPP16ServiceUtils.PayloadValidatorConfig('SetChargingProfile.json'),
- ],
- [
- OCPP16IncomingRequestCommand.TRIGGER_MESSAGE,
- OCPP16ServiceUtils.PayloadValidatorConfig('TriggerMessage.json'),
- ],
- [
- OCPP16IncomingRequestCommand.UNLOCK_CONNECTOR,
- OCPP16ServiceUtils.PayloadValidatorConfig('UnlockConnector.json'),
- ],
- [
- OCPP16IncomingRequestCommand.UPDATE_FIRMWARE,
- OCPP16ServiceUtils.PayloadValidatorConfig('UpdateFirmware.json'),
- ],
- ]
-
- /**
- * Factory options for OCPP 1.6 Incoming Request Service
- * @param moduleName - Name of the OCPP module
- * @param methodName - Name of the method/command
- * @returns Factory options object for OCPP 1.6 incoming request validators
- */
- public static createIncomingRequestPayloadOptions = (moduleName: string, methodName: string) =>
- OCPP16ServiceUtils.PayloadValidatorOptions(
- OCPPVersion.VERSION_16,
- 'assets/json-schemas/ocpp/1.6',
- moduleName,
- methodName
- )
+ ][] =>
+ OCPP16ServiceUtils.incomingRequestSchemaNames.map(([command, schemaBase]) => [
+ command,
+ OCPP16ServiceUtils.PayloadValidatorConfig(`${schemaBase}.json`),
+ ])
/**
* OCPP 1.6 Incoming Request Response Service validator configurations
public static createIncomingRequestResponsePayloadConfigs = (): [
OCPP16IncomingRequestCommand,
{ schemaPath: string }
- ][] => [
- [
- OCPP16IncomingRequestCommand.CANCEL_RESERVATION,
- OCPP16ServiceUtils.PayloadValidatorConfig('CancelReservationResponse.json'),
- ],
- [
- OCPP16IncomingRequestCommand.CHANGE_AVAILABILITY,
- OCPP16ServiceUtils.PayloadValidatorConfig('ChangeAvailabilityResponse.json'),
- ],
- [
- OCPP16IncomingRequestCommand.CHANGE_CONFIGURATION,
- OCPP16ServiceUtils.PayloadValidatorConfig('ChangeConfigurationResponse.json'),
- ],
- [
- OCPP16IncomingRequestCommand.CLEAR_CACHE,
- OCPP16ServiceUtils.PayloadValidatorConfig('ClearCacheResponse.json'),
- ],
- [
- OCPP16IncomingRequestCommand.CLEAR_CHARGING_PROFILE,
- OCPP16ServiceUtils.PayloadValidatorConfig('ClearChargingProfileResponse.json'),
- ],
- [
- OCPP16IncomingRequestCommand.DATA_TRANSFER,
- OCPP16ServiceUtils.PayloadValidatorConfig('DataTransferResponse.json'),
- ],
- [
- OCPP16IncomingRequestCommand.GET_COMPOSITE_SCHEDULE,
- OCPP16ServiceUtils.PayloadValidatorConfig('GetCompositeScheduleResponse.json'),
- ],
- [
- OCPP16IncomingRequestCommand.GET_CONFIGURATION,
- OCPP16ServiceUtils.PayloadValidatorConfig('GetConfigurationResponse.json'),
- ],
- [
- OCPP16IncomingRequestCommand.GET_DIAGNOSTICS,
- OCPP16ServiceUtils.PayloadValidatorConfig('GetDiagnosticsResponse.json'),
- ],
- [
- OCPP16IncomingRequestCommand.REMOTE_START_TRANSACTION,
- OCPP16ServiceUtils.PayloadValidatorConfig('RemoteStartTransactionResponse.json'),
- ],
- [
- OCPP16IncomingRequestCommand.REMOTE_STOP_TRANSACTION,
- OCPP16ServiceUtils.PayloadValidatorConfig('RemoteStopTransactionResponse.json'),
- ],
- [
- OCPP16IncomingRequestCommand.RESERVE_NOW,
- OCPP16ServiceUtils.PayloadValidatorConfig('ReserveNowResponse.json'),
- ],
- [
- OCPP16IncomingRequestCommand.RESET,
- OCPP16ServiceUtils.PayloadValidatorConfig('ResetResponse.json'),
- ],
- [
- OCPP16IncomingRequestCommand.SET_CHARGING_PROFILE,
- OCPP16ServiceUtils.PayloadValidatorConfig('SetChargingProfileResponse.json'),
- ],
- [
- OCPP16IncomingRequestCommand.TRIGGER_MESSAGE,
- OCPP16ServiceUtils.PayloadValidatorConfig('TriggerMessageResponse.json'),
- ],
- [
- OCPP16IncomingRequestCommand.UNLOCK_CONNECTOR,
- OCPP16ServiceUtils.PayloadValidatorConfig('UnlockConnectorResponse.json'),
- ],
- [
- OCPP16IncomingRequestCommand.UPDATE_FIRMWARE,
- OCPP16ServiceUtils.PayloadValidatorConfig('UpdateFirmwareResponse.json'),
- ],
- ]
+ ][] =>
+ OCPP16ServiceUtils.incomingRequestSchemaNames.map(([command, schemaBase]) => [
+ command,
+ OCPP16ServiceUtils.PayloadValidatorConfig(`${schemaBase}Response.json`),
+ ])
/**
- * Factory options for OCPP 1.6 Incoming Request Response Service
+ * Factory options for OCPP 1.6 payload validators
* @param moduleName - Name of the OCPP module
* @param methodName - Name of the method/command
- * @returns Factory options object for OCPP 1.6 incoming request response validators
+ * @returns Factory options object for OCPP 1.6 validators
*/
- public static createIncomingRequestResponsePayloadOptions = (
- moduleName: string,
- methodName: string
- ) =>
+ public static createPayloadOptions = (moduleName: string, methodName: string) =>
OCPP16ServiceUtils.PayloadValidatorOptions(
OCPPVersion.VERSION_16,
'assets/json-schemas/ocpp/1.6',
public static createRequestPayloadConfigs = (): [
OCPP16RequestCommand,
{ schemaPath: string }
- ][] => [
- [OCPP16RequestCommand.AUTHORIZE, OCPP16ServiceUtils.PayloadValidatorConfig('Authorize.json')],
- [
- OCPP16RequestCommand.BOOT_NOTIFICATION,
- OCPP16ServiceUtils.PayloadValidatorConfig('BootNotification.json'),
- ],
- [
- OCPP16RequestCommand.DATA_TRANSFER,
- OCPP16ServiceUtils.PayloadValidatorConfig('DataTransfer.json'),
- ],
- [
- OCPP16RequestCommand.DIAGNOSTICS_STATUS_NOTIFICATION,
- OCPP16ServiceUtils.PayloadValidatorConfig('DiagnosticsStatusNotification.json'),
- ],
- [
- OCPP16RequestCommand.FIRMWARE_STATUS_NOTIFICATION,
- OCPP16ServiceUtils.PayloadValidatorConfig('FirmwareStatusNotification.json'),
- ],
- [OCPP16RequestCommand.HEARTBEAT, OCPP16ServiceUtils.PayloadValidatorConfig('Heartbeat.json')],
- [
- OCPP16RequestCommand.METER_VALUES,
- OCPP16ServiceUtils.PayloadValidatorConfig('MeterValues.json'),
- ],
- [
- OCPP16RequestCommand.START_TRANSACTION,
- OCPP16ServiceUtils.PayloadValidatorConfig('StartTransaction.json'),
- ],
- [
- OCPP16RequestCommand.STATUS_NOTIFICATION,
- OCPP16ServiceUtils.PayloadValidatorConfig('StatusNotification.json'),
- ],
- [
- OCPP16RequestCommand.STOP_TRANSACTION,
- OCPP16ServiceUtils.PayloadValidatorConfig('StopTransaction.json'),
- ],
- ]
-
- /**
- * Factory options for OCPP 1.6 Request Service
- * @param moduleName - Name of the OCPP module
- * @param methodName - Name of the method/command
- * @returns Factory options object for OCPP 1.6 validators
- */
- public static createRequestPayloadOptions = (moduleName: string, methodName: string) =>
- OCPP16ServiceUtils.PayloadValidatorOptions(
- OCPPVersion.VERSION_16,
- 'assets/json-schemas/ocpp/1.6',
- moduleName,
- methodName
- )
+ ][] =>
+ OCPP16ServiceUtils.outgoingRequestSchemaNames.map(([command, schemaBase]) => [
+ command,
+ OCPP16ServiceUtils.PayloadValidatorConfig(`${schemaBase}.json`),
+ ])
/**
* OCPP 1.6 Response Service validator configurations
public static createResponsePayloadConfigs = (): [
OCPP16RequestCommand,
{ schemaPath: string }
- ][] => [
- [
- OCPP16RequestCommand.AUTHORIZE,
- OCPP16ServiceUtils.PayloadValidatorConfig('AuthorizeResponse.json'),
- ],
- [
- OCPP16RequestCommand.BOOT_NOTIFICATION,
- OCPP16ServiceUtils.PayloadValidatorConfig('BootNotificationResponse.json'),
- ],
- [
- OCPP16RequestCommand.DATA_TRANSFER,
- OCPP16ServiceUtils.PayloadValidatorConfig('DataTransferResponse.json'),
- ],
- [
- OCPP16RequestCommand.DIAGNOSTICS_STATUS_NOTIFICATION,
- OCPP16ServiceUtils.PayloadValidatorConfig('DiagnosticsStatusNotificationResponse.json'),
- ],
- [
- OCPP16RequestCommand.FIRMWARE_STATUS_NOTIFICATION,
- OCPP16ServiceUtils.PayloadValidatorConfig('FirmwareStatusNotificationResponse.json'),
- ],
- [
- OCPP16RequestCommand.HEARTBEAT,
- OCPP16ServiceUtils.PayloadValidatorConfig('HeartbeatResponse.json'),
- ],
- [
- OCPP16RequestCommand.METER_VALUES,
- OCPP16ServiceUtils.PayloadValidatorConfig('MeterValuesResponse.json'),
- ],
- [
- OCPP16RequestCommand.START_TRANSACTION,
- OCPP16ServiceUtils.PayloadValidatorConfig('StartTransactionResponse.json'),
- ],
- [
- OCPP16RequestCommand.STATUS_NOTIFICATION,
- OCPP16ServiceUtils.PayloadValidatorConfig('StatusNotificationResponse.json'),
- ],
- [
- OCPP16RequestCommand.STOP_TRANSACTION,
- OCPP16ServiceUtils.PayloadValidatorConfig('StopTransactionResponse.json'),
- ],
- ]
-
- /**
- * Factory options for OCPP 1.6 Response Service
- * @param moduleName - Name of the OCPP module
- * @param methodName - Name of the method/command
- * @returns Factory options object for OCPP 1.6 response validators
- */
- public static createResponsePayloadOptions = (moduleName: string, methodName: string) =>
- OCPP16ServiceUtils.PayloadValidatorOptions(
- OCPPVersion.VERSION_16,
- 'assets/json-schemas/ocpp/1.6',
- moduleName,
- methodName
- )
+ ][] =>
+ OCPP16ServiceUtils.outgoingRequestSchemaNames.map(([command, schemaBase]) => [
+ command,
+ OCPP16ServiceUtils.PayloadValidatorConfig(`${schemaBase}Response.json`),
+ ])
public static hasReservation = (
chargingStation: ChargingStation,
])
this.payloadValidatorFunctions = OCPP20ServiceUtils.createPayloadValidatorMap(
OCPP20ServiceUtils.createIncomingRequestPayloadConfigs(),
- OCPP20ServiceUtils.createIncomingRequestPayloadOptions(moduleName, 'constructor'),
+ OCPP20ServiceUtils.createPayloadOptions(moduleName, 'constructor'),
this.ajv
)
// Handle incoming request events
}
}
)
- this.validatePayload = this.validatePayload.bind(this)
}
public handleRequestGetVariables (
OCPP20ServiceUtils.isIncomingRequestCommandSupported(chargingStation, commandName)
) {
try {
- this.validatePayload(chargingStation, commandName, commandPayload)
+ this.validateIncomingRequestPayload(chargingStation, commandName, commandPayload)
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const incomingRequestHandler = this.incomingRequestHandlers.get(commandName)!
if (isAsyncFunction(incomingRequestHandler)) {
)
return true
}
-
- /**
- * Validates incoming OCPP 2.0 request payload against JSON schema
- * @param chargingStation - The charging station instance processing the request
- * @param commandName - OCPP 2.0 command name to validate against
- * @param commandPayload - JSON payload to validate
- * @returns True if payload validation succeeds, false otherwise
- */
- private validatePayload (
- chargingStation: ChargingStation,
- commandName: OCPP20IncomingRequestCommand,
- commandPayload: JsonType
- ): boolean {
- if (this.payloadValidatorFunctions.has(commandName)) {
- return this.validateIncomingRequestPayload(chargingStation, commandName, commandPayload)
- }
- logger.warn(
- `${chargingStation.logPrefix()} ${moduleName}.validatePayload: No JSON schema validation function found for command '${commandName}' PDU validation`
- )
- return false
- }
}
/**
* 3. Request routed to appropriate handler method
* 4. Business logic executed with variable model integration
* 5. Response payload validated and sent back to CSMS
- * @see {@link validatePayload} Request payload validation method
+ * @see {@link validateIncomingRequestPayload} Request payload validation method
* @see {@link handleRequestStartTransaction} Example OCPP 2.0+ request handler
* @see {@link OCPP20VariableManager} Variable management integration
*/
super(OCPPVersion.VERSION_201, ocppResponseService)
this.payloadValidatorFunctions = OCPP20ServiceUtils.createPayloadValidatorMap(
OCPP20ServiceUtils.createRequestPayloadConfigs(),
- OCPP20ServiceUtils.createRequestPayloadOptions(moduleName, 'constructor'),
+ OCPP20ServiceUtils.createPayloadOptions(moduleName, 'constructor'),
this.ajv
)
this.buildRequestPayload = this.buildRequestPayload.bind(this)
* 3. Response routed to appropriate handler based on original request type
* 4. Charging station state and variable model updated based on response content
* 5. Enhanced follow-up actions triggered based on OCPP 2.0+ capabilities
- * @see {@link validatePayload} Response payload validation method
+ * @see {@link validateResponsePayload} Response payload validation method
* @see {@link handleResponse} Response processing methods
* @see {@link OCPP20VariableManager} Variable management integration
*/
])
this.payloadValidatorFunctions = OCPP20ServiceUtils.createPayloadValidatorMap(
OCPP20ServiceUtils.createResponsePayloadConfigs(),
- OCPP20ServiceUtils.createResponsePayloadOptions(moduleName, 'constructor'),
+ OCPP20ServiceUtils.createPayloadOptions(moduleName, 'constructor'),
this.ajv
)
this.incomingRequestResponsePayloadValidateFunctions =
OCPP20ServiceUtils.createPayloadValidatorMap(
OCPP20ServiceUtils.createIncomingRequestResponsePayloadConfigs(),
- OCPP20ServiceUtils.createIncomingRequestResponsePayloadOptions(moduleName, 'constructor'),
+ OCPP20ServiceUtils.createPayloadOptions(moduleName, 'constructor'),
this.ajvIncomingRequest
)
- this.validatePayload = this.validatePayload.bind(this)
}
// eslint-disable-next-line @typescript-eslint/no-unnecessary-type-parameters
OCPP20ServiceUtils.isRequestCommandSupported(chargingStation, commandName)
) {
try {
- this.validatePayload(chargingStation, commandName, payload)
+ this.validateResponsePayload(chargingStation, commandName, payload)
logger.debug(
`${chargingStation.logPrefix()} ${moduleName}.responseHandler: Handling '${commandName}' response`
)
)
}
}
-
- /**
- * Validates incoming OCPP 2.0 response payload against JSON schema
- * @param chargingStation - The charging station instance receiving the response
- * @param commandName - OCPP 2.0 command name to validate against
- * @param payload - JSON response payload to validate
- * @returns True if payload validation succeeds, false otherwise
- */
- private validatePayload (
- chargingStation: ChargingStation,
- commandName: OCPP20RequestCommand,
- payload: JsonType
- ): boolean {
- if (this.payloadValidatorFunctions.has(commandName)) {
- logger.debug(
- `${chargingStation.logPrefix()} ${moduleName}.validatePayload: Validating '${commandName}' response payload`
- )
- const isValid = this.validateResponsePayload(chargingStation, commandName, payload)
- if (!isValid) {
- logger.warn(
- `${chargingStation.logPrefix()} ${moduleName}.validatePayload: '${commandName}' response payload validation failed`
- )
- } else {
- logger.debug(
- `${chargingStation.logPrefix()} ${moduleName}.validatePayload: '${commandName}' response payload validation successful`
- )
- }
- return isValid
- }
- logger.warn(
- `${chargingStation.logPrefix()} ${moduleName}.validatePayload: No JSON schema validation function found for command '${commandName}' PDU validation`
- )
- return false
- }
}
OCPP20ServiceUtils.PayloadValidatorConfig(`${schemaBase}Request.json`),
])
- /**
- * Factory options for OCPP 2.0 Incoming Request Service
- * @param moduleName - Name of the OCPP module
- * @param methodName - Name of the method/command
- * @returns Factory options object for OCPP 2.0 incoming request validators
- */
- public static createIncomingRequestPayloadOptions = (moduleName: string, methodName: string) =>
- OCPP20ServiceUtils.PayloadValidatorOptions(
- OCPPVersion.VERSION_201,
- 'assets/json-schemas/ocpp/2.0',
- moduleName,
- methodName
- )
-
/**
* Configuration for OCPP 2.0 Incoming Request Response validators
* @returns Array of validator configuration tuples
])
/**
- * Factory options for OCPP 2.0 Incoming Request Response Service
+ * Factory options for OCPP 2.0 payload validators
* @param moduleName - Name of the OCPP module
* @param methodName - Name of the method/command
- * @returns Factory options object for OCPP 2.0 incoming request response validators
+ * @returns Factory options object for OCPP 2.0 validators
*/
- public static createIncomingRequestResponsePayloadOptions = (
- moduleName: string,
- methodName: string
- ) =>
+ public static createPayloadOptions = (moduleName: string, methodName: string) =>
OCPP20ServiceUtils.PayloadValidatorOptions(
OCPPVersion.VERSION_201,
'assets/json-schemas/ocpp/2.0',
OCPP20ServiceUtils.PayloadValidatorConfig(`${schemaBase}Request.json`),
])
- /**
- * Factory options for OCPP 2.0 Request Service
- * @param moduleName - Name of the OCPP module
- * @param methodName - Name of the method/command
- * @returns Factory options object for OCPP 2.0 validators
- */
- public static createRequestPayloadOptions = (moduleName: string, methodName: string) =>
- OCPP20ServiceUtils.PayloadValidatorOptions(
- OCPPVersion.VERSION_201,
- 'assets/json-schemas/ocpp/2.0',
- moduleName,
- methodName
- )
-
/**
* OCPP 2.0 Response Service validator configurations
* @returns Array of validator configuration tuples
OCPP20ServiceUtils.PayloadValidatorConfig(`${schemaBase}Response.json`),
])
- /**
- * Factory options for OCPP 2.0 Response Service
- * @param moduleName - Name of the OCPP module
- * @param methodName - Name of the method/command
- * @returns Factory options object for OCPP 2.0 response validators
- */
- public static createResponsePayloadOptions = (moduleName: string, methodName: string) =>
- OCPP20ServiceUtils.PayloadValidatorOptions(
- OCPPVersion.VERSION_201,
- 'assets/json-schemas/ocpp/2.0',
- moduleName,
- methodName
- )
-
public static enforceMessageLimits<
T extends { attributeType?: unknown; component: unknown; variable: unknown }
>(
return true
}
const validate = this.payloadValidatorFunctions.get(commandName)
- if (validate?.(payload) === true) {
+ if (validate == null) {
+ logger.warn(
+ `${chargingStation.logPrefix()} ${moduleName}.validateIncomingRequestPayload: No JSON schema validation function found for command '${commandName}' PDU validation`
+ )
+ return false
+ }
+ if (validate(payload)) {
return true
}
logger.error(
`${chargingStation.logPrefix()} ${moduleName}.validateIncomingRequestPayload: Command '${commandName}' incoming request PDU is invalid: %j`,
- validate?.errors
+ validate.errors
)
throw new OCPPError(
- ajvErrorsToErrorType(validate?.errors),
+ ajvErrorsToErrorType(validate.errors),
'Incoming request PDU is invalid',
commandName,
- JSON.stringify(validate?.errors, undefined, 2)
+ JSON.stringify(validate.errors, undefined, 2)
)
}
}
if (chargingStation.stationInfo?.ocppStrictCompliance === false) {
return true
}
- if (
- !this.ocppResponseService.incomingRequestResponsePayloadValidateFunctions.has(
- commandName as IncomingRequestCommand
- )
- ) {
+ const validate = this.ocppResponseService.incomingRequestResponsePayloadValidateFunctions.get(
+ commandName as IncomingRequestCommand
+ )
+ if (validate == null) {
logger.warn(
`${chargingStation.logPrefix()} ${moduleName}.validateIncomingRequestResponsePayload: No JSON schema validation function found for command '${commandName}' PDU validation`
)
return true
}
- const validate = this.ocppResponseService.incomingRequestResponsePayloadValidateFunctions.get(
- commandName as IncomingRequestCommand
- )
payload = clone<T>(payload)
convertDateToISOString<T>(payload)
- if (validate?.(payload) === true) {
+ if (validate(payload)) {
return true
}
logger.error(
`${chargingStation.logPrefix()} ${moduleName}.validateIncomingRequestResponsePayload: Command '${commandName}' incoming request response PDU is invalid: %j`,
- validate?.errors
+ validate.errors
)
// OCPPError usage here is debatable: it's an error in the OCPP stack but not targeted to sendError().
throw new OCPPError(
- ajvErrorsToErrorType(validate?.errors),
+ ajvErrorsToErrorType(validate.errors),
'Incoming request response PDU is invalid',
commandName,
- JSON.stringify(validate?.errors, undefined, 2)
+ JSON.stringify(validate.errors, undefined, 2)
)
}
if (chargingStation.stationInfo?.ocppStrictCompliance === false) {
return true
}
- if (!this.payloadValidatorFunctions.has(commandName as RequestCommand)) {
+ const validate = this.payloadValidatorFunctions.get(commandName as RequestCommand)
+ if (validate == null) {
logger.warn(
`${chargingStation.logPrefix()} ${moduleName}.validateRequestPayload: No JSON schema validation function found for command '${commandName}' PDU validation`
)
return true
}
- const validate = this.payloadValidatorFunctions.get(commandName as RequestCommand)
payload = clone<T>(payload)
convertDateToISOString<T>(payload)
- if (validate?.(payload) === true) {
+ if (validate(payload)) {
return true
}
logger.error(
`${chargingStation.logPrefix()} ${moduleName}.validateRequestPayload: Command '${commandName}' request PDU is invalid: %j`,
- validate?.errors
+ validate.errors
)
// OCPPError usage here is debatable: it's an error in the OCPP stack but not targeted to sendError().
throw new OCPPError(
- ajvErrorsToErrorType(validate?.errors),
+ ajvErrorsToErrorType(validate.errors),
'Request PDU is invalid',
commandName,
- JSON.stringify(validate?.errors, undefined, 2)
+ JSON.stringify(validate.errors, undefined, 2)
)
}
}
return true
}
const validate = this.payloadValidatorFunctions.get(commandName)
- if (validate?.(payload) === true) {
+ if (validate == null) {
+ logger.warn(
+ `${chargingStation.logPrefix()} ${moduleName}.validateResponsePayload: No JSON schema validation function found for command '${commandName}' PDU validation`
+ )
+ return false
+ }
+ if (validate(payload)) {
return true
}
logger.error(
`${chargingStation.logPrefix()} ${moduleName}.validateResponsePayload: Command '${commandName}' response PDU is invalid: %j`,
- validate?.errors
+ validate.errors
)
throw new OCPPError(
- ajvErrorsToErrorType(validate?.errors),
+ ajvErrorsToErrorType(validate.errors),
'Response PDU is invalid',
commandName,
- JSON.stringify(validate?.errors, undefined, 2)
+ JSON.stringify(validate.errors, undefined, 2)
)
}
}
* response services) to perform common operations and validation. It acts as a shared
* utility layer that prevents code duplication across OCPP version-specific implementations.
* @see {@link parseJsonSchemaFile} Core JSON schema parsing functionality
- * @see {@link validatePayload} Payload validation methods in service classes
+ * @see {@link validateIncomingRequestPayload} Payload validation methods in service classes
+ * @see {@link validateResponsePayload} Payload validation methods in service classes
*/
// eslint-disable-next-line @typescript-eslint/no-extraneous-class
/**
* Parses and loads a JSON schema file for OCPP payload validation.
- * Handles file reading, JSON parsing, and error recovery for schema validation.
+ * Handles file reading and JSON parsing for schema validation.
* @param relativePath Path to the schema file relative to the OCPP utils directory
* @param ocppVersion The OCPP version for error logging context
* @param moduleName Optional module name for error logging
* @param methodName Optional method name for error logging
- * @returns Parsed JSON schema object or empty object if parsing fails
+ * @returns Parsed JSON schema object
+ * @throws {NodeJS.ErrnoException} If the schema file cannot be read or parsed
*/
protected static parseJsonSchemaFile<T extends JsonType>(
relativePath: string,
moduleName?: string,
methodName?: string
): JSONSchemaType<T> {
- const filePath = join(dirname(fileURLToPath(import.meta.url)), relativePath)
+ const baseDir = dirname(fileURLToPath(import.meta.url))
+ // Primary: resolve from file directory (production esbuild bundle)
+ const primaryPath = join(baseDir, relativePath)
try {
- return JSON.parse(readFileSync(filePath, 'utf8')) as JSONSchemaType<T>
- } catch (error) {
- handleFileException(
- filePath,
- FileType.JsonSchema,
- error as NodeJS.ErrnoException,
- OCPPServiceUtils.logPrefix(ocppVersion, moduleName, methodName),
- { throwError: false }
- )
- return {} as JSONSchemaType<T>
+ return JSON.parse(readFileSync(primaryPath, 'utf8')) as JSONSchemaType<T>
+ } catch (primaryError) {
+ // Fallback: resolve from source root (development/test with tsx)
+ const fallbackPath = join(baseDir, '..', '..', relativePath)
+ try {
+ return JSON.parse(readFileSync(fallbackPath, 'utf8')) as JSONSchemaType<T>
+ } catch {
+ handleFileException(
+ primaryPath,
+ FileType.JsonSchema,
+ primaryError as NodeJS.ErrnoException,
+ OCPPServiceUtils.logPrefix(ocppVersion, moduleName, methodName)
+ )
+ // handleFileException throws by default; this satisfies the compiler
+ throw primaryError
+ }
}
}