#!/opt/lnxall_app/bin/lua -- Created by jiaqiang.ye@lnxall.com -- Simple GPIO FAN control implementation -- 2024/08/28 local posix = require "posix" local invoker = require "invoker" local gfmt = string.format local g_iopath = nil local g_gpio, g_threshold = 141, 65 -- 141, FAN control GPIO for QIYANG latest board local g_fandis, g_fanen = "1\n", "0\n" local g_thermal = "/sys/class/thermal/thermal_zone%d/temp" local function fan_ctrl(onoff) if type(g_iopath) ~= "string" then return nil end local out = io.open(g_iopath, "wb") if not out then io.stderr:write(gfmt("Error, failed to open '%s'\n", g_iopath)) io.stderr:flush() return false end out:write(onoff and g_fanen or g_fandis) out:close(); out = nil return true end local function has_thermal() local i = 0 while i < 8 do local thermal = gfmt(g_thermal, i) if posix.access(thermal) == 0 then return true end i = i + 1 end return false end local function fan_init(arg1, arg2) invoker.setname("FAN_CONTROL") local gnum, thres = nil, nil if type(arg1) == "string" then gnum = tonumber(arg1) end if gnum and gnum >= 0 then g_gpio = math.floor(gnum) end if type(arg2) == "string" then thres = tonumber(arg2) end if thres and thres > 0 then g_threshold = math.floor(thres) end if not has_thermal() then io.stderr:write("Error, no thermal device found.\n") io.stderr:flush() return nil end io.stdout:write(gfmt("FAN GPIO: %d, temperature threshold: %d\n", g_gpio, g_threshold)) io.stdout:flush() local gpath = gfmt("/sys/class/gpio/gpio%d", g_gpio) g_iopath = gpath .. "/value" if posix.access(gpath) ~= 0 then local exp = io.open("/sys/class/gpio/export", "wb") if exp then gnum = gfmt("%d\n", g_gpio) exp:write(gnum) exp:close() invoker.msleep(200) end if posix.access(gpath) ~= 0 then io.stderr:write(gfmt("Error, failed to export GPIO: %d\n", g_gpio)) io.stderr:flush() return false end end gpath = gpath .. "/direction" local isout = invoker.readfile(gpath, invoker.TRIMEND) if isout ~= "out" then local dirp = io.open(gpath, "wb") if dirp then dirp:write("out\n") dirp:close(); dirp = nil end isout = invoker.readfile(gpath, invoker.TRIMEND) end if isout ~= "out" then if type(isout) ~= "string" then isout = "unknown" end io.stderr:write(gfmt("Error, invalid FAN GPIO direction: %s\n", isout)) io.stderr:flush() end return fan_ctrl(false) end local function get_temps(hight) local i, temps, overtemp = 0, {}, false while i < 8 do local thermal = gfmt(g_thermal, i) if posix.access(thermal) == 0 then local t = invoker.readfile(thermal, invoker.TRIMEND) if not t then overtemp = true io.stderr:write(gfmt("Error, failed to read '%s'\n", thermal)) io.stderr:flush() break end t = tonumber(t) if t then t = math.floor(t / 1000 + 0.5) if t > hight then overtemp = true end temps[#temps + 1] = t end end i = i + 1 end return temps, overtemp end local function mainloop() while true do local t, over = get_temps(g_threshold) if over then for i, temp in ipairs(t) do io.stdout:write(gfmt("CPU[%d] temperature: %d\n", i, temp)) io.stdout:flush() end fan_ctrl(true) invoker.waitsec(600) else fan_ctrl(false) invoker.waitsec(120) end end end if not fan_init(arg[1], arg[2]) then invoker.waitsec(900) os.exit(9) end mainloop() os.exit(0)