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 @@ -59,6 +59,7 @@
<q-card-section>
<ChargePointModeButtons :charge-point-id="props.chargePointId" />
</q-card-section>

<q-card-section class="row q-mt-sm">
<div class="col">
<div class="text-subtitle2">Leistung</div>
Expand All @@ -77,8 +78,7 @@
</q-card-section>
<q-card-section>
<SliderDouble
v-if="showSocTargetSlider"
class="q-mt-sm"
:class="['q-mt-sm', limitEditable && 'cursor-pointer']"
:model-value="target"
:readonly="true"
:charge-mode="chargeMode"
Expand All @@ -88,7 +88,16 @@
:vehicle-soc-type="vehicleSocType"
:on-edit-soc="openSocDialog"
:on-refresh-soc="refreshSoc"
/>
@click="openLimitDialog"
>
<template #tooltip>
<q-tooltip
v-if="chargeMode !== 'scheduled_charging' && chargeMode !== 'stop'"
>
Begrenzung einstellen
</q-tooltip>
</template>
</SliderDouble>
</q-card-section>
<q-card-actions v-if="$slots['card-actions']" align="right">
<slot name="card-actions"></slot>
Expand All @@ -98,6 +107,11 @@
:chargePointId="props.chargePointId"
v-model="settingsVisible"
/>
<!-- ////////////////////// modal charge limit settings dialog //////////////////// -->
<ChargePointChargeLimits
:chargePointId="props.chargePointId"
v-model="chargeLimitsVisible"
/>
<!-- ////////////////////// modal soc dialog //////////////////// -->
<ManualSocDialog
:vehicleId="vehicleId"
Expand All @@ -117,6 +131,7 @@ import ChargePointModeButtons from './ChargePointModeButtons.vue';
import ChargePointMessage from './ChargePointMessage.vue';
import ChargePointVehicleSelect from './ChargePointVehicleSelect.vue';
import ChargePointSettings from './ChargePointSettings.vue';
import ChargePointChargeLimits from './ChargePointChargeLimits.vue';
import ManualSocDialog from './ManualSocDialog.vue';
import ChargePointTimeCharging from './ChargePointTimeCharging.vue';
import ChargePointPowerData from './ChargePointPowerData.vue';
Expand Down Expand Up @@ -161,6 +176,16 @@ const limitMode = computed(() => {
});

const settingsVisible = ref<boolean>(false);
const chargeLimitsVisible = ref<boolean>(false);

const limitEditable = computed(() => {
return !['scheduled_charging', 'stop'].includes(chargeMode.value);
});

const openLimitDialog = () => {
if (!limitEditable.value) return;
chargeLimitsVisible.value = true;
};

const socInputVisible = ref<boolean>(false);
const openSocDialog = () => {
Expand Down Expand Up @@ -272,18 +297,6 @@ const target = computed(() => {
}
});

const showSocTargetSlider = computed(() => {
if (target.value && target.value > 999) {
// we have a energy based target
return true;
}
if (vehicleSocType.value) {
// we have a soc module defined
return true;
}
return false;
});

const vehicleTarget = computed(() => {
return mqttStore.vehicleChargeTarget(props.chargePointId).value;
});
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,223 @@
<template>
<q-dialog
v-model="visible"
:backdrop-filter="isSmallScreen ? '' : 'blur(4px)'"
>
<q-card class="card-width">
<q-card-section>
<div class="row nowrap q-mb-sm">
<div class="text-h6">Begrenzung</div>
<q-space />
<q-btn icon="close" flat round dense v-close-popup />
</div>
<q-separator class="q-mt-sm q-mb-sm" />
<div v-if="isSmallScreen" class="row q-pt-md full-width">
<q-btn-dropdown
class="col"
transition-show="scale"
transition-hide="scale"
transition-duration="500"
color="primary"
:label="currentLimitModeLabel"
size="md"
dropdown-icon="none"
cover
push
>
<q-list>
<template v-for="(mode, index) in limitModes" :key="mode.value">
<q-item
clickable
v-close-popup
@click="limitMode.value = mode.value"
:active="limitMode.value === mode.value"
:disable="mode.value === 'soc' && !vehicleSocType"
active-class="bg-primary text-white"
>
<q-item-section class="text-center text-weight-bold">
<q-item-label>{{
mode.label.toLocaleUpperCase()
}}</q-item-label>
</q-item-section>
</q-item>
<q-separator v-if="index < limitModes.length - 1" />
</template>
</q-list>
</q-btn-dropdown>
</div>
<div
v-else
class="row items-center justify-center q-ma-none q-pa-none no-wrap"
>
<q-btn-group class="col">
<q-btn
v-for="mode in limitModes"
:key="mode.value"
:color="limitMode.value === mode.value ? 'primary' : 'grey'"
:label="mode.label"
:disable="mode.value === 'soc' && !vehicleSocType"
:outline="mode.value === 'soc' && !vehicleSocType"
size="sm"
class="col"
@click="limitMode.value = mode.value"
/>
</q-btn-group>
</div>
<SliderStandard
v-if="limitMode.value === 'soc'"
title="SoC-Limit für das Fahrzeug"
:min="5"
:max="100"
:step="5"
color="light-green-14"
:track-size="'1em'"
thumb-size="2.3em"
thumb-color="light-green-14"
unit="%"
v-model="limitSoC.value"
class="q-mt-md"
/>
<SliderStandard
v-if="limitMode.value === 'amount'"
title="Energie-Limit"
:min="1"
:max="50"
color="green-7"
:track-size="'1em'"
thumb-size="2.3em"
thumb-color="green-7"
unit="kWh"
v-model="limitEnergy.value"
class="q-mt-md"
/>
</q-card-section>
</q-card>
</q-dialog>
</template>

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

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

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

