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 @@ -5,14 +5,18 @@
<div class="col flex items-center">
{{ name }}
<ChargePointLock :charge-point-id="props.chargePointId" />
<ChargePointStateIcon :charge-point-id="props.chargePointId" />
<ChargePointStateIcon
:charge-point-id="Number(props.chargePointId)"
/>
</div>
<q-icon name="settings" size="sm" @click="settingsVisible = true" />
</div>
<ChargePointFaultMessage :charge-point-id="props.chargePointId" />
<ChargePointStateMessage :charge-point-id="props.chargePointId" />
<div class="row items-center q-mt-sm">
<ChargePointVehicleSelect :charge-point-id="props.chargePointId" />
<ChargePointVehicleSelect
:charge-point-id="Number(props.chargePointId)"
/>
<ChargePointPriority :charge-point-id="props.chargePointId" />
</div>
<ChargePointModeButtons :charge-point-id="props.chargePointId" />
Expand All @@ -27,29 +31,27 @@
</div>
<div class="col q-pl-sm">
<div class="text-subtitle2">geladen</div>
<!-- {{ energyCharged }} -->
{{ energyChargedPlugged }}
</div>
</div>
<SliderDouble
v-if="showSocTargetSlider"
class="q-mt-sm"
:model-value="target"
:readonly="true"
:charge-mode="chargeMode"
:connected-vehicle-soc="connectedVehicleSoc"
:target-soc="targetSoc"
:limit-mode="limitMode"
:current-value="currentValue"
:target-time="targetTime"
/>
</q-card-section>
</q-card>

<!-- ////////////////////// Settings popup dialog //////////////////// -->
<ChargePointSettings
:chargePointId="props.chargePointId"
v-model="settingsVisible"
/>
</template>

<script setup lang="ts">
import { computed, ref } from 'vue';
import { useMqttStore } from 'src/stores/mqtt-store';
Expand All @@ -62,19 +64,33 @@ import ChargePointStateMessage from './ChargePointStateMessage.vue';
import ChargePointFaultMessage from './ChargePointFaultMessage.vue';
import ChargePointVehicleSelect from './ChargePointVehicleSelect.vue';
import ChargePointSettings from './ChargePointSettings.vue';

const mqttStore = useMqttStore();

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

const limitMode = computed(() => {
switch (chargeMode.value) {
case 'instant_charging':
return mqttStore.chargePointConnectedVehicleInstantChargeLimit(
props.chargePointId,
).value;
case 'pv_charging':
return mqttStore.chargePointConnectedVehiclePvChargeLimit(
props.chargePointId,
).value;
case 'eco_charging':
return mqttStore.chargePointConnectedVehicleEcoChargeLimit(
props.chargePointId,
).value;
default:
return 'soc';
}
});
const settingsVisible = ref<boolean>(false);
const name = computed(() => mqttStore.chargePointName(props.chargePointId));
const power = computed(() =>
mqttStore.chargePointPower(props.chargePointId, 'textValue'),
);

