+ if (
+ chargingStation.getLocalAuthListEnabled() === true &&
+ OCPPServiceUtils.isIdTagLocalAuthorized(chargingStation, idTag)
+ ) {
+ const connectorStatus: ConnectorStatus = chargingStation.getConnectorStatus(connectorId)!;
+ connectorStatus.localAuthorizeIdTag = idTag;
+ connectorStatus.idTagLocalAuthorized = true;
+ return true;
+ } else if (chargingStation.stationInfo?.remoteAuthorization) {
+ return await OCPPServiceUtils.isIdTagRemoteAuthorized(chargingStation, connectorId, idTag);
+ }
+ return false;
+ }
+
+ protected static checkConnectorStatusTransition(
+ chargingStation: ChargingStation,
+ connectorId: number,
+ status: ConnectorStatusEnum,
+ ): boolean {
+ const fromStatus = chargingStation.getConnectorStatus(connectorId)!.status;
+ let transitionAllowed = false;
+ switch (chargingStation.stationInfo?.ocppVersion) {
+ case OCPPVersion.VERSION_16:
+ if (
+ (connectorId === 0 &&
+ OCPP16Constants.ChargePointStatusChargingStationTransitions.findIndex(
+ (transition) => transition.from === fromStatus && transition.to === status,
+ ) !== -1) ||
+ (connectorId > 0 &&
+ OCPP16Constants.ChargePointStatusConnectorTransitions.findIndex(
+ (transition) => transition.from === fromStatus && transition.to === status,
+ ) !== -1)
+ ) {
+ transitionAllowed = true;
+ }
+ break;
+ case OCPPVersion.VERSION_20:
+ case OCPPVersion.VERSION_201:
+ if (
+ (connectorId === 0 &&
+ OCPP20Constants.ChargingStationStatusTransitions.findIndex(
+ (transition) => transition.from === fromStatus && transition.to === status,
+ ) !== -1) ||
+ (connectorId > 0 &&
+ OCPP20Constants.ConnectorStatusTransitions.findIndex(
+ (transition) => transition.from === fromStatus && transition.to === status,
+ ) !== -1)
+ ) {
+ transitionAllowed = true;
+ }
+ break;
+ default:
+ throw new BaseError(
+ // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
+ `Cannot check connector status transition: OCPP version ${chargingStation.stationInfo?.ocppVersion} not supported`,
+ );
+ }
+ if (transitionAllowed === false) {
+ logger.warn(
+ `${chargingStation.logPrefix()} OCPP ${chargingStation.stationInfo
+ ?.ocppVersion} connector id ${connectorId} status transition from '${
+ chargingStation.getConnectorStatus(connectorId)!.status
+ }' to '${status}' is not allowed`,
+ );
+ }
+ return transitionAllowed;
+ }
+
+ protected static parseJsonSchemaFile<T extends JsonType>(
+ relativePath: string,
+ ocppVersion: OCPPVersion,
+ moduleName?: string,
+ methodName?: string,
+ ): JSONSchemaType<T> {
+ const filePath = join(dirname(fileURLToPath(import.meta.url)), 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>;
+ }
+ }
+
+ protected static getSampledValueTemplate(
+ chargingStation: ChargingStation,
+ connectorId: number,
+ measurand: MeterValueMeasurand = MeterValueMeasurand.ENERGY_ACTIVE_IMPORT_REGISTER,
+ phase?: MeterValuePhase,
+ ): SampledValueTemplate | undefined {
+ const onPhaseStr = phase ? `on phase ${phase} ` : '';
+ if (OCPPConstants.OCPP_MEASURANDS_SUPPORTED.includes(measurand) === false) {
+ logger.warn(
+ `${chargingStation.logPrefix()} Trying to get unsupported MeterValues measurand '${measurand}' ${onPhaseStr}in template on connector id ${connectorId}`,
+ );
+ return;
+ }
+ if (
+ measurand !== MeterValueMeasurand.ENERGY_ACTIVE_IMPORT_REGISTER &&
+ getConfigurationKey(
+ chargingStation,
+ StandardParametersKey.MeterValuesSampledData,
+ )?.value?.includes(measurand) === false
+ ) {
+ logger.debug(
+ `${chargingStation.logPrefix()} Trying to get MeterValues measurand '${measurand}' ${onPhaseStr}in template on connector id ${connectorId} not found in '${
+ StandardParametersKey.MeterValuesSampledData
+ }' OCPP parameter`,
+ );
+ return;
+ }
+ const sampledValueTemplates: SampledValueTemplate[] =
+ chargingStation.getConnectorStatus(connectorId)!.MeterValues;
+ for (
+ let index = 0;
+ isNotEmptyArray(sampledValueTemplates) === true && index < sampledValueTemplates.length;
+ index++
+ ) {
+ if (
+ OCPPConstants.OCPP_MEASURANDS_SUPPORTED.includes(
+ sampledValueTemplates[index]?.measurand ??
+ MeterValueMeasurand.ENERGY_ACTIVE_IMPORT_REGISTER,
+ ) === false
+ ) {
+ logger.warn(
+ `${chargingStation.logPrefix()} Unsupported MeterValues measurand '${measurand}' ${onPhaseStr}in template on connector id ${connectorId}`,
+ );
+ } else if (
+ phase &&
+ sampledValueTemplates[index]?.phase === phase &&
+ sampledValueTemplates[index]?.measurand === measurand &&
+ getConfigurationKey(
+ chargingStation,
+ StandardParametersKey.MeterValuesSampledData,
+ )?.value?.includes(measurand) === true
+ ) {
+ return sampledValueTemplates[index];
+ } else if (
+ !phase &&
+ !sampledValueTemplates[index]?.phase &&
+ sampledValueTemplates[index]?.measurand === measurand &&
+ getConfigurationKey(
+ chargingStation,
+ StandardParametersKey.MeterValuesSampledData,
+ )?.value?.includes(measurand) === true
+ ) {
+ return sampledValueTemplates[index];
+ } else if (
+ measurand === MeterValueMeasurand.ENERGY_ACTIVE_IMPORT_REGISTER &&
+ (!sampledValueTemplates[index]?.measurand ||
+ sampledValueTemplates[index]?.measurand === measurand)
+ ) {
+ return sampledValueTemplates[index];
+ }
+ }
+ if (measurand === MeterValueMeasurand.ENERGY_ACTIVE_IMPORT_REGISTER) {
+ const errorMsg = `Missing MeterValues for default measurand '${measurand}' in template on connector id ${connectorId}`;
+ logger.error(`${chargingStation.logPrefix()} ${errorMsg}`);
+ throw new BaseError(errorMsg);
+ }
+ logger.debug(
+ `${chargingStation.logPrefix()} No MeterValues for measurand '${measurand}' ${onPhaseStr}in template on connector id ${connectorId}`,
+ );
+ }
+
+ protected static getLimitFromSampledValueTemplateCustomValue(
+ value: string | undefined,
+ maxLimit: number,
+ minLimit: number,
+ options?: { limitationEnabled?: boolean; fallbackValue?: number; unitMultiplier?: number },