SHOW:
|
|
- or go back to the newest paste.
| 1 | os.loadAPI("ocs/apis/sensor")
| |
| 2 | rs.setOutput("top", false)
| |
| 3 | rednet.open("right")
| |
| 4 | local util = dofile("util")
| |
| 5 | local sensor = sensor.wrap("left")
| |
| 6 | local targets = sensor.getTargets() | |
| 7 | local reactorTarget = nil | |
| 8 | config = dofile("reactor.config")
| |
| 9 | term.clear() | |
| 10 | term.setCursorPos(1,1) | |
| 11 | io.write("Looking for the reactor...")
| |
| 12 | for name, target in pairs(targets) do | |
| 13 | target2 = sensor.getTargetDetails(name) | |
| 14 | if target2.Name == "Nuclear Reactor" then | |
| 15 | io.write("FOUND")
| |
| 16 | print() | |
| 17 | reactorTarget = name | |
| 18 | break | |
| 19 | end | |
| 20 | end | |
| 21 | ||
| 22 | local totalEnergyStored = 0 | |
| 23 | local totalEnergyCapacity = 0 | |
| 24 | local coolingSystemId = nil | |
| 25 | local storageSystemId = nil | |
| 26 | local statsSystemId = nil | |
| 27 | local cobblestoneSystemId = nil | |
| 28 | local coolingStatus = "Unknown" | |
| 29 | local reactorData = nil | |
| 30 | local systemRunning = false | |
| 31 | local totalRuntime = 0 | |
| 32 | local lastOutputAmount = 0 | |
| 33 | local startTime = 0 | |
| 34 | ||
| 35 | local storageBanks = {}
| |
| 36 | ||
| 37 | local function sendStatus() | |
| 38 | local statusMessage = textutils.serialize{type="reactor", sender="monitor", command="status", status = systemRunning and "ONLINE" or "OFFLINE"}
| |
| 39 | if coolingSystemId then rednet.send(coolingSystemId, statusMessage) end | |
| 40 | if cobblestoneSystemId then rednet.send(cobblestoneSystemId, statusMessage) end | |
| 41 | end | |
| 42 | ||
| 43 | local function startSystem() | |
| 44 | if not systemRunning and (coolingStatus == "ONLINE") and ((totalEnergyCapacity - totalEnergyStored) > config.energyBuffer) then | |
| 45 | rs.setOutput("top", true)
| |
| 46 | systemRunning = true | |
| 47 | sendStatus() | |
| 48 | end | |
| 49 | end | |
| 50 | ||
| 51 | local function stopSystem() | |
| 52 | if systemRunning then | |
| 53 | rs.setOutput("top", false)
| |
| 54 | systemRunning = false | |
| 55 | sendStatus() | |
| 56 | end | |
| 57 | end | |
| 58 | ||
| 59 | local function calculateEnergyTotals() | |
| 60 | local energyStored = 0 | |
| 61 | local energyCapacity = 0 | |
| 62 | for bankId,energyTotals in pairs(storageBanks) do | |
| 63 | energyStored = energyStored + energyTotals.stored | |
| 64 | energyCapacity = energyCapacity + energyTotals.capacity | |
| 65 | end | |
| 66 | totalEnergyStored = energyStored | |
| 67 | totalEnergyCapacity = energyCapacity | |
| 68 | if (totalEnergyCapacity - totalEnergyStored) < config.energyBuffer then | |
| 69 | stopSystem() | |
| 70 | else | |
| 71 | startSystem() | |
| 72 | end | |
| 73 | ||
| 74 | end | |
| 75 | ||
| 76 | local function handleCobblestoneSystem(senderId, message) | |
| 77 | if message.command == "announce" then | |
| 78 | cobblestoneSystemId = senderId | |
| 79 | rednet.send(storageSystemId, textutils.serialize{type="reactor", sender="monitor", command="ack"})
| |
| 80 | sendStatus() | |
| 81 | elseif message.command == "ack" then | |
| 82 | cobblestoneSystemId = senderId | |
| 83 | sendStatus() | |
| 84 | end | |
| 85 | end | |
| 86 | ||
| 87 | local function handleCoolingSystem(senderId, message) | |
| 88 | if message.command == "announce" then | |
| 89 | coolingSystemId = senderId | |
| 90 | rednet.send(coolingSystemId, textutils.serialize{type="reactor", sender="monitor", command="ack"})
| |
| 91 | sendStatus() | |
| 92 | elseif message.command == "start" then | |
| 93 | startSystem() | |
| 94 | elseif message.command == "stop" then | |
| 95 | stopSystem() | |
| 96 | elseif message.command == "status" then | |
| 97 | coolingStatus = message.status | |
| 98 | elseif message.command == "ack" then | |
| 99 | coolingSystemId = senderId | |
| 100 | sendStatus() | |
| 101 | end | |
| 102 | end | |
| 103 | ||
| 104 | local function handleStorageSystem(senderId, message) | |
| 105 | if message.command == "announce" then | |
| 106 | storageSystemId = senderId | |
| 107 | rednet.send(storageSystemId, textutils.serialize{type="reactor", sender="monitor", command="ack", id = message.id})
| |
| 108 | elseif message.command == "ack" then | |
| 109 | storageSystemId = senderId | |
| 110 | elseif message.command == "capacity" then | |
| 111 | storageBanks[message.id] = { stored = message.stored, capacity = message.capacity }
| |
| 112 | calculateEnergyTotals() | |
| 113 | end | |
| 114 | end | |
| 115 | ||
| 116 | local function handleStatsSystem(senderId, message) | |
| 117 | if message.command == "announce" then | |
| 118 | statsSystemId = senderId | |
| 119 | rednet.send(storageSystemId, textutils.serialize{type="reactor", sender="monitor", command="ack"})
| |
| 120 | elseif message.command == "ack" then | |
| 121 | statsSystemId = senderId | |
| 122 | end | |
| 123 | end | |
| 124 | ||
| 125 | local function doNetwork() | |
| 126 | print("Starting network...")
| |
| 127 | rednet.broadcast(textutils.serialize{type="reactor", sender="monitor", command="announce"})
| |
| 128 | while true do | |
| 129 | local event, senderId, data, distance = os.pullEvent("rednet_message")
| |
| 130 | local message = textutils.unserialize(data) | |
| 131 | if message and message.type == "reactor" then | |
| 132 | if message.sender == "cooling" then | |
| 133 | handleCoolingSystem(senderId, message) | |
| 134 | elseif message.sender == "storage" then | |
| 135 | handleStorageSystem(senderId, message) | |
| 136 | elseif message.sender == "cobblestone" then | |
| 137 | handleCobblestoneSystem(senderId, message) | |
| 138 | elseif message.sender == "stats" then | |
| 139 | handleStatsSystem(senderId, message) | |
| 140 | elseif message.sender == "controller" then | |
| 141 | -- handleControlSystem(senderId, message) | |
| 142 | end | |
| 143 | end | |
| 144 | end | |
| 145 | print("network coro exiting")
| |
| 146 | end | |
| 147 | ||
| 148 | local function doKeyboard() | |
| 149 | print("Starting keyboard handler...")
| |
| 150 | while true do | |
| 151 | local event, key = os.pullEvent("char")
| |
| 152 | if string.lower(key) == "q" then | |
| 153 | break | |
| 154 | end | |
| 155 | end | |
| 156 | print("keyboard coro exiting")
| |
| 157 | end | |
| 158 | ||
| 159 | local function doMenu() | |
| 160 | print("Displaying menu...")
| |
| 161 | while true do | |
| 162 | sleep(1) | |
| 163 | if reactorData then | |
| 164 | term.clear() | |
| 165 | term.setCursorPos(1,1) | |
| 166 | local runTime = 0 | |
| 167 | if startTime > 0 then | |
| 168 | runTime = totalRuntime + (os.clock() - startTime) | |
| 169 | else | |
| 170 | runTime = totalRuntime | |
| 171 | end | |
| 172 | local totalOutput = 0 | |
| 173 | if reactorData.Output > 0 then lastOutputAmount = reactorData.Output end | |
| 174 | if runTime > 0 then totalOutput = util.round((lastOutputAmount * runTime * 20) / 1000000, 2) end | |
| 175 | print(string.format("System Status: %s", reactorData.Active and "ONLINE" or "OFFLINE"))
| |
| 176 | print(string.format("System Runtime: %ss", util.commavalue(runTime)))
| |
| 177 | print(string.format("Current Output: %s", util.commavalue(reactorData.Output)))
| |
| 178 | print(string.format("Total Output: %sM", util.commavalue(totalOutput)))
| |
| 179 | print(string.format("Heat: %s", util.commavalue(reactorData.Heat)))
| |
| 180 | print(string.format("Max Heat: %s", util.commavalue(reactorData.MaxHeat)))
| |
| 181 | print(string.format("Cooling System: %s", coolingStatus))
| |
| 182 | print(string.format("Energy Stored:\n %s/%s", util.commavalue(totalEnergyStored), util.commavalue(totalEnergyCapacity)))
| |
| 183 | if statsSystemId then | |
| 184 | stats = { status = reactorData.Active, runTime = runTime, output = reactorData.Output, totalOutput = (lastOutputAmount * runTime * 20), heat = reactorData.Heat, maxHeat = reactorData.MaxHeat }
| |
| 185 | rednet.send(statsSystemId, textutils.serialize{type="reactor", sender="monitor", command="stats", stats = stats})
| |
| 186 | end | |
| 187 | print("Press Q to exit")
| |
| 188 | end | |
| 189 | end | |
| 190 | print("menu coro exiting")
| |
| 191 | end | |
| 192 | ||
| 193 | local function fastSleep() | |
| 194 | sleep(.5) | |
| 195 | end | |
| 196 | ||
| 197 | local function monitorReactor() | |
| 198 | print("Starting Reactor Monitor...")
| |
| 199 | while true do | |
| 200 | reactorData = sensor.getTargetDetails(reactorTarget) | |
| 201 | if not reactorData or reactorData.Heat > 0 then | |
| 202 | rs.setOutput("top", false)
| |
| 203 | print("We have heat or reactorData is nil! Aborting to prevent meltdown.")
| |
| 204 | break | |
| 205 | end | |
| 206 | if reactorData.Output > 0 and startTime == 0 then | |
| 207 | startTime = os.clock() | |
| 208 | elseif reactorData.Output == 0 and startTime > 0 then | |
| 209 | totalRuntime = totalRuntime + (os.clock() - startTime) | |
| 210 | startTime = 0; | |
| 211 | end | |
| 212 | fastSleep() | |
| 213 | end | |
| 214 | print("monitor coro exiting")
| |
| 215 | end | |
| 216 | ||
| 217 | local function startup() | |
| 218 | if reactorTarget then | |
| 219 | parallel.waitForAny(monitorReactor, doNetwork, doKeyboard, doMenu) | |
| 220 | else | |
| 221 | error("no reactor found")
| |
| 222 | end | |
| 223 | end | |
| 224 | ||
| 225 | local rtn, error = pcall(startup) | |
| 226 | if not rtn then | |
| 227 | print("Reactor failed: " .. error)
| |
| 228 | end | |
| 229 | print("Forcing reactor OFFLINE.")
| |
| 230 | print("Exiting.")
| |
| 231 | stopSystem() |