const energyChargedPlugged = computed(() =>
mqttStore.chargePointEnergyChargedPlugged(props.chargePointId, 'textValue'),
);
Expand All @@ -84,20 +100,24 @@ const phaseNumber = computed(() =>
const chargingCurrent = computed(() =>
mqttStore.chargePointChargingCurrent(props.chargePointId),
);

const connectedVehicleSoc = computed(() =>
Math.round(
mqttStore.chargePointConnectedVehicleSoc(props.chargePointId).value?.soc ??
const currentValue = computed(() => {
if (limitMode.value === 'soc') {
return Math.round(
mqttStore.chargePointConnectedVehicleSoc(props.chargePointId).value?.soc ??
0,
),
);

);
} else {
return mqttStore.chargePointEnergyChargedPlugged(
props.chargePointId,
'value',
) as number;
}
});
const chargeMode = computed(
() =>
mqttStore.chargePointConnectedVehicleChargeMode(props.chargePointId).value,
);

const targetSoc = computed<number | undefined>(() => {
const target = computed(() => {
switch (chargeMode.value) {
case 'scheduled_charging':
return mqttStore.vehicleScheduledChargingTarget(props.chargePointId).value
Expand All @@ -110,49 +130,49 @@ const targetSoc = computed<number | undefined>(() => {
return instantLimitMode === 'soc'
? mqttStore.chargePointConnectedVehicleInstantChargeLimitSoC(
props.chargePointId,
).value
: undefined;
).value ?? 0
: (mqttStore.chargePointConnectedVehicleInstantChargeLimitEnergy(
props.chargePointId,
).value ?? 0) * 1000;
case 'pv_charging':
const pvLimitMode = mqttStore.chargePointConnectedVehiclePvChargeLimit(
props.chargePointId,
).value;
return pvLimitMode === 'soc'
? mqttStore.chargePointConnectedVehiclePvChargeLimitSoC(
props.chargePointId,
).value
: undefined;
).value ?? 0
: (mqttStore.chargePointConnectedVehiclePvChargeLimitEnergy(
props.chargePointId,
).value ?? 0) * 1000;
case 'eco_charging':
const ecoLimitMode = mqttStore.chargePointConnectedVehicleEcoChargeLimit(
props.chargePointId,
).value;
return ecoLimitMode === 'soc'
? mqttStore.chargePointConnectedVehicleEcoChargeLimitSoC(
props.chargePointId,
).value
: undefined;
).value ?? 0
: (mqttStore.chargePointConnectedVehicleEcoChargeLimitEnergy(
props.chargePointId,
).value ?? 0) * 1000;
default:
return undefined;
return 0;
}
});

const showSocTargetSlider = computed(() => {
return (
chargeMode.value !== undefined &&
!['stop', 'standby'].includes(chargeMode.value)
);
return chargeMode.value !== undefined && !'stop'.includes(chargeMode.value) && limitMode.value !== 'none';
});

const targetTime = computed(() => {
const target = mqttStore.vehicleScheduledChargingTarget(
props.chargePointId,
).value;
if (!target || !target.time || chargeMode.value !== 'scheduled_charging') {
return 'keine';
return undefined;
}
return target.time;
});
</script>

<style lang="scss" scoped>
.card-width {
max-width: 24em;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,22 +42,22 @@
</template>

<script setup lang="ts">
import { ref } from 'vue';
import { ref, computed } from 'vue';
import { useQuasar } from 'quasar';
import EnergyFlowChart from './charts/energyFlowChart/EnergyFlowChart.vue';
import HistoryChart from './charts/historyChart/HistoryChart.vue';
import { useLocalDataStore } from 'src/stores/localData-store';

defineOptions({
name: 'ChartCarousel',
});
const $q = useQuasar();

const legendVisible = ref(!$q.platform.is.mobile);
const localDataStore = useLocalDataStore();

const toggleLegend = () => {
legendVisible.value = !legendVisible.value;
localDataStore.toggleLegendVisibility();
};

const legendVisible = computed(() => localDataStore.legendVisible);
const fullscreen = ref(false);
const chartCarouselItems = [
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,61 +1,80 @@
<template>
<div class="my-card">
<div class="relative-position" style="height: 40px">
<div class="slider-container">
<q-slider
v-model="currentCharge"
:model-value="currentValue"
:min="0"
:max="100"
:max="maxValue"
color="green-7"
class="current-slider"
track-size="1.5em"
thumb-size="0px"
readonly
no-focus
@touchstart.stop
@touchmove.stop
@touchend.stop
style="position: absolute; width: 100%; z-index: 1"
/>
<q-slider
v-model="targetCharge"
v-if="props.limitMode == 'soc'"
v-model="target"
:min="0"
:max="100"
color="light-green-5"
inner-track-color="blue-grey-2"
class="target-slider"
track-size="1.5em"
:thumb-size="props.readonly ? '0' : '2em'"
:readonly="props.readonly"
@touchstart.stop
@touchmove.stop
@touchend.stop
style="position: absolute; width: 100%"
/>
</div>

<div class="row justify-between no-wrap">
<div class="col">
<div>Ladestand</div>
<div>{{ currentCharge }}%</div>
<div>{{ props.limitMode == 'soc' ? 'Ladestand' : 'Geladen' }}</div>
<div>
{{
props.limitMode == 'soc'
? currentValue + '%'
: formatEnergy(currentValue)
}}
</div>
</div>
<div v-if="showTargetTime" class="col text-center">
<div
v-if="props.targetTime"
class="col text-center"
>
<div>Zielzeit</div>
<div>{{ targetTime }}</div>
<div>{{ props.targetTime }}</div>
</div>
<div class="col text-right">
<div>Ladeziel</div>
<div>{{ targetCharge }}%</div>
<div>
{{ props.limitMode == 'soc' ? 'Ladeziel' : 'Energieziel' }}
</div>
<div>
{{
props.limitMode == 'soc'
? target + '%'
: formatEnergy(target)
}}
</div>
</div>
</div>
</div>
</template>

<script setup lang="ts">
import { computed } from 'vue';

defineOptions({
name: 'SliderQuasar',
});

const emit = defineEmits(['update:modelValue']);
const props = defineProps({
modelValue: {
type: Number,
required: true,
},
readonly: {
type: Boolean,
default: false,
Expand All @@ -64,30 +83,58 @@ const props = defineProps({
type: String,
default: '',
},
connectedVehicleSoc: {
type: Number,
default: 0,
limitMode: {
type: String,
default: 'soc',
},
targetSoc: {
currentValue: {
type: Number,
default: 0,
},
targetTime: {
type: String,
default: 'keine',
required: false,
default: undefined,
},
});
const target = computed({
get: () => props.modelValue,
set: (value) => {
if (!props.readonly) {
emit('update:modelValue', value);
}
},
});

const showTargetTime = computed(
() => props.chargeMode === 'scheduled_charging',
);
const currentCharge = computed(() => props.connectedVehicleSoc);
const targetCharge = computed(() => props.targetSoc);
const maxValue = computed(() => {
if (props.limitMode == 'soc') {
return 100;
}
return target.value;
});
const formatEnergy = (value: number) => {
if (value >= 1000) {
return (value / 1000).toFixed(2) + ' kWh';
} else {
return value.toFixed(0) + ' Wh';
}
};
</script>

<style scoped>
.my-card {
width: 100%;
max-width: 300px;
}
.slider-container {
position: relative;
height: 40px;
}
.current-slider {
position: absolute;
width: 100%;
z-index: 1;
}
.target-slider {
position: absolute;
width: 100%;
}
</style>
Loading
Loading