local MODEM_SIDE = "bottom"
local MONITOR_SIDE = "left"
local MASTER_PROTOCOL = "rtm_master_state"
local REQUEST_PROTOCOL = "rtm_master_query"
local CLIENT_NAME = "dispatcher_monitor"
local native = term.current()
local monitor = nil
local masterId = nil
local blink = false
local lastState = nil
local lastSeen = 0
local DEFAULT_MARKERS = {
green = { 26, 4 },
blue = { 42, 4 },
red = { 26, 19 },
purple = { 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 openNet()
if peripheral.getType(MODEM_SIDE) ~= "modem" then error("Nincs modem a bottom oldalon") end
if not rednet.isOpen(MODEM_SIDE) then rednet.open(MODEM_SIDE) end
end
local function initMonitor()
if peripheral.getType(MONITOR_SIDE) ~= "monitor" then error("Nincs monitor a left oldalon") end
monitor = peripheral.wrap(MONITOR_SIDE)
monitor.setTextScale(0.5)
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)
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 routeByKey(key)
if not lastState or not lastState.routes then return nil end
for _, route in ipairs(lastState.routes) do
if route.key == key then return route end
end
return nil
end
local function hasAlert(route)
if not route then return true end
return route.missing or route.offline
end
local function routeColor(route)
if hasAlert(route) and blink then return colors.red end
return route and route.color or colors.gray
end
local function drawSegment(name, color)
local seg = SEGMENTS[name]
if seg then drawPolyline(monitor, seg.points, color) end
end
local function drawMap()
local green = routeByKey("green")
local blue = routeByKey("blue")
local red = routeByKey("red")
local purple = routeByKey("purple")
monitor.setBackgroundColor(colors.black)
monitor.clear()
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 routeColor(green) or colors.gray)
drawSegment("top_right_inner", (blue and not blue.active) and routeColor(blue) or colors.gray)
drawSegment("bot_left_inner", (red and not red.active) and routeColor(red) or colors.gray)
drawSegment("bot_right_inner", (purple and not purple.active) and routeColor(purple) or colors.gray)
drawSegment("green_diag", (green and green.active) and routeColor(green) or colors.gray)
drawSegment("blue_diag", (blue and blue.active) and routeColor(blue) or colors.gray)
drawSegment("red_diag", (red and red.active) and routeColor(red) or colors.gray)
drawSegment("purple_diag", (purple and purple.active) and routeColor(purple) or colors.gray)
end
local function drawMarkers()
if not lastState or not lastState.routes then return end
for i, route in ipairs(lastState.routes) do
local marker = route.marker or DEFAULT_MARKERS[route.key]
if marker then
monitor.setCursorPos(marker[1], marker[2])
monitor.setBackgroundColor(colors.black)
if hasAlert(route) and blink then
monitor.setTextColor(colors.red)
elseif lastState.selected == i then
monitor.setTextColor(colors.white)
else
monitor.setTextColor(route.color)
end
monitor.write(route.active and "[*]" or "[ ]")
end
end
end
local function drawLegend()
if not lastState or not lastState.routes then return end
local _, h = monitor.getSize()
local startY = math.max(1, h - #lastState.routes - 1)
for i, route in ipairs(lastState.routes) do
monitor.setCursorPos(2, startY + i - 1)
monitor.setBackgroundColor(colors.black)
if hasAlert(route) and blink then
monitor.setTextColor(colors.red)
elseif lastState.selected == i 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 drawStatus()
monitor.setCursorPos(2, 22)
monitor.setBackgroundColor(colors.black)
monitor.setTextColor(colors.white)
if masterId then
monitor.write("MASTER ID: " .. masterId .. " LAST: " .. math.floor(os.clock() - lastSeen) .. "s")
else
monitor.write("MASTER KERESES...")
end
end
local function redraw()
term.redirect(monitor)
drawMap()
drawMarkers()
drawLegend()
drawStatus()
term.redirect(native)
end
local function findMaster()
local found = rednet.lookup(MASTER_PROTOCOL, "rtm_master", 2)
if found then masterId = found end
end
local function requestState()
if not masterId then
findMaster()
return
end
rednet.send(masterId, { cmd = "get_panel_state", client = os.getComputerID() }, REQUEST_PROTOCOL)
local senderId, msg, protocol = rednet.receive(REQUEST_PROTOCOL, 0.8)
if senderId == masterId and protocol == REQUEST_PROTOCOL and type(msg) == "table" and msg.routes then
lastState = msg
lastSeen = os.clock()
else
masterId = nil
end
end
openNet()
initMonitor()
redraw()
while true do
requestState()
blink = not blink
redraw()
sleep(1)
end