Updates to Svelte UI

This commit is contained in:
Gunnar Skjold 2022-09-12 07:29:25 +02:00
parent 04cd6ac387
commit 95d3008a66
13 changed files with 551 additions and 11 deletions

View File

@ -9,11 +9,13 @@
"version": "0.0.0",
"devDependencies": {
"@sveltejs/vite-plugin-svelte": "^1.0.1",
"@tailwindcss/forms": "^0.5.2",
"autoprefixer": "^10.4.7",
"http-proxy-middleware": "^2.0.1",
"postcss": "^8.4.14",
"postcss-load-config": "^4.0.1",
"svelte": "^3.49.0",
"svelte-navigator": "^3.2.2",
"svelte-preprocess": "^4.10.7",
"tailwindcss": "^3.1.5",
"vite": "^3.0.7"
@ -110,6 +112,18 @@
}
}
},
"node_modules/@tailwindcss/forms": {
"version": "0.5.3",
"resolved": "https://registry.npmjs.org/@tailwindcss/forms/-/forms-0.5.3.tgz",
"integrity": "sha512-y5mb86JUoiUgBjY/o6FJSFZSEttfb3Q5gllE4xoKjAAD+vBrnIhE4dViwUuow3va8mpH4s9jyUbUbrRGoRdc2Q==",
"dev": true,
"dependencies": {
"mini-svg-data-uri": "^1.2.3"
},
"peerDependencies": {
"tailwindcss": ">=3.0.0 || >= 3.0.0-alpha.1"
}
},
"node_modules/@types/http-proxy": {
"version": "1.17.9",
"resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.9.tgz",
@ -403,6 +417,12 @@
}
}
},
"node_modules/dedent-js": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/dedent-js/-/dedent-js-1.0.1.tgz",
"integrity": "sha512-OUepMozQULMLUmhxS95Vudo0jb0UchLimi3+pQ2plj61Fcy8axbP9hbiD4Sz6DPqn6XG3kfmziVfQ1rSys5AJQ==",
"dev": true
},
"node_modules/deepmerge": {
"version": "4.2.2",
"resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz",
@ -1141,6 +1161,15 @@
"node": ">=10"
}
},
"node_modules/lower-case": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz",
"integrity": "sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==",
"dev": true,
"dependencies": {
"tslib": "^2.0.3"
}
},
"node_modules/magic-string": {
"version": "0.26.3",
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.26.3.tgz",
@ -1184,6 +1213,15 @@
"node": ">=4"
}
},
"node_modules/mini-svg-data-uri": {
"version": "1.4.4",
"resolved": "https://registry.npmjs.org/mini-svg-data-uri/-/mini-svg-data-uri-1.4.4.tgz",
"integrity": "sha512-r9deDe9p5FJUPZAk3A59wGH7Ii9YrjjWw0jmw/liSbHl2CHiyXj6FcDXDu2K3TjVAXqiJdaw3xxwlZZr9E6nHg==",
"dev": true,
"bin": {
"mini-svg-data-uri": "cli.js"
}
},
"node_modules/minimatch": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
@ -1232,6 +1270,16 @@
"node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
}
},
"node_modules/no-case": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz",
"integrity": "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==",
"dev": true,
"dependencies": {
"lower-case": "^2.0.2",
"tslib": "^2.0.3"
}
},
"node_modules/node-releases": {
"version": "2.0.6",
"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.6.tgz",
@ -1274,6 +1322,16 @@
"wrappy": "1"
}
},
"node_modules/pascal-case": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/pascal-case/-/pascal-case-3.1.2.tgz",
"integrity": "sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==",
"dev": true,
"dependencies": {
"no-case": "^3.0.4",
"tslib": "^2.0.3"
}
},
"node_modules/path-is-absolute": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
@ -1666,6 +1724,19 @@
"svelte": ">=3.19.0"
}
},
"node_modules/svelte-navigator": {
"version": "3.2.2",
"resolved": "https://registry.npmjs.org/svelte-navigator/-/svelte-navigator-3.2.2.tgz",
"integrity": "sha512-Xio4ohLUG1nQJ+ENNbLphXXu9L189fnI1WGg+2Q3CIMPe8Jm2ipytKQthdBs8t0mN7p3Eb03SE9hq0xZAqwQNQ==",
"dev": true,
"hasInstallScript": true,
"dependencies": {
"svelte2tsx": "^0.1.151"
},
"peerDependencies": {
"svelte": "3.x"
}
},
"node_modules/svelte-preprocess": {
"version": "4.10.7",
"resolved": "https://registry.npmjs.org/svelte-preprocess/-/svelte-preprocess-4.10.7.tgz",
@ -1741,6 +1812,20 @@
"sourcemap-codec": "^1.4.8"
}
},
"node_modules/svelte2tsx": {
"version": "0.1.193",
"resolved": "https://registry.npmjs.org/svelte2tsx/-/svelte2tsx-0.1.193.tgz",
"integrity": "sha512-vzy4YQNYDnoqp2iZPnJy7kpPAY6y121L0HKrSBjU/IWW7DQ6T7RMJed2VVHFmVYm0zAGYMDl9urPc6R4DDUyhg==",
"dev": true,
"dependencies": {
"dedent-js": "^1.0.1",
"pascal-case": "^3.1.1"
},
"peerDependencies": {
"svelte": "^3.24",
"typescript": "^4.1.2"
}
},
"node_modules/tailwindcss": {
"version": "3.1.8",
"resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.1.8.tgz",
@ -1831,6 +1916,26 @@
"node": ">=8.0"
}
},
"node_modules/tslib": {
"version": "2.4.0",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz",
"integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==",
"dev": true
},
"node_modules/typescript": {
"version": "4.8.2",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.8.2.tgz",
"integrity": "sha512-C0I1UsrrDHo2fYI5oaCGbSejwX4ch+9Y5jTQELvovfmFkK3HHSZJB8MSJcWLmCUBzQBchCrZ9rMRV6GuNrvGtw==",
"dev": true,
"peer": true,
"bin": {
"tsc": "bin/tsc",
"tsserver": "bin/tsserver"
},
"engines": {
"node": ">=4.2.0"
}
},
"node_modules/update-browserslist-db": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.6.tgz",
@ -1987,6 +2092,15 @@
"svelte-hmr": "^0.14.12"
}
},
"@tailwindcss/forms": {
"version": "0.5.3",
"resolved": "https://registry.npmjs.org/@tailwindcss/forms/-/forms-0.5.3.tgz",
"integrity": "sha512-y5mb86JUoiUgBjY/o6FJSFZSEttfb3Q5gllE4xoKjAAD+vBrnIhE4dViwUuow3va8mpH4s9jyUbUbrRGoRdc2Q==",
"dev": true,
"requires": {
"mini-svg-data-uri": "^1.2.3"
}
},
"@types/http-proxy": {
"version": "1.17.9",
"resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.9.tgz",
@ -2185,6 +2299,12 @@
"ms": "2.1.2"
}
},
"dedent-js": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/dedent-js/-/dedent-js-1.0.1.tgz",
"integrity": "sha512-OUepMozQULMLUmhxS95Vudo0jb0UchLimi3+pQ2plj61Fcy8axbP9hbiD4Sz6DPqn6XG3kfmziVfQ1rSys5AJQ==",
"dev": true
},
"deepmerge": {
"version": "4.2.2",
"resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz",
@ -2633,6 +2753,15 @@
"integrity": "sha512-9JROoBW7pobfsx+Sq2JsASvCo6Pfo6WWoUW79HuB1BCoBXD4PLWJPqDF6fNj67pqBYTbAHkE57M1kS/+L1neOg==",
"dev": true
},
"lower-case": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz",
"integrity": "sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==",
"dev": true,
"requires": {
"tslib": "^2.0.3"
}
},
"magic-string": {
"version": "0.26.3",
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.26.3.tgz",
@ -2664,6 +2793,12 @@
"integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==",
"dev": true
},
"mini-svg-data-uri": {
"version": "1.4.4",
"resolved": "https://registry.npmjs.org/mini-svg-data-uri/-/mini-svg-data-uri-1.4.4.tgz",
"integrity": "sha512-r9deDe9p5FJUPZAk3A59wGH7Ii9YrjjWw0jmw/liSbHl2CHiyXj6FcDXDu2K3TjVAXqiJdaw3xxwlZZr9E6nHg==",
"dev": true
},
"minimatch": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
@ -2700,6 +2835,16 @@
"integrity": "sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==",
"dev": true
},
"no-case": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz",
"integrity": "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==",
"dev": true,
"requires": {
"lower-case": "^2.0.2",
"tslib": "^2.0.3"
}
},
"node-releases": {
"version": "2.0.6",
"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.6.tgz",
@ -2733,6 +2878,16 @@
"wrappy": "1"
}
},
"pascal-case": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/pascal-case/-/pascal-case-3.1.2.tgz",
"integrity": "sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==",
"dev": true,
"requires": {
"no-case": "^3.0.4",
"tslib": "^2.0.3"
}
},
"path-is-absolute": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
@ -2973,6 +3128,15 @@
"dev": true,
"requires": {}
},
"svelte-navigator": {
"version": "3.2.2",
"resolved": "https://registry.npmjs.org/svelte-navigator/-/svelte-navigator-3.2.2.tgz",
"integrity": "sha512-Xio4ohLUG1nQJ+ENNbLphXXu9L189fnI1WGg+2Q3CIMPe8Jm2ipytKQthdBs8t0mN7p3Eb03SE9hq0xZAqwQNQ==",
"dev": true,
"requires": {
"svelte2tsx": "^0.1.151"
}
},
"svelte-preprocess": {
"version": "4.10.7",
"resolved": "https://registry.npmjs.org/svelte-preprocess/-/svelte-preprocess-4.10.7.tgz",
@ -2998,6 +3162,16 @@
}
}
},
"svelte2tsx": {
"version": "0.1.193",
"resolved": "https://registry.npmjs.org/svelte2tsx/-/svelte2tsx-0.1.193.tgz",
"integrity": "sha512-vzy4YQNYDnoqp2iZPnJy7kpPAY6y121L0HKrSBjU/IWW7DQ6T7RMJed2VVHFmVYm0zAGYMDl9urPc6R4DDUyhg==",
"dev": true,
"requires": {
"dedent-js": "^1.0.1",
"pascal-case": "^3.1.1"
}
},
"tailwindcss": {
"version": "3.1.8",
"resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.1.8.tgz",
@ -3055,6 +3229,19 @@
"is-number": "^7.0.0"
}
},
"tslib": {
"version": "2.4.0",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz",
"integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==",
"dev": true
},
"typescript": {
"version": "4.8.2",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.8.2.tgz",
"integrity": "sha512-C0I1UsrrDHo2fYI5oaCGbSejwX4ch+9Y5jTQELvovfmFkK3HHSZJB8MSJcWLmCUBzQBchCrZ9rMRV6GuNrvGtw==",
"dev": true,
"peer": true
},
"update-browserslist-db": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.6.tgz",

