Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- local MODEM_SIDE = "bottom"
- local MONITOR_SIDE = "left"
- local DB_FILE = "panel.db"
- local PROTOCOL = "rtm_top_switch"
- local MASTER_PROTOCOL = "rtm_master_state"
- local REQUEST_PROTOCOL = "rtm_master_query"
- local MASTER_HOSTNAME = "rtm_master"
- local native = term.current()
- local running = true
- local monitor = nil
- local blinkState = false
- local status = "Indulas"
- local DEFAULT_MARKERS = {
- green = { 26, 4 },
- blue = { 42, 4 },
- red = { 26, 19 },
- purple = { 42, 19 },
- }
- local panel = {
- version = 10,
- selected = 1,
- routes = {
- { key = "green", name = "Zold ag", color = colors.lime, slaveId = nil, active = false, offline = true, missing = true, marker = { 26, 4 } },
- { key = "blue", name = "Kek ag", color = colors.lightBlue, slaveId = nil, active = false, offline = true, missing = true, marker = { 42, 4 } },
- { key = "red", name = "Piros ag", color = colors.red, slaveId = nil, active = false, offline = true, missing = true, marker = { 26, 19 } },
- { key = "purple", name = "Lila ag", color = colors.purple, slaveId = nil, active = false, offline = true, missing = true, marker = { 42, 19 } },
- }
- }
- local SEGMENTS = {
- top_left_outer = { points = { {4,6}, {9,6}, {14,6}, {19,6} } },
- top_left_inner = { points = { {21,6}, {25,6}, {29,6}, {33,6} } },
- top_right_inner = { points = { {39,6}, {43,6}, {47,6}, {51,6} } },
- top_right_outer = { points = { {53,6}, {58,6}, {63,6}, {68,6} } },
- bot_left_outer = { points = { {4,17}, {9,17}, {14,17}, {19,17} } },
- bot_left_inner = { points = { {21,17}, {25,17}, {29,17}, {33,17} } },
- bot_right_inner = { points = { {39,17}, {43,17}, {47,17}, {51,17} } },
- bot_right_outer = { points = { {53,17}, {58,17}, {63,17}, {68,17} } },
- green_diag = { points = { {19,6}, {23,8}, {27,10}, {31,12}, {35,13} } },
- red_diag = { points = { {21,16}, {25,14}, {29,12}, {33,10}, {36,9} } },
- blue_diag = { points = { {39,10}, {43,9}, {47,7}, {51,6} } },
- purple_diag = { points = { {39,12}, {43,14}, {47,16}, {51,18} } },
- }
- local function setStatus(msg)
- status = msg
- end
- local function getRoute(key)
- for _, route in ipairs(panel.routes) do
- if route.key == key then return route end
- end
- return nil
- end
- local function ensureRouteFlags()
- for _, route in ipairs(panel.routes) do
- if route.active == nil then route.active = false end
- route.missing = route.slaveId == nil
- if route.offline == nil then route.offline = true end
- if route.marker == nil and DEFAULT_MARKERS[route.key] then
- route.marker = { DEFAULT_MARKERS[route.key][1], DEFAULT_MARKERS[route.key][2] }
- end
- end
- end
- local function saveDb()
- local h = fs.open(DB_FILE, "w")
- h.write(textutils.serialize(panel))
- h.close()
- setStatus("Mentve: " .. DB_FILE)
- end
- local function loadDb()
- if not fs.exists(DB_FILE) then
- ensureRouteFlags()
- setStatus("Uj panel adatbazis")
- return
- end
- local h = fs.open(DB_FILE, "r")
- local raw = h.readAll()
- h.close()
- local t = textutils.unserialize(raw)
- if type(t) == "table" then
- panel = t
- if not panel.selected then panel.selected = 1 end
- ensureRouteFlags()
- setStatus("Betoltve: " .. DB_FILE)
- else
- ensureRouteFlags()
- setStatus("Hibas adatbazis")
- end
- end
- local function openNet()
- if peripheral.getType(MODEM_SIDE) ~= "modem" then
- setStatus("Nincs modem a bottom oldalon")
- return false
- end
- if not rednet.isOpen(MODEM_SIDE) then rednet.open(MODEM_SIDE) end
- rednet.host(MASTER_PROTOCOL, MASTER_HOSTNAME)
- return true
- end
- local function buildPanelState()
- local routes = {}
- for i, route in ipairs(panel.routes) do
- routes[i] = {
- key = route.key,
- name = route.name,
- color = route.color,
- slaveId = route.slaveId,
- active = route.active,
- offline = route.offline,
- missing = route.missing,
- marker = route.marker,
- }
- end
- return {
- selected = panel.selected,
- status = status,
- routes = routes,
- }
- end
- local function findRouteBySlave(id)
- for _, route in ipairs(panel.routes) do
- if route.slaveId == id then return route end
- end
- return nil
- end
- local function hasAlert(route)
- return route.missing or route.offline
- end
- local function drawLineTerm(target, x1, y1, x2, y2, color)
- term.redirect(target)
- paintutils.drawLine(x1, y1, x2, y2, color)
- end
- local function drawPolyline(target, points, color)
- if not points or #points < 2 then return end
- for i = 1, #points - 1 do
- drawLineTerm(target, points[i][1], points[i][2], points[i + 1][1], points[i + 1][2], color)
- end
- end
- local function drawSegment(name, color)
- local seg = SEGMENTS[name]
- if seg then drawPolyline(monitor, seg.points, color) end
- end
- local function routeDisplayColor(route)
- if hasAlert(route) and blinkState then return colors.red end
- return route.color
- end
- local function drawDispatcherMap()
- if not monitor then return end
- term.redirect(monitor)
- monitor.setBackgroundColor(colors.black)
- monitor.clear()
- local green = getRoute("green")
- local blue = getRoute("blue")
- local red = getRoute("red")
- local purple = getRoute("purple")
- drawSegment("top_left_outer", colors.gray)
- drawSegment("top_right_outer", colors.gray)
- drawSegment("bot_left_outer", colors.gray)
- drawSegment("bot_right_outer", colors.gray)
- drawSegment("top_left_inner", (green and not green.active) and routeDisplayColor(green) or colors.gray)
- drawSegment("top_right_inner", (blue and not blue.active) and routeDisplayColor(blue) or colors.gray)
- drawSegment("bot_left_inner", (red and not red.active) and routeDisplayColor(red) or colors.gray)
- drawSegment("bot_right_inner", (purple and not purple.active) and routeDisplayColor(purple) or colors.gray)
- drawSegment("green_diag", (green and green.active) and routeDisplayColor(green) or colors.gray)
- drawSegment("blue_diag", (blue and blue.active) and routeDisplayColor(blue) or colors.gray)
- drawSegment("red_diag", (red and red.active) and routeDisplayColor(red) or colors.gray)
- drawSegment("purple_diag", (purple and purple.active) and routeDisplayColor(purple) or colors.gray)
- end
- local function drawRouteMarkers()
- if not monitor then return end
- for index, route in ipairs(panel.routes) do
- local mx, my = route.marker[1], route.marker[2]
- monitor.setCursorPos(mx, my)
- monitor.setBackgroundColor(colors.black)
- if hasAlert(route) and blinkState then
- monitor.setTextColor(colors.red)
- elseif index == panel.selected then
- monitor.setTextColor(colors.white)
- else
- monitor.setTextColor(route.color)
- end
- monitor.write(route.active and "[*]" or "[ ]")
- end
- end
- local function drawLegend()
- if not monitor then return end
- local _, h = monitor.getSize()
- local startY = math.max(1, h - #panel.routes - 1)
- for i, route in ipairs(panel.routes) do
- monitor.setCursorPos(2, startY + i - 1)
- monitor.setBackgroundColor(colors.black)
- if hasAlert(route) and blinkState then
- monitor.setTextColor(colors.red)
- elseif i == panel.selected then
- monitor.setTextColor(colors.white)
- else
- monitor.setTextColor(route.color)
- end
- local stateText = route.active and "KERESZT" or "EGYENES"
- local line = (route.active and "[*] " or "[ ] ") .. route.name .. " ID:" .. tostring(route.slaveId or "-") .. " " .. stateText
- if route.missing then
- line = line .. " NINCS ID"
- elseif route.offline then
- line = line .. " OFFLINE"
- end
- monitor.write(line)
- end
- end
- local function redrawMonitor()
- if not monitor then return end
- drawDispatcherMap()
- drawRouteMarkers()
- drawLegend()
- term.redirect(native)
- end
- local function sendTopState(route, enabled)
- if not route.slaveId then
- route.missing = true
- route.offline = true
- setStatus("Nincs slave ID beallitva")
- return false
- end
- route.missing = false
- if not openNet() then return false end
- rednet.send(route.slaveId, { cmd = "set_top", enabled = enabled }, PROTOCOL)
- local senderId, msg = rednet.receive(PROTOCOL, 2)
- if senderId == route.slaveId and type(msg) == "table" and msg.ok then
- route.active = msg.enabled and true or false
- route.offline = false
- setStatus(route.name .. " -> " .. (route.active and "KERESZT" or "EGYENES"))
- return true
- end
- route.offline = true
- setStatus("Nincs valasz slave #" .. tostring(route.slaveId))
- return false
- end
- local function setAllStraight()
- if not openNet() then return end
- for _, route in ipairs(panel.routes) do
- route.active = false
- route.missing = route.slaveId == nil
- if route.slaveId then
- rednet.send(route.slaveId, { cmd = "set_top", enabled = false }, PROTOCOL)
- end
- end
- setStatus("Alaphelyzet: minden egyenes")
- end
- local function queryStartupStates()
- if not openNet() then return end
- for _, route in ipairs(panel.routes) do
- route.active = false
- route.missing = route.slaveId == nil
- if route.slaveId then
- route.offline = true
- rednet.send(route.slaveId, { cmd = "get_state" }, PROTOCOL)
- else
- route.offline = true
- end
- end
- local timer = os.startTimer(2)
- while true do
- local event, a, b, c = os.pullEvent()
- if event == "rednet_message" then
- local senderId, msg, protocol = a, b, c
- if protocol == PROTOCOL and type(msg) == "table" and msg.ok then
- local route = findRouteBySlave(senderId)
- if route then
- route.missing = false
- route.offline = false
- route.active = msg.enabled and true or false
- end
- end
- elseif event == "timer" and a == timer then
- setStatus("Indulasi allapotok lekerdezve")
- return
- end
- end
- end
- local function pingAll()
- if not openNet() then return end
- for _, route in ipairs(panel.routes) do
- route.missing = route.slaveId == nil
- if route.slaveId then
- route.offline = true
- rednet.send(route.slaveId, { cmd = "ping" }, PROTOCOL)
- else
- route.offline = true
- end
- end
- local timer = os.startTimer(1.5)
- while true do
- local event, a, b, c = os.pullEvent()
- if event == "rednet_message" then
- local senderId, msg, protocol = a, b, c
- if protocol == PROTOCOL and type(msg) == "table" and msg.ok then
- local route = findRouteBySlave(senderId)
- if route then
- route.missing = false
- route.offline = false
- if msg.enabled ~= nil then route.active = msg.enabled and true or false end
- end
- end
- elseif event == "timer" and a == timer then
- setStatus("Ping kesz")
- return
- end
- end
- end
- local function routeFromTouch(x, y)
- for i, route in ipairs(panel.routes) do
- local mx, my = route.marker[1], route.marker[2]
- if x >= mx and x <= mx + 2 and y == my then
- return i, route
- end
- end
- return nil, nil
- end
- local function touchLoop()
- while running and monitor do
- local event, side, x, y = os.pullEvent()
- if event == "monitor_touch" and side == MONITOR_SIDE then
- local index, route = routeFromTouch(x, y)
- if route then
- panel.selected = index
- sendTopState(route, not route.active)
- redrawMonitor()
- end
- elseif event == "monitor_resize" then
- redrawMonitor()
- end
- end
- end
- local function receiverLoop()
- while running do
- local senderId, msg, protocol = rednet.receive()
- if protocol == REQUEST_PROTOCOL and type(msg) == "table" and msg.cmd == "get_panel_state" then
- rednet.send(senderId, buildPanelState(), REQUEST_PROTOCOL)
- elseif protocol == PROTOCOL and type(msg) == "table" and msg.ok then
- local route = findRouteBySlave(senderId)
- if route then
- route.missing = false
- route.offline = false
- if msg.enabled ~= nil then route.active = msg.enabled and true or false end
- redrawMonitor()
- end
- end
- end
- end
- local function blinkLoop()
- while running do
- blinkState = not blinkState
- redrawMonitor()
- sleep(0.5)
- end
- end
- local function prompt(text, default)
- write(text)
- return read(nil, nil, nil, default)
- end
- local function editRoute(index)
- local route = panel.routes[index]
- term.clear()
- term.setCursorPos(1, 1)
- print("Ag szerkesztese: " .. route.name)
- route.name = prompt("Nev [" .. route.name .. "]: ", route.name)
- local sid = prompt("Slave ID [" .. tostring(route.slaveId or "") .. "]: ", route.slaveId and tostring(route.slaveId) or "")
- route.slaveId = tonumber(sid)
- route.missing = route.slaveId == nil
- route.offline = true
- setStatus("Ag frissitve")
- end
- local function uiLoop()
- while running do
- term.redirect(native)
- term.setBackgroundColor(colors.black)
- term.setTextColor(colors.white)
- term.clear()
- term.setCursorPos(1, 1)
- local route = panel.routes[panel.selected]
- print("RTM ROUTE PANEL MANAGER")
- print("=======================")
- print("Kijelolt ag: " .. panel.selected .. " / " .. route.name)
- print("Slave ID: " .. tostring(route.slaveId or "nincs"))
- print("Allapot: " .. (route.active and "KERESZT" or "EGYENES"))
- print("Missing: " .. tostring(route.missing))
- print("Offline: " .. tostring(route.offline))
- print("")
- print("1 - Elozo ag")
- print("2 - Kovetkezo ag")
- print("3 - Ag valtasa")
- print("4 - Slave ID hozzarendeles")
- print("5 - Osszes ping")
- print("6 - Alaphelyzet (minden egyenes)")
- print("7 - Allapotok lekerdezese")
- print("8 - Mentes")
- print("9 - Betoltes")
- print("0 - Kilepes")
- print("")
- print("Status: " .. status)
- write("> ")
- local cmd = read()
- if cmd == "1" then
- panel.selected = panel.selected - 1
- if panel.selected < 1 then panel.selected = #panel.routes end
- elseif cmd == "2" then
- panel.selected = panel.selected + 1
- if panel.selected > #panel.routes then panel.selected = 1 end
- elseif cmd == "3" then
- sendTopState(route, not route.active)
- elseif cmd == "4" then
- editRoute(panel.selected)
- elseif cmd == "5" then
- pingAll()
- elseif cmd == "6" then
- setAllStraight()
- elseif cmd == "7" then
- queryStartupStates()
- elseif cmd == "8" then
- saveDb()
- elseif cmd == "9" then
- loadDb()
- queryStartupStates()
- elseif cmd == "0" then
- running = false
- break
- end
- redrawMonitor()
- end
- end
- loadDb()
- openNet()
- if peripheral.getType(MONITOR_SIDE) == "monitor" then
- monitor = peripheral.wrap(MONITOR_SIDE)
- monitor.setTextScale(0.5)
- end
- queryStartupStates()
- redrawMonitor()
- if monitor then
- parallel.waitForAny(uiLoop, touchLoop, receiverLoop, blinkLoop)
- else
- parallel.waitForAny(uiLoop, receiverLoop, blinkLoop)
- end
- term.redirect(native)
- term.setBackgroundColor(colors.black)
- term.setTextColor(colors.white)
- term.clear()
- term.setCursorPos(1, 1)
- print("Leallva")
Advertisement