16
|
1 import { LitElement, PropertyValues, css, html } from "lit";
|
|
2 import { customElement, property } from "lit/decorators.js";
|
|
3 import { shared } from "./shared";
|
|
4
|
|
5
|
|
6 @customElement("fd-electricity")
|
|
7 export class FdElectricity extends LitElement {
|
|
8 static styles = [
|
|
9 shared,
|
|
10 css`
|
|
11 :host {
|
|
12 font-size: 14px;
|
|
13 }
|
|
14
|
|
15 :host > table {
|
|
16 margin-top: 10px;
|
|
17 }
|
|
18 th {
|
|
19 text-align: left;
|
|
20 }
|
|
21 td {
|
|
22 text-align: right;
|
|
23 }
|
|
24 tr.total td,
|
|
25 tr.total th {
|
|
26 border-top: 1px solid white;
|
|
27 }
|
|
28 .bar {
|
|
29 background: yellow;
|
|
30 display: inline-block;
|
|
31 height: 10px;
|
|
32 }
|
|
33 .total .bar {
|
|
34 background: pink;
|
|
35 }
|
|
36 `,
|
|
37 ];
|
|
38 @property() seriesData: Map<string, number> = new Map();
|
|
39 constructor() {
|
|
40 super();
|
|
41 this.load();
|
|
42 setInterval(this.load.bind(this), 10 * 1000);
|
|
43 }
|
|
44 async load() {
|
|
45 this.seriesData = new Map();
|
|
46 const base = "https://bigasterisk.com/m/vmselect/select/0/prometheus/api/v1/query";
|
|
47 const now = Date.now() / 1000 - 10;
|
|
48 const seriesUrls = [
|
|
49 { url: base + `?query=powermeter_w&time=${now}&step=725ms`, label: "powermeter" },
|
|
50 { url: base + `?query=(sum%20by%20%20(s)%20(house_power_w))%20-%20(sum%20by(s)%20(powermeter_w))&time=${now}&step=725ms`, label: "unmetered" },
|
|
51 { url: base + `?query=house_power_w&time=${now}&step=725ms`, label: "total" },
|
|
52 ];
|
|
53
|
|
54 for (const series of seriesUrls) {
|
|
55 const response = await fetch(series.url);
|
|
56 const data = await response.json();
|
|
57 for (let row of data.data.result) {
|
|
58 this.seriesData.set(series.label + (row.metric.sensor ? "-" + row.metric.sensor : ""), parseFloat(row.value[1]));
|
|
59 }
|
|
60 }
|
|
61 this.update(new Map() as PropertyValues);
|
|
62 }
|
|
63 render() {
|
|
64 const disp = (n: number | undefined) => (n ? `${n.toFixed(1)}` : "");
|
|
65 const pxPerWatt = 150 / this.seriesData.get("total")!;
|
|
66 const bar = (n: number | undefined) => (n ? html`<div style="width: ${(n * pxPerWatt).toFixed(1)}px"></div>` : "");
|
|
67 return html`<h1 data-text="Electricity">Electricity</h1>
|
|
68 <table>
|
|
69 <tr>
|
|
70 <th>(unmetered)</th>
|
|
71 <td>${disp(this.seriesData.get("unmetered"))}</td>
|
|
72 <td class="bar">${bar(this.seriesData.get("unmetered"))}</td>
|
|
73 </tr>
|
|
74 <tr>
|
|
75 <th>dash</th>
|
|
76 <td>${disp(this.seriesData.get("powermeter-do_r"))}</td>
|
|
77 <td class="bar">${bar(this.seriesData.get("powermeter-do_r"))}</td>
|
|
78 </tr>
|
|
79 <tr>
|
|
80 <th>washer</th>
|
|
81 <td>${disp(this.seriesData.get("powermeter-ga_washer"))}</td>
|
|
82 <td class="bar">${bar(this.seriesData.get("powermeter-ga_washer"))}</td>
|
|
83 </tr>
|
|
84 <tr>
|
|
85 <th>fridge</th>
|
|
86 <td>${disp(this.seriesData.get("powermeter-ki_fridge"))}</td>
|
|
87 <td class="bar">${bar(this.seriesData.get("powermeter-ki_fridge"))}</td>
|
|
88 </tr>
|
|
89 <tr>
|
|
90 <th>server closet</th>
|
|
91 <td>${disp(this.seriesData.get("powermeter-st_wall"))}</td>
|
|
92 <td class="bar">${bar(this.seriesData.get("powermeter-st_wall"))}</td>
|
|
93 </tr>
|
|
94 <tr>
|
|
95 <th>theater console</th>
|
|
96 <td>${disp(this.seriesData.get("powermeter-tt_console"))}</td>
|
|
97 <td class="bar">${bar(this.seriesData.get("powermeter-tt_console"))}</td>
|
|
98 </tr>
|
|
99 <tr>
|
|
100 <th>workshop desk</th>
|
|
101 <td>${disp(this.seriesData.get("powermeter-ws_desk"))}</td>
|
|
102 <td class="bar">${bar(this.seriesData.get("powermeter-ws_desk"))}</td>
|
|
103 </tr>
|
|
104 <tr class="total">
|
|
105 <th>Total</th>
|
|
106 <td>${this.seriesData.get("total")} W</td>
|
|
107 <td class="bar">${bar(this.seriesData.get("total"))}</td>
|
|
108 </tr>
|
|
109 </table> `;
|
|
110 }
|
|
111 }
|