View File

@ -10,13 +10,15 @@
},
"devDependencies": {
"@sveltejs/vite-plugin-svelte": "^1.0.1",
"svelte": "^3.49.0",
"vite": "^3.0.7",
"autoprefixer": "^10.4.7",
"http-proxy-middleware": "^2.0.1",
"postcss": "^8.4.14",
"postcss-load-config": "^4.0.1",
"svelte": "^3.49.0",
"svelte-navigator": "^3.2.2",
"svelte-preprocess": "^4.10.7",
"autoprefixer": "^10.4.7",
"tailwindcss": "^3.1.5",
"http-proxy-middleware": "^2.0.1"
"@tailwindcss/forms": "^0.5.2",
"vite": "^3.0.7"
}
}

View File

@ -1,7 +1,10 @@
<script>
import { Router, Route } from "svelte-navigator";
import { dataStore } from './lib/DataStores.js';
import Header from './lib/Header.svelte';
import Dashboard from './lib/Dashboard.svelte';
import ConfigurationPanel from './lib/ConfigurationPanel.svelte';
let data = {};
dataStore.subscribe(update => {
@ -10,6 +13,14 @@
</script>
<div class="container mx-auto m-3">
<Header data={data}/>
<Dashboard data={data}/>
<Router>
<Header data={data}/>
<Route path="/">
<Dashboard data={data}/>
</Route>
<Route path="/configuration">
<ConfigurationPanel/>
</Route>
</Router>
</div>

View File

@ -0,0 +1,212 @@
<script>
</script>
<div class="grid xl:grid-cols-4 lg:grid-cols-2 md:grid-cols-2">
<div class="bg-white m-2 p-2 rounded-md shadow-lg pb-4 text-gray-700">
<strong class="text-sm">General</strong>
<div class="my-3">
Timezone<br/>
<select class="h-10 rounded-md shadow-sm border-gray-300">
<option value="Europe/Oslo">Europe/Oslo</option>
</select>
</div>
<div class="my-3">
Hostname<br/>
<input type="text" class="h-10 rounded-md shadow-sm border-gray-300 w-full"/>
</div>
<div class="my-3">
Security<br/>
<select class="h-10 rounded-md shadow-sm border-gray-300">
<option value="">None</option>
<option value="">Only configuration</option>
<option value="">Everything</option>
</select>
</div>
<div class="my-3">
Username<br/>
<input type="text" class="h-10 rounded-md shadow-sm border-gray-300 w-full"/>
</div>
<div class="my-3">
Password<br/>
<input type="text" class="h-10 rounded-md shadow-sm border-gray-300 w-full"/>
</div>
</div>
<div class="bg-white m-2 p-2 rounded-md shadow-lg pb-4 text-gray-700">
<strong class="text-sm">Meter</strong>
<div class="my-3">
<span>Serial configuration</span>
<div class="flex">
<select class="h-10 rounded-l-md shadow-sm border-r-0 border-gray-300">
<option value="">UART0</option>
<option value="">UART1</option>
<option value="">UART2</option>
<option value="">GPIO33</option>
</select>
<select class="h-10 shadow-sm border-gray-300">
<option value="2400">2400</option>
<option value="4800">4800</option>
<option value="9600">9600</option>
<option value="19200">19200</option>
<option value="38400">38400</option>
<option value="57600">57600</option>
<option value="115200">115200</option>
</select>
<select class="h-10 rounded-r-md shadow-sm border-l-0 border-gray-300">
<option value="2">7N1</option>
<option value="3">8N1</option>
<option value="10">7E1</option>
<option value="11">8E1</option>
</select>
</div>
<label><input type="checkbox" class="rounded"/> inverted</label>
</div>
<div class="grid grid-cols-2">
<div class="mb-1.5 col-span-2">
Distribution<br/>
<select class="h-10 rounded-md shadow-sm border-gray-300 w-full">
<option value="0"></option>
<option value="1">IT or TT (230V)</option>
<option value="2">TN (400V)</option>
</select>
</div>
<div class="my-1.5 mr-2">
Main fuse<br/>
<label class="flex">
<input type="number" min="5" max="255" class="h-10 rounded-l-md shadow-sm border-gray-300 w-full"/>
<div class="flex -mr-px">
<span class="flex items-center bg-gray-100 rounded-r-md border border-l-0 border-gray-300 px-3 whitespace-no-wrap text-grey-dark text-sm">A</span>
</div>
</label>
</div>
<div class="my-1.5">
Production<br/>
<label class="flex">
<input type="number" min="0" max="255" class="h-10 rounded-l-md shadow-sm border-gray-300 w-full"/>
<div class="flex">
<span class="flex items-center bg-gray-100 rounded-r-md border border-l-0 border-gray-300 px-3 whitespace-no-wrap text-grey-dark text-sm">kWp</span>
</div>
</label>
</div>
</div>
<div class="my-3">
Encryption key<br/>
<input type="text" class="h-10 rounded-md shadow-sm border-gray-300 w-full"/>
</div>
<div class="my-3">
Authentication key<br/>
<input type="text" class="h-10 rounded-md shadow-sm border-gray-300 w-full"/>
</div>
</div>
<div class="bg-white m-2 p-2 rounded-md shadow-lg pb-4 text-gray-700">
<strong class="text-sm">WiFi</strong>
<div class="my-3">
SSID<br/>
<input type="text" class="h-10 rounded-md shadow-sm border-gray-300 w-full"/>
</div>
<div class="my-3">
PSK<br/>
<input type="text" class="h-10 rounded-md shadow-sm border-gray-300 w-full"/>
</div>
<div>
Power<br/>
<label class="flex">
<input type="number" min="0" max="19.5" step="0.5" class="h-10 rounded-l-md shadow-sm border-gray-300"/>
<div class="flex -mr-px">
<span class="flex items-center bg-gray-100 rounded-r-md border border-l-0 border-gray-300 px-3 whitespace-no-wrap text-grey-dark text-sm">dBm</span>
</div>
</label>
</div>
</div>
<div class="bg-white m-2 p-2 rounded-md shadow-lg pb-4 text-gray-700">
<strong class="text-sm">Network</strong>
<div class="my-3">
IP<br/>
<div class="flex">
<select class="h-10 rounded-l-md shadow-sm border-r-0 border-gray-300">
<option>DHCP</option>
<option>Static</option>
</select>
<input type="text" class="h-10 shadow-sm border-gray-300 w-full"/>
<select class="h-10 rounded-r-md shadow-sm border-l-0 border-gray-300">
<option>/24</option>
</select>
</div>
</div>
<div class="my-3">
Gateway<br/>
<input type="text" class="h-10 rounded-md shadow-sm border-gray-300 w-full"/>
</div>
<div class="my-3">
DNS<br/>
<div class="flex">
<input type="text" class="h-10 rounded-l-md shadow-sm border-gray-300 w-full"/>
<input type="text" class="h-10 rounded-r-md shadow-sm border-l-0 border-gray-300 w-full"/>
</div>
<label><input type="checkbox" class="rounded"/> enable mDNS</label>
</div>
<div class="my-3">
NTP<br/>
<div class="flex">
<input type="text" class="h-10 rounded-l-md shadow-sm border-gray-300 w-full"/>
<input type="text" class="h-10 rounded-r-md shadow-sm border-l-0 border-gray-300 w-full"/>
</div>
<label><input type="checkbox" class="rounded"/> obtain from DHCP</label>
</div>
</div>
<div class="bg-white m-2 p-2 rounded-md shadow-lg pb-4 text-gray-700">
<strong class="text-sm">MQTT</strong>
<div class="my-3">
Server<br/>
<div class="flex">
<input type="text" class="h-10 rounded-l-md shadow-sm border-gray-300 w-full"/>
<input type="text" class="h-10 rounded-r-md shadow-sm border-l-0 border-gray-300 w-20"/>
</div>
</div>
<div class="my-3">
Username<br/>
<input type="text" class="h-10 rounded-md shadow-sm border-gray-300 w-full"/>
</div>
<div class="my-3">
Password<br/>
<input type="text" class="h-10 rounded-md shadow-sm border-gray-300 w-full"/>
</div>
<div class="my-3">
Client ID<br/>
<input type="text" class="h-10 rounded-md shadow-sm border-gray-300 w-full"/>
</div>
<div class="my-3">
Publish topic<br/>
<div class="flex">
<input type="text" class="h-10 rounded-l-md shadow-sm border-gray-300 w-full"/>
<select class="h-10 rounded-r-md shadow-sm border-l-0 border-gray-300">
<option>JSON</option>
</select>
</div>
</div>
<div class="my-3">
SSL
</div>
</div>
<div class="bg-white m-2 p-2 rounded-md shadow-lg pb-4 text-gray-700">
<strong class="text-sm">Prices</strong>
</div>
<div class="bg-white m-2 p-2 rounded-md shadow-lg pb-4 text-gray-700">
<strong class="text-sm">Webhook</strong>
</div>
<div class="bg-white m-2 p-2 rounded-md shadow-lg pb-4 text-gray-700">
<strong class="text-sm">Backup and restore</strong>
</div>
<div class="bg-white m-2 p-2 rounded-md shadow-lg pb-4 text-gray-700">
<strong class="text-sm">Debugging</strong>
</div>
<div class="bg-white m-2 p-2 rounded-md shadow-lg pb-4 text-gray-700">
<strong class="text-sm">Vendor menu</strong>
Board type<br/>
GPIO<br/>
Vcc<br/>
Favico<br/>
</div>
</div>

View File

@ -0,0 +1,7 @@
<script></script>
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-6 h-6">
<path stroke-linecap="round" stroke-linejoin="round" d="M10.343 3.94c.09-.542.56-.94 1.11-.94h1.093c.55 0 1.02.398 1.11.94l.149.894c.07.424.384.764.78.93.398.164.855.142 1.205-.108l.737-.527a1.125 1.125 0 011.45.12l.773.774c.39.389.44 1.002.12 1.45l-.527.737c-.25.35-.272.806-.107 1.204.165.397.505.71.93.78l.893.15c.543.09.94.56.94 1.109v1.094c0 .55-.397 1.02-.94 1.11l-.893.149c-.425.07-.765.383-.93.78-.165.398-.143.854.107 1.204l.527.738c.32.447.269 1.06-.12 1.45l-.774.773a1.125 1.125 0 01-1.449.12l-.738-.527c-.35-.25-.806-.272-1.203-.107-.397.165-.71.505-.781.929l-.149.894c-.09.542-.56.94-1.11.94h-1.094c-.55 0-1.019-.398-1.11-.94l-.148-.894c-.071-.424-.384-.764-.781-.93-.398-.164-.854-.142-1.204.108l-.738.527c-.447.32-1.06.269-1.45-.12l-.773-.774a1.125 1.125 0 01-.12-1.45l.527-.737c.25-.35.273-.806.108-1.204-.165-.397-.505-.71-.93-.78l-.894-.15c-.542-.09-.94-.56-.94-1.109v-1.094c0-.55.398-1.02.94-1.11l.894-.149c.424-.07.765-.383.93-.78.165-.398.143-.854-.107-1.204l-.527-.738a1.125 1.125 0 01.12-1.45l.773-.773a1.125 1.125 0 011.45-.12l.737.527c.35.25.807.272 1.204.107.397-.165.71-.505.78-.929l.15-.894z" />
<path stroke-linecap="round" stroke-linejoin="round" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z" />
</svg>

View File

@ -1,7 +1,10 @@
<script>
import { Link } from "svelte-navigator";
import GitHubLogo from './../assets/github.svg';
import Uptime from "./Uptime.svelte";
import Badge from './Badge.svelte';
import Clock from './Clock.svelte';
import GearIcon from './GearIcon.svelte';
export let data = {}
let timestamp = new Date(0);
@ -10,10 +13,10 @@
<nav class="bg-violet-600 p-1 rounded-md mx-2">
<div class="flex flex-wrap space-x-4 text-sm text-gray-300">
<div class="flex-none text-lg text-gray-100 p-2">
<a href="/">AMS reader <span>v0.0.0</span></a>
<Link to="/">AMS reader <span>v0.0.0</span></Link>
</div>
<div class="flex-none my-auto p-2 flex space-x-4">
<div class="flex-none my-auto">Up { data.u ? data.u : '-' }</div>
<div class="flex-none my-auto"><Uptime epoch={data.u}/></div>
<div class="flex-none my-auto">{ data.t ? data.t.toFixed(1) : '-' }&deg;C</div>
<div class="flex-none my-auto">Free mem: {data.m ? (data.m/1000).toFixed(1) : '-'}kb</div>
</div>
@ -30,6 +33,9 @@
<div class="flex-none my-auto px-2">
<Clock timestamp={ data.c ? new Date(data.c * 1000) : new Date(0) } />
</div>
<div class="flex-none px-2 mt-1">
<Link to="/configuration"><GearIcon/></Link>
</div>
</div>
</div>
</nav>

View File

@ -0,0 +1,16 @@
<script>
export let epoch;
let days = Math.round(epoch/86400);
let hours = Math.round(epoch/3600);
let minutes = Math.round(epoch/60);
</script>
Up
{#if days > 0}
{days} days
{:else if hours > 0}
{hours} hours
{:else if minutes > 0}
{minutes} minutes
{:else}
{epoch} seconds
{/if}

View File

@ -5,7 +5,9 @@ const config = {
extend: {},
},
plugins: [],
plugins: [
require('@tailwindcss/forms')
],
};
module.exports = config;

View File

@ -22,6 +22,7 @@ export default defineConfig({
"/dayplot.json": "http://192.168.233.235",
"/monthplot.json": "http://192.168.233.235",
"/temperature.json": "http://192.168.233.235",
"/configuration.json": "http://192.168.233.244"
}
}
})

