typed-ocpp
Version:
A library for type-aware parsing, serialization and validation of OCPP 1.6, OCPP 2.0 and OCPP 2.1 messages
131 lines • 7.07 kB
JavaScript
import { startOfDay, addMilliseconds, startOfWeek, differenceInMilliseconds, addWeeks, addDays, addSeconds, min, differenceInSeconds } from 'date-fns';
import { AbstractChargingManager } from '../common/chargingmanager/chargingmanager.js';
export class ChargingManager extends AbstractChargingManager {
_getScheduleFromProfile(context, profile, fromDate, toDate, unit) {
const { csChargingProfiles: { chargingSchedule, validFrom, validTo, recurrencyKind, chargingProfileKind } } = profile;
const schedule = [];
if (validFrom && fromDate < new Date(validFrom)) {
return schedule;
}
if (validTo && fromDate >= new Date(validTo)) {
return schedule;
}
const { duration, chargingRateUnit, chargingSchedulePeriod, minChargingRate, startSchedule } = chargingSchedule;
const scheduleStartEndDatePairs = [];
switch (chargingProfileKind) {
case 'Absolute':
{
const absoluteProfileStartDate = startSchedule ? new Date(startSchedule) : fromDate;
const absoluteProfileEndDate = duration ? addSeconds(absoluteProfileStartDate, duration) : toDate;
scheduleStartEndDatePairs.push([absoluteProfileStartDate, absoluteProfileEndDate]);
}
break;
case 'Relative':
{
const relativeProfileStartDate = fromDate;
const relativeProfileEndDate = duration ? addSeconds(relativeProfileStartDate, duration) : toDate;
scheduleStartEndDatePairs.push([relativeProfileStartDate, relativeProfileEndDate]);
}
break;
case 'Recurring':
{
let recurringProfileStartDate = startSchedule ? new Date(startSchedule) : fromDate;
const startOfFn = recurrencyKind === 'Daily' ? startOfDay : startOfWeek;
const addFn = recurrencyKind === 'Daily' ? addDays : addWeeks;
recurringProfileStartDate = addMilliseconds(startOfFn(fromDate), differenceInMilliseconds(recurringProfileStartDate, startOfFn(recurringProfileStartDate)));
while (recurringProfileStartDate < toDate) {
let recurringProfileEndDate = addFn(recurringProfileStartDate, 1);
let recurringProfileEndDateInclDuration = duration
? min([recurringProfileEndDate, addSeconds(recurringProfileStartDate, duration)])
: recurringProfileEndDate;
scheduleStartEndDatePairs.push([recurringProfileStartDate, recurringProfileEndDateInclDuration]);
recurringProfileStartDate = recurringProfileEndDate;
}
}
break;
}
scheduleStartEndDatePairs.forEach(([scheduleStartDate, scheduleEndDate]) => {
chargingSchedulePeriod.forEach((period, periodIndex) => {
const { startPeriod, limit, numberPhases = 3 } = period;
const nextPeriod = chargingSchedulePeriod[periodIndex + 1];
const periodStartDate = addSeconds(scheduleStartDate, startPeriod);
const periodEndDate = nextPeriod ? addSeconds(scheduleStartDate, nextPeriod.startPeriod) : scheduleEndDate;
schedule.push({
start: periodStartDate,
end: periodEndDate,
data: {
charging: {
min: context.model.convert(minChargingRate ?? 0, chargingRateUnit, unit, numberPhases),
max: context.model.convert(limit >= 0 ? limit : 0, chargingRateUnit, unit, numberPhases),
phases: { qty: numberPhases },
},
discharging: {
min: context.model.convert(0, chargingRateUnit, unit, numberPhases),
max: context.model.convert(limit < 0 ? Math.abs(limit) : 0, chargingRateUnit, unit, numberPhases),
phases: { qty: numberPhases },
},
shouldDischarge: limit < 0,
unit,
},
});
});
});
return schedule;
}
setChargingProfile(request) {
const { csChargingProfiles: { chargingProfilePurpose, stackLevel }, connectorId } = request;
this._setChargingProfile(chargingProfilePurpose, connectorId, stackLevel, request);
}
clearChargingProfile(request) {
this._clearChargingProfiles(request.chargingProfilePurpose, request.connectorId, request.stackLevel);
}
getConnectorSchedule(fromDate, toDate, connectorId, unit, model) {
return this._getChargerSchedule(fromDate, toDate, connectorId, unit, model);
}
getConnectorLimitsAtDate(atDate, connectorId, unit, model) {
return this._getChargerLimitsAtDate(atDate, connectorId, unit, model);
}
getConnectorCompositeSchedule(fromDate, toDate, chargerId, model) {
const now = new Date();
const schedule = this._getChargerSchedule(fromDate, toDate, chargerId, 'W', model);
const min_date = schedule[0].start;
const max_date = schedule.at(-1).end;
return {
status: 'Accepted',
connectorId: chargerId,
chargingSchedule: {
startSchedule: now.toISOString(),
duration: differenceInSeconds(max_date, min_date),
chargingRateUnit: 'W',
chargingSchedulePeriod: schedule.map((interval) => {
const { start, data: { charging, discharging, shouldDischarge } } = interval;
return shouldDischarge
? {
startPeriod: differenceInSeconds(start, min_date),
limit: -1 * discharging.max,
numberPhases: discharging.phases.qty,
}
: {
startPeriod: differenceInSeconds(start, min_date),
limit: charging.max,
numberPhases: charging.phases.qty,
};
}),
},
};
}
getConnectorCompositeProfile(fromDate, toDate, connectorId, model, opts) {
const compositeSchedule = this.getConnectorCompositeSchedule(fromDate, toDate, connectorId, model);
return {
connectorId: compositeSchedule.connectorId,
csChargingProfiles: {
...opts,
chargingProfileKind: 'Absolute',
validFrom: fromDate.toISOString(),
validTo: fromDate.toISOString(),
chargingSchedule: compositeSchedule.chargingSchedule,
},
};
}
}
//# sourceMappingURL=chargingmanager.js.map