Start adding kiosk view

This commit is contained in:
2024-12-12 15:22:23 +00:00
parent 6925319487
commit d563e89c6b
9 changed files with 354 additions and 146 deletions

View File

@@ -0,0 +1,104 @@
<script lang="ts" setup></script>
<template>
<v-container
fluid
class="container">
<v-card class="current-weather">
<CurrentWeather></CurrentWeather>
</v-card>
<v-card class="almanac">
<Almanac></Almanac>
</v-card>
<v-card class="current-power">
<CurrentPower></CurrentPower>
</v-card>
<v-card class="current-laundry-status">
<CurrentLaundryStatus></CurrentLaundryStatus>
</v-card>
<v-card class="upstairs">
<Indoor
title="Upstairs"
deviceName="main"></Indoor>
</v-card>
<v-card class="downstairs">
<Indoor
title="Downstairs"
deviceName="basement"></Indoor>
</v-card>
</v-container>
</template>
<style scoped>
.container {
height: 100%;
background-color: #fafafa;
}
@media (min-width: 1024px) {
.container {
display: grid;
grid-template-columns: 360px 350px 210px 1fr;
grid-template-rows: repeat(3, max-content);
gap: 15px 15px;
grid-auto-flow: row;
grid-template-areas:
'current-weather almanac current-laundry-status'
'current-weather almanac current-power'
'upstairs downstairs .';
}
}
@media (max-width: 1024px) {
.container {
display: grid;
grid-template-columns: repeat(4, 180px);
grid-template-rows: repeat(2, max-content);
gap: 15px 15px;
grid-auto-flow: row;
grid-template-areas:
'current-weather current-weather almanac almanac'
'current-power current-laundry-status upstairs downstairs';
}
}
@media (max-width: 768px) {
.container {
display: grid;
grid-template-columns: repeat(1, 1fr);
grid-template-rows: repeat(6, max-content);
gap: 10px 0px;
grid-template-areas:
'current-weather'
'almanac'
'current-power'
'current-laundry-status'
'upstairs'
'downstairs';
}
}
.current-weather {
grid-area: current-weather;
}
.almanac {
grid-area: almanac;
}
.current-power {
grid-area: current-power;
}
.current-laundry-status {
grid-area: current-laundry-status;
}
.upstairs {
grid-area: upstairs;
}
.downstairs {
grid-area: downstairs;
}
</style>

View File

@@ -0,0 +1,133 @@
<script lang="ts" setup>
import { ref } from 'vue';
import { subHours } from 'date-fns';
import { createIndoorStore } from '@/stores/indoorStore';
import { ConvertCToF } from '@/temperatureConverter';
import { ConvertMillibarToInchesOfMercury } from '@/pressureConverter';
import ValueChart from '@/components/ValueChart.vue';
import TimeRange from '@/components/TimeRange.vue';
import TimeSpan from '@/models/time-span';
const indoorStore = createIndoorStore('charts');
const ready = ref(false);
const end = ref(new Date());
const start = ref(subHours(end.value, 24));
const timeSpan = ref(TimeSpan.Last24Hours);
const mainTemperatureSeries = ref({ name: 'Upstairs', data: [] as number[][] });
const basementTemperatureSeries = ref({ name: 'Downstairs', data: [] as number[][] });
const mainHumiditySeries = ref({ name: 'Upstairs', data: [] as number[][] });
const basementHumiditySeries = ref({ name: 'Downstairs', data: [] as number[][] });
const mainPressureSeries = ref({ name: 'Upstairs', data: [] as number[][] });
const basementPressureSeries = ref({ name: 'Downstairs', data: [] as number[][] });
const load = () => {
ready.value = false;
indoorStore.getReadingValueHistoryGrouped(start.value, end.value, 15).then((groupedReadingsList) => {
mainTemperatureSeries.value.data.length = 0;
basementTemperatureSeries.value.data.length = 0;
mainHumiditySeries.value.data.length = 0;
basementHumiditySeries.value.data.length = 0;
mainPressureSeries.value.data.length = 0;
basementPressureSeries.value.data.length = 0;
groupedReadingsList.forEach((groupedReadings) => {
const date = new Date(groupedReadings.bucket).getTime();
if (groupedReadings.name === 'main') {
mainTemperatureSeries.value.data.push([date, ConvertCToF(groupedReadings.averageTemperature)]);
mainHumiditySeries.value.data.push([date, groupedReadings.averageHumidity]);
mainPressureSeries.value.data.push([date, ConvertMillibarToInchesOfMercury(groupedReadings.averagePressure)]);
} else if (groupedReadings.name === 'basement') {
basementTemperatureSeries.value.data.push([date, ConvertCToF(groupedReadings.averageTemperature)]);
basementHumiditySeries.value.data.push([date, groupedReadings.averageHumidity]);
basementPressureSeries.value.data.push([date, ConvertMillibarToInchesOfMercury(groupedReadings.averagePressure)]);
}
});
ready.value = true;
});
};
load();
</script>
<template>
<v-container
fluid
class="container">
<TimeRange
:time-span="timeSpan"
:start="start"
:end="end"
@change="
(value) => {
timeSpan = value.timeSpan;
start = value.start;
end = value.end;
load();
}
"
@refresh="load"></TimeRange>
<div class="content">
<v-row
dense
align="start">
<v-col
sm="6"
cols="12">
<ValueChart
:ready="ready"
type="line"
title="Temperature"
unit="°F"
group="indoor"
:series="[mainTemperatureSeries, basementTemperatureSeries]"></ValueChart>
</v-col>
<v-col
sm="6"
cols="12">
<ValueChart
:ready="ready"
type="line"
title="Humidity"
unit="%"
group="indoor"
:series="[mainHumiditySeries, basementHumiditySeries]"></ValueChart>
</v-col>
<v-col
sm="6"
cols="12">
<ValueChart
:ready="ready"
type="line"
title="Pressure"
unit='"'
group="indoor"
:y-axis-decimal-points="1"
:series="[mainPressureSeries, basementPressureSeries]"></ValueChart>
</v-col>
</v-row>
</div>
</v-container>
</template>
<style scoped>
.container {
height: 100%;
background-color: #fafafa;
padding: 0;
}
.content {
padding: 10px;
}
</style>

