// Process control and persisted settings, plus the one-function `log` table. #include "../../net.h" #include "../../settings.h" #include "../bindings.h" #include "../lua_app.h" static int l_sys_millis(lua_State* L) { lua_pushinteger(L, millis()); return 1; } static int l_sys_exit(lua_State* L) { app(L)->requestExit(); return 0; } static int l_sys_launch(lua_State* L) { app(L)->requestLaunch(luaL_checkstring(L, 1)); app(L)->requestExit(); return 0; } static int l_sys_getRotation(lua_State* L) { lua_pushinteger(L, settings.rotation); return 1; } // Persisted, unlike gui.setRotation() which only changes the current frame. static int l_sys_setRotation(lua_State* L) { if (!settings.setRotation(luaL_checkinteger(L, 1))) { lua_pushboolean(L, false); return 1; } app(L)->tft.setRotation(settings.rotationIndex()); lua_pushboolean(L, settings.save()); return 1; } static int l_sys_getTheme(lua_State* L) { lua_pushstring(L, settings.theme.c_str()); return 1; } // The firmware only stores the name; /lib/theme.lua decides what it looks like. static int l_sys_setTheme(lua_State* L) { size_t length; const char* name = luaL_checklstring(L, 1, &length); if (!length || length > 32) { lua_pushboolean(L, false); return 1; } settings.theme = String(name, length); lua_pushboolean(L, settings.save()); return 1; } static int l_sys_getTimezone(lua_State* L) { lua_pushstring(L, settings.timezone.c_str()); return 1; } // Takes a POSIX TZ rule, not a zone name: /lib/timezones.lua is only a picker, so a // zone missing from that list is still reachable by writing the rule. static int l_sys_setTimezone(lua_State* L) { size_t length; const char* tz = luaL_checklstring(L, 1, &length); if (!length || length > 48) { lua_pushboolean(L, false); return 1; } settings.timezone = String(tz, length); net::applyTimezone(); lua_pushboolean(L, settings.save()); return 1; } static int l_sys_setCalibration(lua_State* L) { settings.touchX0 = luaL_checkinteger(L, 1); settings.touchY0 = luaL_checkinteger(L, 2); settings.touchX1 = luaL_checkinteger(L, 3); settings.touchY1 = luaL_checkinteger(L, 4); lua_pushboolean(L, settings.save()); return 1; } // Lua's os.time()/os.date() work off the same system clock, so this is the only // binding a clock UI needs: it says whether that clock means anything yet. static int l_sys_clockSynced(lua_State* L) { lua_pushboolean(L, net::clockSynced()); return 1; } static int logAt(lua_State* L, const char* level) { Serial.printf("[lua:%s] %s\n", level, luaL_checkstring(L, 1)); return 0; } static int l_log_debug(lua_State* L) { return logAt(L, "debug"); } static int l_log_info(lua_State* L) { return logAt(L, "info"); } static int l_log_error(lua_State* L) { return logAt(L, "error"); } // Parity with crosspoint: sleeping is the one thing a script cannot express itself, // since the runtime owns the loop. static int l_sys_delay(lua_State* L) { delay(luaL_checkinteger(L, 1)); return 0; } void registerSys(lua_State* L) { static const luaL_Reg lib[] = { // --- Milliseconds since boot. // @return integer {"millis", l_sys_millis}, // --- Blocks for the given time. // @param ms integer {"delay", l_sys_delay}, // --- Ends this app and returns to the launcher. {"exit", l_sys_exit}, // --- Ends this app and starts another one. // @param path string Absolute path to the app's main.lua. {"launch", l_sys_launch}, // --- Saved screen rotation in degrees clockwise. // @return integer {"getRotation", l_sys_getRotation}, // --- Rotates the screen and saves it. // @param degrees integer 0, 90, 180 or 270. // @return boolean Whether the setting was saved. {"setRotation", l_sys_setRotation}, // --- Name of the active theme in /lib/theme.lua. // @return string {"getTheme", l_sys_getTheme}, // --- Selects a theme by name and saves it. // @param name string // @return boolean Whether the setting was saved. {"setTheme", l_sys_setTheme}, // --- Stores touch calibration, in the panel's unrotated frame. // @param x0 integer Raw reading at the left edge. // @param y0 integer Raw reading at the top edge. // @param x1 integer Raw reading at the right edge. // @param y1 integer Raw reading at the bottom edge. // @return boolean Whether the setting was saved. {"setCalibration", l_sys_setCalibration}, // --- Whether SNTP has answered. Until it has, os.time() is only a build-time floor. // @return boolean {"clockSynced", l_sys_clockSynced}, // --- Active POSIX timezone rule. // @return string {"getTimezone", l_sys_getTimezone}, // --- Sets the timezone from a POSIX TZ rule and saves it. // @param tz string For example EST5EDT,M3.2.0,M11.1.0. // @return boolean Whether the setting was saved. {"setTimezone", l_sys_setTimezone}, {nullptr, nullptr}}; luaL_newlib(L, lib); lua_setglobal(L, "sys"); // Too small to deserve its own translation unit. static const luaL_Reg logLib[] = { // --- Writes a debug line to the serial log. // @param message string {"debug", l_log_debug}, // --- Writes an info line to the serial log. // @param message string {"info", l_log_info}, // --- Writes an error line to the serial log. // @param message string {"error", l_log_error}, {nullptr, nullptr}}; luaL_newlib(L, logLib); lua_setglobal(L, "log"); }