agot137

master_manager.lua

Apr 25th, 2026 (edited)
2,790
0
Never
4
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 14.93 KB | None | 0 0
  1. local MODEM_SIDE = "bottom"
  2. local MONITOR_SIDE = "left"
  3. local DB_FILE = "panel.db"
  4. local PROTOCOL = "rtm_top_switch"
  5. local MASTER_PROTOCOL = "rtm_master_state"
  6. local REQUEST_PROTOCOL = "rtm_master_query"
  7. local MASTER_HOSTNAME = "rtm_master"
  8. local native = term.current()
  9.  
  10. local running = true
  11. local monitor = nil
  12. local blinkState = false
  13. local status = "Indulas"
  14.  
  15. local DEFAULT_MARKERS = {
  16. green = { 26, 4 },
  17. blue = { 42, 4 },
  18. red = { 26, 19 },
  19. purple = { 42, 19 },
  20. }
  21.  
  22. local panel = {
  23. version = 10,
  24. selected = 1,
  25. routes = {
  26. { key = "green", name = "Zold ag", color = colors.lime, slaveId = nil, active = false, offline = true, missing = true, marker = { 26, 4 } },
  27. { key = "blue", name = "Kek ag", color = colors.lightBlue, slaveId = nil, active = false, offline = true, missing = true, marker = { 42, 4 } },
  28. { key = "red", name = "Piros ag", color = colors.red, slaveId = nil, active = false, offline = true, missing = true, marker = { 26, 19 } },
  29. { key = "purple", name = "Lila ag", color = colors.purple, slaveId = nil, active = false, offline = true, missing = true, marker = { 42, 19 } },
  30. }
  31. }
  32.  
  33. local SEGMENTS = {
  34. top_left_outer = { points = { {4,6}, {9,6}, {14,6}, {19,6} } },
  35. top_left_inner = { points = { {21,6}, {25,6}, {29,6}, {33,6} } },
  36. top_right_inner = { points = { {39,6}, {43,6}, {47,6}, {51,6} } },
  37. top_right_outer = { points = { {53,6}, {58,6}, {63,6}, {68,6} } },
  38. bot_left_outer = { points = { {4,17}, {9,17}, {14,17}, {19,17} } },
  39. bot_left_inner = { points = { {21,17}, {25,17}, {29,17}, {33,17} } },
  40. bot_right_inner = { points = { {39,17}, {43,17}, {47,17}, {51,17} } },
  41. bot_right_outer = { points = { {53,17}, {58,17}, {63,17}, {68,17} } },
  42. green_diag = { points = { {19,6}, {23,8}, {27,10}, {31,12}, {35,13} } },
  43. red_diag = { points = { {21,16}, {25,14}, {29,12}, {33,10}, {36,9} } },
  44. blue_diag = { points = { {39,10}, {43,9}, {47,7}, {51,6} } },
  45. purple_diag = { points = { {39,12}, {43,14}, {47,16}, {51,18} } },
  46. }
  47.  
  48. local function setStatus(msg)
  49. status = msg
  50. end
  51.  
  52. local function getRoute(key)
  53. for _, route in ipairs(panel.routes) do
  54. if route.key == key then return route end
  55. end
  56. return nil
  57. end
  58.  
  59. local function ensureRouteFlags()
  60. for _, route in ipairs(panel.routes) do
  61. if route.active == nil then route.active = false end
  62. route.missing = route.slaveId == nil
  63. if route.offline == nil then route.offline = true end
  64. if route.marker == nil and DEFAULT_MARKERS[route.key] then
  65. route.marker = { DEFAULT_MARKERS[route.key][1], DEFAULT_MARKERS[route.key][2] }
  66. end
  67. end
  68. end
  69.  
  70. local function saveDb()
  71. local h = fs.open(DB_FILE, "w")
  72. h.write(textutils.serialize(panel))
  73. h.close()
  74. setStatus("Mentve: " .. DB_FILE)
  75. end
  76.  
  77. local function loadDb()
  78. if not fs.exists(DB_FILE) then
  79. ensureRouteFlags()
  80. setStatus("Uj panel adatbazis")
  81. return
  82. end
  83. local h = fs.open(DB_FILE, "r")
  84. local raw = h.readAll()
  85. h.close()
  86. local t = textutils.unserialize(raw)
  87. if type(t) == "table" then
  88. panel = t
  89. if not panel.selected then panel.selected = 1 end
  90. ensureRouteFlags()
  91. setStatus("Betoltve: " .. DB_FILE)
  92. else
  93. ensureRouteFlags()
  94. setStatus("Hibas adatbazis")
  95. end
  96. end
  97.  
  98. local function openNet()
  99. if peripheral.getType(MODEM_SIDE) ~= "modem" then
  100. setStatus("Nincs modem a bottom oldalon")
  101. return false
  102. end
  103. if not rednet.isOpen(MODEM_SIDE) then rednet.open(MODEM_SIDE) end
  104. rednet.host(MASTER_PROTOCOL, MASTER_HOSTNAME)
  105. return true
  106. end
  107.  
  108. local function buildPanelState()
  109. local routes = {}
  110. for i, route in ipairs(panel.routes) do
  111. routes[i] = {
  112. key = route.key,
  113. name = route.name,
  114. color = route.color,
  115. slaveId = route.slaveId,
  116. active = route.active,
  117. offline = route.offline,
  118. missing = route.missing,
  119. marker = route.marker,
  120. }
  121. end
  122. return {
  123. selected = panel.selected,
  124. status = status,
  125. routes = routes,
  126. }
  127. end
  128.  
  129. local function findRouteBySlave(id)
  130. for _, route in ipairs(panel.routes) do
  131. if route.slaveId == id then return route end
  132. end
  133. return nil
  134. end
  135.  
  136. local function hasAlert(route)
  137. return route.missing or route.offline
  138. end
  139.  
  140. local function drawLineTerm(target, x1, y1, x2, y2, color)
  141. term.redirect(target)
  142. paintutils.drawLine(x1, y1, x2, y2, color)
  143. end
  144.  
  145. local function drawPolyline(target, points, color)
  146. if not points or #points < 2 then return end
  147. for i = 1, #points - 1 do
  148. drawLineTerm(target, points[i][1], points[i][2], points[i + 1][1], points[i + 1][2], color)
  149. end
  150. end
  151.  
  152. local function drawSegment(name, color)
  153. local seg = SEGMENTS[name]
  154. if seg then drawPolyline(monitor, seg.points, color) end
  155. end
  156.  
  157. local function routeDisplayColor(route)
  158. if hasAlert(route) and blinkState then return colors.red end
  159. return route.color
  160. end
  161.  
  162. local function drawDispatcherMap()
  163. if not monitor then return end
  164. term.redirect(monitor)
  165. monitor.setBackgroundColor(colors.black)
  166. monitor.clear()
  167.  
  168. local green = getRoute("green")
  169. local blue = getRoute("blue")
  170. local red = getRoute("red")
  171. local purple = getRoute("purple")
  172.  
  173. drawSegment("top_left_outer", colors.gray)
  174. drawSegment("top_right_outer", colors.gray)
  175. drawSegment("bot_left_outer", colors.gray)
  176. drawSegment("bot_right_outer", colors.gray)
  177.  
  178. drawSegment("top_left_inner", (green and not green.active) and routeDisplayColor(green) or colors.gray)
  179. drawSegment("top_right_inner", (blue and not blue.active) and routeDisplayColor(blue) or colors.gray)
  180. drawSegment("bot_left_inner", (red and not red.active) and routeDisplayColor(red) or colors.gray)
  181. drawSegment("bot_right_inner", (purple and not purple.active) and routeDisplayColor(purple) or colors.gray)
  182.  
  183. drawSegment("green_diag", (green and green.active) and routeDisplayColor(green) or colors.gray)
  184. drawSegment("blue_diag", (blue and blue.active) and routeDisplayColor(blue) or colors.gray)
  185. drawSegment("red_diag", (red and red.active) and routeDisplayColor(red) or colors.gray)
  186. drawSegment("purple_diag", (purple and purple.active) and routeDisplayColor(purple) or colors.gray)
  187. end
  188.  
  189. local function drawRouteMarkers()
  190. if not monitor then return end
  191. for index, route in ipairs(panel.routes) do
  192. local mx, my = route.marker[1], route.marker[2]
  193. monitor.setCursorPos(mx, my)
  194. monitor.setBackgroundColor(colors.black)
  195. if hasAlert(route) and blinkState then
  196. monitor.setTextColor(colors.red)
  197. elseif index == panel.selected then
  198. monitor.setTextColor(colors.white)
  199. else
  200. monitor.setTextColor(route.color)
  201. end
  202. monitor.write(route.active and "[*]" or "[ ]")
  203. end
  204. end
  205.  
  206. local function drawLegend()
  207. if not monitor then return end
  208. local _, h = monitor.getSize()
  209. local startY = math.max(1, h - #panel.routes - 1)
  210. for i, route in ipairs(panel.routes) do
  211. monitor.setCursorPos(2, startY + i - 1)
  212. monitor.setBackgroundColor(colors.black)
  213. if hasAlert(route) and blinkState then
  214. monitor.setTextColor(colors.red)
  215. elseif i == panel.selected then
  216. monitor.setTextColor(colors.white)
  217. else
  218. monitor.setTextColor(route.color)
  219. end
  220. local stateText = route.active and "KERESZT" or "EGYENES"
  221. local line = (route.active and "[*] " or "[ ] ") .. route.name .. " ID:" .. tostring(route.slaveId or "-") .. " " .. stateText
  222. if route.missing then
  223. line = line .. " NINCS ID"
  224. elseif route.offline then
  225. line = line .. " OFFLINE"
  226. end
  227. monitor.write(line)
  228. end
  229. end
  230.  
  231. local function redrawMonitor()
  232. if not monitor then return end
  233. drawDispatcherMap()
  234. drawRouteMarkers()
  235. drawLegend()
  236. term.redirect(native)
  237. end
  238.  
  239. local function sendTopState(route, enabled)
  240. if not route.slaveId then
  241. route.missing = true
  242. route.offline = true
  243. setStatus("Nincs slave ID beallitva")
  244. return false
  245. end
  246. route.missing = false
  247. if not openNet() then return false end
  248. rednet.send(route.slaveId, { cmd = "set_top", enabled = enabled }, PROTOCOL)
  249. local senderId, msg = rednet.receive(PROTOCOL, 2)
  250. if senderId == route.slaveId and type(msg) == "table" and msg.ok then
  251. route.active = msg.enabled and true or false
  252. route.offline = false
  253. setStatus(route.name .. " -> " .. (route.active and "KERESZT" or "EGYENES"))
  254. return true
  255. end
  256. route.offline = true
  257. setStatus("Nincs valasz slave #" .. tostring(route.slaveId))
  258. return false
  259. end
  260.  
  261. local function setAllStraight()
  262. if not openNet() then return end
  263. for _, route in ipairs(panel.routes) do
  264. route.active = false
  265. route.missing = route.slaveId == nil
  266. if route.slaveId then
  267. rednet.send(route.slaveId, { cmd = "set_top", enabled = false }, PROTOCOL)
  268. end
  269. end
  270. setStatus("Alaphelyzet: minden egyenes")
  271. end
  272.  
  273. local function queryStartupStates()
  274. if not openNet() then return end
  275. for _, route in ipairs(panel.routes) do
  276. route.active = false
  277. route.missing = route.slaveId == nil
  278. if route.slaveId then
  279. route.offline = true
  280. rednet.send(route.slaveId, { cmd = "get_state" }, PROTOCOL)
  281. else
  282. route.offline = true
  283. end
  284. end
  285. local timer = os.startTimer(2)
  286. while true do
  287. local event, a, b, c = os.pullEvent()
  288. if event == "rednet_message" then
  289. local senderId, msg, protocol = a, b, c
  290. if protocol == PROTOCOL and type(msg) == "table" and msg.ok then
  291. local route = findRouteBySlave(senderId)
  292. if route then
  293. route.missing = false
  294. route.offline = false
  295. route.active = msg.enabled and true or false
  296. end
  297. end
  298. elseif event == "timer" and a == timer then
  299. setStatus("Indulasi allapotok lekerdezve")
  300. return
  301. end
  302. end
  303. end
  304.  
  305. local function pingAll()
  306. if not openNet() then return end
  307. for _, route in ipairs(panel.routes) do
  308. route.missing = route.slaveId == nil
  309. if route.slaveId then
  310. route.offline = true
  311. rednet.send(route.slaveId, { cmd = "ping" }, PROTOCOL)
  312. else
  313. route.offline = true
  314. end
  315. end
  316. local timer = os.startTimer(1.5)
  317. while true do
  318. local event, a, b, c = os.pullEvent()
  319. if event == "rednet_message" then
  320. local senderId, msg, protocol = a, b, c
  321. if protocol == PROTOCOL and type(msg) == "table" and msg.ok then
  322. local route = findRouteBySlave(senderId)
  323. if route then
  324. route.missing = false
  325. route.offline = false
  326. if msg.enabled ~= nil then route.active = msg.enabled and true or false end
  327. end
  328. end
  329. elseif event == "timer" and a == timer then
  330. setStatus("Ping kesz")
  331. return
  332. end
  333. end
  334. end
  335.  
  336. local function routeFromTouch(x, y)
  337. for i, route in ipairs(panel.routes) do
  338. local mx, my = route.marker[1], route.marker[2]
  339. if x >= mx and x <= mx + 2 and y == my then
  340. return i, route
  341. end
  342. end
  343. return nil, nil
  344. end
  345.  
  346. local function touchLoop()
  347. while running and monitor do
  348. local event, side, x, y = os.pullEvent()
  349. if event == "monitor_touch" and side == MONITOR_SIDE then
  350. local index, route = routeFromTouch(x, y)
  351. if route then
  352. panel.selected = index
  353. sendTopState(route, not route.active)
  354. redrawMonitor()
  355. end
  356. elseif event == "monitor_resize" then
  357. redrawMonitor()
  358. end
  359. end
  360. end
  361.  
  362. local function receiverLoop()
  363. while running do
  364. local senderId, msg, protocol = rednet.receive()
  365.  
  366. if protocol == REQUEST_PROTOCOL and type(msg) == "table" and msg.cmd == "get_panel_state" then
  367. rednet.send(senderId, buildPanelState(), REQUEST_PROTOCOL)
  368.  
  369. elseif protocol == PROTOCOL and type(msg) == "table" and msg.ok then
  370. local route = findRouteBySlave(senderId)
  371. if route then
  372. route.missing = false
  373. route.offline = false
  374. if msg.enabled ~= nil then route.active = msg.enabled and true or false end
  375. redrawMonitor()
  376. end
  377. end
  378. end
  379. end
  380.  
  381. local function blinkLoop()
  382. while running do
  383. blinkState = not blinkState
  384. redrawMonitor()
  385. sleep(0.5)
  386. end
  387. end
  388.  
  389. local function prompt(text, default)
  390. write(text)
  391. return read(nil, nil, nil, default)
  392. end
  393.  
  394. local function editRoute(index)
  395. local route = panel.routes[index]
  396. term.clear()
  397. term.setCursorPos(1, 1)
  398. print("Ag szerkesztese: " .. route.name)
  399. route.name = prompt("Nev [" .. route.name .. "]: ", route.name)
  400. local sid = prompt("Slave ID [" .. tostring(route.slaveId or "") .. "]: ", route.slaveId and tostring(route.slaveId) or "")
  401. route.slaveId = tonumber(sid)
  402. route.missing = route.slaveId == nil
  403. route.offline = true
  404. setStatus("Ag frissitve")
  405. end
  406.  
  407. local function uiLoop()
  408. while running do
  409. term.redirect(native)
  410. term.setBackgroundColor(colors.black)
  411. term.setTextColor(colors.white)
  412. term.clear()
  413. term.setCursorPos(1, 1)
  414. local route = panel.routes[panel.selected]
  415. print("RTM ROUTE PANEL MANAGER")
  416. print("=======================")
  417. print("Kijelolt ag: " .. panel.selected .. " / " .. route.name)
  418. print("Slave ID: " .. tostring(route.slaveId or "nincs"))
  419. print("Allapot: " .. (route.active and "KERESZT" or "EGYENES"))
  420. print("Missing: " .. tostring(route.missing))
  421. print("Offline: " .. tostring(route.offline))
  422. print("")
  423. print("1 - Elozo ag")
  424. print("2 - Kovetkezo ag")
  425. print("3 - Ag valtasa")
  426. print("4 - Slave ID hozzarendeles")
  427. print("5 - Osszes ping")
  428. print("6 - Alaphelyzet (minden egyenes)")
  429. print("7 - Allapotok lekerdezese")
  430. print("8 - Mentes")
  431. print("9 - Betoltes")
  432. print("0 - Kilepes")
  433. print("")
  434. print("Status: " .. status)
  435. write("> ")
  436. local cmd = read()
  437. if cmd == "1" then
  438. panel.selected = panel.selected - 1
  439. if panel.selected < 1 then panel.selected = #panel.routes end
  440. elseif cmd == "2" then
  441. panel.selected = panel.selected + 1
  442. if panel.selected > #panel.routes then panel.selected = 1 end
  443. elseif cmd == "3" then
  444. sendTopState(route, not route.active)
  445. elseif cmd == "4" then
  446. editRoute(panel.selected)
  447. elseif cmd == "5" then
  448. pingAll()
  449. elseif cmd == "6" then
  450. setAllStraight()
  451. elseif cmd == "7" then
  452. queryStartupStates()
  453. elseif cmd == "8" then
  454. saveDb()
  455. elseif cmd == "9" then
  456. loadDb()
  457. queryStartupStates()
  458. elseif cmd == "0" then
  459. running = false
  460. break
  461. end
  462. redrawMonitor()
  463. end
  464. end
  465.  
  466. loadDb()
  467. openNet()
  468.  
  469. if peripheral.getType(MONITOR_SIDE) == "monitor" then
  470. monitor = peripheral.wrap(MONITOR_SIDE)
  471. monitor.setTextScale(0.5)
  472. end
  473.  
  474. queryStartupStates()
  475. redrawMonitor()
  476.  
  477. if monitor then
  478. parallel.waitForAny(uiLoop, touchLoop, receiverLoop, blinkLoop)
  479. else
  480. parallel.waitForAny(uiLoop, receiverLoop, blinkLoop)
  481. end
  482.  
  483. term.redirect(native)
  484. term.setBackgroundColor(colors.black)
  485. term.setTextColor(colors.white)
  486. term.clear()
  487. term.setCursorPos(1, 1)
  488. print("Leallva")
Advertisement
Comments
  • User was banned
    • User was banned
  • User was banned
    • User was banned
Add Comment
Please, Sign In to add comment