virtualdxs

Reactor Control Program

Dec 24th, 2015 (edited)
197
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. --
  2. -- Control passively cooled Big Reactor (http://big-reactors.com/).
  3. --
  4. -- Author: VirtualDXS
  5. -- Based heavily on original by kla_sch
  6. --
  7. -- History:
  8. --     v0.1, 2014-05-05:
  9. --         first version by kla_sch
  10. --     v0.2, 2015-10-24:
  11. --         Minor adjustments
  12. --     v0.3, 2020-01-26
  13. --         Transmit telemetry if wireless modem present, allowing
  14. --         for things like remote displays
  15. --
  16. -- Remarks:
  17. --     Reactor API: http://big-reactors.com/#/api.computer
  18. --
  19. sleep(5) --Let the entire chunk load, just in case
  20. --
  21. -- Constant values (configuration)
  22. --
  23.  
  24. -- Port to transmit telemetry on (requires wireless modem)
  25. transmitPort=39124
  26.  
  27. -- Critical energy mark: give us the maximum power.
  28. critEnergy=3000000
  29.  
  30. -- Low energy mark: turn reactor on to get more energy
  31. lowEnergy=7000000
  32.  
  33. -- High energy mark: we have enough, so turn the reactor off.
  34. highEnergy=9000000
  35.  
  36.  
  37. --
  38. -- Calculate the control rod level (in %) by stored energy of internal
  39. -- reactor cell.
  40. --
  41. -- * If cellEnergy <= critEnergy, the calculation results in maximum
  42. --   energy generation (control rod level = 0%).
  43. -- * If cellEnergy >= highEnergy, the calculation results in 10% energy
  44. --   generation (control rod level = 90%).
  45. --
  46. -- Parameters:
  47. --     cellEnergy - stored energy of internal cell in RF
  48. --
  49. -- Return:
  50. --     New control rod level in %.
  51. --
  52. function calcRodLevel(cellEnergy)
  53.    -- Delta between critical and high energy mark
  54.    local deltaEnergy = highEnergy - critEnergy
  55.  
  56.    -- Calculated maximum delta energy (not the real maximum), so that
  57.    -- the high energy mark results into a control rod level of 90%
  58.    local deltaEnergy100 = deltaEnergy * 100 / 90
  59.  
  60.    -- Energy for calculation: value between 0 and 'deltaEnergy'
  61.    local calcEnergy = cellEnergy - critEnergy
  62.  
  63.    if calcEnergy < 0 then
  64.       calcEnergy = 0
  65.    elseif calcEnergy > deltaEnergy then
  66.       calcEnergy = deltaEnergy
  67.    end
  68.  
  69.    -- Calculate control rod level and round the result (math.floor + 0.5)
  70.    return math.floor(calcEnergy * 100 / deltaEnergy100 + 0.5)
  71. end
  72.  
  73.  
  74. --
  75. -- Write text with colors, if possible (advance monitor)
  76. --
  77. -- Parameters:
  78. --     mon   - handle of monitor
  79. --     color - text color
  80. --     text  - text to write
  81. --
  82. function writeColor(mon, color, text)
  83.    if (mon.isColor()) then
  84.       mon.setTextColor(color)
  85.    end
  86.    mon.write(text)
  87.    if (mon.isColor()) then
  88.       mon.setTextColor(colors.white)
  89.    end
  90. end
  91.  
  92.  
  93. --
  94. -- Display reactor status to a monitor.
  95. --
  96. -- Parameters:
  97. --     mon        - handle of monitor.
  98. --     state      - state of reactor (dictionary, see main loop for structure)
  99. --
  100. function displayStatusToMonitor(mon, state)
  101.    mon.clear()
  102.  
  103.    -- First get the monitor size and try to scale, if the feature ist
  104.    -- available.
  105.    if mon.setTextScale ~= nil then
  106.       -- reset text scale
  107.       mon.setTextScale(1)
  108.    end
  109.  
  110.    local width, height = mon.getSize()
  111.    if width < 15 or height < 5 then
  112.       -- too small: try to scale down.
  113.       if mon.setTextScale ~= nil then
  114.          mon.setTextScale(0.5)
  115.       else
  116.          return -- too small and no text scale available
  117.       end
  118.  
  119.       width, height = mon.getSize()
  120.       if width < 15 or height < 5 then
  121.          return -- still too small
  122.       end
  123.    else
  124.       -- Huge monitors? Try to scale up, if possible (max scale=5).
  125.       local scale = math.min(width / 16, height / 5, 5)
  126.       scale = math.floor(scale * 2) / 2 -- multiple of 0.5
  127.  
  128.       if scale > 1 and mon.setTextScale ~= nil then
  129.          mon.setTextScale(scale)
  130.          width, height = mon.getSize()
  131.       end
  132.    end
  133.  
  134.  
  135.    --
  136.    -- Output the data
  137.    --
  138.  
  139.    mon.setCursorPos(1,1)
  140.    mon.write("Reactor")
  141.  
  142.    mon.setCursorPos(1,3)
  143.    mon.write("Status: ")
  144.  
  145.    if state.power then
  146.       writeColor(mon, colors.green, "ACTIVE")
  147.    else
  148.       writeColor(mon, colors.red, "INACTIVE")
  149.    end
  150.  
  151.    mon.setCursorPos(1,4)
  152.    mon.write("Rod Level: " .. state.rodLevel .. "%")
  153.  
  154.    mon.setCursorPos(1,5)
  155.    if width < 16 then
  156.       mon.write("Cell: ") -- One block monitor (15x5 with scale 0.5)
  157.    else
  158.       mon.write("Energy Buffer: ")
  159.    end
  160.  
  161.    local c
  162.    if state.cellEnergy < critEnergy then
  163.       c = colors.red -- Red: We use too much energy
  164.    elseif state.cellEnergy > lowEnergy then
  165.       c = colors.green -- Green: More energy then low water mark
  166.    else
  167.       c = colors.orange -- Orange: Less energy the low water mark, but OK
  168.    end
  169.    writeColor(mon, c, string.format("%d", math.floor(state.cellEnergy/1000 + 0.5)))
  170.    mon.write(" kRF")
  171. end
  172.  
  173.  
  174. --
  175. -- Display reactor status to any connected monitor and also to console.
  176. --
  177. -- Parameters:
  178. --     state      - state of reactor (dictionary, see main loop for structure)
  179. --
  180. function displayStatus(state)
  181.    displayStatusToMonitor(term, state) -- console
  182.    term.setCursorPos(1,7)
  183.    term.write("* Hold Ctrl-T to terminate program")
  184.    term.setCursorPos(1,8)
  185.  
  186.    local pList = peripheral.getNames()
  187.    local i, name
  188.    for i, name in pairs(pList) do
  189.       if peripheral.getType(name) == "monitor" then
  190.          -- found monitor as peripheral
  191.          displayStatusToMonitor(peripheral.wrap(name), state)
  192.       end
  193.    end
  194. end
  195.  
  196.  
  197. --
  198. -- Transmit reactor state to allow for things like wireless displays
  199. --
  200. -- Parameters:
  201. --     state      - state of reactor (dictionary, see main loop for structure)
  202. --
  203. function transmitStatus(state)
  204.    local pList = peripheral.getNames()
  205.    local i, name
  206.    for i, name in pairs(pList) do
  207.       if peripheral.getType(name) == "modem" then
  208.          -- found modem as peripheral; check if wireless
  209.          local modem = peripheral.wrap(name)
  210.          if modem.isWireless() then
  211.             modem.transmit(transmitPort,transmitPort,textutils.serialize(state))
  212.          end
  213.       end
  214.    end
  215. end
  216.  
  217.  
  218. --
  219. -- Find the first connected big reactor and return the wraped handle.
  220. --
  221. -- If no reactor was found this function terminate the program.
  222. --
  223. -- Return:
  224. --     Handle of first connected reactor found.
  225. --
  226. function getReactorHandle()
  227.    local pList = peripheral.getNames()
  228.    local i, name
  229.    for i, name in pairs(pList) do
  230.       if peripheral.getType(name) == "BigReactors-Reactor" then
  231.          return peripheral.wrap(name)
  232.       end
  233.    end
  234.  
  235.    error("No big reactor connected: Exit program")
  236.    exit()
  237. end
  238.  
  239.  
  240. reactor = getReactorHandle()
  241.  
  242. --
  243. -- Endless loop: Recalculate rod level, set rod level, display result
  244. -- and wait for 5 secounds.
  245. --
  246. while true do
  247.    cellEnergy = reactor.getEnergyStored()
  248.    if cellEnergy < lowEnergy then
  249.       -- Low energy: switch reactor ON and calculate control rods by
  250.       -- energy cell level.
  251.       reactor.setActive(true)
  252.       rodLevel=calcRodLevel(cellEnergy)
  253.    elseif cellEnergy > highEnergy then
  254.       -- High energy: switch reactor OFF and set control rod level to 100
  255.       reactor.setActive(false)
  256.       rodLevel=100
  257.    elseif cellEnergy > lowEnergy then
  258.       -- Enough energy: do not change state of reactor. Only recalculate
  259.       -- control rod level.
  260.       --
  261.       -- * If the reactor ist switched off, we will wait until energy
  262.       --   fall below low energy mark.
  263.       --
  264.       -- * If it is turned on, we generate more energy until the
  265.       --   energy level exeeds the high energy mark.
  266.       rodLevel=calcRodLevel(cellEnergy)
  267.    end
  268.  
  269.    reactor.setAllControlRodLevels(rodLevel)
  270.  
  271.    state = {
  272.       power = reactor.getActive(),
  273.       rodLevel = rodLevel,
  274.       cellEnergy = cellEnergy
  275.    }
  276.  
  277.    displayStatus(state)
  278.    transmitStatus(state)
  279.  
  280.    os.sleep(0.5)
  281. end
  282.  
Add Comment
Please, Sign In to add comment