-- -- me_rtu.lua -- -- ME-network RTU: reports the ME system's power/storage/CPU status to the -- coordinator, serves item lookup + craft commands, and shows a simple local -- status screen. Read-mostly - the ME system runs itself; this just watches it. -- -- me_rtu -- status screen on this terminal -- me_rtu monitor_0 -- status screen on a monitor -- -- Needs mimic + facility + me installed, a /config.lua with unit_type="me_network" -- and a modem, and an Advanced Peripherals ME Bridge attached to this computer. -- require("/initenv").init_env() local mimic = require("mimic") local m = require("mimic.elements") local psil = require("scada-common.psil") local facility = require("facility") local melib = require("me") local monitor = ... local style = mimic.style local cpair = mimic.cpair local ALIGN = mimic.ALIGN local cfg = facility.load_config() facility.open(cfg.modem) local STATUS_INTERVAL = cfg.status_interval or 2 local LINK_TIMEOUT = 10 local me = melib.new(cfg) -- -- command handlers (coordinator -> this RTU) -- local handlers = { ping = function () return true, { unit_id = cfg.unit_id } end, get_item = function (a) return me.get_item(a and a.name) end, craft_item = function (a) return me.craft_item(a and a.name, a and a.count) end, } -- -- local status screen -- local ps = psil.create() local root = mimic.init{monitor=monitor, ps=ps} local W = root.get_width() m.TextBox{parent=root, x=1, y=1, width=W-9, text=string.format("ME RTU #%02d", cfg.unit_id), alignment=ALIGN.CENTER, fg_bg=style.theme.header} m.TextBox{parent=root, x=W-8, y=1, width=8, text="", alignment=ALIGN.RIGHT, fg_bg=style.theme.header, bind="clock"} m.StateIndicator{parent=root, x=2, y=3, min_width=12, value=2, states={ { color=cpair(colors.black, colors.green), text="COORD OK" }, { color=cpair(colors.white, colors.red), text="NO COORD" }, }, bind="link"} m.StateIndicator{parent=root, x=16, y=3, min_width=12, value=1, states={ { color=cpair(colors.black, colors.green), text="CELLS OK" }, { color=cpair(colors.black, colors.yellow), text="CELLS HIGH" }, { color=cpair(colors.white, colors.red), text="CELLS FULL" }, }, bind="health"} mimic.Gauge{parent=root, x=2, y=5, width=W-4, label="POWER ", bind="me_epwr", color=cpair(colors.green, style.ind_bkg)} mimic.Gauge{parent=root, x=2, y=6, width=W-4, label="CELLS ", bind="me_ecell", color=cpair(colors.cyan, style.ind_bkg)} local function di(y, label, unit, key) m.DataIndicator{parent=root, x=2, y=y, label=label, unit=unit, format="%9.0f", value=0, width=30, fg_bg=style.text_colors, lu_colors=style.lu_colors, bind=key} end di(8, "AE stored:", "AE", "me_stored") di(9, "Power draw:", "AE/t", "me_usage") di(10, "Cells used:", "", "me_iused") di(11, "Cells total:", "", "me_itot") di(12, "CPUs busy:", "", "me_cpubusy") -- -- loops: poll+broadcast, serve commands, keep link/clock live -- local last_coord = -1e9 local function pollLoop() while true do local st = me.collect() facility.broadcast_status(cfg, st) local epwr = st.power.max > 0 and (st.power.stored / st.power.max) or 0 local ecell = st.items.total > 0 and (st.items.used / st.items.total) or 0 ps.publish("me_epwr", epwr) ps.publish("me_ecell", ecell) ps.publish("me_stored", st.power.stored) ps.publish("me_usage", st.power.usage) ps.publish("me_iused", st.items.used) ps.publish("me_itot", st.items.total) ps.publish("me_cpubusy", st.cpus.busy) local health = 1 if st.items.available <= 0 and st.items.total > 0 then health = 3 elseif st.items.pct >= 85 then health = 2 end ps.publish("health", health) os.sleep(STATUS_INTERVAL) end end local function commandLoop() while true do local id, pkt = facility.receive() if pkt then last_coord = os.clock() facility.handle_command(handlers, id, pkt) end end end local function linkLoop() while true do ps.publish("link", (os.clock() - last_coord) < LINK_TIMEOUT and 1 or 2) ps.publish("clock", os.date("%H:%M:%S")) os.sleep(1) end end parallel.waitForAny(mimic.run, pollLoop, commandLoop, linkLoop)