|
|
|
@ -13,6 +13,7 @@ const groups = {
|
|
|
|
|
|
|
|
|
|
|
|
const deviceCards = new Map(); // device_id -> li
|
|
|
|
const deviceCards = new Map(); // device_id -> li
|
|
|
|
const selected = {}; // category -> { btn, card } подключённого датчика
|
|
|
|
const selected = {}; // category -> { btn, card } подключённого датчика
|
|
|
|
|
|
|
|
const pendingStatus = {}; // category -> status (пришёл до установки selected)
|
|
|
|
|
|
|
|
|
|
|
|
function el(tag, className, text) {
|
|
|
|
function el(tag, className, text) {
|
|
|
|
const node = document.createElement(tag);
|
|
|
|
const node = document.createElement(tag);
|
|
|
|
@ -108,6 +109,10 @@ async function connect(deviceId, btn, category, card) {
|
|
|
|
btn.textContent = "✓";
|
|
|
|
btn.textContent = "✓";
|
|
|
|
btn.classList.add("device__connect--done");
|
|
|
|
btn.classList.add("device__connect--done");
|
|
|
|
selected[category] = { btn, card };
|
|
|
|
selected[category] = { btn, card };
|
|
|
|
|
|
|
|
if (pendingStatus[category]) {
|
|
|
|
|
|
|
|
applyStatus(selected[category], category, pendingStatus[category]);
|
|
|
|
|
|
|
|
delete pendingStatus[category];
|
|
|
|
|
|
|
|
}
|
|
|
|
if (category === "trainer") startBtn.disabled = false;
|
|
|
|
if (category === "trainer") startBtn.disabled = false;
|
|
|
|
} catch (e) {
|
|
|
|
} catch (e) {
|
|
|
|
console.error(e);
|
|
|
|
console.error(e);
|
|
|
|
@ -140,17 +145,14 @@ once("battery", (event) => {
|
|
|
|
if (card) card.querySelector(".device__head").append(batteryIcon(percent));
|
|
|
|
if (card) card.querySelector(".device__head").append(batteryIcon(percent));
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
once("telemetry", (event) => {
|
|
|
|
listen("telemetry", (event) => {
|
|
|
|
const t = event.payload.telemetry;
|
|
|
|
const t = event.payload.telemetry;
|
|
|
|
if (t.Power) setMetric("power-value", t.Power.watts);
|
|
|
|
if (t.Power) setMetric("power-value", t.Power.watts);
|
|
|
|
else if (t.Cadence) setMetric("cadence-value", Math.round(t.Cadence.rpm));
|
|
|
|
else if (t.Cadence) setMetric("cadence-value", Math.round(t.Cadence.rpm));
|
|
|
|
else if (t.HeartRate) setMetric("hr-value", t.HeartRate.bpm);
|
|
|
|
else if (t.HeartRate) setMetric("hr-value", t.HeartRate.bpm);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
listen("connection", (event) => {
|
|
|
|
function applyStatus(sel, category, status) {
|
|
|
|
const { category, status } = event.payload;
|
|
|
|
|
|
|
|
const sel = selected[category];
|
|
|
|
|
|
|
|
if (!sel) return;
|
|
|
|
|
|
|
|
const { btn } = sel;
|
|
|
|
const { btn } = sel;
|
|
|
|
if (status === "reconnecting") {
|
|
|
|
if (status === "reconnecting") {
|
|
|
|
btn.textContent = "переподключение…";
|
|
|
|
btn.textContent = "переподключение…";
|
|
|
|
@ -165,6 +167,16 @@ listen("connection", (event) => {
|
|
|
|
btn.disabled = false;
|
|
|
|
btn.disabled = false;
|
|
|
|
selected[category] = null;
|
|
|
|
selected[category] = null;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
listen("connection", (event) => {
|
|
|
|
|
|
|
|
const { category, status } = event.payload;
|
|
|
|
|
|
|
|
const sel = selected[category];
|
|
|
|
|
|
|
|
if (!sel) {
|
|
|
|
|
|
|
|
pendingStatus[category] = status;
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
applyStatus(sel, category, status);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
// --- Таймер ---
|
|
|
|
// --- Таймер ---
|
|
|
|
@ -212,8 +224,12 @@ timerBtn.addEventListener("click", async () => {
|
|
|
|
|
|
|
|
|
|
|
|
// --- Целевая мощность/каденс ---
|
|
|
|
// --- Целевая мощность/каденс ---
|
|
|
|
document.querySelector("#apply-btn").addEventListener("click", async () => {
|
|
|
|
document.querySelector("#apply-btn").addEventListener("click", async () => {
|
|
|
|
const watts = Number(document.querySelector("#power-input").value);
|
|
|
|
const powerRaw = document.querySelector("#power-input").value.trim();
|
|
|
|
const rpm = Number(document.querySelector("#cadence-input").value);
|
|
|
|
const cadenceRaw = document.querySelector("#cadence-input").value.trim();
|
|
|
|
|
|
|
|
if (powerRaw === "" || cadenceRaw === "") return;
|
|
|
|
|
|
|
|
const watts = Number(powerRaw);
|
|
|
|
|
|
|
|
const rpm = Number(cadenceRaw);
|
|
|
|
|
|
|
|
if (!Number.isFinite(watts) || !Number.isFinite(rpm)) return;
|
|
|
|
try {
|
|
|
|
try {
|
|
|
|
await invoke("set_target_power", { watts });
|
|
|
|
await invoke("set_target_power", { watts });
|
|
|
|
await invoke("set_target_cadence", { rpm });
|
|
|
|
await invoke("set_target_cadence", { rpm });
|
|
|
|
|