From be4878def7d03a8a02d3ebda211955b5c10b1f56 Mon Sep 17 00:00:00 2001 From: Lokman Caliskan Date: Sat, 5 Sep 2026 21:53:39 +0200 Subject: [PATCH] fix: threshold band and failure-preserving battery streak, panel back to normalize --- headsetcontrol/lib/hsc.luau | 31 ++++++++++++++++++++++--------- headsetcontrol/panel.luau | 2 +- headsetcontrol/service.luau | 4 ++-- 3 files changed, 25 insertions(+), 12 deletions(-) diff --git a/headsetcontrol/lib/hsc.luau b/headsetcontrol/lib/hsc.luau index 71a4c66..4c8276c 100644 --- a/headsetcontrol/lib/hsc.luau +++ b/headsetcontrol/lib/hsc.luau @@ -244,22 +244,35 @@ end -- Confirms below-threshold readings: a lone reading at or below `low` -- is normalized to unavailable (no false widget value or warning); two --- in a row pass through as genuinely low. `low` is the caller's --- low-battery threshold (e.g. the battery_low setting). Single owner is --- the service entry; the panel uses it for its one-shot wake read with --- the same threshold. All unavailable/malformed forms reset the streak. +-- in a row pass through as genuinely low. Readings in (low, low+5] show +-- as-is without touching the streak (threshold hover); readings above +-- low+5 reset it. Fetch failures (nil/malformed input) carry no +-- information and leave the streak untouched; an explicit device +-- unavailable (level < 0) resets it. Single owner is the service entry. function M.stableBattery(battery, low) - local norm = M.normalizeBattery(battery) + if battery == nil or type(battery) ~= "table" then + return { status = "BATTERY_UNAVAILABLE", level = -1 } + end + local level = tonumber(battery.level) + if level == nil then + return { status = "BATTERY_UNAVAILABLE", level = -1 } + end local threshold = tonumber(low) or 20 - if norm.level >= 0 and norm.level <= threshold then + if level < 0 then + lowStreak = 0 + return { status = "BATTERY_UNAVAILABLE", level = -1 } + end + if level <= threshold then lowStreak = lowStreak + 1 if lowStreak >= 2 then - return norm + return { status = battery.status, level = level } end return { status = "BATTERY_UNAVAILABLE", level = -1 } end - lowStreak = 0 - return norm + if level > threshold + 5 then + lowStreak = 0 + end + return { status = battery.status, level = level } end -- chatmix direction is device-ambiguous. Negative = game side on signed-convention diff --git a/headsetcontrol/panel.luau b/headsetcontrol/panel.luau index 79761be..adae23d 100644 --- a/headsetcontrol/panel.luau +++ b/headsetcontrol/panel.luau @@ -110,7 +110,7 @@ function onWake() end hsc.fetchStatus(function(status) if status ~= nil then - noctalia.state.set("battery", hsc.stableBattery(status.battery, noctalia.getConfig("battery_low"))) + noctalia.state.set("battery", hsc.normalizeBattery(status.battery)) noctalia.state.set("chatmix", status.chatmix or 0) noctalia.state.set("lastUpdate", noctalia.nowMs()) end diff --git a/headsetcontrol/service.luau b/headsetcontrol/service.luau index 4873baa..d00e234 100644 --- a/headsetcontrol/service.luau +++ b/headsetcontrol/service.luau @@ -41,12 +41,12 @@ local function handleStatus(status) return end noctalia.state.set("error", "") - local battery = hsc.stableBattery(status.battery, config().battery_low) + local low = tonumber(config().battery_low) or 20 + local battery = hsc.stableBattery(status.battery, low) noctalia.state.set("battery", battery) noctalia.state.set("chatmix", status.chatmix or 0) noctalia.state.set("lastUpdate", noctalia.nowMs()) if battery.level ~= nil and battery.level >= 0 and battery.status ~= "BATTERY_UNAVAILABLE" then - local low = config().battery_low or 20 if battery.level <= low and not warned then warned = true noctalia.notifyError(