-- Stand-in for the firmware bindings, so host tests exercise the real ui.lua. -- -- One definition of the binding surface: when a binding is added or renamed, this is -- the file that changes. Tests mutate the returned table to steer the device, and may -- overwrite any stub function outright for a single assertion. local device = { -- Text metrics chosen to match the firmware's default GLCD font, since layout -- assertions are written in real pixels. fontHeight = 8, charWidth = 6, now = 0, rotation = 0, theme = "light", clockSynced = false, tickInterval = 0, appName = "test", textSize = 1, fullscreen = false, timezone = "UTC0", raw = nil, -- pending raw touch reading, {x, y} or nil networks = {}, -- what wifi.scan() returns status = {state = "disconnected", ssid = "", ip = "", rssi = 0}, painted = {}, -- every drawText call, in order calibration = nil, -- last settings.setCalibration() freeHeap = 200000, totalHeap = 320000, connected = nil, -- last wifi.connect() exited = false, launched = nil, saveFails = false, -- make every persisting call report failure } local function saved() return not device.saveFails end function device.install() device.painted = {} gui = { color = function(r, g, b) return r * 65536 + g * 256 + b end, -- Rotation swaps the frame, exactly as TFT_eSPI reports it. getWidth = function() return device.rotation % 180 == 0 and 320 or 480 end, getHeight = function() return device.rotation % 180 == 0 and 480 or 320 end, clear = function() end, fillRect = function() end, drawRect = function() end, fillCircle = function() end, drawLine = function() end, roundRect = function() end, drawText = function(label, x, y) device.painted[#device.painted + 1] = {label = label, x = x, y = y} end, setTextSize = function(size) device.textSize = size end, getFontHeight = function() return device.fontHeight * device.textSize end, getTextWidth = function(text) return #text * device.charWidth * device.textSize end, setRotation = function(degrees) device.rotation = degrees end, getRotation = function() return device.rotation end, setFullscreen = function(on) device.fullscreen = on and true or false end, } sys = { getMillis = function() return device.now end, exit = function() device.exited = true end, getAppName = function() return device.appName end, getMemory = function() return device.freeHeap, device.totalHeap end, isClockSynced = function() return device.clockSynced end, setTickInterval = function(ms) assert(ms == 0 or on_tick, "setTickInterval without on_tick") device.tickInterval = ms end, launch = function(path) device.launched = path end, } settings = { getRotation = function() return device.rotation end, setRotation = function(degrees) if degrees % 90 ~= 0 or degrees < 0 or degrees > 270 then return false end device.rotation = degrees return saved() end, getTheme = function() return device.theme end, setTheme = function(name) device.theme = name return saved() end, setCalibration = function(...) device.calibration = {...} return saved() end, getTimezone = function() return device.timezone end, setTimezone = function(tz) device.timezone = tz return saved() end, } input = { isTouched = function() return device.raw ~= nil end, getTouch = function() if not device.raw then return nil end return device.raw[1], device.raw[2] end, getRawTouch = function() if not device.raw then return nil end return device.raw[1], device.raw[2] end, } fs = { readFile = function() return nil end, writeFile = function() return saved() end, exists = function() return false end, listFiles = function() return {} end, listDirs = function() return {} end, } wifi = { scan = function() return device.networks end, getStatus = function() return device.status end, connect = function(ssid, password) device.connected = {ssid, password} return saved() end, forget = function() device.connected = nil return saved() end, } log = {debug = function() end, info = function() end, error = function() end} return device end return device