Skip to content

Commit

Permalink
Merge pull request #30 from Jalle19/pages
Browse files Browse the repository at this point in the history
Refactor UI state handling, add navigation, fix systemd unit
  • Loading branch information
Jalle19 authored Oct 21, 2023
2 parents 2443608 + e38a1cf commit 212ad95
Show file tree
Hide file tree
Showing 12 changed files with 137 additions and 88 deletions.
1 change: 1 addition & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@
"author": "Sam Stenvall <[email protected]>",
"license": "GPL-3.0-or-later",
"scripts": {
"postinstall": "cd webif/ && npm install",
"build": "rm -rf dist/* && npx tsc",
"build-all": "npm run build && cd webif/ && npm run build",
"prettier": "prettier --write src/ tests/",
"prettier-check": "prettier --check src/ tests/",
"lint": "eslint 'src/**/*.ts'",
Expand Down
3 changes: 2 additions & 1 deletion systemd/eachwatt.service
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ After=network.target

[Service]
WorkingDirectory=/opt/eachwatt
ExecStartPre=/usr/bin/npm run build
ExecStartPre=/usr/bin/npm install
ExecStartPre=/usr/bin/npm run build-all
ExecStart=/usr/bin/node /opt/eachwatt/dist/eachwatt.js -c /etc/eachwatt/config.yml
Restart=always
RestartSec=5
Expand Down
8 changes: 8 additions & 0 deletions webif/src/lib/stores.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { writable } from 'svelte/store'

export const configurationStore = writable({})
export const characteristicsStore = writable([])
export const mainSensorDataStore = writable([])
export const circuitSensorDataStore = writable([])
export const lastUpdateTimestampStore = writable(undefined)
export const webSocketUrlStore = writable(undefined)
90 changes: 87 additions & 3 deletions webif/src/routes/+layout.svelte
Original file line number Diff line number Diff line change
@@ -1,36 +1,109 @@
<script>
import 'purecss/build/pure.css'
import {
configurationStore,
characteristicsStore,
mainSensorDataStore,
circuitSensorDataStore,
lastUpdateTimestampStore,
webSocketUrlStore
} from '../lib/stores'
import { onMount } from 'svelte'
import { determineWebSocketUrl } from '../lib/websocket'
const parseTimestamp = (sensorData) => {
return new Date(sensorData[0].timestamp)
}
onMount(() => {
// Determine WebSocket URL from URL parameters
$webSocketUrlStore = determineWebSocketUrl()
const ws = new WebSocket($webSocketUrlStore)
ws.addEventListener('open', () => {
console.log(`Connected to WebSocket at ${$webSocketUrlStore}`)
})
ws.addEventListener('message', (event) => {
const data = event.data
const message = JSON.parse(data)
// Parse last update timestamp from sensor data messages
switch (message.type) {
case 'characteristicsSensorData':
case 'powerSensorData':
$lastUpdateTimestampStore = parseTimestamp(message.data)
break
}
// Handle each message type
switch (message.type) {
case 'characteristicsSensorData':
$characteristicsStore = message.data
break
case 'powerSensorData':
$mainSensorDataStore = message.data.filter((d) => {
// Filter out unmetered
return d.circuit.type === 'main' && d.circuit.sensor.type !== 'unmetered'
})
$circuitSensorDataStore = message.data
break
case 'configuration':
$configurationStore = message.data
break
}
})
})
</script>
<svelte:head>
<title>EachWatt</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
</svelte:head>
<div class="pure-g container">
<div class="pure-u-1-1 l-box">
<nav class="pure-menu pure-menu-horizontal">
<ul class="pure-menu-list">
<li class="pure-menu-item">
<a href="/" class="pure-menu-link">Dashboard</a>
</li>
<li class="pure-menu-item">
<a href="/configuration" class="pure-menu-link">Configuration</a>
</li>
</ul>
</nav>
</div>

<slot />
</div>

<style>
:root {
--background: #fff;
--color: #222;
--table-background: #e0e0e0;
--component-background: #e0e0e0;
--highlight-color: #ff3d00;
}
@media (prefers-color-scheme: dark){
:root {
--background: #272727;
--color: #aaa;
--table-background: #3b3b3b;
--component-background: #3b3b3b;
--highlight-color: #ff3d00;
}
nav {
background-color: var(--component-background);
}
/* pure-table overrides */
:global(.pure-table) {
border: 2px solid #424242;
}
:global(.pure-table thead) {
background-color: var(--table-background);
background-color: var(--component-background);
color: var(--color);
}
Expand Down Expand Up @@ -77,4 +150,15 @@
:global(.l-box) {
padding: 1em;
}
/* pure-menu tweaks */
:global(.pure-menu-link) {
border-bottom: 2px solid var(--component-background);
}
:global(.pure-menu-link:hover) {
border-bottom: 2px solid var(--highlight-color);
background: inherit !important;
}
/* end pure-menu tweaks */
</style>
69 changes: 10 additions & 59 deletions webif/src/routes/+page.svelte
Original file line number Diff line number Diff line change
@@ -1,63 +1,14 @@
<script>
import { onMount } from 'svelte'
import { determineWebSocketUrl } from '$lib/websocket'
import {
lastUpdateTimestampStore,
webSocketUrlStore
} from '../lib/stores'
import LastUpdate from './LastUpdate.svelte'
import Characteristics from './Characteristics.svelte'
import MainsPower from './MainsPower.svelte'
import Circuits from './Circuits.svelte'
import Loader from './Loader.svelte'
let webSocketUrl
let lastUpdateTimestamp
let characteristicsSensorData
let mainsSensorData
let circuitSensorData
const parseTimestamp = (sensorData) => {
return new Date(sensorData[0].timestamp)
}
onMount(() => {
// Determine WebSocket URL from URL parameters
webSocketUrl = determineWebSocketUrl()
const ws = new WebSocket(webSocketUrl)
ws.addEventListener('open', () => {
console.log(`Connected to WebSocket at ${webSocketUrl}`)
})
ws.addEventListener('message', (event) => {
const data = event.data
const message = JSON.parse(data)
// Parse last update timestamp from sensor data messages
switch (message.type) {
case 'characteristicsSensorData':
case 'powerSensorData':
lastUpdateTimestamp = parseTimestamp(message.data)
break
}
// Handle each message type
switch (message.type) {
case 'characteristicsSensorData':
characteristicsSensorData = message.data
break
case 'powerSensorData':
mainsSensorData = message.data.filter((d) => {
// Filter out unmetered
return d.circuit.type === 'main' && d.circuit.sensor.type !== 'unmetered'
})
circuitSensorData = message.data
break
case 'configuration':
// configuration = message.data
break
}
})
})
</script>

<style>
Expand All @@ -66,24 +17,24 @@
}
</style>

{#if lastUpdateTimestamp === undefined}
{#if $lastUpdateTimestampStore === undefined}
<div class="pure-u-1-8 l-box">
<Loader />
</div>
<div class="pure-u-7-8 l-box">
<p class="connecting">Connecting to {webSocketUrl}</p>
<p class="connecting">Connecting to {$webSocketUrlStore}</p>
</div>
{:else}
<div class="pure-u-1-1 l-box">
<LastUpdate {lastUpdateTimestamp} {webSocketUrl} />
<LastUpdate />
</div>
<div class="pure-u-1-1 l-box">
<Characteristics sensorData={characteristicsSensorData} />
<Characteristics />
</div>
<div class="pure-u-1-1 l-box">
<MainsPower sensorData={mainsSensorData} />
<MainsPower />
</div>
<div class="pure-u-1-1 l-box">
<Circuits sensorData={circuitSensorData} />
<Circuits />
</div>
{/if}
4 changes: 2 additions & 2 deletions webif/src/routes/Characteristics.svelte
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<script>
export let sensorData = []
import { characteristicsStore } from '../lib/stores'
</script>

<h2>Characteristics</h2>
Expand All @@ -13,7 +13,7 @@
</tr>
</thead>
<tbody>
{#each sensorData as data}
{#each $characteristicsStore as data}
<tr>
<td>{data.characteristics.name}</td>
<td>{data.characteristics.phase}</td>
Expand Down
5 changes: 2 additions & 3 deletions webif/src/routes/Circuits.svelte
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
<script>
import { circuitSensorDataStore } from '../lib/stores'
import { formatPf } from '../lib/format'
export let sensorData = []
</script>

<h2>All circuits</h2>
Expand All @@ -19,7 +18,7 @@
</tr>
</thead>
<tbody>
{#each sensorData as data}
{#each $circuitSensorDataStore as data}
<tr>
<td>{data.circuit.name}</td>
<td>{data.circuit.group ?? ''}</td>
Expand Down
15 changes: 0 additions & 15 deletions webif/src/routes/Configuration.svelte

This file was deleted.

4 changes: 2 additions & 2 deletions webif/src/routes/LastUpdate.svelte
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<script>
export let lastUpdateTimestamp, webSocketUrl
import { lastUpdateTimestampStore, webSocketUrlStore } from '../lib/stores'
</script>

<style>
Expand All @@ -9,5 +9,5 @@
</style>

<p>
Last update: {lastUpdateTimestamp?.toISOString()}, connected to {webSocketUrl}
Last update: {$lastUpdateTimestampStore?.toISOString()}, connected to {$webSocketUrlStore}
</p>
6 changes: 3 additions & 3 deletions webif/src/routes/MainsPower.svelte
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
<script>
export let sensorData = []
import { mainSensorDataStore} from '../lib/stores'
</script>

<div class="mains-power-cards">
{#each sensorData as data}
{#each $mainSensorDataStore as data}
<div class="mains-power-card">
<h4>{data.circuit.name}</h4>
<span>{data.power}W</span>
Expand All @@ -22,7 +22,7 @@
.mains-power-cards {
padding: 0.8em;
box-sizing: border-box;
background-color: var(--table-background);
background-color: var(--component-background);
margin-bottom: 1em;
}
Expand Down
18 changes: 18 additions & 0 deletions webif/src/routes/configuration/+page.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<script>
import { configurationStore } from '../../lib/stores'
</script>

<div class="pure-u-1-1 l-box">
<h2>Configuration</h2>
<pre id="configuration">{$configurationStore}</pre>
</div>

<style>
pre {
padding: 0.8em;
box-sizing: border-box;
background-color: var(--component-background);
overflow: hidden;
}
</style>

0 comments on commit 212ad95

Please sign in to comment.