Files
community-plugins/um5606_fan_state/fan_state_service.luau
T
Kainoa KanterandGitHub b1f9588bfd ASUS UM5606 Fan State plugin (#21)
* ASUS fan state plugin

* submission guidelines

* fix validation ci

* fix label

* Update plugin.toml

* update thumbnail categories
2026-07-15 20:25:22 -04:00

130 lines
3.3 KiB
Luau

-- ASUS UM5606 Fan State - headless service.
-- Owns all fan_state shell calls and runs for the whole session. The bar widget
-- is a thin client: it reads the published "status" and drives this service by
-- writing to the "command" channel.
local STATE_COUNT = 4
local fanState = -1
local available = false
local refreshPending = false
local lastStatusKey
local function publishStatus()
local key = tostring(fanState) .. (available and "/1" or "/0")
if key == lastStatusKey then return end
lastStatusKey = key
noctalia.state.set("status", { state = fanState, available = available })
end
local function setState(state)
if fanState == state then return end
fanState = state
end
local function parseFanState(stdout)
return tonumber((stdout or ""):match("^%s*(.-)%s*$"))
end
local function refreshFanState()
if refreshPending then return end
refreshPending = true
local ok = noctalia.runAsync("fan_state get --int", function(result)
refreshPending = false
if result.exitCode ~= 0 then
available = false
noctalia.log("fan_control: failed to get fan state")
publishStatus()
return
end
local parsed = parseFanState(result.stdout)
if parsed == nil then
available = false
noctalia.log("fan_control: failed to parse fan state")
publishStatus()
return
end
available = true
setState(parsed)
publishStatus()
end)
if not ok then
refreshPending = false
available = false
noctalia.log("fan_control: failed to start fan state command")
publishStatus()
end
end
local function setFanState(nextState)
if type(nextState) ~= "number" then return end
if nextState < 0 or nextState >= STATE_COUNT then return end
available = true
setState(nextState)
publishStatus()
local ok = noctalia.runAsync("fan_state set " .. tostring(nextState), function(result)
if result.exitCode ~= 0 then
noctalia.log("fan_control: failed to set fan state")
end
refreshFanState()
end)
if not ok then
noctalia.log("fan_control: failed to start fan state command")
refreshFanState()
end
end
local function cycleFanState()
if not available then
refreshFanState()
return
end
setFanState((fanState + 1) % STATE_COUNT)
end
local function handleCommand(command)
local action = command
local state = nil
if type(command) == "table" then
action = command.action
state = tonumber(command.state)
end
if action == "cycle" then
cycleFanState()
elseif action == "refresh" then
refreshFanState()
elseif action == "set" then
setFanState(state)
elseif type(action) == "string" then
local parsed = tonumber(action:match("^set%s+([0-3])$"))
if parsed ~= nil then
setFanState(parsed)
else
noctalia.log("fan_control: unknown command '" .. tostring(action) .. "'")
end
end
end
local pollInterval = tonumber(noctalia.getConfig("poll_interval")) or 2000
noctalia.setUpdateInterval(pollInterval)
publishStatus()
refreshFanState()
function update()
refreshFanState()
end
noctalia.state.watch("command", handleCommand)