Mercurial > code > home > repos > light-bridge
view src/main.ts @ 11:028ed39aa78f
more ts types; attempted multiplayer but the change events are managed wrong
author | drewp@bigasterisk.com |
---|---|
date | Sun, 28 Jan 2024 17:31:06 -0800 |
parents | 9f427d8073c3 |
children | 7cc004eafb82 |
line wrap: on
line source
import { LitElement, css, html } from "lit"; import { customElement, state } from "lit/decorators.js"; interface Light { name: string; address: string; requestingColor: string; requestingDeviceColor: object; emittingColor: string; online: boolean; latencyMs: number; } @customElement("lb-page") export class LbPage extends LitElement { static styles = [ css` :host { display: flex; flex-direction: column; height: 100vh; } table { border-collapse: collapse; } td, th { border: 1px solid #aaa; text-align: center; } .color { display: inline-block; width: 30px; height: 30px; border-radius: 50%; margin: 3px; vertical-align: middle; } .col-group-1 { background: #e0ecf4; } .col-group-2 { background: #e0f3db; } .col-group-3 { background: #fee8c8; } `, ]; // bug https://github.com/lit/lit/issues/4305 @((state as any)()) lights: Light[] = []; @((state as any)()) lightByName: Map<string, Light> = new Map(); @((state as any)()) reportTime: Date = new Date(0); connectedCallback(): void { super.connectedCallback(); const es = new EventSource("api/table"); es.onmessage = (ev) => { const body = JSON.parse(ev.data); this.lights = body.lights.map((wrappedLight: any) => wrappedLight.light as Light); this.rebuildLightByName(); this.reportTime = new Date(body.now * 1000); }; } private rebuildLightByName() { this.lightByName = new Map(); this.lights.forEach((light: any) => { this.lightByName.set(light.name, light); }); } render() { return html` <h1>Light-bridge</h1> <table> <tr> <th class="col-group-1">light</th> <th class="col-group-1">address</th> <th class="col-group-2">requested color</th> <th class="col-group-2">requested device color</th> <th class="col-group-3">emitting color</th> <th class="col-group-3">online</th> <th class="col-group-3">latency</th> </tr> ${this.lights.map( (d: Light) => html` <tr> <td class="col-group-1">${d.name}</td> <td class="col-group-1"><code>${d.address}</code></td> <td class="col-group-2"> <code>${d.requestingColor}</code> <input type="color" @input=${this.onRequestingColor.bind(this, d.name)} .value="${d.requestingColor}" /> </td> <td class="col-group-2"><code>${JSON.stringify(d.requestingDeviceColor)}</code></td> <td class="col-group-3">${d.emittingColor} <span class="color" style="background: ${d.emittingColor}"></span></td> <td class="col-group-3">${d.online ? "✔" : ""}</td> <td class="col-group-3">${d.latencyMs} ms</td> </tr> ` )} </table> <p>Updated ${this.reportTime.toLocaleString("sv")}</p> <p> <a href="metrics">metrics</a> | <a href="api/graph">graph</a> </p> <bigast-loginbar></bigast-loginbar> `; } async onRequestingColor(lightName: string, ev: InputEvent) { const currentRequest = this.lightByName.get(lightName)!.requestingColor; const value = (ev.target as HTMLInputElement).value; console.log("LbPage ~ onRequestingColor ~ value === currentRequest:", value, currentRequest); if (value === currentRequest) { return; } const url = new URL("api/output", location as any); url.searchParams.append("light", lightName); fetch(url, { method: "PUT", body: value }); // todo: only run one fetch at a time, per light // sometime after this, the SSE table will send us back the change we made (probably) } }