UNPKG

typed-ocpp

Version:

A library for type-aware parsing, serialization and validation of OCPP 1.6, OCPP 2.0 and OCPP 2.1 messages

110 lines 6.36 kB
import { addHours } from 'date-fns'; import { merge, getPeriodForDate, fillGaps } from '../schedule/schedule.js'; import { CHARGING_PROFILE_PURPOSES } from '../utils.js'; import { mergeChargingLimitsMin, mergeChargingLimitsRight, mergeChargingLimitsAdd, cloneChargingLimits, } from './utils.js'; export class AbstractChargingManager { #profiles; constructor() { this.#profiles = { ['ChargingStationExternalConstraints']: [], ['ChargingStationMaxProfile']: [], ['TxDefaultProfile']: [], ['TxProfile']: [], ['PriorityCharging']: [], ['LocalGeneration']: [], }; } getDefaultLimits = (fromDate, toDate, chargerId) => { return { unit: 'W', charging: { min: 4200, max: 6000, phases: { qty: 1 } }, discharging: { min: 0, max: 0, phases: { qty: 1 } }, shouldDischarge: false, }; }; _setChargingProfile(purpose, chargerId, stackLevel, profile) { const _purpose = purpose === 'ChargePointMaxProfile' ? 'ChargingStationMaxProfile' : purpose; if (_purpose === 'ChargingStationMaxProfile' || _purpose === 'LocalGeneration' && chargerId !== 0) { throw new Error(`"${purpose}" profiles cannot be added for evseId other than "0"`); } if (_purpose === 'TxProfile' && chargerId === 0) { throw new Error('"TxProfile" profiles cannot be added for evseId "0"'); } this._clearChargingProfiles(purpose, chargerId, stackLevel); this.#profiles[_purpose].push({ chargerId, stackLevel, profile, }); this.#profiles[_purpose].sort((l, r) => l.stackLevel < r.stackLevel ? -1 : 1); } _clearChargingProfiles(purpose, chargerId, stackLevel) { purpose = purpose === 'ChargePointMaxProfile' ? 'ChargingStationMaxProfile' : purpose; (purpose ? [purpose] : CHARGING_PROFILE_PURPOSES).forEach((purpose) => { this.#profiles[purpose] = this.#profiles[purpose].filter((profile) => { if (typeof chargerId === 'number' && chargerId !== profile.chargerId) { return false; } if (typeof stackLevel === 'number' && stackLevel !== profile.stackLevel) { return false; } true; }); }); } #reduceChargingProfilesToSchedule(context, purpose, profileFilterFn, fromDate, toDate, mergeLimits, unit) { return this.#profiles[purpose].reduce((schedule, profile) => { if (profileFilterFn(profile)) { return merge(schedule, this._getScheduleFromProfile(context, profile.profile, fromDate, toDate, unit), cloneChargingLimits, mergeLimits); } return schedule; }, []); } getStationSchedule(fromDate, toDate, unit, model) { let schedule = []; const context = { model }; const maxSchedule = this.#reduceChargingProfilesToSchedule(context, 'ChargingStationMaxProfile', (profile) => true, fromDate, toDate, mergeChargingLimitsRight, unit); schedule = merge(schedule, maxSchedule, cloneChargingLimits, mergeChargingLimitsRight); const localGenerationSchedule = this.#reduceChargingProfilesToSchedule(context, 'LocalGeneration', (profile) => true, fromDate, toDate, mergeChargingLimitsRight, unit); schedule = merge(schedule, localGenerationSchedule, cloneChargingLimits, mergeChargingLimitsAdd); const externalMaxSchedule = this.#reduceChargingProfilesToSchedule(context, 'ChargingStationExternalConstraints', (profile) => profile.chargerId === 0, fromDate, toDate, mergeChargingLimitsRight, unit); schedule = merge(schedule, externalMaxSchedule, cloneChargingLimits, mergeChargingLimitsMin); return fillGaps(schedule, fromDate, toDate, (fromDate, toDate) => this.getDefaultLimits(fromDate, toDate, 0)); } _getChargerSchedule(fromDate, toDate, chargerId, unit, model, priority) { let schedule = []; const context = { model }; const defaultSchedule = this.#reduceChargingProfilesToSchedule(context, 'TxDefaultProfile', (profile) => profile.chargerId === 0 || profile.chargerId === chargerId, fromDate, toDate, mergeChargingLimitsRight, unit); schedule = merge(schedule, defaultSchedule, cloneChargingLimits, mergeChargingLimitsRight); if (priority) { const defaultPrioritySchedule = this.#reduceChargingProfilesToSchedule(context, 'PriorityCharging', (profile) => profile.chargerId === 0, fromDate, toDate, mergeChargingLimitsRight, unit); schedule = merge(schedule, defaultPrioritySchedule, cloneChargingLimits, mergeChargingLimitsRight); } if (chargerId !== 0) { const transactionSchedule = this.#reduceChargingProfilesToSchedule(context, 'TxProfile', (profile) => profile.chargerId === chargerId, fromDate, toDate, mergeChargingLimitsRight, unit); schedule = merge(schedule, transactionSchedule, cloneChargingLimits, mergeChargingLimitsRight); if (priority) { const transactionPrioritySchedule = this.#reduceChargingProfilesToSchedule(context, 'PriorityCharging', (profile) => profile.chargerId === chargerId, fromDate, toDate, mergeChargingLimitsRight, unit); merge(schedule, transactionPrioritySchedule, cloneChargingLimits, mergeChargingLimitsRight); } } return fillGaps(schedule, fromDate, toDate, (fromDate, toDate) => this.getDefaultLimits(fromDate, toDate, 0)); } getStationLimitsAtDate(atDate, unit, model) { const schedule = this.getStationSchedule(atDate, addHours(atDate, 1), unit, model); const period = getPeriodForDate(schedule, atDate); if (!period) { throw new Error('period not found'); } return period.data; } _getChargerLimitsAtDate(atDate, chargerId, unit, model, priority) { const schedule = this._getChargerSchedule(atDate, addHours(atDate, 1), chargerId, unit, model, priority); const period = getPeriodForDate(schedule, atDate); if (!period) { throw new Error('period not found'); } return period.data; } } //# sourceMappingURL=chargingmanager.js.map