} from '../utils/index.js'
import { checkChargingStationState } from './Helpers.js'
import { IdTagsCache } from './IdTagsCache.js'
-import { isIdTagAuthorized } from './ocpp/index.js'
-import { startTransactionOnConnector, stopTransactionOnConnector } from './ocpp/OCPPServiceUtils.js'
+import {
+ isIdTagAuthorized,
+ startTransactionOnConnector,
+ stopTransactionOnConnector,
+} from './ocpp/index.js'
export class AutomaticTransactionGenerator {
private static readonly instances: Map<string, AutomaticTransactionGenerator> = new Map<
} from './Helpers.js'
import { IdTagsCache } from './IdTagsCache.js'
import {
+ flushQueuedTransactionMessages,
OCPP16IncomingRequestService,
OCPP16RequestService,
OCPP16ResponseService,
type OCPPIncomingRequestService,
type OCPPRequestService,
sendAndSetConnectorStatus,
+ stopRunningTransactions,
} from './ocpp/index.js'
-import { flushQueuedTransactionMessages, stopRunningTransactions } from './ocpp/OCPPServiceUtils.js'
import { SharedLRUCache } from './SharedLRUCache.js'
export class ChargingStation extends EventEmitter {
import { isIdTagAuthorized } from '../IdTagAuthorization.js'
import { OCPPConstants } from '../OCPPConstants.js'
import { OCPPIncomingRequestService } from '../OCPPIncomingRequestService.js'
-import { buildMeterValue, sendAndSetConnectorStatus } from '../OCPPServiceUtils.js'
+import {
+ buildMeterValue,
+ createPayloadValidatorMap,
+ isConnectorIdValid,
+ isIncomingRequestCommandSupported,
+ isMessageTriggerSupported,
+ sendAndSetConnectorStatus,
+} from '../OCPPServiceUtils.js'
import { OCPP16Constants } from './OCPP16Constants.js'
import { OCPP16ServiceUtils } from './OCPP16ServiceUtils.js'
OCPP16IncomingRequestCommand.REMOTE_STOP_TRANSACTION,
]
+ /**
+ * Constructs an OCPP 1.6 Incoming Request Service with request handlers, validators, and event listeners.
+ */
public constructor () {
super(OCPPVersion.VERSION_16)
this.incomingRequestHandlers = new Map<IncomingRequestCommand, IncomingRequestHandler>([
this.toRequestHandler(this.handleRequestUpdateFirmware.bind(this)),
],
])
- this.payloadValidatorFunctions = OCPP16ServiceUtils.createPayloadValidatorMap(
+ this.payloadValidatorFunctions = createPayloadValidatorMap(
OCPP16ServiceUtils.createIncomingRequestPayloadConfigs(),
OCPP16ServiceUtils.createPayloadOptions(moduleName, 'constructor'),
this.ajv
)
}
+ /**
+ * Stops the incoming request service for the given charging station.
+ * @param chargingStation - Target charging station
+ */
public override stop (chargingStation: ChargingStation): void {
/* no-op for OCPP 1.6 */
}
+ /**
+ * Checks whether the given incoming request command is supported by the charging station.
+ * @param chargingStation - Target charging station
+ * @param commandName - Incoming request command to check
+ * @returns Whether the command is supported
+ */
protected isIncomingRequestCommandSupported (
chargingStation: ChargingStation,
commandName: IncomingRequestCommand
): boolean {
- return OCPP16ServiceUtils.isIncomingRequestCommandSupported(
+ return isIncomingRequestCommandSupported(
chargingStation,
commandName as OCPP16IncomingRequestCommand
)
OCPP16SupportedFeatureProfiles.RemoteTrigger,
OCPP16IncomingRequestCommand.TRIGGER_MESSAGE
) ||
- !OCPP16ServiceUtils.isMessageTriggerSupported(chargingStation, requestedMessage)
+ !isMessageTriggerSupported(chargingStation, requestedMessage)
) {
return OCPP16Constants.OCPP_TRIGGER_MESSAGE_RESPONSE_NOT_IMPLEMENTED
}
if (
connectorId != null &&
- !OCPP16ServiceUtils.isConnectorIdValid(
+ !isConnectorIdValid(
chargingStation,
OCPP16IncomingRequestCommand.TRIGGER_MESSAGE,
connectorId
import {
buildStatusNotificationRequest,
buildTransactionEndMeterValue,
+ createPayloadValidatorMap,
+ isRequestCommandSupported,
sendAndSetConnectorStatus,
} from '../OCPPServiceUtils.js'
import { OCPP16Constants } from './OCPP16Constants.js'
*/
public constructor (ocppResponseService: OCPPResponseService) {
super(OCPPVersion.VERSION_16, ocppResponseService)
- this.payloadValidatorFunctions = OCPP16ServiceUtils.createPayloadValidatorMap(
+ this.payloadValidatorFunctions = createPayloadValidatorMap(
OCPP16ServiceUtils.createRequestPayloadConfigs(),
OCPP16ServiceUtils.createPayloadOptions(moduleName, 'constructor'),
this.ajv
logger.debug(
`${chargingStation.logPrefix()} ${moduleName}.requestHandler: Processing '${commandName}' request`
)
- if (OCPP16ServiceUtils.isRequestCommandSupported(chargingStation, commandName)) {
+ if (isRequestCommandSupported(chargingStation, commandName)) {
try {
logger.debug(
`${chargingStation.logPrefix()} ${moduleName}.requestHandler: Building request payload for '${commandName}'`
import { OCPPResponseService } from '../OCPPResponseService.js'
import {
buildTransactionEndMeterValue,
+ createPayloadValidatorMap,
+ isRequestCommandSupported,
restoreConnectorStatus,
sendAndSetConnectorStatus,
} from '../OCPPServiceUtils.js'
protected readonly responseHandlers: Map<RequestCommand, ResponseHandler>
+ /**
+ * Constructs an OCPP 1.6 Response Service instance with response handlers and validators.
+ */
public constructor () {
super(OCPPVersion.VERSION_16)
this.responseHandlers = new Map<RequestCommand, ResponseHandler>([
this.toResponseHandler(this.handleResponseStopTransaction.bind(this)),
],
])
- this.payloadValidatorFunctions = OCPP16ServiceUtils.createPayloadValidatorMap(
+ this.payloadValidatorFunctions = createPayloadValidatorMap(
OCPP16ServiceUtils.createResponsePayloadConfigs(),
OCPP16ServiceUtils.createPayloadOptions(moduleName, 'constructor'),
this.ajv
)
- this.incomingRequestResponsePayloadValidateFunctions =
- OCPP16ServiceUtils.createPayloadValidatorMap(
- OCPP16ServiceUtils.createIncomingRequestResponsePayloadConfigs(),
- OCPP16ServiceUtils.createPayloadOptions(moduleName, 'constructor'),
- this.ajvIncomingRequest
- )
+ this.incomingRequestResponsePayloadValidateFunctions = createPayloadValidatorMap(
+ OCPP16ServiceUtils.createIncomingRequestResponsePayloadConfigs(),
+ OCPP16ServiceUtils.createPayloadOptions(moduleName, 'constructor'),
+ this.ajvIncomingRequest
+ )
}
+ /**
+ * Checks whether the given request command is supported by the charging station.
+ * @param chargingStation - Target charging station
+ * @param commandName - Request command to check
+ * @returns Whether the command is supported
+ */
protected isRequestCommandSupported (
chargingStation: ChargingStation,
commandName: RequestCommand
): boolean {
- return OCPP16ServiceUtils.isRequestCommandSupported(
- chargingStation,
- commandName as OCPP16RequestCommand
- )
+ return isRequestCommandSupported(chargingStation, commandName as OCPP16RequestCommand)
}
private handleResponseAuthorize (
buildSampledValue,
buildTransactionEndMeterValue,
getSampledValueTemplate,
- OCPPServiceUtils,
+ PayloadValidatorConfig,
+ PayloadValidatorOptions,
sendAndSetConnectorStatus,
} from '../OCPPServiceUtils.js'
import { OCPP16Constants } from './OCPP16Constants.js'
const moduleName = 'OCPP16ServiceUtils'
-export class OCPP16ServiceUtils extends OCPPServiceUtils {
+// eslint-disable-next-line @typescript-eslint/no-extraneous-class
+export class OCPP16ServiceUtils {
private static readonly incomingRequestSchemaNames: readonly [
OCPP16IncomingRequestCommand,
string
[OCPP16RequestCommand.STOP_TRANSACTION, 'StopTransaction'],
]
+ /**
+ * Builds a meter value for the beginning of a transaction.
+ * @param chargingStation - Target charging station
+ * @param connectorId - Connector identifier
+ * @param meterStart - Initial meter reading in Wh
+ * @returns Meter value with the transaction begin context
+ */
public static buildTransactionBeginMeterValue (
chargingStation: ChargingStation,
connectorId: number,
return meterValue
}
+ /**
+ * Builds an array of transaction data meter values from begin and end values.
+ * @param transactionBeginMeterValue - Meter value at transaction start
+ * @param transactionEndMeterValue - Meter value at transaction end
+ * @returns Array containing the begin and end meter values
+ */
public static buildTransactionDataMeterValues (
transactionBeginMeterValue: OCPP16MeterValue,
transactionEndMeterValue: OCPP16MeterValue
return meterValues
}
+ /**
+ * Changes the availability of connectors and updates their status.
+ * @param chargingStation - Target charging station
+ * @param connectorIds - Array of connector identifiers to update
+ * @param chargePointStatus - New charge point status to set
+ * @param availabilityType - Operative or inoperative availability type
+ * @returns Accepted or scheduled availability change response
+ */
public static changeAvailability = async (
chargingStation: ChargingStation,
connectorIds: number[],
return OCPP16Constants.OCPP_AVAILABILITY_RESPONSE_ACCEPTED
}
+ /**
+ * Checks whether a feature profile is enabled on the charging station.
+ * @param chargingStation - Target charging station
+ * @param featureProfile - Feature profile to check
+ * @param command - OCPP command requiring the feature profile
+ * @returns Whether the feature profile is enabled
+ */
public static checkFeatureProfile (
chargingStation: ChargingStation,
featureProfile: OCPP16SupportedFeatureProfiles,
return true
}
+ /**
+ * Clears charging profiles matching the given criteria from the profiles array.
+ * @param chargingStation - Target charging station
+ * @param commandPayload - Clear charging profile request with filter criteria
+ * @param chargingProfiles - Array of charging profiles to filter
+ * @returns Whether any charging profiles were cleared
+ */
public static clearChargingProfiles = (
chargingStation: ChargingStation,
commandPayload: OCPP16ClearChargingProfileRequest,
return clearedCP
}
+ /**
+ * Composes a composite charging schedule from higher and lower priority schedules.
+ * @param chargingScheduleHigher - Higher priority charging schedule
+ * @param chargingScheduleLower - Lower priority charging schedule
+ * @param compositeInterval - Time interval for the composite schedule
+ * @returns Composed charging schedule or undefined if both inputs are null
+ */
public static composeChargingSchedules = (
chargingScheduleHigher: OCPP16ChargingSchedule | undefined,
chargingScheduleLower: OCPP16ChargingSchedule | undefined,
][] =>
OCPP16ServiceUtils.incomingRequestSchemaNames.map(([command, schemaBase]) => [
command,
- OCPP16ServiceUtils.PayloadValidatorConfig(`${schemaBase}.json`),
+ PayloadValidatorConfig(`${schemaBase}.json`),
])
/**
][] =>
OCPP16ServiceUtils.incomingRequestSchemaNames.map(([command, schemaBase]) => [
command,
- OCPP16ServiceUtils.PayloadValidatorConfig(`${schemaBase}Response.json`),
+ PayloadValidatorConfig(`${schemaBase}Response.json`),
])
/**
* @returns Factory options object for OCPP 1.6 validators
*/
public static createPayloadOptions = (moduleName: string, methodName: string) =>
- OCPP16ServiceUtils.PayloadValidatorOptions(
+ PayloadValidatorOptions(
OCPPVersion.VERSION_16,
'assets/json-schemas/ocpp/1.6',
moduleName,
][] =>
OCPP16ServiceUtils.outgoingRequestSchemaNames.map(([command, schemaBase]) => [
command,
- OCPP16ServiceUtils.PayloadValidatorConfig(`${schemaBase}.json`),
+ PayloadValidatorConfig(`${schemaBase}.json`),
])
/**
][] =>
OCPP16ServiceUtils.outgoingRequestSchemaNames.map(([command, schemaBase]) => [
command,
- OCPP16ServiceUtils.PayloadValidatorConfig(`${schemaBase}Response.json`),
+ PayloadValidatorConfig(`${schemaBase}Response.json`),
])
+ /**
+ * Checks whether a connector or the charging station has a valid reservation for the given idTag.
+ * @param chargingStation - Target charging station
+ * @param connectorId - Connector identifier to check
+ * @param idTag - RFID tag to match against the reservation
+ * @returns Whether a valid reservation exists for the idTag
+ */
public static hasReservation = (
chargingStation: ChargingStation,
connectorId: number,
return false
}
+ /**
+ * Determines whether a configuration key should be visible in GetConfiguration responses.
+ * @param key - Configuration key to check
+ * @returns Whether the key is visible
+ */
public static isConfigurationKeyVisible (key: ConfigurationKey): boolean {
if (key.visible == null) {
return true
return key.visible
}
+ /**
+ * Stops a transaction remotely on the given connector.
+ * @param chargingStation - Target charging station
+ * @param connectorId - Connector identifier with the active transaction
+ * @returns Accepted or rejected generic response
+ */
public static remoteStopTransaction = async (
chargingStation: ChargingStation,
connectorId: number
return OCPP16Constants.OCPP_RESPONSE_REJECTED
}
+ /**
+ * Sets or replaces a charging profile on a connector.
+ * @param chargingStation - Target charging station
+ * @param connectorId - Connector identifier to set the profile on
+ * @param cp - Charging profile to set
+ */
public static setChargingProfile (
chargingStation: ChargingStation,
connectorId: number,
!cpReplaced && chargingStation.getConnectorStatus(connectorId)?.chargingProfiles?.push(cp)
}
+ /**
+ * Sends a StartTransaction request to the central system for the given connector.
+ * @param chargingStation - Target charging station
+ * @param connectorId - Connector identifier to start the transaction on
+ * @param idTag - Optional RFID tag for the transaction
+ * @returns Start transaction response from the central system
+ */
public static async startTransactionOnConnector (
chargingStation: ChargingStation,
connectorId: number,
})
}
+ /**
+ * Starts periodic meter value updates for an active transaction on a connector.
+ * @param chargingStation - Target charging station
+ * @param connectorId - Connector identifier with the active transaction
+ * @param interval - Meter value sample interval in milliseconds
+ */
public static startUpdatedMeterValues (
chargingStation: ChargingStation,
connectorId: number,
}, clampToSafeTimerValue(interval))
}
+ /**
+ * Sends a StopTransaction request to the central system for the given connector.
+ * @param chargingStation - Target charging station
+ * @param connectorId - Connector identifier with the active transaction
+ * @param reason - Optional stop transaction reason
+ * @returns Stop transaction response from the central system
+ */
public static async stopTransactionOnConnector (
chargingStation: ChargingStation,
connectorId: number,
})
}
+ /**
+ * Stops periodic meter value updates for a connector.
+ * @param chargingStation - Target charging station
+ * @param connectorId - Connector identifier to stop updates for
+ */
public static stopUpdatedMeterValues (
chargingStation: ChargingStation,
connectorId: number
import { OCPPIncomingRequestService } from '../OCPPIncomingRequestService.js'
import {
buildMeterValue,
+ createPayloadValidatorMap,
+ isIncomingRequestCommandSupported,
restoreConnectorStatus,
sendAndSetConnectorStatus,
} from '../OCPPServiceUtils.js'
this.toRequestHandler(this.handleRequestUpdateFirmware.bind(this)),
],
])
- this.payloadValidatorFunctions = OCPP20ServiceUtils.createPayloadValidatorMap(
+ this.payloadValidatorFunctions = createPayloadValidatorMap(
OCPP20ServiceUtils.createIncomingRequestPayloadConfigs(),
OCPP20ServiceUtils.createPayloadOptions(moduleName, 'constructor'),
this.ajv
)
}
+ /**
+ * Handle OCPP 2.0.1 GetVariables request from the CSMS.
+ * @param chargingStation - Target charging station
+ * @param commandPayload - GetVariables request payload
+ * @returns GetVariables response with variable results
+ */
public handleRequestGetVariables (
chargingStation: ChargingStation,
commandPayload: OCPP20GetVariablesRequest
return getVariablesResponse
}
+ /**
+ * Handle OCPP 2.0.1 SetVariables request from the CSMS.
+ * @param chargingStation - Target charging station
+ * @param commandPayload - SetVariables request payload
+ * @returns SetVariables response with variable results
+ */
public handleRequestSetVariables (
chargingStation: ChargingStation,
commandPayload: OCPP20SetVariablesRequest
return setVariablesResponse
}
+ /**
+ * Stop the incoming request service and clean up per-station state.
+ * @param chargingStation - Target charging station to stop
+ */
public override stop (chargingStation: ChargingStation): void {
const stationState = this.stationsState.get(chargingStation)
if (stationState != null) {
}
}
+ /**
+ * Check whether an incoming request command is supported by the charging station.
+ * @param chargingStation - Target charging station
+ * @param commandName - Incoming request command to check
+ * @returns Whether the command is supported
+ */
protected isIncomingRequestCommandSupported (
chargingStation: ChargingStation,
commandName: IncomingRequestCommand
): boolean {
- return OCPP20ServiceUtils.isIncomingRequestCommandSupported(
+ return isIncomingRequestCommandSupported(
chargingStation,
commandName as OCPP20IncomingRequestCommand
)
} from '../../../types/index.js'
import { generateUUID, logger } from '../../../utils/index.js'
import { OCPPRequestService } from '../OCPPRequestService.js'
-import { buildStatusNotificationRequest } from '../OCPPServiceUtils.js'
+import {
+ buildStatusNotificationRequest,
+ createPayloadValidatorMap,
+ isRequestCommandSupported,
+} from '../OCPPServiceUtils.js'
import { generatePkcs10Csr } from './Asn1DerUtils.js'
import { OCPP20Constants } from './OCPP20Constants.js'
import { buildTransactionEvent, OCPP20ServiceUtils } from './OCPP20ServiceUtils.js'
*/
public constructor (ocppResponseService: OCPPResponseService) {
super(OCPPVersion.VERSION_201, ocppResponseService)
- this.payloadValidatorFunctions = OCPP20ServiceUtils.createPayloadValidatorMap(
+ this.payloadValidatorFunctions = createPayloadValidatorMap(
OCPP20ServiceUtils.createRequestPayloadConfigs(),
OCPP20ServiceUtils.createPayloadOptions(moduleName, 'constructor'),
this.ajv
logger.debug(
`${chargingStation.logPrefix()} ${moduleName}.requestHandler: Processing '${commandName}' request`
)
- if (OCPP20ServiceUtils.isRequestCommandSupported(chargingStation, commandName)) {
+ if (isRequestCommandSupported(chargingStation, commandName)) {
try {
logger.debug(
`${chargingStation.logPrefix()} ${moduleName}.requestHandler: Building request payload for '${commandName}'`
import { convertToDate, logger } from '../../../utils/index.js'
import { mapOCPP20TokenType, OCPPAuthServiceFactory } from '../auth/index.js'
import { OCPPResponseService } from '../OCPPResponseService.js'
-import { sendAndSetConnectorStatus } from '../OCPPServiceUtils.js'
+import {
+ createPayloadValidatorMap,
+ isRequestCommandSupported,
+ sendAndSetConnectorStatus,
+} from '../OCPPServiceUtils.js'
import { OCPP20ServiceUtils } from './OCPP20ServiceUtils.js'
const moduleName = 'OCPP20ResponseService'
this.toResponseHandler(this.handleResponseTransactionEvent.bind(this)),
],
])
- this.payloadValidatorFunctions = OCPP20ServiceUtils.createPayloadValidatorMap(
+ this.payloadValidatorFunctions = createPayloadValidatorMap(
OCPP20ServiceUtils.createResponsePayloadConfigs(),
OCPP20ServiceUtils.createPayloadOptions(moduleName, 'constructor'),
this.ajv
)
- this.incomingRequestResponsePayloadValidateFunctions =
- OCPP20ServiceUtils.createPayloadValidatorMap(
- OCPP20ServiceUtils.createIncomingRequestResponsePayloadConfigs(),
- OCPP20ServiceUtils.createPayloadOptions(moduleName, 'constructor'),
- this.ajvIncomingRequest
- )
+ this.incomingRequestResponsePayloadValidateFunctions = createPayloadValidatorMap(
+ OCPP20ServiceUtils.createIncomingRequestResponsePayloadConfigs(),
+ OCPP20ServiceUtils.createPayloadOptions(moduleName, 'constructor'),
+ this.ajvIncomingRequest
+ )
}
+ /**
+ * Check whether a request command is supported by the charging station.
+ * @param chargingStation - Target charging station
+ * @param commandName - Request command to check
+ * @returns Whether the command is supported
+ */
protected isRequestCommandSupported (
chargingStation: ChargingStation,
commandName: RequestCommand
): boolean {
- return OCPP20ServiceUtils.isRequestCommandSupported(
- chargingStation,
- commandName as OCPP20RequestCommand
- )
+ return isRequestCommandSupported(chargingStation, commandName as OCPP20RequestCommand)
}
private handleResponseAuthorize (
import { buildConfigKey, getConfigurationKey } from '../../ConfigurationKeyUtils.js'
import {
buildMeterValue,
- OCPPServiceUtils,
+ PayloadValidatorConfig,
+ PayloadValidatorOptions,
sendAndSetConnectorStatus,
} from '../OCPPServiceUtils.js'
import { OCPP20VariableManager } from './OCPP20VariableManager.js'
reasonCode: ReasonCodeEnumType
}
-export class OCPP20ServiceUtils extends OCPPServiceUtils {
+// eslint-disable-next-line @typescript-eslint/no-extraneous-class
+export class OCPP20ServiceUtils {
private static readonly incomingRequestSchemaNames: readonly [
OCPP20IncomingRequestCommand,
string
[OCPP20RequestCommand.TRANSACTION_EVENT, 'TransactionEvent'],
]
+ /**
+ * Build meter values for the start of a transaction.
+ * @param chargingStation - Target charging station
+ * @param transactionId - Transaction identifier
+ * @returns Array of OCPP 2.0 meter values at transaction begin
+ */
static buildTransactionStartedMeterValues (
chargingStation: ChargingStation,
transactionId: number | string
}
}
+ /**
+ * Clean up connector state after a transaction has ended.
+ * @param chargingStation - Target charging station
+ * @param connectorId - Connector identifier
+ * @param connectorStatus - Connector status to reset
+ */
public static async cleanupEndedTransaction (
chargingStation: ChargingStation,
connectorId: number,
][] =>
OCPP20ServiceUtils.incomingRequestSchemaNames.map(([command, schemaBase]) => [
command,
- OCPP20ServiceUtils.PayloadValidatorConfig(`${schemaBase}Request.json`),
+ PayloadValidatorConfig(`${schemaBase}Request.json`),
])
/**
][] =>
OCPP20ServiceUtils.incomingRequestSchemaNames.map(([command, schemaBase]) => [
command,
- OCPP20ServiceUtils.PayloadValidatorConfig(`${schemaBase}Response.json`),
+ PayloadValidatorConfig(`${schemaBase}Response.json`),
])
/**
* @returns Factory options object for OCPP 2.0 validators
*/
public static createPayloadOptions = (moduleName: string, methodName: string) =>
- OCPP20ServiceUtils.PayloadValidatorOptions(
+ PayloadValidatorOptions(
OCPPVersion.VERSION_201,
'assets/json-schemas/ocpp/2.0',
moduleName,
][] =>
OCPP20ServiceUtils.outgoingRequestSchemaNames.map(([command, schemaBase]) => [
command,
- OCPP20ServiceUtils.PayloadValidatorConfig(`${schemaBase}Request.json`),
+ PayloadValidatorConfig(`${schemaBase}Request.json`),
])
/**
][] =>
OCPP20ServiceUtils.outgoingRequestSchemaNames.map(([command, schemaBase]) => [
command,
- OCPP20ServiceUtils.PayloadValidatorConfig(`${schemaBase}Response.json`),
+ PayloadValidatorConfig(`${schemaBase}Response.json`),
])
+ /**
+ * Enforce ItemsPerMessage and BytesPerMessage limits on request data.
+ * @param chargingStation - Charging station providing log prefix
+ * @param chargingStation.logPrefix - Log prefix function
+ * @param moduleName - Module name for logging context
+ * @param context - Method name for logging context
+ * @param data - Array of variable data items to validate
+ * @param itemsLimit - Maximum allowed items per message (0 = unlimited)
+ * @param bytesLimit - Maximum allowed bytes per message (0 = unlimited)
+ * @param buildRejected - Factory function to build rejection results
+ * @param logger - Logger instance for debug output
+ * @param logger.debug - Debug logging function
+ * @returns Object indicating whether data was rejected and the rejection results
+ */
public static enforceMessageLimits<
T extends { attributeType?: unknown; component: unknown; variable: unknown },
R
return { rejected: false, results: [] }
}
+ /**
+ * Enforce BytesPerMessage limit after results have been computed.
+ * @param chargingStation - Charging station providing log prefix
+ * @param chargingStation.logPrefix - Log prefix function
+ * @param moduleName - Module name for logging context
+ * @param context - Method name for logging context
+ * @param originalData - Original variable data items
+ * @param currentResults - Computed results to check against byte limit
+ * @param bytesLimit - Maximum allowed bytes per message (0 = unlimited)
+ * @param buildRejected - Factory function to build rejection results
+ * @param logger - Logger instance for debug output
+ * @param logger.debug - Debug logging function
+ * @returns Original results if within limit, or rejection results if exceeded
+ */
public static enforcePostCalculationBytesLimit<
T extends { attributeType?: unknown; component: unknown; variable: unknown },
R
return currentResults
}
+ /**
+ * Retrieve the AlignedDataCtrlr interval in milliseconds.
+ * @param chargingStation - Target charging station
+ * @returns Aligned data interval in milliseconds
+ */
public static getAlignedDataInterval (chargingStation: ChargingStation): number {
return OCPP20ServiceUtils.readVariableAsIntervalMs(
chargingStation,
)
}
+ /**
+ * Retrieve the SampledDataCtrlr TxEndedInterval in milliseconds.
+ * @param chargingStation - Target charging station
+ * @returns Transaction ended meter values interval in milliseconds
+ */
public static getTxEndedInterval (chargingStation: ChargingStation): number {
return OCPP20ServiceUtils.readVariableAsIntervalMs(
chargingStation,
)
}
+ /**
+ * Retrieve the SampledDataCtrlr TxUpdatedInterval in milliseconds.
+ * @param chargingStation - Target charging station
+ * @returns Transaction updated meter values interval in milliseconds
+ */
public static getTxUpdatedInterval (chargingStation: ChargingStation): number {
return OCPP20ServiceUtils.readVariableAsIntervalMs(
chargingStation,
return { bytesLimit, itemsLimit }
}
+ /**
+ * Deauthorize an active transaction per OCPP 2.0.1 E05 requirements.
+ * @param chargingStation - Target charging station
+ * @param connectorId - Connector identifier with the active transaction
+ * @param evseId - Optional EVSE identifier
+ * @returns Promise resolving to the TransactionEvent response
+ */
public static async requestDeauthorizeTransaction (
chargingStation: ChargingStation,
connectorId: number,
)
}
+ /**
+ * Stop an active transaction by sending a TransactionEvent(Ended).
+ * @param chargingStation - Target charging station
+ * @param connectorId - Connector identifier with the active transaction
+ * @param evseId - Optional EVSE identifier
+ * @param triggerReason - Trigger reason for the stop event
+ * @param stoppedReason - Reason the transaction was stopped
+ * @returns Promise resolving to the TransactionEvent response
+ */
public static async requestStopTransaction (
chargingStation: ChargingStation,
connectorId: number,
}
}
+ /**
+ * Send queued TransactionEvent requests accumulated while offline.
+ * @param chargingStation - Target charging station
+ * @param connectorId - Connector identifier whose queue to drain
+ */
public static async sendQueuedTransactionEvents (
chargingStation: ChargingStation,
connectorId: number
}
}
+ /**
+ * Send a TransactionEvent request to the CSMS, or queue it if offline.
+ * @param chargingStation - Target charging station
+ * @param eventType - Transaction event type (Started, Updated, Ended)
+ * @param triggerReason - Reason that triggered the event
+ * @param connectorId - Connector identifier
+ * @param transactionId - Transaction identifier
+ * @param options - Additional transaction event options
+ * @returns Promise resolving to the TransactionEvent response
+ */
public static async sendTransactionEvent (
chargingStation: ChargingStation,
eventType: OCPP20TransactionEventEnumType,
}
}
+ /**
+ * Start periodic collection of TxEnded meter values for a connector.
+ * @param chargingStation - Target charging station
+ * @param connectorId - Connector identifier
+ * @param interval - Collection interval in milliseconds
+ */
public static startEndedMeterValues (
chargingStation: ChargingStation,
connectorId: number,
)
}
+ /**
+ * Start periodic TransactionEvent(Updated) with meter values for a connector.
+ * @param chargingStation - Target charging station
+ * @param connectorId - Connector identifier
+ * @param interval - Sending interval in milliseconds
+ */
public static startUpdatedMeterValues (
chargingStation: ChargingStation,
connectorId: number,
)
}
+ /**
+ * Stop all active transactions on the charging station or a specific EVSE.
+ * @param chargingStation - Target charging station
+ * @param triggerReason - Trigger reason for stop events
+ * @param stoppedReason - Reason the transactions were stopped
+ * @param evseId - Optional EVSE identifier to limit scope
+ */
public static async stopAllTransactions (
chargingStation: ChargingStation,
triggerReason: OCPP20TriggerReasonEnumType = OCPP20TriggerReasonEnumType.RemoteStop,
}
}
+ /**
+ * Stop periodic TxEnded meter value collection for a connector.
+ * @param chargingStation - Target charging station
+ * @param connectorId - Connector identifier
+ */
public static stopEndedMeterValues (chargingStation: ChargingStation, connectorId: number): void {
const connectorStatus = chargingStation.getConnectorStatus(connectorId)
if (connectorStatus?.transactionEndedMeterValuesSetInterval != null) {
}
}
+ /**
+ * Stop periodic TransactionEvent(Updated) sending for a connector.
+ * @param chargingStation - Target charging station
+ * @param connectorId - Connector identifier
+ */
public static stopUpdatedMeterValues (
chargingStation: ChargingStation,
connectorId: number
--- /dev/null
+import type { StopTransactionReason } from '../../types/index.js'
+
+import { type ChargingStation } from '../../charging-station/index.js'
+import { OCPPError } from '../../exception/index.js'
+import {
+ AuthorizationStatus,
+ ErrorType,
+ OCPP20AuthorizationStatusEnumType,
+ OCPP20IdTokenEnumType,
+ OCPP20TransactionEventEnumType,
+ OCPP20TriggerReasonEnumType,
+ OCPPVersion,
+ type StartTransactionResult,
+ type StopTransactionResult,
+} from '../../types/index.js'
+import { generateUUID, logger } from '../../utils/index.js'
+import { OCPP16ServiceUtils } from './1.6/OCPP16ServiceUtils.js'
+import { OCPP20ServiceUtils } from './2.0/OCPP20ServiceUtils.js'
+import { mapStopReasonToOCPP20 } from './OCPPServiceUtils.js'
+
+/**
+ * Starts a transaction on a specific connector using the appropriate OCPP version handler.
+ * @param chargingStation - Target charging station
+ * @param connectorId - Connector ID to start the transaction on
+ * @param idTag - Optional RFID tag for authorization
+ * @returns Result indicating whether the transaction was accepted
+ */
+export const startTransactionOnConnector = async (
+ chargingStation: ChargingStation,
+ connectorId: number,
+ idTag?: string
+): Promise<StartTransactionResult> => {
+ switch (chargingStation.stationInfo?.ocppVersion) {
+ case OCPPVersion.VERSION_16: {
+ const response = await OCPP16ServiceUtils.startTransactionOnConnector(
+ chargingStation,
+ connectorId,
+ idTag
+ )
+ return { accepted: response.idTagInfo.status === AuthorizationStatus.ACCEPTED }
+ }
+ case OCPPVersion.VERSION_20:
+ case OCPPVersion.VERSION_201: {
+ const connectorStatus = chargingStation.getConnectorStatus(connectorId)
+ let transactionId = connectorStatus?.transactionId as string | undefined
+ if (transactionId == null) {
+ transactionId = generateUUID()
+ if (connectorStatus != null) {
+ connectorStatus.transactionId = transactionId
+ }
+ OCPP20ServiceUtils.resetTransactionSequenceNumber(chargingStation, connectorId)
+ }
+ const startedMeterValues = OCPP20ServiceUtils.buildTransactionStartedMeterValues(
+ chargingStation,
+ transactionId
+ )
+ const response = await OCPP20ServiceUtils.sendTransactionEvent(
+ chargingStation,
+ OCPP20TransactionEventEnumType.Started,
+ OCPP20TriggerReasonEnumType.Authorized,
+ connectorId,
+ transactionId,
+ {
+ idToken:
+ idTag != null ? { idToken: idTag, type: OCPP20IdTokenEnumType.ISO14443 } : undefined,
+ ...(startedMeterValues.length > 0 && { meterValue: startedMeterValues }),
+ }
+ )
+ return {
+ accepted:
+ response.idTokenInfo == null ||
+ response.idTokenInfo.status === OCPP20AuthorizationStatusEnumType.Accepted,
+ }
+ }
+ default:
+ throw new OCPPError(
+ ErrorType.INTERNAL_ERROR,
+ // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
+ `startTransactionOnConnector: unsupported OCPP version ${chargingStation.stationInfo?.ocppVersion}`
+ )
+ }
+}
+
+/**
+ * Stops a transaction on a specific connector using the appropriate OCPP version handler.
+ * @param chargingStation - Target charging station
+ * @param connectorId - Connector ID to stop the transaction on
+ * @param reason - Optional reason for stopping the transaction
+ * @returns Result indicating whether the stop was accepted
+ */
+export const stopTransactionOnConnector = async (
+ chargingStation: ChargingStation,
+ connectorId: number,
+ reason?: StopTransactionReason
+): Promise<StopTransactionResult> => {
+ switch (chargingStation.stationInfo?.ocppVersion) {
+ case OCPPVersion.VERSION_16: {
+ const response = await OCPP16ServiceUtils.stopTransactionOnConnector(
+ chargingStation,
+ connectorId,
+ reason
+ )
+ return { accepted: response.idTagInfo?.status === AuthorizationStatus.ACCEPTED }
+ }
+ case OCPPVersion.VERSION_20:
+ case OCPPVersion.VERSION_201: {
+ const evseId = chargingStation.getEvseIdByConnectorId(connectorId)
+ if (evseId == null) {
+ logger.warn(
+ `${chargingStation.logPrefix()} stopTransactionOnConnector: cannot resolve EVSE ID for connector ${connectorId.toString()}, skipping`
+ )
+ return { accepted: false }
+ }
+ const { stoppedReason, triggerReason } = mapStopReasonToOCPP20(reason)
+ const response = await OCPP20ServiceUtils.requestStopTransaction(
+ chargingStation,
+ connectorId,
+ evseId,
+ triggerReason,
+ stoppedReason
+ )
+ return {
+ accepted:
+ response.idTokenInfo == null ||
+ response.idTokenInfo.status === OCPP20AuthorizationStatusEnumType.Accepted,
+ }
+ }
+ default:
+ throw new OCPPError(
+ ErrorType.INTERNAL_ERROR,
+ // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
+ `stopTransactionOnConnector: unsupported OCPP version ${chargingStation.stationInfo?.ocppVersion}`
+ )
+ }
+}
+
+/**
+ * Stops all running transactions on all connectors of a charging station.
+ * @param chargingStation - Target charging station
+ * @param reason - Optional reason for stopping the transactions
+ */
+export const stopRunningTransactions = async (
+ chargingStation: ChargingStation,
+ reason?: StopTransactionReason
+): Promise<void> => {
+ switch (chargingStation.stationInfo?.ocppVersion) {
+ case OCPPVersion.VERSION_16: {
+ for (const { connectorId, connectorStatus } of chargingStation.iterateConnectors(true)) {
+ if (connectorStatus.transactionStarted === true) {
+ await OCPP16ServiceUtils.stopTransactionOnConnector(chargingStation, connectorId, reason)
+ }
+ }
+ break
+ }
+ case OCPPVersion.VERSION_20:
+ case OCPPVersion.VERSION_201: {
+ const { stoppedReason, triggerReason } = mapStopReasonToOCPP20(reason)
+ await OCPP20ServiceUtils.stopAllTransactions(chargingStation, triggerReason, stoppedReason)
+ break
+ }
+ default:
+ logger.warn(
+ // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
+ `${chargingStation.logPrefix()} stopRunningTransactions: unsupported OCPP version ${chargingStation.stationInfo?.ocppVersion}, no transactions stopped`
+ )
+ }
+}
+
+/**
+ * Starts periodic meter value updates for a connector during an active transaction.
+ * @param chargingStation - Target charging station
+ * @param connectorId - Connector ID to start meter value updates for
+ * @param interval - Meter value sampling interval in milliseconds
+ */
+export const startUpdatedMeterValues = (
+ chargingStation: ChargingStation,
+ connectorId: number,
+ interval: number
+): void => {
+ switch (chargingStation.stationInfo?.ocppVersion) {
+ case OCPPVersion.VERSION_16:
+ OCPP16ServiceUtils.startUpdatedMeterValues(chargingStation, connectorId, interval)
+ break
+ case OCPPVersion.VERSION_20:
+ case OCPPVersion.VERSION_201:
+ OCPP20ServiceUtils.startUpdatedMeterValues(chargingStation, connectorId, interval)
+ break
+ default:
+ logger.error(
+ // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
+ `${chargingStation.logPrefix()} startUpdatedMeterValues: unsupported OCPP version ${chargingStation.stationInfo?.ocppVersion}`
+ )
+ }
+}
+
+/**
+ * Stops periodic meter value updates for a connector.
+ * @param chargingStation - Target charging station
+ * @param connectorId - Connector ID to stop meter value updates for
+ */
+export const stopUpdatedMeterValues = (
+ chargingStation: ChargingStation,
+ connectorId: number
+): void => {
+ switch (chargingStation.stationInfo?.ocppVersion) {
+ case OCPPVersion.VERSION_16:
+ OCPP16ServiceUtils.stopUpdatedMeterValues(chargingStation, connectorId)
+ break
+ case OCPPVersion.VERSION_20:
+ case OCPPVersion.VERSION_201:
+ OCPP20ServiceUtils.stopUpdatedMeterValues(chargingStation, connectorId)
+ break
+ default:
+ break
+ }
+}
+
+/**
+ * Flushes queued transaction event messages for all connectors on an OCPP 2.0 charging station.
+ * @param chargingStation - Target charging station
+ */
+export const flushQueuedTransactionMessages = async (
+ chargingStation: ChargingStation
+): Promise<void> => {
+ switch (chargingStation.stationInfo?.ocppVersion) {
+ case OCPPVersion.VERSION_16:
+ break
+ case OCPPVersion.VERSION_20:
+ case OCPPVersion.VERSION_201:
+ for (const { connectorId, connectorStatus } of chargingStation.iterateConnectors()) {
+ if ((connectorStatus.transactionEventQueue?.length ?? 0) > 0) {
+ await OCPP20ServiceUtils.sendQueuedTransactionEvents(chargingStation, connectorId).catch(
+ (error: unknown) => {
+ logger.error(
+ `${chargingStation.logPrefix()} flushQueuedTransactionMessages: Error flushing queued TransactionEvents:`,
+ error
+ )
+ }
+ )
+ }
+ }
+ break
+ default:
+ break
+ }
+}
import { type ChargingStation, getConfigurationKey } from '../../charging-station/index.js'
import { BaseError, OCPPError } from '../../exception/index.js'
import {
- AuthorizationStatus,
ChargePointErrorCode,
ChargingStationEvents,
type ConfigurationKeyType,
type OCPP16SampledValue,
type OCPP16StatusNotificationRequest,
OCPP16StopTransactionReason,
- OCPP20AuthorizationStatusEnumType,
type OCPP20ConnectorStatusEnumType,
- OCPP20IdTokenEnumType,
type OCPP20MeterValue,
OCPP20ReasonEnumType,
type OCPP20SampledValue,
type OCPP20StatusNotificationRequest,
- OCPP20TransactionEventEnumType,
OCPP20TriggerReasonEnumType,
OCPPVersion,
RequestCommand,
type SampledValue,
type SampledValueTemplate,
StandardParametersKey,
- type StartTransactionResult,
type StatusNotificationRequest,
type StatusNotificationResponse,
- type StopTransactionResult,
} from '../../types/index.js'
import {
ACElectricUtils,
convertToFloat,
convertToInt,
DCElectricUtils,
- generateUUID,
getRandomFloatFluctuatedRounded,
getRandomFloatRounded,
handleFileException,
value: number
}
+/**
+ * Builds a StatusNotification request payload for the appropriate OCPP version.
+ * @param chargingStation - Target charging station
+ * @param commandParams - Status notification parameters including connector ID and status
+ * @returns Formatted StatusNotification request payload
+ */
export const buildStatusNotificationRequest = (
chargingStation: ChargingStation,
commandParams: StatusNotificationRequest
}
}
+/**
+ * Sends a StatusNotification request and updates the connector status locally.
+ * @param chargingStation - Target charging station
+ * @param commandParams - Status notification parameters including connector ID and status
+ * @param options - Optional settings to control whether the request is actually sent
+ * @param options.send - Whether to actually send the status notification
+ */
export const sendAndSetConnectorStatus = async (
chargingStation: ChargingStation,
commandParams: StatusNotificationRequest,
})
}
+/**
+ * Restores a connector status to Reserved or Available based on its current state.
+ * @param chargingStation - Target charging station
+ * @param connectorId - Connector ID to restore
+ * @param connectorStatus - Current connector status to evaluate
+ */
export const restoreConnectorStatus = async (
chargingStation: ChargingStation,
connectorId: number,
}
}
+/**
+ * Maps an OCPP 1.6 or generic stop transaction reason to OCPP 2.0 stopped and trigger reasons.
+ * @param reason - Stop transaction reason to map
+ * @returns Object containing the OCPP 2.0 stoppedReason and triggerReason
+ */
export const mapStopReasonToOCPP20 = (
reason?: StopTransactionReason
): {
}
}
-export const startTransactionOnConnector = async (
- chargingStation: ChargingStation,
- connectorId: number,
- idTag?: string
-): Promise<StartTransactionResult> => {
- switch (chargingStation.stationInfo?.ocppVersion) {
- case OCPPVersion.VERSION_16: {
- const { OCPP16ServiceUtils } = await import('./1.6/OCPP16ServiceUtils.js')
- const response = await OCPP16ServiceUtils.startTransactionOnConnector(
- chargingStation,
- connectorId,
- idTag
- )
- return { accepted: response.idTagInfo.status === AuthorizationStatus.ACCEPTED }
- }
- case OCPPVersion.VERSION_20:
- case OCPPVersion.VERSION_201: {
- const { OCPP20ServiceUtils } = await import('./2.0/OCPP20ServiceUtils.js')
- const connectorStatus = chargingStation.getConnectorStatus(connectorId)
- let transactionId = connectorStatus?.transactionId as string | undefined
- if (transactionId == null) {
- transactionId = generateUUID()
- if (connectorStatus != null) {
- connectorStatus.transactionId = transactionId
- }
- OCPP20ServiceUtils.resetTransactionSequenceNumber(chargingStation, connectorId)
- }
- const startedMeterValues = OCPP20ServiceUtils.buildTransactionStartedMeterValues(
- chargingStation,
- transactionId
- )
- const response = await OCPP20ServiceUtils.sendTransactionEvent(
- chargingStation,
- OCPP20TransactionEventEnumType.Started,
- OCPP20TriggerReasonEnumType.Authorized,
- connectorId,
- transactionId,
- {
- idToken:
- idTag != null ? { idToken: idTag, type: OCPP20IdTokenEnumType.ISO14443 } : undefined,
- ...(startedMeterValues.length > 0 && { meterValue: startedMeterValues }),
- }
- )
- return {
- accepted:
- response.idTokenInfo == null ||
- response.idTokenInfo.status === OCPP20AuthorizationStatusEnumType.Accepted,
- }
- }
- default:
- throw new OCPPError(
- ErrorType.INTERNAL_ERROR,
- // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
- `startTransactionOnConnector: unsupported OCPP version ${chargingStation.stationInfo?.ocppVersion}`
- )
- }
-}
-
-export const stopTransactionOnConnector = async (
- chargingStation: ChargingStation,
- connectorId: number,
- reason?: StopTransactionReason
-): Promise<StopTransactionResult> => {
- switch (chargingStation.stationInfo?.ocppVersion) {
- case OCPPVersion.VERSION_16: {
- const { OCPP16ServiceUtils } = await import('./1.6/OCPP16ServiceUtils.js')
- const response = await OCPP16ServiceUtils.stopTransactionOnConnector(
- chargingStation,
- connectorId,
- reason
- )
- return { accepted: response.idTagInfo?.status === AuthorizationStatus.ACCEPTED }
- }
- case OCPPVersion.VERSION_20:
- case OCPPVersion.VERSION_201: {
- const { OCPP20ServiceUtils } = await import('./2.0/OCPP20ServiceUtils.js')
- const evseId = chargingStation.getEvseIdByConnectorId(connectorId)
- if (evseId == null) {
- logger.warn(
- `${chargingStation.logPrefix()} stopTransactionOnConnector: cannot resolve EVSE ID for connector ${connectorId.toString()}, skipping`
- )
- return { accepted: false }
- }
- const { stoppedReason, triggerReason } = mapStopReasonToOCPP20(reason)
- const response = await OCPP20ServiceUtils.requestStopTransaction(
- chargingStation,
- connectorId,
- evseId,
- triggerReason,
- stoppedReason
- )
- return {
- accepted:
- response.idTokenInfo == null ||
- response.idTokenInfo.status === OCPP20AuthorizationStatusEnumType.Accepted,
- }
- }
- default:
- throw new OCPPError(
- ErrorType.INTERNAL_ERROR,
- // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
- `stopTransactionOnConnector: unsupported OCPP version ${chargingStation.stationInfo?.ocppVersion}`
- )
- }
-}
-
-export const stopRunningTransactions = async (
- chargingStation: ChargingStation,
- reason?: StopTransactionReason
-): Promise<void> => {
- switch (chargingStation.stationInfo?.ocppVersion) {
- case OCPPVersion.VERSION_16: {
- const { OCPP16ServiceUtils } = await import('./1.6/OCPP16ServiceUtils.js')
- // Sequential — OCPP 1.6 behavior
- for (const { connectorId, connectorStatus } of chargingStation.iterateConnectors(true)) {
- if (connectorStatus.transactionStarted === true) {
- await OCPP16ServiceUtils.stopTransactionOnConnector(chargingStation, connectorId, reason)
- }
- }
- break
- }
- case OCPPVersion.VERSION_20:
- case OCPPVersion.VERSION_201: {
- const { OCPP20ServiceUtils } = await import('./2.0/OCPP20ServiceUtils.js')
- const { stoppedReason, triggerReason } = mapStopReasonToOCPP20(reason)
- await OCPP20ServiceUtils.stopAllTransactions(chargingStation, triggerReason, stoppedReason)
- break
- }
- default:
- logger.warn(
- // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
- `${chargingStation.logPrefix()} stopRunningTransactions: unsupported OCPP version ${chargingStation.stationInfo?.ocppVersion}, no transactions stopped`
- )
- }
-}
-
-export const startUpdatedMeterValues = async (
- chargingStation: ChargingStation,
- connectorId: number,
- interval: number
-): Promise<void> => {
- switch (chargingStation.stationInfo?.ocppVersion) {
- case OCPPVersion.VERSION_16: {
- const { OCPP16ServiceUtils } = await import('./1.6/OCPP16ServiceUtils.js')
- OCPP16ServiceUtils.startUpdatedMeterValues(chargingStation, connectorId, interval)
- break
- }
- case OCPPVersion.VERSION_20:
- case OCPPVersion.VERSION_201: {
- const { OCPP20ServiceUtils } = await import('./2.0/OCPP20ServiceUtils.js')
- OCPP20ServiceUtils.startUpdatedMeterValues(chargingStation, connectorId, interval)
- break
- }
- default:
- logger.error(
- // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
- `${chargingStation.logPrefix()} OCPPServiceUtils.startUpdatedMeterValues: unsupported OCPP version ${chargingStation.stationInfo?.ocppVersion}`
- )
- }
-}
-
-export const stopUpdatedMeterValues = async (
- chargingStation: ChargingStation,
- connectorId: number
-): Promise<void> => {
- switch (chargingStation.stationInfo?.ocppVersion) {
- case OCPPVersion.VERSION_16: {
- const { OCPP16ServiceUtils } = await import('./1.6/OCPP16ServiceUtils.js')
- OCPP16ServiceUtils.stopUpdatedMeterValues(chargingStation, connectorId)
- break
- }
- case OCPPVersion.VERSION_20:
- case OCPPVersion.VERSION_201: {
- const { OCPP20ServiceUtils } = await import('./2.0/OCPP20ServiceUtils.js')
- OCPP20ServiceUtils.stopUpdatedMeterValues(chargingStation, connectorId)
- break
- }
- default:
- break
- }
-}
-
-export const flushQueuedTransactionMessages = async (
- chargingStation: ChargingStation
-): Promise<void> => {
- switch (chargingStation.stationInfo?.ocppVersion) {
- case OCPPVersion.VERSION_16:
- break
- case OCPPVersion.VERSION_20:
- case OCPPVersion.VERSION_201: {
- const { OCPP20ServiceUtils } = await import('./2.0/OCPP20ServiceUtils.js')
- for (const { connectorId, connectorStatus } of chargingStation.iterateConnectors()) {
- if ((connectorStatus.transactionEventQueue?.length ?? 0) > 0) {
- await OCPP20ServiceUtils.sendQueuedTransactionEvents(chargingStation, connectorId).catch(
- (error: unknown) => {
- logger.error(
- `${chargingStation.logPrefix()} OCPPServiceUtils.flushQueuedTransactionMessages: Error flushing queued TransactionEvents:`,
- error
- )
- }
- )
- }
- }
- break
- }
- default:
- break
- }
-}
-
const checkConnectorStatusTransition = (
chargingStation: ChargingStation,
connectorId: number,
return transitionAllowed
}
+/**
+ * Converts Ajv validation errors to the corresponding OCPP error type.
+ * @param errors - Array of Ajv validation error objects
+ * @returns OCPP ErrorType corresponding to the validation failure
+ */
export const ajvErrorsToErrorType = (errors: ErrorObject[] | null | undefined): ErrorType => {
if (isNotEmptyArray(errors)) {
for (const error of errors) {
return ErrorType.FORMAT_VIOLATION
}
+/**
+ * Recursively converts Date values to ISO 8601 strings within a JSON-compatible object.
+ * @param object - Object whose Date properties will be converted in-place
+ */
// eslint-disable-next-line @typescript-eslint/no-unnecessary-type-parameters
export const convertDateToISOString = <T extends JsonType>(object: T): void => {
for (const [key, value] of Object.entries(object as Record<string, unknown>)) {
}
}
+/**
+ * Builds an empty MeterValue with no sampled values and the current timestamp.
+ * @returns Empty MeterValue object
+ */
export const buildEmptyMeterValue = (): MeterValue => ({
sampledValue: [],
timestamp: new Date(),
})
+/**
+ * Builds a complete MeterValue with all configured measurands for a transaction.
+ * @param chargingStation - Target charging station
+ * @param transactionId - Active transaction identifier
+ * @param interval - Meter value sampling interval in milliseconds
+ * @param measurandsKey - Configuration key for the sampled measurands list
+ * @param context - Meter value reading context
+ * @param debug - Enable debug logging for measurand validation
+ * @returns Populated MeterValue object
+ */
export const buildMeterValue = (
chargingStation: ChargingStation,
transactionId: number | string | undefined,
}
}
+/**
+ * Builds a MeterValue for the end of a transaction with the final energy register value.
+ * @param chargingStation - Target charging station
+ * @param connectorId - Connector ID associated with the transaction
+ * @param meterStop - Final meter reading in Wh at transaction end
+ * @returns MeterValue containing the transaction end energy reading
+ */
export const buildTransactionEndMeterValue = (
chargingStation: ChargingStation,
connectorId: number,
return supportedMeasurands.includes(measurand as string)
}
+/**
+ * Retrieves the sampled value template matching the given measurand and phase from configuration.
+ * @param chargingStation - Target charging station
+ * @param connectorId - Connector ID to look up templates for
+ * @param measurandsKey - Configuration key containing the list of sampled measurands
+ * @param measurand - Meter value measurand to match
+ * @param evseId - Optional EVSE ID for OCPP 2.0 template lookup
+ * @param phase - Optional phase to match in the template
+ * @returns Matching sampled value template, or undefined if not found
+ */
export const getSampledValueTemplate = (
chargingStation: ChargingStation,
connectorId: number,
}
/**
- * Utility class providing core OCPP (Open Charge Point Protocol) service functionality
- * and common operations across all OCPP versions and protocol implementations.
- *
- * This class serves as the foundation for OCPP protocol handling, providing:
- * - JSON schema-based payload validation using AJV (Another JSON Schema Validator)
- * - Common OCPP operations like connector status management and transaction handling
- * - Utility functions for meter value processing and ID tag authorization
- * - Shared functionality between OCPP 1.6 and OCPP 2.0+ implementations
- *
- * Key Features:
- * - **Schema Validation**: Centralized JSON schema loading and validation functions
- * - **Protocol Agnostic**: Provides utilities that work across OCPP versions
- * - **Transaction Management**: Utilities for transaction lifecycle and meter values
- * - **Status Management**: Connector and charging station status operations
- * - **Static Interface**: All functionality exposed as static methods for easy access
- *
- * Usage Pattern:
- * This class is typically used by other OCPP service classes (incoming request services,
- * 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 validateIncomingRequestPayload} Payload validation methods in service classes
- * @see {@link validateResponsePayload} Payload validation methods in service classes
+ * Creates a Map of compiled OCPP payload validators from configurations.
+ * Reduces code duplication across OCPP services.
+ * @param configs - Array of tuples containing command and validator configuration
+ * @param options - Factory options including OCPP version, schema directory, etc.
+ * @param options.ocppVersion - The OCPP version for schema validation
+ * @param options.schemaDir - Directory path containing JSON schemas
+ * @param options.moduleName - Name of the module for logging
+ * @param options.methodName - Name of the method for logging
+ * @param ajvInstance - Configured Ajv instance for validation
+ * @returns Map of commands to their compiled validation functions
*/
+export function createPayloadValidatorMap<Command extends JsonType> (
+ configs: [Command, { schemaPath: string }][],
+ options: {
+ methodName: string
+ moduleName: string
+ ocppVersion: OCPPVersion
+ schemaDir: string
+ },
+ ajvInstance: Ajv
+): Map<Command, ValidateFunction<JsonType>> {
+ return new Map<Command, ValidateFunction<JsonType>>(
+ configs.map(([command, config]) => {
+ const fullSchemaPath = `${options.schemaDir}/${config.schemaPath}`
+ const schema = parseJsonSchemaFile<JsonType>(
+ fullSchemaPath,
+ options.ocppVersion,
+ options.moduleName,
+ options.methodName
+ )
+ return [command, ajvInstance.compile(schema)]
+ })
+ )
+}
-// eslint-disable-next-line @typescript-eslint/no-extraneous-class
-export class OCPPServiceUtils {
- protected constructor () {
- // This is intentional
- }
-
- /**
- * Creates a Map of compiled OCPP payload validators from configurations.
- * Reduces code duplication across OCPP services.
- * @param configs - Array of tuples containing command and validator configuration
- * @param options - Factory options including OCPP version, schema directory, etc.
- * @param options.ocppVersion - The OCPP version for schema validation
- * @param options.schemaDir - Directory path containing JSON schemas
- * @param options.moduleName - Name of the module for logging
- * @param options.methodName - Name of the method for logging
- * @param ajvInstance - Configured Ajv instance for validation
- * @returns Map of commands to their compiled validation functions
- */
- public static createPayloadValidatorMap<Command extends JsonType>(
- configs: [Command, { schemaPath: string }][],
- options: {
- methodName: string
- moduleName: string
- ocppVersion: OCPPVersion
- schemaDir: string
- },
- ajvInstance: Ajv
- ): Map<Command, ValidateFunction<JsonType>> {
- return new Map<Command, ValidateFunction<JsonType>>(
- configs.map(([command, config]) => {
- const fullSchemaPath = `${options.schemaDir}/${config.schemaPath}`
- const schema = OCPPServiceUtils.parseJsonSchemaFile<JsonType>(
- fullSchemaPath,
- options.ocppVersion,
- options.moduleName,
- options.methodName
- )
- return [command, ajvInstance.compile(schema)]
- })
+/**
+ * @param chargingStation - Target charging station
+ * @param ocppCommand - OCPP command triggering the validation
+ * @param connectorId - Connector ID to validate
+ * @returns Whether the connector ID is valid (>= 0)
+ */
+export function isConnectorIdValid (
+ chargingStation: ChargingStation,
+ ocppCommand: IncomingRequestCommand,
+ connectorId: number
+): boolean {
+ if (connectorId < 0) {
+ logger.error(
+ `${chargingStation.logPrefix()} ${ocppCommand} incoming request received with invalid connector id ${connectorId.toString()}`
)
+ return false
}
+ return true
+}
- public static isConnectorIdValid (
- chargingStation: ChargingStation,
- ocppCommand: IncomingRequestCommand,
- connectorId: number
- ): boolean {
- if (connectorId < 0) {
- logger.error(
- `${chargingStation.logPrefix()} ${ocppCommand} incoming request received with invalid connector id ${connectorId.toString()}`
- )
- return false
- }
+/**
+ * @param chargingStation - Target charging station
+ * @param command - Incoming request command to check
+ * @returns Whether the command is supported by the station configuration
+ */
+export function isIncomingRequestCommandSupported (
+ chargingStation: ChargingStation,
+ command: IncomingRequestCommand
+): boolean {
+ const isIncomingRequestCommand =
+ Object.values<IncomingRequestCommand>(IncomingRequestCommand).includes(command)
+ if (
+ isIncomingRequestCommand &&
+ chargingStation.stationInfo?.commandsSupport?.incomingCommands == null
+ ) {
return true
+ } else if (
+ isIncomingRequestCommand &&
+ chargingStation.stationInfo?.commandsSupport?.incomingCommands[command] != null
+ ) {
+ return chargingStation.stationInfo.commandsSupport.incomingCommands[command]
}
+ logger.error(`${chargingStation.logPrefix()} Unknown incoming OCPP command '${command}'`)
+ return false
+}
- public static isIncomingRequestCommandSupported (
- chargingStation: ChargingStation,
- command: IncomingRequestCommand
- ): boolean {
- const isIncomingRequestCommand =
- Object.values<IncomingRequestCommand>(IncomingRequestCommand).includes(command)
- if (
- isIncomingRequestCommand &&
- chargingStation.stationInfo?.commandsSupport?.incomingCommands == null
- ) {
- return true
- } else if (
- isIncomingRequestCommand &&
- chargingStation.stationInfo?.commandsSupport?.incomingCommands[command] != null
- ) {
- return chargingStation.stationInfo.commandsSupport.incomingCommands[command]
- }
- logger.error(`${chargingStation.logPrefix()} Unknown incoming OCPP command '${command}'`)
- return false
+/**
+ * @param chargingStation - Target charging station
+ * @param messageTrigger - Message trigger to check
+ * @returns Whether the trigger is supported by the station configuration
+ */
+export function isMessageTriggerSupported (
+ chargingStation: ChargingStation,
+ messageTrigger: MessageTrigger
+): boolean {
+ const isMessageTrigger = (Object.values(MessageTrigger) as MessageTrigger[]).includes(
+ messageTrigger
+ )
+ if (isMessageTrigger && chargingStation.stationInfo?.messageTriggerSupport == null) {
+ return true
+ } else if (
+ isMessageTrigger &&
+ chargingStation.stationInfo?.messageTriggerSupport?.[messageTrigger] != null
+ ) {
+ return chargingStation.stationInfo.messageTriggerSupport[messageTrigger]
}
+ logger.error(
+ `${chargingStation.logPrefix()} Unknown incoming OCPP message trigger '${messageTrigger}'`
+ )
+ return false
+}
- public static isMessageTriggerSupported (
- chargingStation: ChargingStation,
- messageTrigger: MessageTrigger
- ): boolean {
- const isMessageTrigger = (Object.values(MessageTrigger) as MessageTrigger[]).includes(
- messageTrigger
- )
- if (isMessageTrigger && chargingStation.stationInfo?.messageTriggerSupport == null) {
- return true
- } else if (
- isMessageTrigger &&
- chargingStation.stationInfo?.messageTriggerSupport?.[messageTrigger] != null
- ) {
- return chargingStation.stationInfo.messageTriggerSupport[messageTrigger]
- }
- logger.error(
- `${chargingStation.logPrefix()} Unknown incoming OCPP message trigger '${messageTrigger}'`
- )
- return false
+/**
+ * @param chargingStation - Target charging station
+ * @param command - Outgoing request command to check
+ * @returns Whether the command is supported by the station configuration
+ */
+export function isRequestCommandSupported (
+ chargingStation: ChargingStation,
+ command: RequestCommand
+): boolean {
+ const isRequestCommand = Object.values<RequestCommand>(RequestCommand).includes(command)
+ if (isRequestCommand && chargingStation.stationInfo?.commandsSupport?.outgoingCommands == null) {
+ return true
+ } else if (
+ isRequestCommand &&
+ chargingStation.stationInfo?.commandsSupport?.outgoingCommands?.[command] != null
+ ) {
+ return chargingStation.stationInfo.commandsSupport.outgoingCommands[command]
}
+ logger.error(`${chargingStation.logPrefix()} Unknown outgoing OCPP command '${command}'`)
+ return false
+}
- public static isRequestCommandSupported (
- chargingStation: ChargingStation,
- command: RequestCommand
- ): boolean {
- const isRequestCommand = Object.values<RequestCommand>(RequestCommand).includes(command)
- if (
- isRequestCommand &&
- chargingStation.stationInfo?.commandsSupport?.outgoingCommands == null
- ) {
- return true
- } else if (
- isRequestCommand &&
- chargingStation.stationInfo?.commandsSupport?.outgoingCommands?.[command] != null
- ) {
- return chargingStation.stationInfo.commandsSupport.outgoingCommands[command]
- }
- logger.error(`${chargingStation.logPrefix()} Unknown outgoing OCPP command '${command}'`)
- return false
- }
+/**
+ * Configuration for a single payload validator.
+ * @param schemaPath - Path to the JSON schema file
+ * @returns Configuration object for payload validator creation
+ */
+export const PayloadValidatorConfig = (schemaPath: string) =>
+ ({
+ schemaPath,
+ }) as const
- /**
- * Configuration for a single payload validator.
- * @param schemaPath - Path to the JSON schema file
- * @returns Configuration object for payload validator creation
- */
- public static readonly PayloadValidatorConfig = (schemaPath: string) =>
- ({
- schemaPath,
- }) as const
-
- /**
- * Options for payload validator creation.
- * @param ocppVersion - The OCPP version
- * @param schemaDir - Directory containing JSON schemas
- * @param moduleName - Name of the OCPP module
- * @param methodName - Name of the method/command
- * @returns Options object for payload validator creation
- */
- public static readonly PayloadValidatorOptions = (
- ocppVersion: OCPPVersion,
- schemaDir: string,
- moduleName: string,
- methodName: string
- ) =>
- ({
- methodName,
- moduleName,
- ocppVersion,
- schemaDir,
- }) as const
-
- /**
- * Parses and loads a JSON schema file for OCPP payload 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
- * @throws {NodeJS.ErrnoException} If the schema file cannot be read or parsed
- */
- protected static parseJsonSchemaFile<T extends JsonType>(
- relativePath: string,
- ocppVersion: OCPPVersion,
- moduleName?: string,
- methodName?: string
- ): JSONSchemaType<T> {
- const baseDir = dirname(fileURLToPath(import.meta.url))
- // Primary: resolve from file directory (production esbuild bundle)
- const primaryPath = join(baseDir, relativePath)
+/**
+ * Options for payload validator creation.
+ * @param ocppVersion - The OCPP version
+ * @param schemaDir - Directory containing JSON schemas
+ * @param moduleName - Name of the OCPP module
+ * @param methodName - Name of the method/command
+ * @returns Options object for payload validator creation
+ */
+export const PayloadValidatorOptions = (
+ ocppVersion: OCPPVersion,
+ schemaDir: string,
+ moduleName: string,
+ methodName: string
+) =>
+ ({
+ methodName,
+ moduleName,
+ ocppVersion,
+ schemaDir,
+ }) as const
+
+/**
+ * Parses and loads a JSON schema file for OCPP payload 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
+ * @throws {NodeJS.ErrnoException} If the schema file cannot be read or parsed
+ */
+export function parseJsonSchemaFile<T extends JsonType> (
+ relativePath: string,
+ ocppVersion: OCPPVersion,
+ moduleName?: string,
+ methodName?: string
+): JSONSchemaType<T> {
+ 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(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(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
- }
+ return JSON.parse(readFileSync(fallbackPath, 'utf8')) as JSONSchemaType<T>
+ } catch {
+ handleFileException(
+ primaryPath,
+ FileType.JsonSchema,
+ primaryError as NodeJS.ErrnoException,
+ ocppServiceUtilsLogPrefix(ocppVersion, moduleName, methodName)
+ )
+ // handleFileException throws by default; this satisfies the compiler
+ throw primaryError
}
}
+}
- private static readonly logPrefix = (
- ocppVersion: OCPPVersion,
- moduleName?: string,
- methodName?: string
- ): string => {
- const logMsg =
- isNotEmptyString(moduleName) && isNotEmptyString(methodName)
- ? ` OCPP ${ocppVersion} | ${moduleName}.${methodName}:`
- : ` OCPP ${ocppVersion} |`
- return logPrefix(logMsg)
- }
+const ocppServiceUtilsLogPrefix = (
+ ocppVersion: OCPPVersion,
+ moduleName?: string,
+ methodName?: string
+): string => {
+ const logMsg =
+ isNotEmptyString(moduleName) && isNotEmptyString(methodName)
+ ? ` OCPP ${ocppVersion} | ${moduleName}.${methodName}:`
+ : ` OCPP ${ocppVersion} |`
+ return logPrefix(logMsg)
}
+++ /dev/null
-export { InMemoryAuthCache } from './InMemoryAuthCache.js'
+++ /dev/null
-export { AuthComponentFactory } from './AuthComponentFactory.js'
// Utils
// ============================================================================
-export * from './utils/index.js'
+export { AuthValidators } from './utils/AuthValidators.js'
+export { AuthConfigValidator } from './utils/ConfigValidator.js'
+++ /dev/null
-/**
- * Authentication utilities module
- *
- * Provides validation and helper functions for authentication operations
- */
-
-export { AuthValidators } from './AuthValidators.js'
-export { AuthConfigValidator } from './ConfigValidator.js'
export { isIdTagAuthorized } from './IdTagAuthorization.js'
export { OCPPIncomingRequestService } from './OCPPIncomingRequestService.js'
export { OCPPRequestService } from './OCPPRequestService.js'
+export {
+ flushQueuedTransactionMessages,
+ startTransactionOnConnector,
+ stopRunningTransactions,
+ stopTransactionOnConnector,
+} from './OCPPServiceOperations.js'
export {
buildMeterValue,
buildStatusNotificationRequest,
import { afterEach, describe, it } from 'node:test'
import { OCPP16ServiceUtils } from '../../../../src/charging-station/ocpp/1.6/OCPP16ServiceUtils.js'
-import { buildTransactionEndMeterValue } from '../../../../src/charging-station/ocpp/OCPPServiceUtils.js'
+import {
+ buildTransactionEndMeterValue,
+ isIncomingRequestCommandSupported,
+ isRequestCommandSupported,
+} from '../../../../src/charging-station/ocpp/OCPPServiceUtils.js'
import {
type OCPP16ChargingProfile,
OCPP16ChargingProfileKindType,
})
// Act
- const result = OCPP16ServiceUtils.isRequestCommandSupported(
- station,
- OCPP16RequestCommand.HEARTBEAT
- )
+ const result = isRequestCommandSupported(station, OCPP16RequestCommand.HEARTBEAT)
// Assert
assert.strictEqual(result, true)
},
})
- const result = OCPP16ServiceUtils.isRequestCommandSupported(
- station,
- OCPP16RequestCommand.HEARTBEAT
- )
+ const result = isRequestCommandSupported(station, OCPP16RequestCommand.HEARTBEAT)
assert.strictEqual(result, true)
})
},
})
- const result = OCPP16ServiceUtils.isRequestCommandSupported(
- station,
- OCPP16RequestCommand.HEARTBEAT
- )
+ const result = isRequestCommandSupported(station, OCPP16RequestCommand.HEARTBEAT)
assert.strictEqual(result, false)
})
stationInfo: { commandsSupport: undefined },
})
- const result = OCPP16ServiceUtils.isIncomingRequestCommandSupported(
- station,
- OCPP16IncomingRequestCommand.RESET
- )
+ const result = isIncomingRequestCommandSupported(station, OCPP16IncomingRequestCommand.RESET)
assert.strictEqual(result, true)
})
},
})
- const result = OCPP16ServiceUtils.isIncomingRequestCommandSupported(
- station,
- OCPP16IncomingRequestCommand.RESET
- )
+ const result = isIncomingRequestCommandSupported(station, OCPP16IncomingRequestCommand.RESET)
assert.strictEqual(result, true)
})
},
})
- const result = OCPP16ServiceUtils.isIncomingRequestCommandSupported(
+ const result = isIncomingRequestCommandSupported(
station,
OCPP16IncomingRequestCommand.REMOTE_START_TRANSACTION
)
OCPP20ServiceUtils,
} from '../../../../src/charging-station/ocpp/2.0/OCPP20ServiceUtils.js'
import { OCPP20VariableManager } from '../../../../src/charging-station/ocpp/2.0/OCPP20VariableManager.js'
-import { startUpdatedMeterValues } from '../../../../src/charging-station/ocpp/OCPPServiceUtils.js'
+import { startUpdatedMeterValues } from '../../../../src/charging-station/ocpp/OCPPServiceOperations.js'
import { OCPPError } from '../../../../src/exception/index.js'
import {
AttributeEnumType,
await describe('startUpdatedMeterValues', async () => {
await it('should not start OCPP 2.0 timer for OCPP 1.6 stations via dispatch', async t => {
- await withMockTimers(t, ['setInterval'], async () => {
+ await withMockTimers(t, ['setInterval'], () => {
const { station: ocpp16Station } = createMockChargingStation({
baseName: TEST_CHARGING_STATION_BASE_NAME,
connectorsCount: 1,
},
})
- await startUpdatedMeterValues(ocpp16Station, 1, 60000)
+ startUpdatedMeterValues(ocpp16Station, 1, 60000)
const connectorStatus = ocpp16Station.getConnectorStatus(1)
assert.strictEqual(connectorStatus?.transactionUpdatedMeterValuesSetInterval, undefined)
import {
flushQueuedTransactionMessages,
- mapStopReasonToOCPP20,
startTransactionOnConnector,
stopRunningTransactions,
stopTransactionOnConnector,
-} from '../../../src/charging-station/ocpp/OCPPServiceUtils.js'
+} from '../../../src/charging-station/ocpp/OCPPServiceOperations.js'
+import { mapStopReasonToOCPP20 } from '../../../src/charging-station/ocpp/OCPPServiceUtils.js'
import {
type OCPP20TransactionEventRequest,
OCPPVersion,
import {
ajvErrorsToErrorType,
convertDateToISOString,
- OCPPServiceUtils,
+ isConnectorIdValid,
} from '../../../src/charging-station/ocpp/OCPPServiceUtils.js'
import { ErrorType, IncomingRequestCommand, type JsonType } from '../../../src/types/index.js'
import { standardCleanup } from '../../helpers/TestLifecycleHelpers.js'
await describe('OCPPServiceUtils.isConnectorIdValid', async () => {
await it('should return true for connector ID greater than zero', () => {
- const result = OCPPServiceUtils.isConnectorIdValid(
+ const result = isConnectorIdValid(
makeStationMock(),
IncomingRequestCommand.REMOTE_START_TRANSACTION,
1
})
await it('should return true for connector ID zero', () => {
- const result = OCPPServiceUtils.isConnectorIdValid(
+ const result = isConnectorIdValid(
makeStationMock(),
IncomingRequestCommand.REMOTE_START_TRANSACTION,
0
})
await it('should return false for negative connector ID', () => {
- const result = OCPPServiceUtils.isConnectorIdValid(
+ const result = isConnectorIdValid(
makeStationMock(),
IncomingRequestCommand.REMOTE_START_TRANSACTION,
-1
import type { ChargingStation } from '../../../src/charging-station/index.js'
-import { OCPPServiceUtils } from '../../../src/charging-station/ocpp/OCPPServiceUtils.js'
+import {
+ isIncomingRequestCommandSupported,
+ isMessageTriggerSupported,
+ isRequestCommandSupported,
+} from '../../../src/charging-station/ocpp/OCPPServiceUtils.js'
import { IncomingRequestCommand, MessageTrigger, RequestCommand } from '../../../src/types/index.js'
import { standardCleanup } from '../../helpers/TestLifecycleHelpers.js'
},
})
- const result = OCPPServiceUtils.isIncomingRequestCommandSupported(
- station,
- IncomingRequestCommand.RESET
- )
+ const result = isIncomingRequestCommandSupported(station, IncomingRequestCommand.RESET)
assert.strictEqual(result, true)
})
},
})
- const result = OCPPServiceUtils.isIncomingRequestCommandSupported(
- station,
- IncomingRequestCommand.RESET
- )
+ const result = isIncomingRequestCommandSupported(station, IncomingRequestCommand.RESET)
assert.strictEqual(result, false)
})
await it('should return true when commandsSupport is undefined', () => {
const station = makeStationMock({})
- const result = OCPPServiceUtils.isIncomingRequestCommandSupported(
- station,
- IncomingRequestCommand.RESET
- )
+ const result = isIncomingRequestCommandSupported(station, IncomingRequestCommand.RESET)
assert.strictEqual(result, true)
})
commandsSupport: {},
})
- const result = OCPPServiceUtils.isIncomingRequestCommandSupported(
- station,
- IncomingRequestCommand.RESET
- )
+ const result = isIncomingRequestCommandSupported(station, IncomingRequestCommand.RESET)
assert.strictEqual(result, true)
})
},
})
- const result = OCPPServiceUtils.isRequestCommandSupported(station, RequestCommand.HEARTBEAT)
+ const result = isRequestCommandSupported(station, RequestCommand.HEARTBEAT)
assert.strictEqual(result, true)
})
},
})
- const result = OCPPServiceUtils.isRequestCommandSupported(station, RequestCommand.HEARTBEAT)
+ const result = isRequestCommandSupported(station, RequestCommand.HEARTBEAT)
assert.strictEqual(result, false)
})
await it('should return true when commandsSupport is undefined', () => {
const station = makeStationMock({})
- const result = OCPPServiceUtils.isRequestCommandSupported(station, RequestCommand.HEARTBEAT)
+ const result = isRequestCommandSupported(station, RequestCommand.HEARTBEAT)
assert.strictEqual(result, true)
})
commandsSupport: {},
})
- const result = OCPPServiceUtils.isRequestCommandSupported(station, RequestCommand.HEARTBEAT)
+ const result = isRequestCommandSupported(station, RequestCommand.HEARTBEAT)
assert.strictEqual(result, true)
})
},
})
- const result = OCPPServiceUtils.isMessageTriggerSupported(station, MessageTrigger.Heartbeat)
+ const result = isMessageTriggerSupported(station, MessageTrigger.Heartbeat)
assert.strictEqual(result, true)
})
},
})
- const result = OCPPServiceUtils.isMessageTriggerSupported(station, MessageTrigger.Heartbeat)
+ const result = isMessageTriggerSupported(station, MessageTrigger.Heartbeat)
assert.strictEqual(result, false)
})
await it('should return true when messageTriggerSupport is undefined', () => {
const station = makeStationMock({})
- const result = OCPPServiceUtils.isMessageTriggerSupported(station, MessageTrigger.Heartbeat)
+ const result = isMessageTriggerSupported(station, MessageTrigger.Heartbeat)
assert.strictEqual(result, true)
})
messageTriggerSupport: null,
})
- const result = OCPPServiceUtils.isMessageTriggerSupported(station, MessageTrigger.Heartbeat)
+ const result = isMessageTriggerSupported(station, MessageTrigger.Heartbeat)
assert.strictEqual(result, true)
})