View File

@ -82,6 +82,8 @@ private:
void energyPriceJson();
void temperatureJson();
void configurationJson();
void notFound();
};

View File

@ -0,0 +1,7 @@
{
"i" : %d,
"a" : "%s",
"n" : "%s",
"c" : %d,
"v" : %.1f
},

View File

@ -1,6 +1,9 @@
#include "AmsWebServer.h"
#include "AmsWebHeaders.h"
#include "base64.h"
#include "hexutils.h"
#include <ArduinoJson.h>
#include "html/index_html.h"
#include "html/index_css.h"
@ -10,7 +13,9 @@
#include "html/dayplot_json.h"
#include "html/monthplot_json.h"
#include "html/energyprice_json.h"
#include "html/tempsensor_json.h"
#include "version.h"
AmsWebServer::AmsWebServer(uint8_t* buf, RemoteDebug* Debug, HwTools* hw) {
@ -36,6 +41,9 @@ void AmsWebServer::setup(AmsConfiguration* config, GpioConfig* gpioConfig, Meter
server.on("/dayplot.json", HTTP_GET, std::bind(&AmsWebServer::dayplotJson, this));
server.on("/monthplot.json", HTTP_GET, std::bind(&AmsWebServer::monthplotJson, this));
server.on("/energyprice.json", HTTP_GET, std::bind(&AmsWebServer::energyPriceJson, this));
server.on("/temperature.json", HTTP_GET, std::bind(&AmsWebServer::temperatureJson, this));
server.on("/configuration.json", HTTP_GET, std::bind(&AmsWebServer::configurationJson, this));
server.onNotFound(std::bind(&AmsWebServer::notFound, this));
@ -462,6 +470,41 @@ void AmsWebServer::energyPriceJson() {
server.send(200, MIME_JSON, buf);
}
void AmsWebServer::temperatureJson() {
if(debugger->isActive(RemoteDebug::DEBUG)) debugger->printf("Serving /temperature.json over http...\n");
if(!checkSecurity(2))
return;
int count = hw->getTempSensorCount();
snprintf(buf, 16, "{\"c\":%d,\"s\":[", count);
for(int i = 0; i < count; i++) {
TempSensorData* data = hw->getTempSensorData(i);
if(data == NULL) continue;
TempSensorConfig* conf = config->getTempSensorConfig(data->address);
char* pos = buf+strlen(buf);
snprintf_P(pos, 72, TEMPSENSOR_JSON,
i,
toHex(data->address, 8).c_str(),
conf == NULL ? "" : String(conf->name).substring(0,16).c_str(),
conf == NULL || conf->common ? 1 : 0,
data->lastRead
);
delay(10);
}
char* pos = buf+strlen(buf);
snprintf(count == 0 ? pos : pos-1, 8, "]}");
server.sendHeader(HEADER_CACHE_CONTROL, CACHE_CONTROL_NO_CACHE);
server.sendHeader(HEADER_PRAGMA, PRAGMA_NO_CACHE);
server.sendHeader(HEADER_EXPIRES, EXPIRES_OFF);
server.setContentLength(strlen(buf));
server.send(200, MIME_JSON, buf);
}
void AmsWebServer::indexHtml() {
if(debugger->isActive(RemoteDebug::DEBUG)) debugger->printf("Serving /index.html over http...\n");
@ -502,3 +545,47 @@ void AmsWebServer::indexJs() {
server.setContentLength(INDEX_JS_LEN);
server.send_P(200, MIME_JS, INDEX_JS);
}
void AmsWebServer::configurationJson() {
if(debugger->isActive(RemoteDebug::DEBUG)) debugger->printf("Serving /config.json over http...\n");
server.sendHeader(HEADER_CACHE_CONTROL, CACHE_CONTROL_NO_CACHE);
server.sendHeader(HEADER_PRAGMA, PRAGMA_NO_CACHE);
server.sendHeader(HEADER_EXPIRES, EXPIRES_OFF);
if(!checkSecurity(1))
return;
DynamicJsonDocument doc(512);
doc["version"] = VERSION;
doc["general"]["t"] = "";
doc["general"]["h"] = "";
doc["general"]["s"] = "";
doc["general"]["u"] = "";
doc["general"]["p"] = "";
/*
uint16_t wattageMultiplier;
uint16_t voltageMultiplier;
uint16_t amperageMultiplier;
uint16_t accumulatedMultiplier;
uint8_t source;
uint8_t parser
*/
config->getGpioConfig(*gpioConfig);
config->getMeterConfig(*meterConfig);
doc["meter"]["s"] = gpioConfig->hanPin;
doc["meter"]["b"] = meterConfig->baud;
doc["meter"]["p"] = meterConfig->parity;
doc["meter"]["i"] = meterConfig->invert;
doc["meter"]["d"] = meterConfig->distributionSystem;
doc["meter"]["f"] = meterConfig->mainFuse;
doc["meter"]["o"] = meterConfig->productionCapacity;
doc["meter"]["e"] = toHex(meterConfig->encryptionKey, 16);
doc["meter"]["a"] = toHex(meterConfig->authenticationKey, 16);
serializeJson(doc, buf, BufferSize);
server.send(200, MIME_JSON, buf);
}

View File

@ -2,14 +2,14 @@
extra_configs = platformio-user.ini
[common]
lib_deps = EEPROM, LittleFS, DNSServer, 256dpi/MQTT@2.5.0, OneWireNg@0.10.0, DallasTemperature@3.9.1, EspSoftwareSerial@6.14.1, https://github.com/gskjold/RemoteDebug.git, Time@1.6.1, Timezone@1.2.4, AmsConfiguration, AmsData, AmsDataStorage, HwTools, Uptime, EntsoePriceApi, EnergyAccounting, AmsMqttHandler, RawMqttHandler, JsonMqttHandler, DomoticzMqttHandler, HomeAssistantMqttHandler, ClassicUi
lib_deps = EEPROM, LittleFS, DNSServer, 256dpi/MQTT@2.5.0, OneWireNg@0.10.0, DallasTemperature@3.9.1, EspSoftwareSerial@6.14.1, https://github.com/gskjold/RemoteDebug.git, Time@1.6.1, Timezone@1.2.4, AmsConfiguration, AmsData, AmsDataStorage, HwTools, Uptime, EntsoePriceApi, EnergyAccounting, AmsMqttHandler, RawMqttHandler, JsonMqttHandler, DomoticzMqttHandler, HomeAssistantMqttHandler, ArduinoJson, SvelteUi
lib_ignore = OneWire
extra_scripts =
pre:scripts/addversion.py
lib/JsonMqttHandler/scripts/generate_includes.py
lib/DomoticzMqttHandler/scripts/generate_includes.py
lib/HomeAssistantMqttHandler/scripts/generate_includes.py
lib/ClassicUi/scripts/generate_includes.py
lib/SvelteUi/scripts/generate_includes.py
[esp32]
lib_deps = WiFi, ESPmDNS, WiFiClientSecure, HTTPClient, FS, Update, HTTPUpdate, WebServer, ${common.lib_deps}