View difference between Paste ID: 4WrsTJ8V and svcXu5TT
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()