diff --git a/packages/helpermodules/command.py b/packages/helpermodules/command.py
index 2d1b79d96c..ba43da1506 100644
--- a/packages/helpermodules/command.py
+++ b/packages/helpermodules/command.py
@@ -16,7 +16,7 @@
from control.chargepoint import chargepoint
from control.chargepoint.chargepoint_template import get_chargepoint_template_default
-from control.ev.charge_template import get_new_charge_template
+from control.ev.charge_template import ChargeTemplate, get_new_charge_template
from control.ev.ev_template import EvTemplateData
from helpermodules import pub
from helpermodules.abstract_plans import AutolockPlan, ScheduledChargingPlan, TimeChargingPlan
@@ -488,13 +488,36 @@ def removeChargeTemplate(self, connection_id: str, payload: dict) -> None:
pub_user_message(payload, connection_id, "Lade-Profil mit ID 0 darf nicht gelöscht werden.",
MessageType.ERROR)
+ def _get_charge_template_by_source(self, payload: dict) -> ChargeTemplate:
+ """ gibt das ChargeTemplate-Objekt zurück, je nachdem ob es sich um das persistente Ladeprofil oder das
+ Ladeprofil des Ladepunkts handelt.
+ """
+ if payload["data"]["changed_in_theme"]:
+ charge_template = data.data.cp_data[f"cp{payload['data']['chargepoint']}"].data.set.charge_template
+ else:
+ charge_template = data.data.ev_charge_template_data[f'ct{payload["data"]["template"]}']
+ return charge_template
+
+ def _pub_charge_template_to_source(self, payload: dict, charge_template: ChargeTemplate) -> None:
+ """ veröffentlicht das ChargeTemplate-Objekt, je nachdem ob es sich um das persistente Ladeprofil oder das
+ Ladeprofil des Ladepunkts handelt.
+ """
+ if payload["data"]["changed_in_theme"]:
+ Pub().pub(
+ f'openWB/set/chargepoint/{payload["data"]["chargepoint"]}/set/charge_template',
+ dataclass_utils.asdict(charge_template.data))
+ else:
+ Pub().pub(
+ f'openWB/set/vehicle/template/charge_template/{payload["data"]["template"]}',
+ dataclass_utils.asdict(charge_template.data))
+
def addChargeTemplateSchedulePlan(self, connection_id: str, payload: dict) -> None:
""" sendet das Topic, zu dem ein neuer Zielladen-Plan erstellt werden soll.
"""
+ charge_template = self._get_charge_template_by_source(payload)
# check if "payload" contains "data.copy"
if "data" in payload and "copy" in payload["data"]:
- for plan in data.data.ev_charge_template_data[
- f'ct{payload["data"]["template"]}'].data.chargemode.scheduled_charging.plans:
+ for plan in charge_template.data.chargemode.scheduled_charging.plans:
if plan.id == payload["data"]["copy"]:
new_charge_template_schedule_plan = copy.deepcopy(plan)
break
@@ -503,12 +526,8 @@ def addChargeTemplateSchedulePlan(self, connection_id: str, payload: dict) -> No
new_charge_template_schedule_plan = ScheduledChargingPlan()
new_id = self.max_id_charge_template_scheduled_plan + 1
new_charge_template_schedule_plan.id = new_id
- data.data.ev_charge_template_data[
- f'ct{payload["data"]["template"]}'].data.chargemode.scheduled_charging.plans.append(
- new_charge_template_schedule_plan)
- Pub().pub(
- f'openWB/set/vehicle/template/charge_template/{payload["data"]["template"]}',
- dataclass_utils.asdict(data.data.ev_charge_template_data[f'ct{payload["data"]["template"]}'].data))
+ charge_template.data.chargemode.scheduled_charging.plans.append(new_charge_template_schedule_plan)
+ self._pub_charge_template_to_source(payload, charge_template)
self.max_id_charge_template_scheduled_plan = new_id
Pub().pub(
"openWB/set/command/max_id/charge_template_scheduled_plan", new_id)
@@ -521,21 +540,17 @@ def addChargeTemplateSchedulePlan(self, connection_id: str, payload: dict) -> No
def removeChargeTemplateSchedulePlan(self, connection_id: str, payload: dict) -> None:
""" löscht einen Zielladen-Plan.
"""
+ charge_template = self._get_charge_template_by_source(payload)
if self.max_id_charge_template_scheduled_plan < payload["data"]["plan"]:
log.error(
payload, connection_id,
f'Die ID \'{payload["data"]["plan"]}\' ist größer als die maximal vergebene '
f'ID \'{self.max_id_charge_template_scheduled_plan}\'.', MessageType.ERROR)
- for plan in data.data.ev_charge_template_data[
- f'ct{payload["data"]["template"]}'].data.chargemode.scheduled_charging.plans:
+ for plan in charge_template.data.chargemode.scheduled_charging.plans:
if plan.id == payload["data"]["plan"]:
- data.data.ev_charge_template_data[
- f'ct{payload["data"]["template"]}'].data.chargemode.scheduled_charging.plans.remove(
- plan)
+ charge_template.data.chargemode.scheduled_charging.plans.remove(plan)
break
- Pub().pub(
- f'openWB/vehicle/template/charge_template/{payload["data"]["template"]}',
- dataclass_utils.asdict(data.data.ev_charge_template_data[f'ct{payload["data"]["template"]}'].data))
+ self._pub_charge_template_to_source(payload, charge_template)
pub_user_message(
payload, connection_id,
f'Zielladen-Plan mit ID \'{payload["data"]["plan"]}\' von Profil '
@@ -545,9 +560,10 @@ def removeChargeTemplateSchedulePlan(self, connection_id: str, payload: dict) ->
def addChargeTemplateTimeChargingPlan(self, connection_id: str, payload: dict) -> None:
""" sendet das Topic, zu dem ein neuer Zeitladen-Plan erstellt werden soll.
"""
+ charge_template = self._get_charge_template_by_source(payload)
# check if "payload" contains "data.copy"
if "data" in payload and "copy" in payload["data"]:
- for plan in data.data.ev_charge_template_data[f'ct{payload["data"]["template"]}'].data.time_charging.plans:
+ for plan in charge_template.data.time_charging.plans:
if plan.id == payload["data"]["copy"]:
new_time_charging_plan = copy.deepcopy(plan)
break
@@ -556,11 +572,8 @@ def addChargeTemplateTimeChargingPlan(self, connection_id: str, payload: dict) -
new_time_charging_plan = TimeChargingPlan()
new_id = self.max_id_charge_template_time_charging_plan + 1
new_time_charging_plan.id = new_id
- data.data.ev_charge_template_data[f'ct{payload["data"]["template"]}'].data.time_charging.plans.append(
- new_time_charging_plan)
- Pub().pub(
- f'openWB/set/vehicle/template/charge_template/{payload["data"]["template"]}',
- dataclass_utils.asdict(data.data.ev_charge_template_data[f'ct{payload["data"]["template"]}'].data))
+ charge_template.data.time_charging.plans.append(new_time_charging_plan)
+ self._pub_charge_template_to_source(payload, charge_template)
self.max_id_charge_template_time_charging_plan = new_id
Pub().pub(
"openWB/set/command/max_id/charge_template_time_charging_plan", new_id)
@@ -572,17 +585,15 @@ def addChargeTemplateTimeChargingPlan(self, connection_id: str, payload: dict) -
def removeChargeTemplateTimeChargingPlan(self, connection_id: str, payload: dict) -> None:
""" löscht einen Zeitladen-Plan.
"""
+ charge_template = self._get_charge_template_by_source(payload)
if self.max_id_charge_template_time_charging_plan < payload["data"]["plan"]:
log.error(payload, connection_id, "Die ID ist größer als die maximal vergebene ID.",
MessageType.ERROR)
- for plan in data.data.ev_charge_template_data[f'ct{payload["data"]["template"]}'].data.time_charging.plans:
+ for plan in charge_template.data.time_charging.plans:
if plan.id == payload["data"]["plan"]:
- data.data.ev_charge_template_data[f'ct{payload["data"]["template"]}'].data.time_charging.plans.remove(
- plan)
+ charge_template.data.time_charging.plans.remove(plan)
break
- Pub().pub(
- f'openWB/vehicle/template/charge_template/{payload["data"]["template"]}',
- dataclass_utils.asdict(data.data.ev_charge_template_data[f'ct{payload["data"]["template"]}'].data))
+ self._pub_charge_template_to_source(payload, charge_template)
pub_user_message(
payload, connection_id,
f'Zeitladen-Plan mit ID \'{payload["data"]["plan"]}\' zu Profil '
diff --git a/packages/modules/web_themes/koala/source/src/components/ChargePointScheduledPlanButton.vue b/packages/modules/web_themes/koala/source/src/components/ChargePointScheduledPlanButton.vue
index 935b8171c4..25341a1365 100644
--- a/packages/modules/web_themes/koala/source/src/components/ChargePointScheduledPlanButton.vue
+++ b/packages/modules/web_themes/koala/source/src/components/ChargePointScheduledPlanButton.vue
@@ -4,7 +4,7 @@
align="center"
class="cursor-pointer"
:color="planActive.value ? 'positive' : 'negative'"
- @click="planActive.value = !planActive.value"
+ @click="$emit('editPlan', plan)"
>
{{ plan.name }}
diff --git a/packages/modules/web_themes/koala/source/src/components/ChargePointScheduledPlanDetails.vue b/packages/modules/web_themes/koala/source/src/components/ChargePointScheduledPlanDetails.vue
new file mode 100644
index 0000000000..f8f308fdc8
--- /dev/null
+++ b/packages/modules/web_themes/koala/source/src/components/ChargePointScheduledPlanDetails.vue
@@ -0,0 +1,404 @@
+
+
+
+
+
+ {{ planName.value }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ kW
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Bidirektionales Überschussladen
+
+
+
+
+
+
Wiederholungen
+
+
+
+
+
+
+
+
+
+
+
+
+
Strompreisbasiert laden
+
+
+ Anzahl Phasen Zielladen
+
+
+
+
+
+
+ Anzahl Phasen bei PV-Überschuss
+
+
+
+
+
+
+
+ Plan löschen
+
+
+
+
+
+
+
+
diff --git a/packages/modules/web_themes/koala/source/src/components/ChargePointScheduledSettings.vue b/packages/modules/web_themes/koala/source/src/components/ChargePointScheduledSettings.vue
index 78a604b9ef..972dbac27b 100644
--- a/packages/modules/web_themes/koala/source/src/components/ChargePointScheduledSettings.vue
+++ b/packages/modules/web_themes/koala/source/src/components/ChargePointScheduledSettings.vue
@@ -2,6 +2,16 @@
+
+
+
+
+
+
+
diff --git a/packages/modules/web_themes/koala/source/src/components/ChargePointTimeChargingPlanButton.vue b/packages/modules/web_themes/koala/source/src/components/ChargePointTimeChargingPlanButton.vue
index e478ff49b1..3ace7ee5bb 100644
--- a/packages/modules/web_themes/koala/source/src/components/ChargePointTimeChargingPlanButton.vue
+++ b/packages/modules/web_themes/koala/source/src/components/ChargePointTimeChargingPlanButton.vue
@@ -4,7 +4,7 @@
align="center"
class="cursor-pointer"
:color="planActive.value ? 'positive' : 'negative'"
- @click="planActive.value = !planActive.value"
+ @click="$emit('editPlan', plan)"
>
{{ plan.name }}
diff --git a/packages/modules/web_themes/koala/source/src/components/ChargePointTimeChargingPlanDetails.vue b/packages/modules/web_themes/koala/source/src/components/ChargePointTimeChargingPlanDetails.vue
new file mode 100644
index 0000000000..0dbf91f998
--- /dev/null
+++ b/packages/modules/web_themes/koala/source/src/components/ChargePointTimeChargingPlanDetails.vue
@@ -0,0 +1,300 @@
+
+
+
+
+
+ {{ planName.value }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Begrenzung
+
+
+
+
+
+
+
+
+
+
+
+
Wiederholungen
+
+
+
+
+
+
+
+
+
+
+
+
+ Anzahl Phasen
+
+
+
+
+
+
+ Plan löschen
+
+
+
+
+
+
+
+
diff --git a/packages/modules/web_themes/koala/source/src/components/ChargePointTimeChargingSettings.vue b/packages/modules/web_themes/koala/source/src/components/ChargePointTimeChargingSettings.vue
index e4f34e0558..921db87d8e 100644
--- a/packages/modules/web_themes/koala/source/src/components/ChargePointTimeChargingSettings.vue
+++ b/packages/modules/web_themes/koala/source/src/components/ChargePointTimeChargingSettings.vue
@@ -3,12 +3,25 @@
class="row items-center q-ma-none q-pa-none no-wrap items-center justify-between"
>
Zeitladen
+
-
+
+
+
+
diff --git a/packages/modules/web_themes/koala/source/src/stores/mqtt-store-model.ts b/packages/modules/web_themes/koala/source/src/stores/mqtt-store-model.ts
index 6fc5ef8958..38b2c50e1d 100644
--- a/packages/modules/web_themes/koala/source/src/stores/mqtt-store-model.ts
+++ b/packages/modules/web_themes/koala/source/src/stores/mqtt-store-model.ts
@@ -135,6 +135,7 @@ export interface ScheduledChargingPlan {
name: string;
active: boolean;
bidi_charging_enabled: boolean;
+ bidi_power: number;
et_active: boolean;
current: number;
dc_current: number;
diff --git a/packages/modules/web_themes/koala/source/src/stores/mqtt-store.ts b/packages/modules/web_themes/koala/source/src/stores/mqtt-store.ts
index 2659be64c4..7f5048bef5 100644
--- a/packages/modules/web_themes/koala/source/src/stores/mqtt-store.ts
+++ b/packages/modules/web_themes/koala/source/src/stores/mqtt-store.ts
@@ -1659,6 +1659,106 @@ export const useMqttStore = defineStore('mqtt', () => {
});
};
+ /** * Get the charge point connected vehicle bidi enabled state from vehicle template identified by the charge point id
+ * @param chargePointId charge point id
+ * @returns boolean
+ */
+ const chargePointConnectedVehicleBidiEnabled = (chargePointId: number) => {
+ return computed(() => {
+ const connectedVehicleEvTemplateId =
+ chargePointConnectedVehicleConfig(chargePointId).value.ev_template;
+ return getValue.value(
+ `openWB/vehicle/template/ev_template/${connectedVehicleEvTemplateId}`,
+ 'bidi',
+ ) as boolean;
+ });
+ };
+
+ /**
+ * Get or set the plan name for the time charging plan identified by the time charging plan id
+ * @param chargePointId charge point id
+ * @param planId time charging plan id
+ * @returns string | undefined
+ */
+ const vehicleTimeChargingPlanName = (
+ chargePointId: number,
+ planId: number,
+ ) => {
+ return computed({
+ get() {
+ const plans = vehicleTimeChargingPlans.value(chargePointId);
+ const plan = plans.find((plane) => plane.id === planId);
+ return plan?.name;
+ },
+ set(newValue: string) {
+ updateTimeChargingPlanSubtopic(chargePointId, planId, 'name', newValue);
+ },
+ });
+ };
+
+ /**
+ * Add a new time charging plan for a charge point
+ * @param chargePointId charge point id
+ * @returns void
+ */
+ const addTimeChargingPlanForChargePoint = (chargePointId: number) => {
+ const templateId =
+ chargePointConnectedVehicleChargeTemplate(chargePointId).value?.id;
+ if (templateId !== undefined) {
+ sendSystemCommand('addChargeTemplateTimeChargingPlan', {
+ template: templateId,
+ chargepoint: chargePointId,
+ changed_in_theme: true,
+ });
+ }
+ };
+
+ /**
+ * Remove a time charging plan for a charge point
+ * @param chargePointId charge point id
+ * @param planId time charging plan id
+ * @returns void
+ */
+ const removeTimeChargingPlanForChargePoint = (
+ chargePointId: number,
+ planId: number,
+ ) => {
+ const templateId =
+ chargePointConnectedVehicleChargeTemplate(chargePointId).value?.id;
+ sendSystemCommand('removeChargeTemplateTimeChargingPlan', {
+ template: templateId,
+ plan: planId,
+ chargepoint: chargePointId,
+ changed_in_theme: true,
+ });
+ };
+
+ /**
+ * Helper function to update a subtopic of a time charging plan
+ * @param chargePointId charge point id
+ * @param planId time charging plan id
+ * @param propertyPath path to the property to update
+ * @param newValue new value to set
+ * @returns void
+ */
+ const updateTimeChargingPlanSubtopic = (
+ chargePointId: number,
+ planId: number,
+ propertyPath: string,
+ newValue: T,
+ ): void => {
+ const plans = vehicleTimeChargingPlans.value(chargePointId);
+ const planIndex = plans.findIndex((plan) => plan.id === planId);
+ if (planIndex === -1) return;
+ const objectPath = `time_charging.plans.${planIndex}.${propertyPath}`;
+ updateTopic(
+ `openWB/chargepoint/${chargePointId}/set/charge_template`,
+ newValue,
+ objectPath,
+ true,
+ );
+ };
+
/**
* Get or set the active state of the time charging plan identified by the time charge plan id
* @param chargePointId charge point id
@@ -1676,15 +1776,345 @@ export const useMqttStore = defineStore('mqtt', () => {
return plan?.active;
},
set(newValue: boolean) {
+ updateTimeChargingPlanSubtopic(
+ chargePointId,
+ planId,
+ 'active',
+ newValue,
+ );
+ },
+ });
+ };
+
+ /**
+ * Get or set the start time for the time charging plan identified by the time charge plan id
+ * @param chargePointId charge point id
+ * @param planId time charging plan id
+ * @returns string | undefined
+ */
+ const vehicleTimeChargingPlanStartTime = (
+ chargePointId: number,
+ planId: number,
+ ) => {
+ return computed({
+ get() {
const plans = vehicleTimeChargingPlans.value(chargePointId);
- const planIndex = plans.findIndex((plan) => plan.id === planId);
- if (planIndex === -1) return;
- const objectPath = `time_charging.plans.${planIndex}.active`;
- updateTopic(
- `openWB/chargepoint/${chargePointId}/set/charge_template`,
+ const plan = plans.find((plane) => plane.id === planId);
+ return plan?.time?.[0];
+ },
+ set(newValue: string) {
+ updateTimeChargingPlanSubtopic(
+ chargePointId,
+ planId,
+ 'time.0',
+ newValue,
+ );
+ },
+ });
+ };
+
+ /**
+ * Get or set the start time for the time charging plan identified by the time charge plan id
+ * @param chargePointId charge point id
+ * @param planId time charging plan id
+ * @returns string | undefined
+ */
+ const vehicleTimeChargingPlanEndTime = (
+ chargePointId: number,
+ planId: number,
+ ) => {
+ return computed({
+ get() {
+ const plans = vehicleTimeChargingPlans.value(chargePointId);
+ const plan = plans.find((plane) => plane.id === planId);
+ return plan?.time?.[1];
+ },
+ set(newValue: string) {
+ updateTimeChargingPlanSubtopic(
+ chargePointId,
+ planId,
+ 'time.1',
+ newValue,
+ );
+ },
+ });
+ };
+
+ /**
+ * Get or set the current for the time charging plan identified by the time charging plan id
+ * @param chargePointId charge point id
+ * @param planId time charging plan id
+ * @returns number | undefined
+ */
+ const vehicleTimeChargingPlanCurrent = (
+ chargePointId: number,
+ planId: number,
+ ) => {
+ return computed({
+ get() {
+ const plans = vehicleTimeChargingPlans.value(chargePointId);
+ const plan = plans.find((plane) => plane.id === planId);
+ return plan?.current;
+ },
+ set(newValue: number) {
+ updateTimeChargingPlanSubtopic(
+ chargePointId,
+ planId,
+ 'current',
+ newValue,
+ );
+ },
+ });
+ };
+
+ /**
+ * Get or set the limit selected mode for the time charging plan identified by the time charging plan id
+ * @param chargePointId charge point id
+ * @param planId time charging plan id
+ * @returns string | undefined
+ */
+ const vehicleTimeChargingPlanLimitSelected = (
+ chargePointId: number,
+ planId: number,
+ ) => {
+ return computed({
+ get() {
+ const plans = vehicleTimeChargingPlans.value(chargePointId);
+ const plan = plans.find((plane) => plane.id === planId);
+ return plan?.limit?.selected;
+ },
+ set(newValue: string) {
+ updateTimeChargingPlanSubtopic(
+ chargePointId,
+ planId,
+ 'limit.selected',
+ newValue,
+ );
+ },
+ });
+ };
+
+ /**
+ * Get or set the SoC limit for the time charging plan identified by the time charging plan id
+ * @param chargePointId charge point id
+ * @param planId time charging plan id
+ * @returns number | undefined
+ */
+ const vehicleTimeChargingPlanSocLimit = (
+ chargePointId: number,
+ planId: number,
+ ) => {
+ return computed({
+ get() {
+ const plans = vehicleTimeChargingPlans.value(chargePointId);
+ const plan = plans.find((plane) => plane.id === planId);
+ return plan?.limit?.soc;
+ },
+ set(newValue: number) {
+ updateTimeChargingPlanSubtopic(
+ chargePointId,
+ planId,
+ 'limit.soc',
+ newValue,
+ );
+ },
+ });
+ };
+
+ /**
+ * Get or set the energy amount limit for the time charging plan identified by the time charging plan id
+ * @param chargePointId charge point id
+ * @param planId time charging plan id
+ * @returns number | undefined
+ */
+ const vehicleTimeChargingPlanEnergyAmount = (
+ chargePointId: number,
+ planId: number,
+ ) => {
+ return computed({
+ get() {
+ const plans = vehicleTimeChargingPlans.value(chargePointId);
+ const plan = plans.find((plane) => plane.id === planId);
+ const amount = plan?.limit?.amount;
+ if (amount === undefined) {
+ return;
+ }
+ const valueObject = getValueObject.value(amount, 'Wh', '', true);
+ return valueObject.scaledValue;
+ },
+ set(newValue: number) {
+ const amountKiloWattHours = newValue * 1000;
+ updateTimeChargingPlanSubtopic(
+ chargePointId,
+ planId,
+ 'limit.amount',
+ amountKiloWattHours,
+ );
+ },
+ });
+ };
+
+ /**
+ * Get or set the frequency mode for the time charging plan identified by the time charging plan id
+ * @param chargePointId charge point id
+ * @param planId time charging plan id
+ * @returns string | undefined
+ */
+ const vehicleTimeChargingPlanFrequencySelected = (
+ chargePointId: number,
+ planId: number,
+ ) => {
+ return computed({
+ get() {
+ const plans = vehicleTimeChargingPlans.value(chargePointId);
+ const plan = plans.find((plane) => plane.id === planId);
+ return plan?.frequency?.selected;
+ },
+ set(newValue: string) {
+ updateTimeChargingPlanSubtopic(
+ chargePointId,
+ planId,
+ 'frequency.selected',
+ newValue,
+ );
+ },
+ });
+ };
+
+ /**
+ * Get or set the "valid from" date for the time charging plan identified by the time charging plan id (once)
+ * @param chargePointId charge point id
+ * @param planId time charging plan id
+ * @returns string | undefined
+ */
+ const vehicleTimeChargingPlanOnceDateStart = (
+ chargePointId: number,
+ planId: number,
+ ) => {
+ return computed({
+ get() {
+ const plans = vehicleTimeChargingPlans.value(chargePointId);
+ const plan = plans.find((plane) => plane.id === planId);
+ return plan?.frequency?.once?.[0];
+ },
+ set(newValue: string) {
+ updateTimeChargingPlanSubtopic(
+ chargePointId,
+ planId,
+ 'frequency.once.0',
+ newValue,
+ );
+ },
+ });
+ };
+
+ /**
+ * Get or set the "valid to" date for the time charging plan identified by the time charging plan id (once)
+ * @param chargePointId charge point id
+ * @param planId time charging plan id
+ * @returns string | undefined
+ */
+ const vehicleTimeChargingPlanOnceDateEnd = (
+ chargePointId: number,
+ planId: number,
+ ) => {
+ return computed({
+ get() {
+ const plans = vehicleTimeChargingPlans.value(chargePointId);
+ const plan = plans.find((plane) => plane.id === planId);
+ return plan?.frequency?.once?.[1];
+ },
+ set(newValue: string) {
+ updateTimeChargingPlanSubtopic(
+ chargePointId,
+ planId,
+ 'frequency.once.1',
+ newValue,
+ );
+ },
+ });
+ };
+
+ /**
+ * Get or set the number of phases for the time charging plan identified by the time charging plan id
+ * @param chargePointId charge point id
+ * @param planId time charging plan id
+ * @returns number | undefined
+ */
+ const vehicleTimeChargingPlanPhases = (
+ chargePointId: number,
+ planId: number,
+ ) => {
+ return computed({
+ get() {
+ const plans = vehicleTimeChargingPlans.value(chargePointId);
+ const plan = plans.find((plane) => plane.id === planId);
+ return plan?.phases_to_use;
+ },
+ set(newValue: number) {
+ updateTimeChargingPlanSubtopic(
+ chargePointId,
+ planId,
+ 'phases_to_use',
+ newValue,
+ );
+ },
+ });
+ };
+
+ /**
+ * Get or set the weekly days array for the time charging plan identified by the time charging plan id
+ * @param chargePointId charge point id
+ * @param planId time charging plan id
+ * @returns boolean[] | undefined
+ */
+ const vehicleTimeChargingPlanWeeklyDays = (
+ chargePointId: number,
+ planId: number,
+ ) => {
+ return computed({
+ get() {
+ const plans = vehicleTimeChargingPlans.value(chargePointId);
+ const plan = plans.find((plane) => plane.id === planId);
+ return plan?.frequency?.weekly ?? Array(7).fill(false);
+ },
+ set(newValue: boolean[]) {
+ updateTimeChargingPlanSubtopic(
+ chargePointId,
+ planId,
+ 'frequency.weekly',
newValue,
- objectPath,
- true,
+ );
+ },
+ });
+ };
+
+ /**
+ * Get or set the DC charging power for the time charging plan identified by the time charging plan id
+ * @param chargePointId charge point id
+ * @param planId time charging plan id
+ * @returns boolean[] | undefined
+ */
+ const vehicleTimeChargingPlanDcPower = (
+ chargePointId: number,
+ planId: number,
+ ) => {
+ return computed({
+ get() {
+ const plans = vehicleTimeChargingPlans.value(chargePointId);
+ const plan = plans.find((plane) => plane.id === planId);
+ const current = plan?.dc_current;
+ const power = convertDcCurrentToPower(current);
+ const valueObject = getValueObject.value(power, 'W', '', true);
+ return valueObject.scaledValue;
+ },
+ set(newValue) {
+ const current = convertPowerToDcCurrent(newValue);
+ updateTimeChargingPlanSubtopic(
+ chargePointId,
+ planId,
+ 'dc_current',
+ current,
);
},
});
@@ -2171,6 +2601,38 @@ export const useMqttStore = defineStore('mqtt', () => {
};
});
+ function addScheduledChargingPlanForChargePoint(chargePointId: number) {
+ const templateId =
+ chargePointConnectedVehicleChargeTemplate(chargePointId).value?.id;
+ if (templateId !== undefined) {
+ sendSystemCommand('addChargeTemplateSchedulePlan', {
+ template: templateId,
+ chargepoint: chargePointId,
+ changed_in_theme: true,
+ });
+ } else {
+ console.warn('Kein Template für ChargePoint gefunden:', chargePointId);
+ }
+ }
+
+ function removeScheduledChargingPlanForChargePoint(
+ chargePointId: number,
+ planId: number,
+ ) {
+ const templateId =
+ chargePointConnectedVehicleChargeTemplate(chargePointId).value?.id;
+ if (templateId !== undefined) {
+ sendSystemCommand('removeChargeTemplateSchedulePlan', {
+ template: templateId,
+ plan: planId,
+ chargepoint: chargePointId,
+ changed_in_theme: true,
+ });
+ } else {
+ console.warn('Kein Template für ChargePoint gefunden:', chargePointId);
+ }
+ }
+
/**
* Get time charging plan/s data identified by the charge point id
* @param chargePointId charge point id
@@ -2418,11 +2880,12 @@ export const useMqttStore = defineStore('mqtt', () => {
return valueObject.scaledValue;
},
set(newValue: number) {
+ const amountKiloWattHours = newValue * 1000;
updateScheduledChargingPlanSubtopic(
chargePointId,
planId,
'limit.amount',
- newValue,
+ amountKiloWattHours,
);
},
});
@@ -2441,7 +2904,7 @@ export const useMqttStore = defineStore('mqtt', () => {
return computed({
get() {
const plans = vehicleScheduledChargingPlans.value(chargePointId);
- const plan = plans.find((p) => p.id === planId);
+ const plan = plans.find((plan) => plan.id === planId);
return plan?.name;
},
set(newValue: string) {
@@ -2468,7 +2931,7 @@ export const useMqttStore = defineStore('mqtt', () => {
return computed({
get() {
const plans = vehicleScheduledChargingPlans.value(chargePointId);
- const plan = plans.find((p) => p.id === planId);
+ const plan = plans.find((plan) => plan.id === planId);
return plan?.time;
},
set(newValue: string) {
@@ -2495,7 +2958,7 @@ export const useMqttStore = defineStore('mqtt', () => {
return computed({
get() {
const plans = vehicleScheduledChargingPlans.value(chargePointId);
- const plan = plans.find((p) => p.id === planId);
+ const plan = plans.find((plan) => plan.id === planId);
return plan?.frequency.selected;
},
set(newValue: 'once' | 'daily' | 'weekly') {
@@ -2522,7 +2985,7 @@ export const useMqttStore = defineStore('mqtt', () => {
return computed({
get() {
const plans = vehicleScheduledChargingPlans.value(chargePointId);
- const plan = plans.find((p) => p.id === planId);
+ const plan = plans.find((plan) => plan.id === planId);
return plan?.frequency.once;
},
set(newValue: string) {
@@ -2549,7 +3012,7 @@ export const useMqttStore = defineStore('mqtt', () => {
return computed({
get() {
const plans = vehicleScheduledChargingPlans.value(chargePointId);
- const plan = plans.find((p) => p.id === planId);
+ const plan = plans.find((plan) => plan.id === planId);
return plan?.frequency.weekly;
},
set(newValue: boolean[]) {
@@ -2576,7 +3039,7 @@ export const useMqttStore = defineStore('mqtt', () => {
return computed({
get() {
const plans = vehicleScheduledChargingPlans.value(chargePointId);
- const plan = plans.find((p) => p.id === planId);
+ const plan = plans.find((plan) => plan.id === planId);
return plan?.limit.soc_limit;
},
set(newValue: number) {
@@ -2603,7 +3066,7 @@ export const useMqttStore = defineStore('mqtt', () => {
return computed({
get() {
const plans = vehicleScheduledChargingPlans.value(chargePointId);
- const plan = plans.find((p) => p.id === planId);
+ const plan = plans.find((plan) => plan.id === planId);
return plan?.limit.soc_scheduled;
},
set(newValue: number) {
@@ -2629,7 +3092,7 @@ export const useMqttStore = defineStore('mqtt', () => {
return computed({
get() {
const plans = vehicleScheduledChargingPlans.value(chargePointId);
- const plan = plans.find((p) => p.id === planId);
+ const plan = plans.find((plan) => plan.id === planId);
return plan?.phases_to_use;
},
set(newValue: number) {
@@ -2655,7 +3118,7 @@ export const useMqttStore = defineStore('mqtt', () => {
return computed({
get() {
const plans = vehicleScheduledChargingPlans.value(chargePointId);
- const plan = plans.find((p) => p.id === planId);
+ const plan = plans.find((plan) => plan.id === planId);
return plan?.phases_to_use_pv;
},
set(newValue: number) {
@@ -2669,6 +3132,94 @@ export const useMqttStore = defineStore('mqtt', () => {
});
};
+ /**
+ * Get or set the bidirectional charging enabled state for a scheduled charging plan
+ * @param chargePointId charge point id
+ * @param planId scheduled charging plan id
+ * @returns boolean | undefined
+ */
+ const vehicleScheduledChargingPlanBidiEnabled = (
+ chargePointId: number,
+ planId: number,
+ ) => {
+ return computed({
+ get() {
+ const plans = vehicleScheduledChargingPlans.value(chargePointId);
+ const plan = plans.find((plan) => plan.id === planId);
+ return plan?.bidi_charging_enabled;
+ },
+ set(newValue: boolean) {
+ updateScheduledChargingPlanSubtopic(
+ chargePointId,
+ planId,
+ 'bidi_charging_enabled',
+ newValue,
+ );
+ },
+ });
+ };
+
+ /**
+ * Get or set the bidirectional charging enabled state for a scheduled charging plan
+ * @param chargePointId charge point id
+ * @param planId scheduled charging plan id
+ * @returns boolean | undefined
+ */
+ const vehicleScheduledChargingPlanBidiPower = (
+ chargePointId: number,
+ planId: number,
+ ) => {
+ return computed({
+ get() {
+ const plans = vehicleScheduledChargingPlans.value(chargePointId);
+ const plan = plans.find((plan) => plan.id === planId);
+ const power = plan?.bidi_power;
+ const valueObject = getValueObject.value(power, 'W', '', true);
+ return valueObject.scaledValue;
+ },
+ set(newValue: number) {
+ const watts = Math.round(newValue * 1000);
+ updateScheduledChargingPlanSubtopic(
+ chargePointId,
+ planId,
+ 'bidi_power',
+ watts,
+ );
+ },
+ });
+ };
+
+ /**
+ * Get or set the DC charging power for a scheduled charging plan (plan.dc_current)
+ * @param chargePointId charge point id
+ * @param planId scheduled charging plan id
+ * @returns number | undefined (in kW)
+ */
+ const vehicleScheduledChargingPlanDcPower = (
+ chargePointId: number,
+ planId: number,
+ ) => {
+ return computed({
+ get() {
+ const plans = vehicleScheduledChargingPlans.value(chargePointId);
+ const plan = plans.find((plan) => plan.id === planId);
+ const current = plan?.dc_current;
+ const power = convertDcCurrentToPower(current);
+ const valueObject = getValueObject.value(power, 'W', '', true);
+ return valueObject.scaledValue;
+ },
+ set(newValue: number) {
+ const current = convertPowerToDcCurrent(newValue);
+ updateScheduledChargingPlanSubtopic(
+ chargePointId,
+ planId,
+ 'dc_current',
+ current,
+ );
+ },
+ });
+ };
+
/////////////////////////////// Grid Data /////////////////////////////////////
/**
@@ -2898,6 +3449,7 @@ export const useMqttStore = defineStore('mqtt', () => {
chargePointConnectedVehiclePriority,
chargePointConnectedVehicleTimeCharging,
chargePointConnectedVehicleChargeTemplate,
+ chargePointConnectedVehicleBidiEnabled,
// vehicle data
vehicleList,
chargePointConnectedVehicleConfig,
@@ -2910,6 +3462,8 @@ export const useMqttStore = defineStore('mqtt', () => {
chargePointConnectedVehicleSoc,
vehicleActivePlan,
vehicleChargeTarget,
+ addScheduledChargingPlanForChargePoint,
+ removeScheduledChargingPlanForChargePoint,
vehicleScheduledChargingPlans,
vehicleScheduledChargingPlanActive,
vehicleScheduledChargingPlanEtActive,
@@ -2925,8 +3479,26 @@ export const useMqttStore = defineStore('mqtt', () => {
vehicleScheduledChargingPlanSocScheduled,
vehicleScheduledChargingPlanPhases,
vehicleScheduledChargingPlanPhasesPv,
+ vehicleScheduledChargingPlanBidiEnabled,
+ vehicleScheduledChargingPlanBidiPower,
+ vehicleScheduledChargingPlanDcPower,
vehicleTimeChargingPlans,
+ vehicleTimeChargingPlanName,
+ addTimeChargingPlanForChargePoint,
+ removeTimeChargingPlanForChargePoint,
vehicleTimeChargingPlanActive,
+ vehicleTimeChargingPlanStartTime,
+ vehicleTimeChargingPlanEndTime,
+ vehicleTimeChargingPlanCurrent,
+ vehicleTimeChargingPlanLimitSelected,
+ vehicleTimeChargingPlanSocLimit,
+ vehicleTimeChargingPlanEnergyAmount,
+ vehicleTimeChargingPlanFrequencySelected,
+ vehicleTimeChargingPlanOnceDateStart,
+ vehicleTimeChargingPlanOnceDateEnd,
+ vehicleTimeChargingPlanPhases,
+ vehicleTimeChargingPlanWeeklyDays,
+ vehicleTimeChargingPlanDcPower,
chargePointConnectedVehicleSocType,
chargePointConnectedVehicleSocManual,
// Battery data