View File

@@ -0,0 +1,216 @@
<script lang="ts" setup>
import { ref } from 'vue';
import { subHours } from 'date-fns';
import { useWeatherStore } from '@/stores/weatherStore';
import { ConvertPascalToInchesOfMercury } from '@/pressureConverter';
import ValueChart from '@/components/ValueChart.vue';
import TimeRange from '@/components/TimeRange.vue';
import TimeSpan from '@/models/time-span';
import { ConvertDegreesToShortLabel, ConvertWindDirectionToDegrees } from '@/windConverter';
const weatherStore = useWeatherStore();
const readingsReady = ref(false);
const windReady = ref(false);
const temperatureSeries = ref({ name: 'Average Temperature', data: [] as number[][] });
const humiditySeries = ref({ name: 'Average Humidity', data: [] as number[][] });
const pressureSeries = ref({ name: 'Average Pressure', data: [] as number[][] });
const lightSeries = ref({ name: 'Average Light', data: [] as number[][] });
const rainSeries = ref({ name: 'Total Rain', data: [] as number[][] });
const windMinimumSeries = ref({ name: 'Minimum', data: [] as number[][] });
const windAverageSeries = ref({ name: 'Average', data: [] as number[][] });
const windMaximumSeries = ref({ name: 'Maximum', data: [] as number[][] });
const windDirectionSeries = ref({ name: 'Average Direction', data: [] as number[][] });
const end = ref(new Date());
const start = ref(subHours(end.value, 24));
const timeSpan = ref(TimeSpan.Last24Hours);
const load = () => {
readingsReady.value = false;
windReady.value = false;
weatherStore.getReadingHistoryGrouped(start.value, end.value, 15).then((groupedReadingsList) => {
temperatureSeries.value.data.length = 0;
humiditySeries.value.data.length = 0;
pressureSeries.value.data.length = 0;
lightSeries.value.data.length = 0;
rainSeries.value.data.length = 0;
groupedReadingsList.forEach((groupedReadings) => {
const date = new Date(groupedReadings.bucket).getTime();
temperatureSeries.value.data.push([date, groupedReadings.averageTemperature]);
humiditySeries.value.data.push([date, groupedReadings.averageHumidity]);
pressureSeries.value.data.push([date, ConvertPascalToInchesOfMercury(groupedReadings.averagePressure)]);
lightSeries.value.data.push([date, groupedReadings.averageLightLevel]);
rainSeries.value.data.push([date, groupedReadings.rainTotal]);
});
readingsReady.value = true;
});
weatherStore.getWindHistoryGrouped(start.value, end.value, 15).then((groupedReadingsList) => {
windMinimumSeries.value.data.length = 0;
windAverageSeries.value.data.length = 0;
windMaximumSeries.value.data.length = 0;
windDirectionSeries.value.data.length = 0;
groupedReadingsList.forEach((groupedReadings) => {
const date = new Date(groupedReadings.bucket).getTime();
windMinimumSeries.value.data.push([date, groupedReadings.minimumSpeed]);
windAverageSeries.value.data.push([date, groupedReadings.averageSpeed]);
windMaximumSeries.value.data.push([date, groupedReadings.maximumSpeed]);
windDirectionSeries.value.data.push([date, ConvertWindDirectionToDegrees(groupedReadings.averageDirection)]);
});
windReady.value = true;
});
};
load();
</script>
<template>
<v-container
fluid
class="container">
<TimeRange
:time-span="timeSpan"
:start="start"
:end="end"
@change="
(value) => {
timeSpan = value.timeSpan;
start = value.start;
end = value.end;
load();
}
"
@refresh="load"></TimeRange>
<div class="content">
<v-row
dense
align="start">
<v-col
sm="4"
xl="6"
cols="12">
<ValueChart
:ready="readingsReady"
type="line"
title="Temperature"
unit="°F"
group="outdoor"
:series="[temperatureSeries]">
</ValueChart>
</v-col>
<v-col
sm="4"
xl="6"
cols="12">
<ValueChart
:ready="readingsReady"
type="line"
title="Humidity"
unit="%"
group="outdoor"
:series="[humiditySeries]">
</ValueChart>
</v-col>
<v-col
sm="4"
xl="6"
cols="12">
<ValueChart
:ready="readingsReady"
type="line"
title="Pressure"
unit='"'
group="outdoor"
:y-axis-decimal-points="1"
:series="[pressureSeries]">
</ValueChart>
</v-col>
<v-col
sm="4"
xl="6"
cols="12">
<ValueChart
:ready="readingsReady"
type="line"
title="Light"
unit=" lx"
group="outdoor"
:series="[lightSeries]">
</ValueChart>
</v-col>
<v-col
sm="4"
xl="6"
cols="12">
<ValueChart
:ready="readingsReady"
type="line"
title="Rain"
unit='"'
group="outdoor"
:stepline="true"
:y-axis-decimal-points="3"
:value-decimal-points="2"
:series="[rainSeries]">
</ValueChart>
</v-col>
<v-col
sm="4"
xl="6"
cols="12">
<ValueChart
:ready="windReady"
type="line"
title="Wind Speed"
unit=" MPH"
group="outdoor"
:y-axis-decimal-points="0"
:series="[windMaximumSeries, windAverageSeries, windMinimumSeries]">
</ValueChart>
</v-col>
<v-col
sm="4"
xl="6"
cols="12">
<ValueChart
:ready="windReady"
type="line"
title="Wind Direction"
unit=""
group="outdoor"
:tick-amount="4"
:y-axis-minimum="0"
:y-axis-maximum="360"
:y-axis-label-formatter="ConvertDegreesToShortLabel"
:y-axis-value-formatter="ConvertDegreesToShortLabel"
:series="[windDirectionSeries]">
</ValueChart>
</v-col>
</v-row>
</div>
</v-container>
</template>
<style scoped>
.container {
height: 100%;
background-color: #fafafa;
padding: 0;
}
.content {
padding: 10px;
}
</style>

