Advertisement
DanFrmSpace

solar_remote_monitor

Jun 7th, 2025 (edited)
263
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 10.99 KB | None | 0 0
  1. -- Remote Energy Farm Monitor Script
  2. -- Receives wireless data and displays on monitor
  3.  
  4. local WIRELESS_CHANNEL = 100
  5. local MONITOR_SIDE = "top" -- Change this to match your monitor position
  6. local REFRESH_TIMEOUT = 30 -- seconds before showing "no data" warning
  7.  
  8. -- Initialize peripherals
  9. local wirelessModem = peripheral.find("modem", function(name, modem)
  10.     return modem.isWireless()
  11. end)
  12.  
  13. if not wirelessModem then
  14.     error("No wireless modem found")
  15. end
  16.  
  17. print("Found wireless modem: " .. peripheral.getName(wirelessModem))
  18.  
  19. local monitor = peripheral.wrap(MONITOR_SIDE)
  20. if not monitor then
  21.     error("No monitor found on " .. MONITOR_SIDE)
  22. end
  23.  
  24. -- Open wireless channel
  25. wirelessModem.open(WIRELESS_CHANNEL)
  26. print("Opened wireless channel " .. WIRELESS_CHANNEL)
  27.  
  28. -- Monitor setup
  29. monitor.setTextScale(0.5)
  30. local monitorWidth, monitorHeight = monitor.getSize()
  31.  
  32. -- Color definitions
  33. local colorScheme = {
  34.     background = colors.black,
  35.     header = colors.yellow,
  36.     good = colors.green,
  37.     warning = colors.orange,
  38.     critical = colors.red,
  39.     info = colors.white,
  40.     accent = colors.cyan
  41. }
  42.  
  43. -- Data storage
  44. local lastData = nil
  45. local lastUpdateTime = 0
  46.  
  47. -- Function to format energy values
  48. local function formatEnergy(energy)
  49.     if energy >= 1000000000 then
  50.         return string.format("%.2fGFE", energy / 1000000000)
  51.     elseif energy >= 1000000 then
  52.         return string.format("%.2fMFE", energy / 1000000)
  53.     elseif energy >= 1000 then
  54.         return string.format("%.2fkFE", energy / 1000)
  55.     else
  56.         return string.format("%.0fFE", energy)
  57.     end
  58. end
  59.  
  60. -- Function to get color based on percentage
  61. local function getPercentageColor(percentage)
  62.     if percentage >= 80 then
  63.         return colorScheme.good
  64.     elseif percentage >= 50 then
  65.         return colorScheme.warning
  66.     else
  67.         return colorScheme.critical
  68.     end
  69. end
  70.  
  71. -- Function to draw a progress bar
  72. local function drawProgressBar(x, y, width, percentage, label)
  73.     local fillWidth = math.floor((percentage / 100) * width)
  74.    
  75.     monitor.setCursorPos(x, y)
  76.     monitor.setTextColor(colorScheme.info)
  77.     monitor.write(label .. ":")
  78.    
  79.     monitor.setCursorPos(x, y + 1)
  80.     monitor.setBackgroundColor(colors.gray)
  81.     monitor.write(string.rep(" ", width))
  82.    
  83.     monitor.setCursorPos(x, y + 1)
  84.     monitor.setBackgroundColor(getPercentageColor(percentage))
  85.     monitor.write(string.rep(" ", fillWidth))
  86.    
  87.     monitor.setCursorPos(x + width + 1, y + 1)
  88.     monitor.setBackgroundColor(colorScheme.background)
  89.     monitor.setTextColor(colorScheme.info)
  90.     monitor.write(string.format(" %.1f%%", percentage))
  91. end
  92.  
  93. -- Function to draw header
  94. local function drawHeader()
  95.     monitor.setBackgroundColor(colorScheme.background)
  96.     monitor.clear()
  97.    
  98.     monitor.setCursorPos(1, 1)
  99.     monitor.setTextColor(colorScheme.header)
  100.     monitor.setBackgroundColor(colorScheme.background)
  101.    
  102.     local title = "ENERGY FARM MONITORING SYSTEM"
  103.     local centerX = math.floor((monitorWidth - string.len(title)) / 2) + 1
  104.     monitor.setCursorPos(centerX, 1)
  105.     monitor.write(title)
  106.    
  107.     monitor.setCursorPos(1, 2)
  108.     monitor.setTextColor(colorScheme.accent)
  109.     monitor.write(string.rep("=", monitorWidth))
  110. end
  111.  
  112. -- Function to draw connection status
  113. local function drawConnectionStatus()
  114.     local currentTime = os.epoch("utc") / 1000
  115.     local timeSinceUpdate = currentTime - lastUpdateTime
  116.    
  117.     monitor.setCursorPos(1, 3)
  118.     monitor.setTextColor(colorScheme.info)
  119.     monitor.write("Status: ")
  120.    
  121.     if timeSinceUpdate > REFRESH_TIMEOUT then
  122.         monitor.setTextColor(colorScheme.critical)
  123.         monitor.write("NO DATA - Connection Lost")
  124.     elseif timeSinceUpdate > 10 then
  125.         monitor.setTextColor(colorScheme.warning)
  126.         monitor.write("Delayed - " .. math.floor(timeSinceUpdate) .. "s ago")
  127.     else
  128.         monitor.setTextColor(colorScheme.good)
  129.         monitor.write("Connected - Live Data")
  130.     end
  131.    
  132.     monitor.setCursorPos(monitorWidth - 19, 3)
  133.     monitor.setTextColor(colorScheme.info)
  134.     monitor.write("Time: " .. textutils.formatTime(os.time(), true))
  135. end
  136.  
  137. -- Function to draw solar panel section
  138. local function drawSolarSection(stats, startY)
  139.     monitor.setCursorPos(1, startY)
  140.     monitor.setTextColor(colorScheme.header)
  141.     monitor.write("SOLAR PANELS")
  142.    
  143.     local y = startY + 1
  144.     monitor.setCursorPos(1, y)
  145.     monitor.setTextColor(colorScheme.info)
  146.     monitor.write("Energy: " .. formatEnergy(stats.solar.totalEnergy) .. " / " .. formatEnergy(stats.solar.totalMaxEnergy))
  147.    
  148.     y = y + 1
  149.     monitor.setCursorPos(1, y)
  150.     monitor.write("Production: " .. formatEnergy(stats.solar.totalProductionRate) .. "/t")
  151.    
  152.     y = y + 1
  153.     monitor.setCursorPos(1, y)
  154.     monitor.setTextColor(stats.solar.panelsSeeSun == stats.solar.totalPanels and colorScheme.good or colorScheme.warning)
  155.     monitor.write("Sun Visibility: " .. stats.solar.panelsSeeSun .. "/" .. stats.solar.totalPanels .. " panels")
  156.    
  157.     y = y + 2
  158.     drawProgressBar(1, y, 30, stats.solar.averagePercentage, "Solar Fill Level")
  159.    
  160.     return y + 3
  161. end
  162.  
  163. -- Function to draw energy cube section
  164. local function drawCubeSection(stats, startY)
  165.     monitor.setCursorPos(1, startY)
  166.     monitor.setTextColor(colorScheme.header)
  167.     monitor.write("ENERGY STORAGE")
  168.    
  169.     local y = startY + 1
  170.     monitor.setCursorPos(1, y)
  171.     monitor.setTextColor(colorScheme.info)
  172.     monitor.write("Energy: " .. formatEnergy(stats.cubes.totalEnergy) .. " / " .. formatEnergy(stats.cubes.totalMaxEnergy))
  173.    
  174.     y = y + 1
  175.     monitor.setCursorPos(1, y)
  176.     monitor.setTextColor(stats.cubes.ejectingCubes > 0 and colorScheme.good or colorScheme.warning)
  177.     monitor.write("Ejecting: " .. stats.cubes.ejectingCubes .. "/" .. stats.cubes.totalCubes .. " cubes")
  178.    
  179.     y = y + 2
  180.     drawProgressBar(1, y, 30, stats.cubes.averagePercentage, "Storage Fill Level")
  181.    
  182.     return y + 3
  183. end
  184.  
  185. -- Function to draw system overview
  186. local function drawSystemOverview(stats, startY)
  187.     monitor.setCursorPos(1, startY)
  188.     monitor.setTextColor(colorScheme.header)
  189.     monitor.write("SYSTEM OVERVIEW")
  190.    
  191.     local y = startY + 1
  192.     monitor.setCursorPos(1, y)
  193.     monitor.setTextColor(colorScheme.info)
  194.     monitor.write("Total Energy: " .. formatEnergy(stats.system.totalSystemEnergy))
  195.    
  196.     y = y + 1
  197.     monitor.setCursorPos(1, y)
  198.     monitor.write("Total Capacity: " .. formatEnergy(stats.system.totalSystemCapacity))
  199.    
  200.     y = y + 2
  201.     drawProgressBar(1, y, 40, stats.system.systemPercentage, "System Fill Level")
  202.    
  203.     return y + 3
  204. end
  205.  
  206. -- Function to draw individual device details
  207. local function drawDeviceDetails(data, startY)
  208.     if startY >= monitorHeight - 2 then
  209.         return startY
  210.     end
  211.    
  212.     monitor.setCursorPos(1, startY)
  213.     monitor.setTextColor(colorScheme.header)
  214.     monitor.write("DEVICE STATUS")
  215.    
  216.     local y = startY + 1
  217.     local col1 = 1
  218.     local col2 = math.floor(monitorWidth / 2) + 1
  219.    
  220.     -- Solar panels column
  221.     monitor.setCursorPos(col1, y)
  222.     monitor.setTextColor(colorScheme.accent)
  223.     monitor.write("Solar Panels:")
  224.     y = y + 1
  225.    
  226.     local solarCount = 0
  227.     for name, panelData in pairs(data.solar) do
  228.         if y >= monitorHeight then break end
  229.         solarCount = solarCount + 1
  230.         if solarCount <= 5 then -- Show first 5 panels
  231.             monitor.setCursorPos(col1, y)
  232.             monitor.setTextColor(panelData.canSeeSun and colorScheme.good or colorScheme.warning)
  233.             local shortName = string.gsub(name, "advancedSolarGenerator_", "S")
  234.             monitor.write(shortName .. ": " .. string.format("%.0f%%", panelData.energyPercentage))
  235.             y = y + 1
  236.         end
  237.     end
  238.    
  239.     -- Energy cubes column
  240.     y = startY + 1
  241.     monitor.setCursorPos(col2, y)
  242.     monitor.setTextColor(colorScheme.accent)
  243.     monitor.write("Energy Cubes:")
  244.     y = y + 1
  245.    
  246.     local cubeCount = 0
  247.     for name, cubeData in pairs(data.cubes) do
  248.         if y >= monitorHeight then break end
  249.         cubeCount = cubeCount + 1
  250.         if cubeCount <= 5 then -- Show first 5 cubes
  251.             monitor.setCursorPos(col2, y)
  252.             monitor.setTextColor(cubeData.isEjecting and colorScheme.good or colorScheme.info)
  253.             local shortName = string.gsub(name, "advancedEnergyCube_", "C")
  254.             monitor.write(shortName .. ": " .. string.format("%.0f%%", cubeData.energyPercentage))
  255.             y = y + 1
  256.         end
  257.     end
  258.    
  259.     return math.max(startY + 7, y)
  260. end
  261.  
  262. -- Function to update display
  263. local function updateDisplay()
  264.     if not lastData then
  265.         drawHeader()
  266.         drawConnectionStatus()
  267.         monitor.setCursorPos(1, 5)
  268.         monitor.setTextColor(colorScheme.warning)
  269.         monitor.write("Waiting for data from energy farm...")
  270.         return
  271.     end
  272.    
  273.     drawHeader()
  274.     drawConnectionStatus()
  275.    
  276.     local y = 5
  277.     y = drawSolarSection(lastData.stats, y)
  278.     y = drawCubeSection(lastData.stats, y)
  279.     y = drawSystemOverview(lastData.stats, y)
  280.    
  281.     if y < monitorHeight - 5 then
  282.         drawDeviceDetails(lastData, y)
  283.     end
  284. end
  285.  
  286. -- Function to handle incoming messages
  287. local function handleMessage(message)
  288.     print("Received message: " .. textutils.serialize(message))
  289.     if type(message) == "table" and message.data and message.source == "computer_1" then
  290.         lastData = message.data
  291.         lastUpdateTime = os.epoch("utc") / 1000
  292.         updateDisplay()
  293.         print("Data updated successfully")
  294.     else
  295.         print("Message format invalid or wrong source")
  296.     end
  297. end
  298.  
  299. -- Main program loop
  300. local function main()
  301.     print("Starting Remote Energy Monitor...")
  302.     print("Listening on channel: " .. WIRELESS_CHANNEL)
  303.     print("Monitor size: " .. monitorWidth .. "x" .. monitorHeight)
  304.    
  305.     -- Initial display
  306.     updateDisplay()
  307.    
  308.     while true do
  309.         local event, side, channel, replyChannel, message, distance = os.pullEvent()
  310.        
  311.         if event == "modem_message" then
  312.             print("Modem message received on channel " .. channel .. " (listening on " .. WIRELESS_CHANNEL .. ")")
  313.             if channel == WIRELESS_CHANNEL then
  314.                 handleMessage(message)
  315.             end
  316.         elseif event == "timer" then
  317.             -- Periodic update to refresh connection status
  318.             updateDisplay()
  319.         end
  320.        
  321.         -- Set a timer for periodic updates
  322.         os.startTimer(5)
  323.     end
  324. end
  325.  
  326. -- Error handling wrapper
  327. local function runWithErrorHandling()
  328.     local success, error = pcall(main)
  329.     if not success then
  330.         monitor.setBackgroundColor(colors.black)
  331.         monitor.clear()
  332.         monitor.setCursorPos(1, 1)
  333.         monitor.setTextColor(colors.red)
  334.         monitor.write("ERROR: " .. tostring(error))
  335.         print("Error occurred: " .. tostring(error))
  336.         print("Restarting in 5 seconds...")
  337.         sleep(5)
  338.         runWithErrorHandling()
  339.     end
  340. end
  341.  
  342. -- Start the program
  343. runWithErrorHandling()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement