Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,18 @@
:limit-mode="limitMode"
:current-value="currentValue"
:target-time="vehicleTarget.time"
/>
>
<template v-if="vehicleSocType === 'manual'" v-slot:update-soc-icon>
<q-icon
name="edit"
size="xs"
class="q-ml-xs cursor-pointer"
@click="socInputVisible = true"
>
<q-tooltip>SoC eingeben</q-tooltip>
</q-icon>
</template>
</SliderDouble>
<slot name="card-footer"></slot>
</q-card-section>
</q-card>
Expand All @@ -52,6 +63,10 @@
:chargePointId="props.chargePointId"
v-model="settingsVisible"
/>
<ChargePointManualSocDialog
:chargePointId="props.chargePointId"
v-model:socDialogVisible="socInputVisible"
/>
</template>
<script setup lang="ts">
import { computed, ref } from 'vue';
Expand All @@ -65,6 +80,7 @@ import ChargePointStateMessage from './ChargePointStateMessage.vue';
import ChargePointFaultMessage from './ChargePointFaultMessage.vue';
import ChargePointVehicleSelect from './ChargePointVehicleSelect.vue';
import ChargePointSettings from './ChargePointSettings.vue';
import ChargePointManualSocDialog from './ChargePointManualSocDialog.vue';

const mqttStore = useMqttStore();

Expand Down Expand Up @@ -95,6 +111,7 @@ const limitMode = computed(() => {

const settingsVisible = ref<boolean>(false);

const socInputVisible = ref<boolean>(false);
const name = computed(() => mqttStore.chargePointName(props.chargePointId));

const power = computed(() =>
Expand Down Expand Up @@ -182,6 +199,8 @@ const showSocTargetSlider = computed(() => {
const vehicleTarget = computed(() => {
return mqttStore.vehicleChargeTarget(props.chargePointId).value;
});

const vehicleSocType = computed(() => mqttStore.chargePointConnectedVehicleSocType(props.chargePointId))?.value;
</script>
<style lang="scss" scoped>
.card-width {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
<template>
<q-dialog v-model="visible">
<q-card>
<q-card-section>
<div class="row">
<div class="text-h6 q-mr-md">SoC-Eingabe {{ vehicleName }}</div>
<q-space />
<q-btn icon="close" flat round dense v-close-popup />
</div>
</q-card-section>
<q-card-section class="q-py-none">
<div class="row justify-center items-center q-ma-none q-pa-none">
<div class="col-6 col-sm-8 col-md-6">
<q-input
v-model.number="socInputValue"
type="text"
inputmode="numeric"
class="text-center"
suffix="%"
hide-spinner
>
<template v-slot:prepend>
<q-btn round flat dense icon="remove" @click="socInputValue--" />
</template>
<template v-slot:append>
<q-btn round flat dense icon="add" @click="socInputValue++" />
</template>
</q-input>
</div>
</div>
</q-card-section>
<q-card-actions align="center" class="q-mt-md">
<q-btn
label="Abbrechen"
color="negative"
v-close-popup
@click="cancelChanges"
/>
<q-btn
label="Bestätigen"
color="primary"
v-close-popup
@click="confirmChanges"
/>
</q-card-actions>
</q-card>
</q-dialog>
</template>

<script setup lang="ts">
import { useMqttStore } from 'src/stores/mqtt-store';
import { computed, ref } from 'vue';

const mqttStore = useMqttStore();

const props = defineProps<{
chargePointId: number;
socDialogVisible: boolean;
}>();

const emit = defineEmits<{
'update:socDialogVisible': [value: boolean];
}>();

const visible = computed({
get: () => props.socDialogVisible,
set: (value) => {
emit('update:socDialogVisible', value);
},
});

const vehicleName = computed(() => {
return mqttStore.chargePointConnectedVehicleInfo(props.chargePointId).value
?.name;
});

const socValue = ref<number | undefined>(undefined);

const socInputValue = computed({
get: () => {
return socValue.value ?? mqttStore.chargePointConnectedVehicleSocManual(props.chargePointId).value ?? 0;
},
set: (newValue: number) => {
// limit new value to 0-100
socValue.value = Math.min(Math.max(0, newValue), 100);
},
});

const confirmChanges = () => {
mqttStore.chargePointConnectedVehicleSocManual(props.chargePointId).value =
socInputValue.value;
};

const cancelChanges = () => {
// Reset temporary soc value
socValue.value = undefined;
};
</script>
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
? formatEnergy(currentValue)
: currentValue + '%'
}}
<slot name="update-soc-icon"></slot>
</div>
</div>
<div v-if="props.targetTime" class="col text-center">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,12 @@ export interface VehicleChargeTarget {
limit?: number;
}

export interface CalculatedSocState {
imported_start: number;
manual_soc?: number;
soc_start: number;
}

export interface GraphDataPoint {
timestamp: number;
time: string;
Expand Down
56 changes: 56 additions & 0 deletions packages/modules/web_themes/koala/source/src/stores/mqtt-store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import type {
VehicleActivePlan,
TimeChargingPlan,
VehicleChargeTarget,
CalculatedSocState,
} from './mqtt-store-model';

export const useMqttStore = defineStore('mqtt', () => {
Expand Down Expand Up @@ -1465,6 +1466,59 @@ export const useMqttStore = defineStore('mqtt', () => {
});
};

/**
* Get or set the manual SoC for a vehicle connected to a charge point
* @param chargePointId charge point id
* @returns number | undefined
*/
const chargePointConnectedVehicleSocManual = (chargePointId: number) => {
return computed({
get() {
const vehicleInfo =
chargePointConnectedVehicleInfo(chargePointId).value;
const vehicleId = vehicleInfo?.id;
const topic = `openWB/vehicle/${vehicleId}/soc_module/calculated_soc_state`;
const socState = getValue.value(topic) as CalculatedSocState | undefined;
return socState?.manual_soc ?? socState?.soc_start ?? 0;
},
set(newValue: number) {
const vehicleInfo =
chargePointConnectedVehicleInfo(chargePointId).value;
if (!vehicleInfo) {
console.warn('No vehicle connected to charge point', chargePointId);
return;
}
const vehicleId = vehicleInfo.id;
doPublish(
`openWB/set/vehicle/${vehicleId}/soc_module/calculated_soc_state/manual_soc`,
newValue,
);
// Also update the charge point connected vehicle soc
const cpTopic = `openWB/chargepoint/${chargePointId}/get/connected_vehicle/soc`;
const cpSoc = getValue.value(cpTopic) as { soc?: number };
if (cpSoc && cpSoc.soc !== undefined) {
updateTopic(cpTopic, newValue, 'soc', true);
}
},
});
};

/**
* Get the charge point connected vehicle SoC type identified by the charge point id
* @param chargePointId charge point id
* @returns string | null | undefined
*/
const chargePointConnectedVehicleSocType = (chargePointId: number) => {
return computed(() => {
const vehicleId = chargePointConnectedVehicleInfo(chargePointId).value?.id;
if (!vehicleId) return undefined;
const socConfig = getValue.value(
`openWB/vehicle/${vehicleId}/soc_module/config`,
) as { type: string } | null;
return socConfig?.type;
});
};

/**
* Get or set the charge point connected vehicle charge template identified by the charge point id
* @param chargePointId charge point id
Expand Down Expand Up @@ -2484,6 +2538,8 @@ export const useMqttStore = defineStore('mqtt', () => {
vehicleScheduledChargingPlanSocScheduled,
vehicleScheduledChargingPlanPhases,
vehicleScheduledChargingPlanPhasesPv,
chargePointConnectedVehicleSocType,
chargePointConnectedVehicleSocManual,
// Battery data
batteryConfigured,
batteryIds,
Expand Down