View File

@@ -0,0 +1,122 @@
<script lang="ts" setup>
import { ref } from 'vue';
import { subHours } from 'date-fns';
import { usePowerStore } from '@/stores/powerStore';
import { useWeatherStore } from '@/stores/weatherStore';
import ValueChart from '@/components/ValueChart.vue';
import TimeRange from '@/components/TimeRange.vue';
import WeatherValueType from '@/models/weather/weather-value-type';
import TimeSpan from '@/models/time-span';
const powerStore = usePowerStore();
const weatherStore = useWeatherStore();
const powerReady = ref(false);
const lightReady = ref(false);
const generationSeries = ref({ name: 'Generation', data: [] as number[][] });
const consumptionSeries = ref({ name: 'Consumption', data: [] as number[][] });
const lightSeries = ref({ name: 'Average Light', data: [] as number[][] });
const end = ref(new Date());
const start = ref(subHours(end.value, 24));
const timeSpan = ref(TimeSpan.Last24Hours);
const load = () => {
powerReady.value = false;
lightReady.value = false;
powerStore.getReadingHistoryGrouped(start.value, end.value, 15).then((groupedReadingsList) => {
generationSeries.value.data.length = 0;
consumptionSeries.value.data.length = 0;
groupedReadingsList.forEach((groupedReadings) => {
const date = new Date(groupedReadings.bucket).getTime();
generationSeries.value.data.push([date, groupedReadings.averageGeneration]);
consumptionSeries.value.data.push([date, groupedReadings.averageConsumption]);
});
powerReady.value = true;
});
weatherStore.getReadingValueHistoryGrouped(WeatherValueType.Light, start.value, end.value, 15).then((groupedReadingsList) => {
lightSeries.value.data.length = 0;
groupedReadingsList.forEach((groupedReadings) => {
const date = new Date(groupedReadings.bucket).getTime();
lightSeries.value.data.push([date, groupedReadings.averageValue]);
});
lightReady.value = true;
});
};
load();
</script>
<template>
<v-container
fluid
class="container">
<TimeRange
:time-span="timeSpan"
:start="start"
:end="end"
@change="
(value) => {
timeSpan = value.timeSpan;
start = value.start;
end = value.end;
load();
}
"
@refresh="load"></TimeRange>
<div class="content">
<v-row
dense
align="start">
<v-col
sm="6"
cols="12">
<ValueChart
:ready="powerReady"
type="line"
title="Power"
unit=" W"
group="power"
:y-axis-decimal-points="0"
:value-decimal-points="0"
:series="[generationSeries, consumptionSeries]"></ValueChart>
</v-col>
<v-col
sm="6"
cols="12">
<ValueChart
:ready="lightReady"
type="line"
title="Light"
unit=" lx"
group="power"
:series="[lightSeries]">
</ValueChart>
</v-col>
</v-row>
</div>
</v-container>
</template>
<style scoped>
.container {
height: 100%;
background-color: #fafafa;
padding: 0;
}
.content {
padding: 10px;
}
</style>

