-// Partial Copyright Jerome Benoit. 2021. All Rights Reserved.
+// Partial Copyright Jerome Benoit. 2021-2023. All Rights Reserved.
+
+import path from 'node:path';
+import { fileURLToPath } from 'node:url';
+
+import type { JSONSchemaType } from 'ajv';
import OCPPError from '../../../exception/OCPPError';
import { CurrentType, Voltage } from '../../../types/ChargingStationTemplate';
+import type { JsonType } from '../../../types/JsonType';
import type {
MeasurandPerPhaseSampledValueTemplates,
SampledValueTemplate,
MeterValueContext,
MeterValueLocation,
MeterValueUnit,
- OCPP16MeterValue,
+ type OCPP16MeterValue,
OCPP16MeterValueMeasurand,
OCPP16MeterValuePhase,
- OCPP16SampledValue,
+ type OCPP16SampledValue,
} from '../../../types/ocpp/1.6/MeterValues';
import {
- OCPP16IncomingRequestCommand,
+ type OCPP16IncomingRequestCommand,
OCPP16RequestCommand,
} from '../../../types/ocpp/1.6/Requests';
import { ErrorType } from '../../../types/ocpp/ErrorType';
+import { OCPPVersion } from '../../../types/ocpp/OCPPVersion';
import Constants from '../../../utils/Constants';
import { ACElectricUtils, DCElectricUtils } from '../../../utils/ElectricUtils';
import logger from '../../../utils/Logger';
debug = false
): OCPP16MeterValue {
const meterValue: OCPP16MeterValue = {
- timestamp: new Date().toISOString(),
+ timestamp: new Date(),
sampledValue: [],
};
const connector = chargingStation.getConnectorStatus(connectorId);
`${chargingStation.logPrefix()} MeterValues measurand ${
meterValue.sampledValue[sampledValuesIndex].measurand ??
OCPP16MeterValueMeasurand.ENERGY_ACTIVE_IMPORT_REGISTER
- }: connectorId ${connectorId}, transaction ${connector.transactionId}, value: ${
+ }: connectorId ${connectorId}, transaction ${connector?.transactionId}, value: ${
meterValue.sampledValue[sampledValuesIndex].value
}/100`
);
OCPP16ServiceUtils.buildSampledValue(
voltagePhaseLineToNeutralSampledValueTemplate ?? voltageSampledValueTemplate,
voltagePhaseLineToNeutralMeasurandValue ?? voltageMeasurandValue,
- null,
+ undefined,
phaseLineToNeutralValue as OCPP16MeterValuePhase
)
);
OCPP16ServiceUtils.buildSampledValue(
voltagePhaseLineToLineSampledValueTemplate ?? voltageSampledValueTemplate,
voltagePhaseLineToLineMeasurandValue ?? defaultVoltagePhaseLineToLineMeasurandValue,
- null,
+ undefined,
phaseLineToLineValue as OCPP16MeterValuePhase
)
);
`${chargingStation.logPrefix()} MeterValues measurand ${
meterValue.sampledValue[sampledValuesIndex].measurand ??
OCPP16MeterValueMeasurand.ENERGY_ACTIVE_IMPORT_REGISTER
- }: connectorId ${connectorId}, transaction ${connector.transactionId}, value: ${
+ }: connectorId ${connectorId}, transaction ${connector?.transactionId}, value: ${
meterValue.sampledValue[sampledValuesIndex].value
}/${connectorMaximumPowerRounded}`
);
(powerPerPhaseSampledValueTemplates[`L${phase}`] as SampledValueTemplate) ??
powerSampledValueTemplate,
powerMeasurandValues[`L${phase}`] as number,
- null,
+ undefined,
phaseValue as OCPP16MeterValuePhase
)
);
OCPP16MeterValueMeasurand.ENERGY_ACTIVE_IMPORT_REGISTER
}: phase ${
meterValue.sampledValue[sampledValuesPerPhaseIndex].phase
- }, connectorId ${connectorId}, transaction ${connector.transactionId}, value: ${
+ }, connectorId ${connectorId}, transaction ${connector?.transactionId}, value: ${
meterValue.sampledValue[sampledValuesPerPhaseIndex].value
}/${connectorMaximumPowerPerPhaseRounded}`
);
`${chargingStation.logPrefix()} MeterValues measurand ${
meterValue.sampledValue[sampledValuesIndex].measurand ??
OCPP16MeterValueMeasurand.ENERGY_ACTIVE_IMPORT_REGISTER
- }: connectorId ${connectorId}, transaction ${connector.transactionId}, value: ${
+ }: connectorId ${connectorId}, transaction ${connector?.transactionId}, value: ${
meterValue.sampledValue[sampledValuesIndex].value
}/${connectorMaximumAmperage}`
);
(currentPerPhaseSampledValueTemplates[phaseValue] as SampledValueTemplate) ??
currentSampledValueTemplate,
currentMeasurandValues[phaseValue] as number,
- null,
+ undefined,
phaseValue as OCPP16MeterValuePhase
)
);
OCPP16MeterValueMeasurand.ENERGY_ACTIVE_IMPORT_REGISTER
}: phase ${
meterValue.sampledValue[sampledValuesPerPhaseIndex].phase
- }, connectorId ${connectorId}, transaction ${connector.transactionId}, value: ${
+ }, connectorId ${connectorId}, transaction ${connector?.transactionId}, value: ${
meterValue.sampledValue[sampledValuesPerPhaseIndex].value
}/${connectorMaximumAmperage}`
);
// Persist previous value on connector
if (
connector &&
- !Utils.isNullOrUndefined(connector.energyActiveImportRegisterValue) &&
+ Utils.isNullOrUndefined(connector.energyActiveImportRegisterValue) === false &&
connector.energyActiveImportRegisterValue >= 0 &&
- !Utils.isNullOrUndefined(connector.transactionEnergyActiveImportRegisterValue) &&
+ Utils.isNullOrUndefined(connector.transactionEnergyActiveImportRegisterValue) === false &&
connector.transactionEnergyActiveImportRegisterValue >= 0
) {
connector.energyActiveImportRegisterValue += energyValueRounded;
meterValue.sampledValue[sampledValuesIndex].measurand ??
OCPP16MeterValueMeasurand.ENERGY_ACTIVE_IMPORT_REGISTER
}: connectorId ${connectorId}, transaction ${
- connector.transactionId
+ connector?.transactionId
}, value: ${energyValueRounded}/${connectorMaximumEnergyRounded}, duration: ${Utils.roundTo(
interval / (3600 * 1000),
4
meterStart: number
): OCPP16MeterValue {
const meterValue: OCPP16MeterValue = {
- timestamp: new Date().toISOString(),
+ timestamp: new Date(),
sampledValue: [],
};
// Energy.Active.Import.Register measurand (default)
meterValue.sampledValue.push(
OCPP16ServiceUtils.buildSampledValue(
sampledValueTemplate,
- Utils.roundTo(meterStart / unitDivider, 4),
+ Utils.roundTo((meterStart ?? 0) / unitDivider, 4),
MeterValueContext.TRANSACTION_BEGIN
)
);
meterStop: number
): OCPP16MeterValue {
const meterValue: OCPP16MeterValue = {
- timestamp: new Date().toISOString(),
+ timestamp: new Date(),
sampledValue: [],
};
// Energy.Active.Import.Register measurand (default)
meterValue.sampledValue.push(
OCPP16ServiceUtils.buildSampledValue(
sampledValueTemplate,
- Utils.roundTo(meterStop / unitDivider, 4),
+ Utils.roundTo((meterStop ?? 0) / unitDivider, 4),
MeterValueContext.TRANSACTION_END
)
);
connectorId: number,
cp: OCPP16ChargingProfile
): void {
- if (Utils.isNullOrUndefined(chargingStation.getConnectorStatus(connectorId).chargingProfiles)) {
+ if (
+ Utils.isNullOrUndefined(chargingStation.getConnectorStatus(connectorId)?.chargingProfiles)
+ ) {
logger.error(
`${chargingStation.logPrefix()} Trying to set a charging profile on connectorId ${connectorId} with an uninitialized charging profiles array attribute, applying deferred initialization`
);
chargingStation.getConnectorStatus(connectorId).chargingProfiles = [];
}
- if (Array.isArray(chargingStation.getConnectorStatus(connectorId).chargingProfiles) === false) {
+ if (
+ Array.isArray(chargingStation.getConnectorStatus(connectorId)?.chargingProfiles) === false
+ ) {
logger.error(
`${chargingStation.logPrefix()} Trying to set a charging profile on connectorId ${connectorId} with an improper attribute type for the charging profiles array, applying proper type initialization`
);
chargingStation.getConnectorStatus(connectorId).chargingProfiles = [];
}
let cpReplaced = false;
- if (!Utils.isEmptyArray(chargingStation.getConnectorStatus(connectorId).chargingProfiles)) {
+ if (Utils.isNotEmptyArray(chargingStation.getConnectorStatus(connectorId)?.chargingProfiles)) {
chargingStation
.getConnectorStatus(connectorId)
- .chargingProfiles?.forEach((chargingProfile: OCPP16ChargingProfile, index: number) => {
+ ?.chargingProfiles?.forEach((chargingProfile: OCPP16ChargingProfile, index: number) => {
if (
chargingProfile.chargingProfileId === cp.chargingProfileId ||
(chargingProfile.stackLevel === cp.stackLevel &&
}
});
}
- !cpReplaced && chargingStation.getConnectorStatus(connectorId).chargingProfiles?.push(cp);
+ !cpReplaced && chargingStation.getConnectorStatus(connectorId)?.chargingProfiles?.push(cp);
+ }
+
+ public static parseJsonSchemaFile<T extends JsonType>(
+ relativePath: string,
+ moduleName?: string,
+ methodName?: string
+ ): JSONSchemaType<T> {
+ return super.parseJsonSchemaFile<T>(
+ path.resolve(path.dirname(fileURLToPath(import.meta.url)), relativePath),
+ OCPPVersion.VERSION_16,
+ moduleName,
+ methodName
+ );
}
private static buildSampledValue(