This commit is contained in:
96
tools/button-simulator/public/app.js
Normal file
96
tools/button-simulator/public/app.js
Normal file
@@ -0,0 +1,96 @@
|
||||
const $ = (sel, root = document) => root.querySelector(sel);
|
||||
const $$ = (sel, root = document) => [...root.querySelectorAll(sel)];
|
||||
|
||||
async function api(path, body) {
|
||||
const opts = { method: body ? "POST" : "GET" };
|
||||
if (body) {
|
||||
opts.headers = { "Content-Type": "application/json" };
|
||||
opts.body = JSON.stringify(body);
|
||||
}
|
||||
const res = await fetch(path, opts);
|
||||
return res.json();
|
||||
}
|
||||
|
||||
function formatLog(entries) {
|
||||
return entries
|
||||
.map((e) => {
|
||||
const ts = new Date(e.t).toLocaleTimeString();
|
||||
const arrow = e.direction === "out" ? "→" : e.direction === "in" ? "←" : e.direction === "err" ? "✖" : "·";
|
||||
return `${ts} ${arrow} ${e.text}`;
|
||||
})
|
||||
.join("\n");
|
||||
}
|
||||
|
||||
let lastKnownButtons = null;
|
||||
|
||||
async function refreshStatus() {
|
||||
try {
|
||||
const s = await api("/api/status");
|
||||
$("#status").textContent = s.connected ? "online" : "offline";
|
||||
$("#status").className = "status " + (s.connected ? "online" : "offline");
|
||||
|
||||
if (!lastKnownButtons) {
|
||||
$("#brokerUrl").value = s.brokerUrl;
|
||||
$("#hbEnabled").checked = s.heartbeatEnabled;
|
||||
$("#hbInterval").value = s.heartbeatIntervalMs;
|
||||
for (const key of ["start1", "stop1", "start2", "stop2"]) {
|
||||
const card = $(`.button-card[data-button="${key}"]`);
|
||||
card.querySelector(".mac").value = s.buttons[key].mac;
|
||||
card.querySelector(".mv").value = s.buttons[key].voltage;
|
||||
card.querySelector(".mv-value").textContent = s.buttons[key].voltage;
|
||||
}
|
||||
lastKnownButtons = s.buttons;
|
||||
}
|
||||
|
||||
$("#log").textContent = formatLog(s.log);
|
||||
$("#log").scrollTop = $("#log").scrollHeight;
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
}
|
||||
}
|
||||
|
||||
$("#btnConnect").addEventListener("click", async () => {
|
||||
await api("/api/connect", { brokerUrl: $("#brokerUrl").value.trim() });
|
||||
refreshStatus();
|
||||
});
|
||||
|
||||
$("#btnDisconnect").addEventListener("click", async () => {
|
||||
await api("/api/disconnect", {});
|
||||
refreshStatus();
|
||||
});
|
||||
|
||||
$("#btnHbApply").addEventListener("click", async () => {
|
||||
await api("/api/heartbeat", {
|
||||
enabled: $("#hbEnabled").checked,
|
||||
intervalMs: parseInt($("#hbInterval").value, 10),
|
||||
});
|
||||
refreshStatus();
|
||||
});
|
||||
|
||||
$$(".button-card").forEach((card) => {
|
||||
const button = card.dataset.button;
|
||||
const macInput = card.querySelector(".mac");
|
||||
const mvInput = card.querySelector(".mv");
|
||||
const mvValue = card.querySelector(".mv-value");
|
||||
const pressBtn = card.querySelector(".press");
|
||||
|
||||
macInput.addEventListener("change", async () => {
|
||||
await api("/api/config", { button, mac: macInput.value.trim() });
|
||||
});
|
||||
|
||||
mvInput.addEventListener("input", () => {
|
||||
mvValue.textContent = mvInput.value;
|
||||
});
|
||||
|
||||
mvInput.addEventListener("change", async () => {
|
||||
await api("/api/battery", { button, voltage: parseInt(mvInput.value, 10) });
|
||||
});
|
||||
|
||||
pressBtn.addEventListener("click", async () => {
|
||||
await api("/api/press", { button });
|
||||
refreshStatus();
|
||||
});
|
||||
});
|
||||
|
||||
refreshStatus();
|
||||
setInterval(refreshStatus, 1500);
|
||||
Reference in New Issue
Block a user