const mqttStore = useMqttStore();

const isSmallScreen = computed(() => Screen.lt.sm);
const tempValue = ref<boolean>(props.modelValue);

const limitModes = [
{ value: 'none', label: 'keine' },
{ value: 'soc', label: 'EV-SoC' },
{ value: 'amount', label: 'Energie' },
];

const vehicleSocType = computed(() =>
mqttStore.chargePointConnectedVehicleSocType(props.chargePointId),
)?.value;

const chargeMode = computed(
() =>
mqttStore.chargePointConnectedVehicleChargeMode(props.chargePointId)?.value,
);

const activeChargeLimitConfig = computed(() => {
switch (chargeMode.value) {
case 'instant_charging':
return {
mode: mqttStore.chargePointConnectedVehicleInstantChargeLimit(
props.chargePointId,
),
soc: mqttStore.chargePointConnectedVehicleInstantChargeLimitSoC(
props.chargePointId,
),
energy: mqttStore.chargePointConnectedVehicleInstantChargeLimitEnergy(
props.chargePointId,
),
};
case 'pv_charging':
return {
mode: mqttStore.chargePointConnectedVehiclePvChargeLimit(
props.chargePointId,
),
soc: mqttStore.chargePointConnectedVehiclePvChargeLimitSoC(
props.chargePointId,
),
energy: mqttStore.chargePointConnectedVehiclePvChargeLimitEnergy(
props.chargePointId,
),
};
case 'eco_charging':
return {
mode: mqttStore.chargePointConnectedVehicleEcoChargeLimit(
props.chargePointId,
),
soc: mqttStore.chargePointConnectedVehicleEcoChargeLimitSoC(
props.chargePointId,
),
energy: mqttStore.chargePointConnectedVehicleEcoChargeLimitEnergy(
props.chargePointId,
),
};
default:
return {
mode: ref('none'),
soc: ref(0),
energy: ref(0),
};
}
});

const limitMode = computed(() => activeChargeLimitConfig.value.mode);
const limitSoC = computed(() => activeChargeLimitConfig.value.soc);
const limitEnergy = computed(() => activeChargeLimitConfig.value.energy);

const visible = computed({
get: () => tempValue.value,
set: (value) => {
tempValue.value = value;
emit('update:model-value', value);
},
});

const currentLimitModeLabel = computed(
() => limitModes.find((mode) => mode.value === limitMode.value.value)?.label,
);

watch(
() => props.modelValue,
(value) => {
tempValue.value = value;
},
);
</script>

<style scoped>
.card-width {
width: 25em;
}
.q-btn-group .q-btn {
min-width: 100px !important;
}

body.mobile .q-btn-group .q-btn {
padding: 4px 8px;
font-size: 12px !important;
min-height: 30px;
}

:deep(.q-btn-dropdown__arrow-container) {
width: 0;
padding: 0;
margin: 0;
}
</style>
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
<template>
<div class="double-slider-container">
<div>
<div class="slider-container">
<q-slider
:model-value="currentValue"
:model-value="props.currentValue"
:min="0"
:max="maxValue"
:markers="props.limitMode == 'amount' ? 10000 : 10"
Expand All @@ -16,6 +16,7 @@
@touchmove.stop
@touchend.stop
/>
<slot name="tooltip" />
<q-slider
v-if="props.limitMode == 'soc'"
v-model="target"
Expand All @@ -37,25 +38,27 @@
<div>{{ props.limitMode == 'amount' ? 'Geladen' : 'Ladestand' }}</div>
<div>
{{
props.limitMode == 'amount'
? formatEnergy(currentValue)
: currentValue + '%'
props.limitMode === 'amount'
? formatEnergy(props.currentValue)
: !props.vehicleSocType
? 'Kein SoC-Modul konfiguriert'
: props.currentValue + '%'
}}
<q-icon
v-if="vehicleSocType === 'manual' && limitMode !== 'amount'"
v-if="props.vehicleSocType === 'manual' && props.limitMode !== 'amount'"
name="edit"
size="xs"
class="q-ml-xs cursor-pointer"
@click="onEditSoc"
@click.stop="onEditSoc"
>
<q-tooltip>Ladestand eingeben</q-tooltip>
</q-icon>
<q-icon
v-else-if="vehicleSocType !== undefined && limitMode !== 'amount'"
v-else-if="props.vehicleSocType && props.vehicleSocType !== 'manual' && props.limitMode !== 'amount'"
name="refresh"
size="xs"
class="q-ml-xs cursor-pointer"
@click="onRefreshSoc"
@click.stop="onRefreshSoc"
>
<q-tooltip>Ladestand aktualisieren</q-tooltip>
</q-icon>
Expand Down Expand Up @@ -116,7 +119,7 @@ const props = defineProps({
vehicleSocType: {
type: String,
required: false,
default: undefined,
default: null,
},
onEditSoc: {
type: Function,
Expand Down
Loading
Loading