View File

@@ -0,0 +1,108 @@
<script lang="ts" setup>
import { ref } from 'vue';
import { subHours } from 'date-fns';
import TimeSpan from '@/models/time-span';
import TimeRange from '@/components/TimeRange.vue';
import WeatherSummary from '@/components/WeatherSummary.vue';
const end = ref(new Date());
const start = ref(subHours(end.value, 24));
const timeSpan = ref(TimeSpan.Last24Hours);
</script>
<template>
<v-container
fluid
class="container">
<TimeRange
:time-span="timeSpan"
:start="start"
:end="end"
@change="
(value) => {
timeSpan = value.timeSpan;
start = value.start;
end = value.end;
}
"></TimeRange>
<v-card class="weather-summary">
<WeatherSummary
:start="start"
:end="end"></WeatherSummary>
</v-card>
<v-card class="main-summary">
<IndoorSummary
name="main"
title="Upstairs"
:start="start"
:end="end"></IndoorSummary>
</v-card>
<v-card class="basement-summary">
<IndoorSummary
name="basement"
title="Downstairs"
:start="start"
:end="end"></IndoorSummary>
</v-card>
</v-container>
</template>
<style scoped>
.container {
height: 100%;
background-color: #fafafa;
}
@media (min-width: 1024px) {
.container {
display: grid;
grid-template-columns: 425px max-content;
grid-template-rows: repeat(2, max-content);
gap: 15px 15px;
grid-auto-flow: row;
grid-template-areas:
'weather-summary main-summary'
'weather-summary basement-summary';
}
}
@media (max-width: 1024px) {
.container {
display: grid;
grid-template-columns: 425px;
grid-template-rows: repeat(3, max-content);
gap: 15px 0px;
grid-auto-flow: row;
grid-template-areas:
'weather-summary'
'main-summary'
'basement-summary';
}
}
@media (max-width: 768px) {
.container {
display: grid;
grid-template-columns: 1fr;
grid-template-rows: repeat(3, max-content);
gap: 15px 0px;
grid-auto-flow: row;
grid-template-areas:
'weather-summary'
'main-summary'
'basement-summary';
}
}
.weather-summary {
grid-area: weather-summary;
}
.main-summary {
grid-area: main-summary;
}
.basement-summary {
grid-area: basement-summary;
}
</style>