mirror of
https://github.com/KevinMidboe/hivemonitor.git
synced 2025-10-29 01:20:25 +00:00
Hive & gateway elements that update live from message queues
This commit is contained in:
50
src/lib/components/GatewaySummary.svelte
Normal file
50
src/lib/components/GatewaySummary.svelte
Normal file
@@ -0,0 +1,50 @@
|
||||
<script lang="ts">
|
||||
import { onMount } from 'svelte';
|
||||
import { gatewayMessageQueue } from '$lib/store';
|
||||
import { formatTemperature, formatBattery, diffTime } from '$lib/telemetryFormatters';
|
||||
|
||||
import NetworkIcon from '$lib/icons/network.svelte';
|
||||
import SyncIcon from '$lib/icons/Sync.svelte';
|
||||
import ThermometerIcon from '$lib/icons/thermometer.svelte';
|
||||
import BatteryIcon from '$lib/icons/Battery.svelte';
|
||||
import Card from './Card.svelte';
|
||||
import GatewayModal from './modals/GatewayModal.svelte';
|
||||
import type { IGatewayTelemetry } from '$lib/interfaces/ITelemetry';
|
||||
|
||||
let gateways: IGatewayTelemetry[] = [];
|
||||
let sinceUpdate = 0;
|
||||
let interval: number;
|
||||
|
||||
function updateGateways(telemetry: IGatewayTelemetry) {
|
||||
if (interval) clearInterval(interval);
|
||||
sinceUpdate = 0;
|
||||
|
||||
const hiveName = telemetry?.gateway_name;
|
||||
if (!hiveName) return;
|
||||
sinceUpdate = diffTime(new Date(telemetry?.t));
|
||||
|
||||
let hiveIndex = gateways.findIndex((g) => g.gateway_name === hiveName);
|
||||
if (hiveIndex >= 0) gateways[hiveIndex] = telemetry;
|
||||
else gateways.push(telemetry);
|
||||
|
||||
gateways = gateways.sort((a, b) => (a.gateway_name > b.gateway_name ? 1 : -1));
|
||||
interval = setInterval(() => (sinceUpdate = Math.floor(sinceUpdate + 1)), 1000);
|
||||
}
|
||||
|
||||
onMount(() => gatewayMessageQueue.subscribe(updateGateways));
|
||||
</script>
|
||||
|
||||
{#each gateways as gateway}
|
||||
<Card title={gateway.gateway_name} opens={GatewayModal} data={gateway}>
|
||||
<NetworkIcon slot="logo" />
|
||||
|
||||
<ThermometerIcon slot="first-icon" />
|
||||
<span slot="first-value">{formatTemperature(gateway?.temperature)}°C</span>
|
||||
|
||||
<SyncIcon slot="second-icon" />
|
||||
<span slot="second-value">{sinceUpdate} s</span>
|
||||
|
||||
<BatteryIcon slot="third-icon" />
|
||||
<span slot="third-value">{formatBattery(gateway?.battery_level)} V</span>
|
||||
</Card>
|
||||
{/each}
|
||||
56
src/lib/components/HiveSummary.svelte
Normal file
56
src/lib/components/HiveSummary.svelte
Normal file
@@ -0,0 +1,56 @@
|
||||
<script lang="ts">
|
||||
import { onMount } from 'svelte';
|
||||
import { hiveMessageQueue } from '$lib/store';
|
||||
import {
|
||||
formatWeight,
|
||||
formatTemperature,
|
||||
formatHumidity,
|
||||
diffTime
|
||||
} from '$lib/telemetryFormatters';
|
||||
|
||||
import HiveLogo from '$lib/icons/hive.svelte';
|
||||
import WeightLogo from '$lib/icons/weight.svelte';
|
||||
import ThermometerIcon from '$lib/icons/thermometer.svelte';
|
||||
import HumidityLogo from '$lib/icons/humidity.svelte';
|
||||
import Card from './Card.svelte';
|
||||
import HiveModal from './modals/HiveModal.svelte';
|
||||
import type { IHiveTelemetry } from '$lib/interfaces/ITelemetry';
|
||||
|
||||
let sinceUpdate = 0;
|
||||
let interval: number;
|
||||
let hives: IHiveTelemetry[] = [];
|
||||
|
||||
function updateHives(telemetry: IHiveTelemetry) {
|
||||
if (interval) clearInterval(interval);
|
||||
|
||||
const hiveName = telemetry?.hive_name;
|
||||
if (!hiveName) return;
|
||||
sinceUpdate = diffTime(new Date(telemetry?.t));
|
||||
|
||||
let hiveIndex = hives.findIndex((h) => h.hive_name === hiveName);
|
||||
if (hiveIndex >= 0) hives[hiveIndex] = telemetry;
|
||||
else hives.push(telemetry);
|
||||
|
||||
hives = hives.sort((a, b) => (a.hive_name > b.hive_name ? 1 : -1));
|
||||
interval = setInterval(() => (sinceUpdate = Number((sinceUpdate + 0.1).toFixed(1))), 100);
|
||||
}
|
||||
|
||||
onMount(() => hiveMessageQueue.subscribe(updateHives));
|
||||
</script>
|
||||
|
||||
{#each hives as hive}
|
||||
<Card title={hive.hive_name} opens={HiveModal} data={hive}>
|
||||
<HiveLogo slot="logo" />
|
||||
|
||||
<WeightLogo slot="first-icon" />
|
||||
<span slot="first-value">{formatWeight(hive?.weight)}kg</span>
|
||||
|
||||
<ThermometerIcon slot="second-icon" />
|
||||
<span slot="second-value">{formatTemperature(hive?.temperature)}°C</span>
|
||||
|
||||
<HumidityLogo slot="third-icon" />
|
||||
<span slot="third-value">{formatHumidity(hive?.humidity)}%</span>
|
||||
</Card>
|
||||
{/each}
|
||||
|
||||
<p style="text-align: right; margin-top: 0">{sinceUpdate} s since last update</p>
|
||||
17
src/lib/store.ts
Normal file
17
src/lib/store.ts
Normal file
@@ -0,0 +1,17 @@
|
||||
import { derived, writable } from 'svelte/store';
|
||||
import type { Writable } from 'svelte/store';
|
||||
import type IModal from '$lib/interfaces/IModal';
|
||||
import type { IGatewayTelemetry, IHiveTelemetry } from './interfaces/ITelemetry';
|
||||
|
||||
// message queues
|
||||
export const hiveMessageQueue: Writable<IHiveTelemetry> = writable();
|
||||
export const gatewayMessageQueue: Writable<IGatewayTelemetry> = writable();
|
||||
|
||||
// setters
|
||||
export const addHiveMessage = (msg: IHiveTelemetry) => hiveMessageQueue.set(msg);
|
||||
export const addGatewayMessageQueue = (msg: IGatewayTelemetry) => gatewayMessageQueue.set(msg);
|
||||
|
||||
// modal state
|
||||
export const modal: Writable<IModal | null> = writable(null);
|
||||
export const modalOpen = derived(modal, ($modal) => $modal != null);
|
||||
export const resetModal = () => modal.set(null);
|
||||
Reference in New Issue
Block a user