toastonrye

Mekanism Induction Matrix Manager

Aug 6th, 2022
82
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. --[[
  2.   Wolfe's Mekanism Induction Matrix Monitor
  3.   Usage: Put computer with code near an Induction Port and a monitor (2x3 array should work fine) and run.
  4.   Configuration: You can add a file called "config" with the options below, or append them to the command when running it via terminal:
  5.     energy_type = 'FE' -- Energy type you want to use
  6.     update_frequency = 1 -- Update frequency, in seconds
  7.     text_scale = 1 -- The text scale on the monitor, use 0.5 if you want to run on less displays
  8.     side_monitor = 'right' -- Hardcodes which side the monitor should be, defaults to auto-detection
  9.     side_inductor = 'back' -- Hardcodes which side the Induction Port should be, defaults to auto-detection
  10. ]]
  11.  
  12. --
  13. -- Usage: Put computer near an Induction Port and a monitor , set the sides below and run.
  14.  
  15. -- Default settings
  16. options = {
  17.   energy_type = 'FE',
  18.   update_frequency = 1,
  19.   text_scale = 1,
  20. }
  21.  
  22. -- Loads custom options from file (if available)
  23. if fs.exists('config') then
  24.   -- Opens the file for reading
  25.   local handle = fs.open('config')
  26.  
  27.   -- Reads configs
  28.   raw_options = {}
  29.   local line = handle.readLine()
  30.   while line do
  31.     table.insert(raw_options, line)
  32.     line = handle.readLine()
  33.   end
  34.  
  35.   -- Sets custom options
  36.   custom_options = string.format('{%s}', table.concat(raw_options, '\n,'))
  37.  
  38.   -- Closes the handle properly
  39.   handle.close()
  40. end
  41.  
  42. -- Gets custom settings via arguments
  43. args = {...}
  44. if args and #args > 0 then
  45.   -- Parses custom settings from args
  46.   custom_options = string.format('{%s}', table.concat(args, '\n,'))
  47. end
  48.  
  49. -- Detects custom options
  50. if custom_options then
  51.   -- Debug only
  52.   print('Running with custom options:')
  53.  
  54.   -- Makes sure we're dealing with a table to prevent code injection
  55.   if '{' == custom_options:sub(1, 1) then
  56.     -- Parses the object
  57.     custom_options, err = loadstring(string.format('return %s', custom_options))
  58.  
  59.     -- Handles invalid object
  60.     if not custom_options then
  61.       print('Invalid options:')
  62.       print(err)
  63.     else
  64.       -- Replaces settings
  65.       for k, v in pairs(custom_options()) do
  66.         print(string.format('%s = %s', k, v))
  67.         options[k] = v
  68.       end
  69.     end
  70.   end
  71. end
  72.  
  73. -- Auto-detects sides
  74. for _, side in pairs(peripheral.getNames()) do
  75.   -- Auto-detects monitor
  76.   if 'monitor' == peripheral.getType(side) and (not options.side_monitor) then
  77.     options.side_monitor = side
  78.   end
  79.  
  80.   -- Auto-detects Induction Port
  81.   if 'inductionPort' == peripheral.getType(side) and (not options.side_inductor) then
  82.     options.side_inductor = side
  83.   end
  84. end
  85.  
  86. -- Connects to Peripherals
  87. monitor = peripheral.wrap(options.side_monitor)
  88.  
  89. -- Queues a new print command to be sent
  90. buffer = {}
  91. function queue (text)
  92.   table.insert(buffer, text)
  93. end
  94.  
  95. -- Queues a new print command with string.format
  96. function queuef (fmt, ...)
  97.   queue(string.format(fmt, ...))
  98. end
  99.  
  100. -- Flushes (prints) buffer content
  101. function queue_flush ()
  102.   -- Clears terminal
  103.   term.clear()
  104.   term.setCursorPos(1, 1)
  105.  
  106.   -- Writes new data
  107.   print(table.concat(buffer, '\n'))
  108.   buffer = {}
  109. end
  110.  
  111. -- Formats time
  112. function time (secs)
  113.   -- Prepare value
  114.   secs = math.floor(secs)
  115.  
  116.   -- Days
  117.   local weeks = math.floor(secs / 604800)
  118.   secs = secs - (604800 * weeks)
  119.  
  120.   -- Days
  121.   local days = math.floor(secs / 86400)
  122.   secs = secs - (86400 * days)
  123.  
  124.   -- Hours
  125.   local hours = math.floor(secs / 3600)
  126.   secs = secs - (3600 * hours)
  127.  
  128.   -- Minutes
  129.   local mins = math.floor(secs / 60)
  130.   secs = secs - (60 * mins)
  131.  
  132.   -- If we have more than 72h worth of storage, switch to week, day, hour format
  133.   if weeks > 0 then
  134.     return string.format('%dwk %dd %dh', weeks, days, hours)
  135.   elseif days >= 3 then
  136.     return string.format('%dd %dh', days, hours)
  137.   end
  138.  
  139.   -- Formatting to have trailing zeros on H:MM:SS
  140.   return string.format('%d:%02d:%02d', hours, mins, secs)
  141. end
  142.  
  143. -- Rounds number
  144. function rnd (val, dec)
  145.   local X = math.pow(10, dec)
  146.   return math.floor(val * X) / X
  147. end
  148.  
  149. -- Converts to percentage
  150. function pct (val, dec)
  151.   return rnd(100 * val, dec or 1) .. '%'
  152. end
  153.  
  154. -- Converts to readable power
  155. function pwr (val, dec)
  156.   local pre = ''
  157.   local suf = ''
  158.  
  159.   local is_neg = false
  160.   if val < 0 then
  161.     pre = '-'
  162.     is_neg = true
  163.     val = -val
  164.   end
  165.  
  166.   val = energy_function(val)
  167.  
  168.   if val > 1000 then
  169.     suf = 'k'
  170.     val = val / 1000
  171.   end
  172.  
  173.   if val > 1000 then
  174.     suf = 'M'
  175.     val = val / 1000
  176.   end
  177.  
  178.   if val > 1000 then
  179.     suf = 'G'
  180.     val = val / 1000
  181.   end
  182.  
  183.   if val > 1000 then
  184.     suf = 'T'
  185.     val = val / 1000
  186.   end
  187.  
  188.   return string.format('%s%s%s%s', pre, rnd(val, dec or 1), suf, energy_type)
  189. end
  190.  
  191. -- Checks induction port
  192. function check_connection ()
  193.   return inductor and inductor.getEnergy and inductor.getLastInput
  194. end
  195.  
  196. -- Detects energy type, sets energy function
  197. energy_type = options.energy_type
  198. energy_function = mekanismEnergyHelper[string.format('joulesTo%s', energy_type)]
  199.  
  200. -- Function not found, use default Joules and a stub
  201. if not energy_function then
  202.   energy_type = 'J'
  203.   energy_function = function (val) return val end
  204. end
  205.  
  206. -- Starts monitor
  207. term.redirect(monitor)
  208. monitor.setTextScale(options.text_scale)
  209.  
  210. -- Checks if Inductor Port is missing or multiblock not ready
  211. inductor = peripheral.wrap(options.side_inductor)
  212. while not check_connection() do
  213.   -- Writes error message
  214.   queue('Ind.Port not found')
  215.   queue('Check connections.')
  216.   queue('Waiting...')
  217.  
  218.   -- Prints
  219.   queue_flush()
  220.  
  221.   -- Wait for next update
  222.   os.sleep(options.update_frequency)
  223.  
  224.   -- Tries to detect port
  225.   if not options.side_inductor then
  226.     for _, side in pairs(peripheral.getNames()) do
  227.       -- Tries to find an induction port
  228.       if 'inductionPort' == peripheral.getType(side) then
  229.         options.side_inductor = side
  230.         inductor = peripheral.wrap(options.side_inductor)
  231.       end
  232.     end
  233.   else
  234.     -- Try again on pre-set port
  235.     inductor = peripheral.wrap(options.side_inductor)
  236.   end
  237. end
  238.  
  239. -- Initializes balance
  240. balance = inductor.getEnergy()
  241. while true do
  242.   local status, err = pcall(function ()
  243.     -- Main script
  244.     queue('Ind.Matrix Monitor')
  245.     queue('------------------')
  246.     queue('')
  247.     queuef('Power : %s', pwr(inductor.getEnergy()))
  248.     queuef('Limit : %s', pwr(inductor.getMaxEnergy()))
  249.     queuef('Charge: %s', pct(inductor.getEnergyFilledPercentage()))
  250.     queue('')
  251.     queuef('Input : %s', pwr(inductor.getLastInput()))
  252.     queuef('Output: %s', pwr(inductor.getLastOutput()))
  253.     queuef('Max IO: %s/t', pwr(inductor.getTransferCap()))
  254.     queue('')
  255.    
  256.     -- Power balance per second
  257.     local balance_last = balance
  258.     balance = inductor.getEnergy()
  259.     local balance_change = (balance - balance_last) / options.update_frequency
  260.    
  261.     -- If we have negative value here, we'll save a character by removing the space so it fits same line
  262.     if balance_change < 0 then
  263.       queuef('Change:%s/s', pwr(balance_change))
  264.     else
  265.       queuef('Change: %s/s', pwr(balance_change))
  266.     end
  267.  
  268.     -- Status (charged/depleted in)
  269.     queue('Status:')
  270.     if balance_change > 0 then
  271.       -- Charging
  272.       local remaining_charge = inductor.getMaxEnergy() - inductor.getEnergy()
  273.       local seconds_remaining = remaining_charge / balance_change
  274.       queuef('Charg. %s', time(seconds_remaining))
  275.     elseif balance_change < 0 then
  276.       -- Discharging
  277.       local remaining_charge = inductor.getEnergy()
  278.       local seconds_remaining = remaining_charge / -balance_change
  279.       queuef('Disch. %s', time(seconds_remaining))
  280.     else
  281.       -- No changes, so we won't be charged or depleted, rare.
  282.       queue('Idle')
  283.     end
  284.   end)
  285.  
  286.   -- Checks for errors (might be disconnected)
  287.   if not status then
  288.     -- Clears buffer first
  289.     buffer = {}
  290.  
  291.     -- Shows error message
  292.     queue('Error reading data')
  293.     queue('Check connections.')
  294.     queue('------------------')
  295.     queue(err)
  296.   end
  297.  
  298.   -- Prints
  299.   queue_flush()
  300.  
  301.   -- Wait for next update
  302.   os.sleep(options.update_frequency)
  303. end
Add Comment
Please, Sign In to add comment