Advertisement
meigrafd

OpenComputers: Nuclear Reactor Control - Robot (v0.2)

Aug 13th, 2015
102
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 17.97 KB | None | 0 0
  1. --[[
  2.  
  3.  Nuclear Reactor Control - by meigrafd @ 16.08.2015
  4.  
  5.  This Script is used to automatically control a Nuclear-Reactor with a Robot.
  6.  The Robot checks the Reactor-Inventory, push Coolant Cells into and replaces depleted Uran.
  7.  It also monitores Reactor heat and drops Uran if it still heats up after shutdown to prevent explosion.
  8.  
  9.  Requires:
  10.    OpenComputers >=1.5
  11.  
  12.  Setup Reactor like:
  13.   https://app.box.com/s/fu5sqhgd19cf3vt6qu3j15r9lx7efjty
  14.  Robot must be placed so the Reactor is in front of it!
  15.  Bundled Cable ends to Robot.
  16.  First Thermal Sensor turns Reactor off. Set this to max 1500.
  17.  Second Thermal Sensor tells Robot to drop Uran Cells to prevent explosion. Set this to max 2500.
  18.   (when Reactor was on it will still heat up after shutdown)
  19.  For a little bit better Cooling and Blastprotection you also should add Water above the complete Reactor.
  20.  
  21.  As Robot you should use a Creative one because it doesnt use Power and you have enough space for Addons.
  22.  
  23.  Craft the Robot minimum with:
  24.  - Inventory Controller Upgrade
  25.  - Inventory Upgrade
  26.  - Chunkloader Upgrade
  27.  - Geolyzer Block
  28.  - Screen (tier 1)
  29.  - Keyboard
  30.  - Disk Drive
  31.  - Wireless Network Card (you should add this later and add instead an 'Card Container'-Upgrade (tier3))
  32.  - Redstone Card (tier 2)
  33.  - Internet Card (otherwise pastebin cmd doesnt work)
  34.  - APU (Creative)
  35.  - EEPROM (lua)
  36.  - Hard Disk Drive
  37.  - RAM (tier 2)
  38.  
  39.  NOTE: You must craft each Wireless Card yourself so it have an unique Modem-Address!
  40.  
  41.  Setup Reactor Inventory as (you only need to place all the Reactor Heat Vent. Robot does the rest):
  42.    http://s2.postimage.org/5r41iiq15/Reactor_Setup.jpg
  43.  (biggest Setup with 1120 EU/t)
  44.  
  45.  Install the Scripts as 'autorun.lua'
  46.  
  47.  Scroll down to: CONFIG - START
  48.  
  49.  
  50. --]]
  51.  
  52.  
  53. --[[ Internal values - DONT change! ]]
  54.  
  55. local color = require("colors")  -- http://ocdoc.cil.li/api:colors .. only works for bundled cables
  56. local component = require("component")  -- http://ocdoc.cil.li/api:component
  57. local event = require("event")  -- http://ocdoc.cil.li/api:event
  58. local robot = require("robot")  -- http://ocdoc.cil.li/api:robot
  59. local side = require("sides")  -- http://ocdoc.cil.li/api:sides
  60. local serial = require("serialization")
  61. local term = require("term")  -- http://ocdoc.cil.li/api:term
  62. local ic = component.inventory_controller  -- http://ocdoc.cil.li/component:inventory_controller
  63. local geo = component.geolyzer  -- http://ocdoc.cil.li/component:geolyzer
  64. local gpu = component.gpu  -- http://ocdoc.cil.li/component:gpu
  65. local rs = component.redstone
  66. local wlan = component.modem
  67. local wlanPort = 7331
  68.  
  69. local version = 0.2
  70. reactorState = 'off'
  71. uranDropped = false
  72. thermalTriggered = false
  73. commandsexecdCount=1
  74. w,h = gpu.getResolution()
  75. serverAddress = nil
  76. wlan.open(wlanPort)
  77.  
  78.  
  79. ---[[ CONFIG - START ]]
  80.  
  81.  
  82. -- Chest Inventory Sides for which Items. Only valid sides: left, right, back, up, down
  83. -- NOTE: Only use one Chest for one Type of Item!
  84. -- Fastest for Coolant will be "up" or "down"
  85. -- Put a Chest below the Robot as Trash, where it drops all it takes out of Reactor.
  86. chestCoolant = "up"
  87. chestUran = "left"
  88. chestTrash = "down"
  89. chestReactor = "front"
  90.  
  91. -- Wire Colors. Available Colors with Bundled Cable: http://computercraft.info/wiki/Colors_(API)#Colors
  92. wireReactor = color.green -- To turn Reactor on/off
  93. wireThermal1 = color.blue -- If Reactor Temperature gets >1500
  94. wireThermal2 = color.red -- If Reactor Temperature gets >2500
  95.  
  96. -- Bundled Cable Side. Only valid sides: back, left, right
  97. wireSide = side.back
  98.  
  99. local CheckEvery = 0.5 -- sec. Dont set too high! (but also not lower 0.5)
  100.  
  101. local UseReactorSetup = 1
  102. --[[ Set to 1 or 2.
  103. 1 = Biggest with five Quad-Fuel-Rods in a row, twice = 1120EU/t. NOTE: heats much faster up!
  104. 2 = three Quad-Fuel-Rods in a row, twice = 640EU/t.
  105. --]]
  106.  
  107.  
  108. ---[[ CONFIG - END ]]
  109.  
  110.  
  111.  
  112. --[[
  113.  
  114.   Required Reactor Inventory setup Table.
  115.   first row from left to right, then the second row from left to right, etc.
  116.   one row = 9 columns.
  117.   NOTE: Not the exact Item-Name is used, just a match of e.g. *Coolant* so 10k or 60k Coolant Cells can be used,
  118.         but better use 60k Coolant Cells instead of 10k.
  119. --]]
  120.  
  121. if UseReactorSetup == 1 then
  122.     -- 5 Quad-Fuel-Rods in a row, twice.
  123.     RequiredReactorInventory = {
  124.         "Reactor Heat Vent",
  125.         "Reactor Heat Vent",
  126.         "Reactor Heat Vent",
  127.         "Reactor Heat Vent",
  128.         "Reactor Heat Vent",
  129.         "Reactor Heat Vent",
  130.         "Reactor Heat Vent",
  131.         "Reactor Heat Vent",
  132.         "Reactor Heat Vent",
  133.    
  134.         "Reactor Heat Vent",
  135.         "Coolant Cell",
  136.         "Coolant Cell",
  137.         "Coolant Cell",
  138.         "Coolant Cell",
  139.         "Coolant Cell",
  140.         "Coolant Cell",
  141.         "Coolant Cell",
  142.         "Reactor Heat Vent",
  143.    
  144.         "Reactor Heat Vent",
  145.         "Coolant Cell",
  146.         "Uran",
  147.         "Uran",
  148.         "Uran",
  149.         "Uran",
  150.         "Uran",
  151.         "Coolant Cell",
  152.         "Reactor Heat Vent",
  153.    
  154.         "Reactor Heat Vent",
  155.         "Coolant Cell",
  156.         "Uran",
  157.         "Uran",
  158.         "Uran",
  159.         "Uran",
  160.         "Uran",
  161.         "Coolant Cell",
  162.         "Reactor Heat Vent",
  163.    
  164.         "Reactor Heat Vent",
  165.         "Coolant Cell",
  166.         "Coolant Cell",
  167.         "Coolant Cell",
  168.         "Coolant Cell",
  169.         "Coolant Cell",
  170.         "Coolant Cell",
  171.         "Coolant Cell",
  172.         "Reactor Heat Vent",
  173.    
  174.         "Reactor Heat Vent",
  175.         "Reactor Heat Vent",
  176.         "Reactor Heat Vent",
  177.         "Reactor Heat Vent",
  178.         "Reactor Heat Vent",
  179.         "Reactor Heat Vent",
  180.         "Reactor Heat Vent",
  181.         "Reactor Heat Vent",
  182.         "Reactor Heat Vent"
  183.     }
  184. else
  185.     -- only 3 Quad-Fuel-Rods in a row, twice
  186.     RequiredReactorInventory = {
  187.         "Reactor Heat Vent",
  188.         "Reactor Heat Vent",
  189.         "Reactor Heat Vent",
  190.         "Reactor Heat Vent",
  191.         "Reactor Heat Vent",
  192.         "Reactor Heat Vent",
  193.         "Reactor Heat Vent",
  194.         "Reactor Heat Vent",
  195.         "Reactor Heat Vent",
  196.    
  197.         "Reactor Heat Vent",
  198.         "Coolant Cell",
  199.         "Coolant Cell",
  200.         "Coolant Cell",
  201.         "Coolant Cell",
  202.         "Coolant Cell",
  203.         "Coolant Cell",
  204.         "Coolant Cell",
  205.         "Reactor Heat Vent",
  206.    
  207.         "Reactor Heat Vent",
  208.         "Coolant Cell",
  209.         "Coolant Cell",
  210.         "Uran",
  211.         "Uran",
  212.         "Uran",
  213.         "Coolant Cell",
  214.         "Coolant Cell",
  215.         "Reactor Heat Vent",
  216.    
  217.         "Reactor Heat Vent",
  218.         "Coolant Cell",
  219.         "Coolant Cell",
  220.         "Uran",
  221.         "Uran",
  222.         "Uran",
  223.         "Coolant Cell",
  224.         "Coolant Cell",
  225.         "Reactor Heat Vent",
  226.    
  227.         "Reactor Heat Vent",
  228.         "Coolant Cell",
  229.         "Coolant Cell",
  230.         "Coolant Cell",
  231.         "Coolant Cell",
  232.         "Coolant Cell",
  233.         "Coolant Cell",
  234.         "Coolant Cell",
  235.         "Reactor Heat Vent",
  236.    
  237.         "Reactor Heat Vent",
  238.         "Reactor Heat Vent",
  239.         "Reactor Heat Vent",
  240.         "Reactor Heat Vent",
  241.         "Reactor Heat Vent",
  242.         "Reactor Heat Vent",
  243.         "Reactor Heat Vent",
  244.         "Reactor Heat Vent",
  245.         "Reactor Heat Vent"
  246.     }
  247. end
  248.  
  249.  
  250. ---[[ functions ]]
  251.  
  252.  
  253. -- display text on terminal screen
  254. function draw_text_term(x, y, text)
  255.     term.setCursor(x, y)
  256.     term.write(text)
  257. end
  258.  
  259.  
  260. -- This function can be useful for sending/receiving messages via network.
  261. function encode(data)
  262.     return serial.serialize(data)
  263. end
  264. function decode(data)
  265.     status, result = pcall(serial.unserialize, data)
  266.     return status, result
  267. end
  268.  
  269.  
  270. -- http://stackoverflow.com/questions/1426954/split-string-in-lua
  271. function split(pString, pPattern)
  272.     local Table = {}  -- NOTE: use {n = 0} in Lua-5.0
  273.     local fpat = "(.-)" .. pPattern
  274.     local last_end = 1
  275.     local s, e, cap = pString:find(fpat, 1)
  276.     while s do
  277.         if s ~= 1 or cap ~= "" then
  278.             table.insert(Table, cap)
  279.         end
  280.         last_end = e+1
  281.         s, e, cap = pString:find(fpat, last_end)
  282.     end
  283.     if last_end <= #pString then
  284.         cap = pString:sub(last_end)
  285.         table.insert(Table, cap)
  286.     end
  287.     return Table
  288. end
  289.  
  290. function stringMatch(text, find)
  291.     if string.find(string.lower(text), string.lower(find)) then
  292.         return true
  293.     else
  294.         return false
  295.     end
  296. end
  297.  
  298.  
  299. function turn(side)
  300.     if side == "left" then
  301.         robot.turnLeft()
  302.     elseif side == "right" then
  303.         robot.turnRight()
  304.     elseif side == "front" then
  305.         robot.turnRight()
  306.         robot.turnRight()
  307.     elseif side == "back" then
  308.         robot.turnLeft()
  309.         robot.turnLeft()
  310.     end
  311. end
  312.  
  313. -- drop item in current robots slot to Trash
  314. function drop()
  315.     if chestTrash == "down" then
  316.         success = robot.dropDown()
  317.     elseif chestTrash == "up" then
  318.         success = robot.dropUp()
  319.     elseif chestTrash == "left" then
  320.         turn('left')
  321.         success = robot.drop()
  322.         turn('right')
  323.     elseif chestTrash == "right" then
  324.         turn('right')
  325.         success = robot.drop()
  326.         turn('left')
  327.     end
  328. end
  329.  
  330. function suck(side)
  331.     local success = true
  332.     if side == "up" then
  333.         if not robot.suckUp(1) then
  334.             success = false
  335.         end
  336.     elseif side == "down" then
  337.         if not robot.suckDown(1) then
  338.             success = false
  339.         end
  340.     elseif side == "left" then
  341.         turn('left')
  342.         if not robot.suck(1) then
  343.             success = false
  344.         end
  345.         turn('right')
  346.     elseif side == "right" then
  347.         turn('right')
  348.         if not robot.suck(1) then
  349.             success = false
  350.         end
  351.         turn('left')
  352.     end
  353.     return success
  354. end
  355.  
  356. -- verify reactor in front
  357. function verifyReactor()
  358.     local data = geo.analyze(side.front)
  359.     if stringMatch(data.name, "ReactorChamber") then
  360.         return true
  361.     else
  362.         return false
  363.     end
  364. end
  365.  
  366.  
  367. -- get coolant from chest and put into reactors toSlot
  368. function Coolant(toSlot)
  369.     while (robot.count() > 0) do
  370.         drop()
  371.     end
  372.     -- get coolant from chest
  373.     local success = suck(chestCoolant)
  374.     if success == false then
  375.         print("WARNING: can't pick up Coolant!")
  376.         changeReactorState('OFF', 'Coolant')
  377.         if serverAddress ~= nil then
  378.             wlan.send(serverAddress, wlanPort, 'MISSING:Coolant')
  379.         end
  380.     else
  381.         -- verify reactor in front
  382.         while verifyReactor() == false do
  383.             turn('left')
  384.         end
  385.         -- put coolant into reactors toSlot
  386.         success, reason = ic.dropIntoSlot(side.front, toSlot)
  387.         commandsexecdCount = commandsexecdCount + 1
  388.     end
  389. end
  390.  
  391. -- get uran from chest and put into reactors toSlot
  392. function Uran(toSlot)
  393.     while (robot.count() > 0) do
  394.         drop()
  395.     end
  396.     -- get uran from chest
  397.     local success = suck(chestUran)
  398.     if success == false then
  399.         print("WARNING: can't pick up Uran!")
  400.         changeReactorState('OFF', 'Uran')
  401.         if serverAddress ~= nil then
  402.             wlan.send(serverAddress, wlanPort, 'MISSING:Uran')
  403.         end
  404.     else
  405.         -- verify reactor in front
  406.         while verifyReactor() == false do
  407.             turn('left')
  408.         end
  409.         -- put uran into reactors toSlot
  410.         success, reason = ic.dropIntoSlot(side.front, toSlot)
  411.         commandsexecdCount = commandsexecdCount + 1
  412.     end
  413. end
  414.  
  415. function Depleted_Uran(fromSlot, replace)
  416.     success = ic.suckFromSlot(side.front, fromSlot)
  417.     while (robot.count() > 0) do
  418.         drop()
  419.     end
  420.     -- only drop Uran from Reactor to Trash or replace it too?
  421.     if replace == true then
  422.         Uran(fromSlot)
  423.     end
  424.     commandsexecdCount = commandsexecdCount + 1
  425. end
  426.  
  427.  
  428. function checkInventory()
  429.     draw_text_term(1, 1, "Checking Reactor Inventory..")
  430.     local linecount = 1
  431.     local allFine = true
  432.     for Slot=1, #RequiredReactorInventory do
  433.         local Item = RequiredReactorInventory[Slot]
  434.         local found = false
  435.         local depleted_uran = false
  436.         local slotDetails = ic.getStackInSlot(side.front, Slot)
  437.         if slotDetails ~= nil then
  438.             if (stringMatch(slotDetails.label, Item) == true) then
  439.                 --draw_text_term(1, linecount, 'Slot#'..Slot..': '..Item)
  440.                 if (stringMatch(slotDetails.label, "depleted") == true) then
  441.                     depleted_uran = true
  442.                 else
  443.                     found = true
  444.                 end
  445.             end
  446.         end
  447.         if depleted_uran == true then
  448.             allFine = false
  449.             linecount = linecount + 1
  450.             -- does not meet the requirements. replace it!
  451.             draw_text_term(1, linecount, 'Slot#'..Slot..': "Depleted Uran". Replacing it!')
  452.             -- Replace Depleted Uran.
  453.             Depleted_Uran(Slot, true)
  454.         elseif found == false then
  455.             allFine = false
  456.             linecount = linecount + 1
  457.             -- does not meet the requirements. replace it!
  458.             draw_text_term(1, linecount, 'Slot#'..Slot..': "'..Item..'" not found!')
  459.             -- Replace Item.
  460.             if (stringMatch(Item, "Coolant") == true) then
  461.                 Coolant(Slot)
  462.             elseif (stringMatch(Item, "Uran") == true) then
  463.                 Uran(Slot)
  464.             end
  465.         end
  466.     end
  467.     if allFine == true then
  468.         draw_text_term(1, 2, "Nothing to do.")
  469.     end
  470. end
  471.  
  472. -- http://ocdoc.cil.li/component:redstone
  473. function changeReactorState(state, reason)
  474.     reason = reason or ''
  475.     if reason ~= '' then
  476.         msg = "Changing Reactor State to: "..state.." coz: "..reason
  477.     else
  478.         msg = "Changing Reactor State to: "..state
  479.     end
  480.     draw_text_term(1, h-1, msg)
  481.     if state == "ON" then
  482.         if uranDropped == true then
  483.             uranDropped = false
  484.         end
  485.         rs.setBundledOutput(wireSide, wireReactor, 255)
  486.     else
  487.         rs.setBundledOutput(wireSide, wireReactor, 0)
  488.     end
  489.     reactorState = state
  490.     if (serverAddress ~= nil) then
  491.         wlan.send(serverAddress, wlanPort, 'POWER:'..state)
  492.     end
  493. end
  494.  
  495.  
  496. --[[ End functions ]]
  497.  
  498.  
  499. --[[ Main Script ]]
  500.  
  501.  
  502. term.clear()
  503.  
  504. local linecount = 3
  505. draw_text_term(1, linecount, "Checking peripherals...")
  506. os.sleep(0.2)
  507.  
  508. -- detect Robot
  509. local linecount = linecount + 2
  510. draw_text_term(2, linecount, "Checking Robot...")
  511. os.sleep(0.2)
  512. if not component.isAvailable("robot") then
  513.     draw_text_term(2, (linecount + 1), "Error:", rgb.red, rgb.black)
  514.     draw_text_term(2, (linecount + 2), "Can only run on robots")
  515.     return
  516. else
  517.     draw_text_term(40, linecount, "success")
  518.     os.sleep(0.2)
  519. end
  520.  
  521. -- detect Inventory Controller
  522. local linecount = linecount + 1
  523. draw_text_term(2, linecount, "Checking Inventory Controller...")
  524. os.sleep(0.2)
  525. if not component.isAvailable("inventory_controller") then
  526.     draw_text_term(2, (linecount + 1), "Error:")
  527.     draw_text_term(2, (linecount + 2), "Could find Inventory Controller")
  528.     return
  529. else
  530.     draw_text_term(40, linecount, "success")
  531.     os.sleep(0.2)
  532. end
  533.  
  534. --local dbAddress = false
  535. --for k,_ in component.list("database") do dbAddress = k break end
  536.  
  537. draw_text_term(1, (linecount + 2), "Setup Complete!")
  538. os.sleep(1)
  539. draw_text_term(1, (linecount + 3), "Starting")
  540. robot.select(1)
  541.  
  542.  
  543. function messageReceived(event, localAddress, remoteAddress, port, senderDistance, message)
  544.     -- Determine if message contains ':'
  545.     if string.find(message, ":") then
  546.         -- split message into a table
  547.         msgTable = split(message, ":")
  548.         if msgTable[1] == "POWER" then
  549.             changeReactorState(msgTable[2], 'Server told')
  550.  
  551.         elseif (msgTable[1] == "PONG") and (msgTable[2] == "OK") then
  552.             -- PING/PONG verificated
  553.             serverAddress = remoteAddress
  554.             wlan.send(serverAddress, wlanPort, 'OK')
  555.         end
  556.     -- message doesnt contain ':'
  557.     else
  558.         if (message == "PING") and (serverAddress == nil) then
  559.             if UseReactorSetup == 1 then
  560.                 reactorPower = 1120
  561.             else
  562.                 reactorPower = 640
  563.             end
  564.             wlan.send(serverAddress, wlanPort, 'PONG:'..reactorPower)
  565.         end
  566.     end
  567. end
  568.  
  569. -- http://ocdoc.cil.li/component:signals
  570. event.listen("modem_message", messageReceived)
  571.  
  572.  
  573. -- all seems fine, start main loop
  574.  
  575.  
  576. while true do
  577.     term.clear()
  578.     -- check State of Thermal1
  579.     if (rs.getBundledInput(wireSide, wireThermal1) > 0) then
  580.         -- turn Reactor off
  581.         changeReactorState('OFF', 'Thermal 1 triggered')
  582.         thermalTriggered = true
  583.         if serverAddress ~= nil then
  584.             wlan.send(serverAddress, wlanPort, 'OVERHEAT:Thermal 1 triggered')
  585.         end
  586.     end
  587.     -- check State of Thermal2
  588.     if (rs.getBundledInput(wireSide, wireThermal2) > 0) then
  589.         -- turn Reactor off
  590.         changeReactorState('OFF', 'Thermal 2 triggered')
  591.         thermalTriggered = true
  592.         if serverAddress ~= nil then
  593.             wlan.send(serverAddress, wlanPort, 'OVERHEAT:Thermal 2 triggered')
  594.         end
  595.         -- tell Robot to drop all Uran Cells to prevent explosion
  596.         if uranDropped == false then
  597.             draw_text_term(1, linecount+1, 'Dropping all Uran Cells to prevent explosion..')
  598.             for i=1, #RequiredReactorInventory do
  599.                 if stringMatch(RequiredReactorInventory[i], "Uran") == true then
  600.                     Depleted_Uran(i, false)
  601.                 end
  602.             end
  603.             -- after drop cmd was exec make sure to not exec it again
  604.             uranDropped = true
  605.         end
  606.     end
  607.     if (thermalTriggered == true
  608.             and rs.getBundledInput(wireSide, wireThermal1) == 0
  609.             and rs.getBundledInput(wireSide, wireThermal2) == 0) then
  610.                 thermalTriggered = false
  611.                 changeReactorState('ON')
  612.     end
  613.  
  614.     -- only check inventory when we didnt told robot to remove uran to prevent explosion..
  615.     if (uranDropped == false) and (serverAddress ~= nil) then
  616.         checkInventory()
  617.     end
  618.  
  619.     os.sleep(CheckEvery)
  620. end
  621.  
  622.  
  623. --
  624. -- EOF
  625. --
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement