--Mekanism Fission Reactor Control w/Remote Emergency Monitor
--v0.92 by SemlerPDX Aug21-26 2021
--Reactor Control & Monitor Scripts
-- Control PC (this script): https://pastebin.com/2VrXwGNH
-- and
-- Emergency Monitor PC: https://pastebin.com/uxE2jE2B
-- and
-- Remote Status Monitor PC: https://pastebin.com/59EWW86J
--
-- example image of setup: https://imgur.com/a/nrKeBcH
--Redstone I/O Sides
battery = "left"
reactor = "right"
monitoring = "top"
--Peripheral Sides
monitorSide = "bottom"
modemSide = "back"
--Battery Monitor Redstone Min/Max Levels (0-15)
minBank = 7
maxBank = 15
--id of rednet protocols
protocol = "PowerSys"
protocolCMD = "PowerCMD"
controlPC = 20 --id of (this) reactor control PC
remotePC = 21 --id of remote display status monitor PC
hazardPC = 22 --id of critical shutdown monitor PC
--Remote Command Keywords
msgConfirmed = "copycopy"
msgDenied = "samestate"
faultClear = "FaultCleared"
clearFaults = "ClearFault"
commandClear = "enable"
commandON = "on"
commandOFF = "off"
--Remote Command Receive Timeout (in seconds)
timeout = 5
--Array of Redstone (0-15) into % of 100 for Text Display
batteryLevels = {7,13,20,27,33,40,47,53,60,67,73,80,87,93,100}
--Init
y = 1
online = false
reacting = false
shutdownReason = "unknown"
redstone.setOutput(reactor,false)
redstone.setOutput(monitoring,false)
monitor = peripheral.wrap(monitorSide)
modem = peripheral.wrap(modemSide)
rednet.open(modemSide)
--Remote Reactor Status Monitor Send Function
local function fStatusUpdate(msg)
rednet.send(remotePC,msg,protocol)
end
--Refresh/Clear Display(s) Function
local function fSet(remoteClear)
y = 1
term.clear()
monitor.clear()
term.setCursorPos(1,1)
monitor.setCursorPos(1,1)
if remoteClear then
fStatusUpdate("clear")
end
end
--Direct Monitor Screen Write Function
local function fDisplay(txt)
monitor.write(txt)
monitor.setCursorPos(1,y)
end
--Combined Term/Monitor/Remote Write Function
local function fWrite(msg,display,send)
y = y + 1
term.write(msg)
term.setCursorPos(1,y)
if display then
fDisplay(msg)
end
if send then
fStatusUpdate(msg)
end
end
--Change Redstone Input (0-15) into Percentage for Text Display
local function fBankStatus(cellLevel)
bankCapacity = "Bank Capacity < 7%"
if cellLevel == 1 then
bankCapacity = "Bank Capacity > "..batteryLevels[cellLevel].."%"
elseif cellLevel >= 2 and cellLevel <= 14 then
bankCapacity = "Bank Capacity >"..batteryLevels[cellLevel].."%"
else
bankCapacity = "Bank Capacity 100%"
end
return bankCapacity
end
--Acknowledge Emergency Shutdown Fault and Get Reason from Monitoring PC
local function fAcknowledge()
shutdownReason = "unknown"
id,reason = rednet.receive(protocol)
rednet.send(id,msgConfirmed,protocol)
if reason ~= nil then
shutdownReason = reason
end
end
--MAIN LOOP
while true do
--Emergency Shutdown Monitor Function
local function fShutdown()
local criticalShutdown = redstone.getInput(monitoring)
while true do
sleep(0.05)
criticalShutdown = redstone.getInput(monitoring)
if criticalShutdown then
redstone.setOutput(reactor,false)
criticalShutdown = nil
return true
end
end
end
--Master Online State & Battery Monitor Function
local function fBatteryMonitor()
while true do
sleep(5)
fSet(true)
currBank = redstone.getAnalogInput(battery)
reacting = redstone.getOutput(reactor)
currStatus = fBankStatus(currBank)
fWrite(currStatus,true,true)
if currBank == maxBank and reacting then
fWrite("Bank at capacity",true,true)
fWrite("Shutting down...",true,true)
redstone.setOutput(monitoring,false)
redstone.setOutput(reactor,false)
sleep(10)
elseif currBank <= minBank and not reacting and online then
fWrite("Bank below min",true,true)
fWrite("Enabling reaction",true,true)
redstone.setOutput(monitoring,true)
sleep(5)
redstone.setOutput(reactor,true)
elseif currBank >= minBank and not reacting and online then
fWrite("Bank at capacity",true,true)
fWrite("Reactor in standby",true,true)
elseif reacting and not online then
fWrite("Command Offline",true,true)
fWrite("Shutting down...",true,true)
redstone.setOutput(monitoring,false)
redstone.setOutput(reactor,false)
sleep(10)
elseif not reacting and not online then
fWrite("Systems Offline",true,true)
fWrite("Reactor in standby",true,true)
else
fWrite("Systems Online",true,true)
if reacting then
fWrite("Reactor operating",true,true)
else
fWrite("Reactor in standby",true,true)
end
end
monitor.setCursorPos(1,5)
if online then
fDisplay(" -Tap to Disable- ")
fStatusUpdate(commandON)
else
fDisplay(" -Tap to Enable- ")
fStatusUpdate(commandOFF)
end
end
end
--Touchscreen Systems Online Toggle
local function fTouch()
while true do
sleep(3)
event,side,xPos,yPos = os.pullEvent("monitor_touch")
if not online then
online = true
elseif online then
online = false
end
end
end
--Rednet Systems Online Toggle
local function fListen()
while true do
id,message = rednet.receive(protocolCMD)
rednet.send(id,msgConfirmed,protocolCMD)
id,message = rednet.receive(protocolCMD,timeout)
if message ~= nil then
if message == commandON and not online then
online = true
rednet.send(id,msgConfirmed,protocolCMD)
elseif message == commandOFF and online then
online = false
rednet.send(id,msgConfirmed,protocolCMD)
else
rednet.send(id,msgDenied,protocolCMD)
end
end
end
end
--Emergency Shutdown Fault Acknowledgment
local function fClearFault()
while true do
sleep(5)
local faultsActive = redstone.getInput(monitoring)
if not faultsActive then
faultsActive = nil
return true
end
end
end
--Fault Clear Terminal Input Confirmation Function
local function fConfirmCleared()
while true do
fSet(true)
currBank = redstone.getAnalogInput(battery)
currStatus = fBankStatus(currBank)
fWrite(currStatus,true,true)
fWrite("Critical "..shutdownReason.."!",true,true)
fWrite("EMERGENCY SHUTDOWN",true,true)
fWrite("Clear faults, then type 'enable' and press Enter")
term.write("> ")
local confirmCleared = read()
fSet()
if confirmCleared == commandClear then
fWrite("Confirming Cleared")
rednet.send(hazardPC,faultClear,protocol)
id,message = rednet.receive(protocol,15)
if message == faultCleared then
sleep(5)
end
faultsActive = redstone.getInput(monitoring)
fSet()
if not faultsActive then
fWrite("Clear Confirmed")
fWrite("Zero Faults Detected")
fWrite("Enabling Operations")
return true
else
fWrite("Clear Disregarded")
fWrite("Reactor Faults Detected!")
fWrite("Cannot Enable Operations!")
end
else
fWrite("Invalid Command...")
fWrite("Reactor Faults Detected!")
fWrite("Clear faults and enter 'enable'")
end
sleep(4)
end
end
--MAIN Reactor Function monitoring battery, cmd input, and shutdown signal
reactorFunction = parallel.waitForAny(fShutdown,fBatteryMonitor,fTouch,fListen)
--Emergency Shutdown, output to screens/rednet
if reactorFunction == 1 then
redstone.setOutput(monitoring,false)
fAcknowledge()
--Force Terminal Input that faults cleared
faultAcknowledged = parallel.waitForAll(fClearFault,fConfirmCleared)
end
end
Comments