+
+ public static setChargingProfile(
+ chargingStation: ChargingStation,
+ connectorId: number,
+ cp: OCPP16ChargingProfile
+ ): void {
+ 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
+ ) {
+ 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)) {
+ chargingStation
+ .getConnectorStatus(connectorId)
+ ?.chargingProfiles?.forEach((chargingProfile: OCPP16ChargingProfile, index: number) => {
+ if (
+ chargingProfile.chargingProfileId === cp.chargingProfileId ||
+ (chargingProfile.stackLevel === cp.stackLevel &&
+ chargingProfile.chargingProfilePurpose === cp.chargingProfilePurpose)
+ ) {
+ chargingStation.getConnectorStatus(connectorId).chargingProfiles[index] = cp;
+ cpReplaced = true;
+ }
+ });
+ }
+ !cpReplaced && chargingStation.getConnectorStatus(connectorId)?.chargingProfiles?.push(cp);
+ }
+
+ public static parseJsonSchemaFile<T extends JsonType>(relativePath: string): JSONSchemaType<T> {
+ return super.parseJsonSchemaFile<T>(
+ path.resolve(path.dirname(fileURLToPath(import.meta.url)), relativePath),
+ OCPPVersion.VERSION_16
+ );
+ }
+
+ private static buildSampledValue(
+ sampledValueTemplate: SampledValueTemplate,
+ value: number,
+ context?: MeterValueContext,
+ phase?: OCPP16MeterValuePhase
+ ): OCPP16SampledValue {
+ const sampledValueValue = value ?? sampledValueTemplate?.value ?? null;
+ const sampledValueContext = context ?? sampledValueTemplate?.context ?? null;
+ const sampledValueLocation =
+ sampledValueTemplate?.location ??
+ OCPP16ServiceUtils.getMeasurandDefaultLocation(sampledValueTemplate?.measurand ?? null);
+ const sampledValuePhase = phase ?? sampledValueTemplate?.phase ?? null;
+ return {
+ ...(!Utils.isNullOrUndefined(sampledValueTemplate.unit) && {
+ unit: sampledValueTemplate.unit,
+ }),
+ ...(!Utils.isNullOrUndefined(sampledValueContext) && { context: sampledValueContext }),
+ ...(!Utils.isNullOrUndefined(sampledValueTemplate.measurand) && {
+ measurand: sampledValueTemplate.measurand,
+ }),
+ ...(!Utils.isNullOrUndefined(sampledValueLocation) && { location: sampledValueLocation }),
+ ...(!Utils.isNullOrUndefined(sampledValueValue) && { value: sampledValueValue.toString() }),
+ ...(!Utils.isNullOrUndefined(sampledValuePhase) && { phase: sampledValuePhase }),
+ };
+ }
+
+ private static checkMeasurandPowerDivider(
+ chargingStation: ChargingStation,
+ measurandType: OCPP16MeterValueMeasurand
+ ): void {
+ if (Utils.isUndefined(chargingStation.powerDivider)) {
+ const errMsg = `MeterValues measurand ${
+ measurandType ?? OCPP16MeterValueMeasurand.ENERGY_ACTIVE_IMPORT_REGISTER
+ }: powerDivider is undefined`;
+ logger.error(`${chargingStation.logPrefix()} ${errMsg}`);
+ throw new OCPPError(ErrorType.INTERNAL_ERROR, errMsg, OCPP16RequestCommand.METER_VALUES);
+ } else if (chargingStation?.powerDivider <= 0) {
+ const errMsg = `MeterValues measurand ${
+ measurandType ?? OCPP16MeterValueMeasurand.ENERGY_ACTIVE_IMPORT_REGISTER
+ }: powerDivider have zero or below value ${chargingStation.powerDivider}`;
+ logger.error(`${chargingStation.logPrefix()} ${errMsg}`);
+ throw new OCPPError(ErrorType.INTERNAL_ERROR, errMsg, OCPP16RequestCommand.METER_VALUES);
+ }
+ }
+
+ private static getMeasurandDefaultLocation(
+ measurandType: OCPP16MeterValueMeasurand
+ ): MeterValueLocation | undefined {
+ switch (measurandType) {
+ case OCPP16MeterValueMeasurand.STATE_OF_CHARGE:
+ return MeterValueLocation.EV;
+ }
+ }
+
+ private static getMeasurandDefaultUnit(
+ measurandType: OCPP16MeterValueMeasurand
+ ): MeterValueUnit | undefined {
+ switch (measurandType) {
+ case OCPP16MeterValueMeasurand.CURRENT_EXPORT:
+ case OCPP16MeterValueMeasurand.CURRENT_IMPORT:
+ case OCPP16MeterValueMeasurand.CURRENT_OFFERED:
+ return MeterValueUnit.AMP;
+ case OCPP16MeterValueMeasurand.ENERGY_ACTIVE_EXPORT_REGISTER:
+ case OCPP16MeterValueMeasurand.ENERGY_ACTIVE_IMPORT_REGISTER:
+ return MeterValueUnit.WATT_HOUR;
+ case OCPP16MeterValueMeasurand.POWER_ACTIVE_EXPORT:
+ case OCPP16MeterValueMeasurand.POWER_ACTIVE_IMPORT:
+ case OCPP16MeterValueMeasurand.POWER_OFFERED:
+ return MeterValueUnit.WATT;
+ case OCPP16MeterValueMeasurand.STATE_OF_CHARGE:
+ return MeterValueUnit.PERCENT;
+ case OCPP16MeterValueMeasurand.VOLTAGE:
+ return MeterValueUnit.VOLT;
+ }
+ }