View difference between Paste ID: YRxK4sRE and UNSweFgi
SHOW: | | - or go back to the newest paste.
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