View difference between Paste ID: jBv9A3Jc and WNvmVrYh
SHOW: | | - or go back to the newest paste.
1
-- Variable definitions
2
local valve, monitor, screenw, screenh
3
local serverID = nil
4
local clients = {}
5
local args = {...}
6
local redlimit, redside, on
7
local sides = {"left", "right", "top", "bottom", "front", "back"};
8
 
9
----------------------------------------------------
10
-- Function definitions
11
----------------------------------------------------
12
local liquidColors = {{"Water", colors.blue },
13
                                        {"tile.oilStill", colors.gray, "Oil"},
14
                                        {"Creosote Oil", colors.brown},
15
                                        {"Essence", colors.lime},
16
                                        {"Steam", colors.lightGray},
17
                                        {"Honey", colors.yellow},
18
                                        {"Ethanol", colors.orange},
19
                                        {"Lava", colors.orange},
20
                                        {"item.fuel", colors.yellow, "Fuel"},
21
                                        {"Biomass", colors.green},
22
                                        {"Fortron", colors.lightBlue},
23
                                        {"Sludge", colors.black},
24
                                        {"Liquid DNA", colors.magenta},
25
                                        {"Fruit Juice", colors.green},
26
                                        {"Seed Oil", colors.yellow},
27
                                        {"Liquid Force", colors.yellow},
28
                                        {"Oil", colors.black, "Oil"},
29
                                        {"Fuel", colors.yellow, "Fuel"},
30
                                        {"uumatter", colors.purple, "UUMatter"},
31
                                        {"vegetable", colors.magenta, "Veg"},
32
                                        {"deuterium", colors.lightBlue, "Deuterium"},
33
--liquid names for OpenPeripherals 0.2.1 by AmigaLink
34
                                        {"creosote", colors.brown, "Creosote Oil"},
35
                                        {"essence", colors.lime, "Essence"},
36
                                        {"steam", colors.lightGray, "Steam"},
37
                                        {"honey", colors.yellow, "Honey"},
38
                                        {"bioethanol", colors.orange, "Ethanol"},
39
                                        {"lava", colors.orange, "Lava"},
40
                                        {"biomass", colors.green, "Biomass"},
41
                                        {"fortron", colors.lightBlue, "Fortron"},
42
                                        {"sludge", colors.black, "Sludge"},
43
                                        {"liquiddna", colors.magenta, "Liquid DNA"},
44
                                        {"fruitjuice", colors.green, "Fruit Juice"},
45
                                        {"seedoil", colors.yellow, "Seed Oil"},
46
                                        {"xpjuice", colors.lime, "XP Juice"},
47
                                        {"liquidforce", colors.yellow, "Liquid Force"},
48
                                        {"oil", colors.gray, "Oil"},
49
                                        {"fuel", colors.yellow, "Fuel"},
50
                                        {"milk", colors.white, "Milk"},
51
-- Life Essence suggested by Fyrhtu
52
                                        {"life essence", colors.red, "Life Essence"},
53
-- My liquids
54
                                        {"nitrofuel", colors.green, "Nitrofuel"}
55
                                }
56
 
57
local function getLiquidColor(liquid)
58
    for c, color in pairs (liquidColors) do
59
        if (liquid == color[1]) then
60
                return color[2],color[3] or liquid
61
        end
62
    end
63
    return colors.white, liquid;
64
end
65
 
66
local function getDeviceSide(deviceType)
67
        for i,side in pairs(sides) do
68
                if (peripheral.isPresent(side)) then
69
                        if (peripheral.getType(side)) == string.lower(deviceType) then
70
                                        return side;
71
                        end
72
                end
73
        end
74
end
75
 
76
local function showLevel(count,max,filled,color,label, amt, threshold, signal)
77-
        local screenw, screenh = monitor.getSize() / 4
77+
        local screenw, screenh = monitor.getSize()
78
        screenw = screenw / 4
79
        screenh = screenh / 4
80
        max = max + 1
81
        if (not screenw) then
82
                return nil;
83
                -- monitor has been broken
84
        end
85
       
86
      local starty = screenh -  math.floor((screenh * filled))
87
      local width  = math.ceil(screenw / max + .5)
88
      local offset = math.ceil(width * (count - 1))
89
        local amtw = string.len(amt)
90
        local thresholdy = (threshold and ( screenh - ((threshold / 100) * screenh)))
91
       
92
        if (count == max) then
93
        --  the final column should use up the remaining space.  A hack!
94
                width = screenw - offset
95
        end
96
        --truncate the label to the width of the bar.
97
        label = string.sub(label, 1, math.max((width - 1), 0))
98
 
99
        if (thresholdy and thresholdy < 1) then
100
                thresholdy = 1
101
        else
102
                if (thresholdy and thresholdy > screenh) then
103
                        thresholdy = screenh
104
                end
105
        end
106
 
107
      term.redirect(monitor)
108
      for c=starty, screenh + 1, 1 do
109
            for line=0, width, 1 do
110
                        paintutils.drawPixel(line + offset, c, color)
111
            end
112
      end
113
        if (thresholdy) then
114
                local thresholdColor = color
115
                for line=0, width, 1 do
116
                        thresholdColor = color
117
                        if (signal) then
118
                                        thresholdColor = colors.red
119
                        else
120
                                        -- makes a dotted line when there is no redstone signal
121
                                        if (line % 2 == 0) then
122
                                                thresholdColor = colors.red
123
                                        end
124
                        end
125
                        paintutils.drawPixel(line + offset, thresholdy, thresholdColor)
126
            end
127
        end
128
 
129
        monitor.setBackgroundColor(color)
130
        if (color == colors.white) then
131
                monitor.setTextColor(colors.black)
132
        end
133
       
134
        labely = math.min((starty + 1), screenh - 1)
135
        monitor.setCursorPos(offset + 1, labely)
136
        write(label)
137
       
138
        if (amtw <= width) then
139
                amty = math.min(labely + 1, screenh)
140
                monitor.setCursorPos(offset + 1, amty)
141
                write(amt)
142
        end
143
        monitor.setTextColor(colors.white)
144
  --    term.restore()
145
end
146
 
147
local function tankStats(tank)
148
        if(tank) then
149
                local amt = tank["amount"]
150
                local size = tank["capacity"]
151
                local filled = (amt and 1 / (size / amt)) or 0
152
                return amt, size, filled
153
        else
154
                return nil;
155
        end
156
end
157
 
158
local function tableCount(t)
159
        local total=0
160
        for k,v in pairs (t) do
161
                total = total + 1
162
        end
163
        return total
164
end
165
 
166
local function updateDisplay()
167
        local total = tableCount(clients)
168
        local count = 1
169
 
170
        monitor.setBackgroundColor(colors.black)
171
        monitor.setTextScale(.5)
172
        monitor.clear()
173
   
174
        for ix,client in pairs (clients) do
175
                local tank = client[1]
176
                local threshold = client[2]
177
                local signalOn = client[3]
178
                local amt,size,filled = tankStats(tank)
179
                local kind = tank["name"]
180
                local color,name = getLiquidColor(kind)
181
                local unit = ""
182
                local amount = math.max(amt or 0, 0)
183
   
184
                if (amount > 1000000) then
185
                        unit="M"
186
                        amount=string.format("%.2f", math.floor(amt / 1000) / 1000)
187
                else
188
                        if(amount > 0) then
189
                          unit="K"
190
                          amount=string.format("%.2f", amt / 1000)
191
                        else
192
                          amount = ""
193
                        end
194
                end
195
                amount = amount..unit
196
                showLevel(count, total, filled, color, name or "Empty", amount, threshold, signalOn)
197
                count = count + 1    
198
        end
199
        return nil;
200
end
201
 
202
local function broadcast ()
203
        term.clear()
204
        term.setCursorPos(1,1)
205
        print("_____________ tankmon Server started __________")
206
        print("Broadcasting that tank display is available...")
207
        print("Hold Ctrl+T to Terminate.")
208
        while true do
209
                rednet.broadcast(os.getComputerID())
210
                -- term.setCursorPos(1, 5)
211
                -- term.clearLine()
212
                -- write("Connected tankmon clients: " .. tostring(tableCount(clients)))
213
                sleep(7)
214
        end
215
end
216
 
217
local function receive()
218
    while true do
219
      local senderID, message, distance = rednet.receive()
220
      if (message) then
221
                local data = textutils.unserialize(message)
222
                clients[senderID] = data
223
    end
224
  end
225
end
226
 
227
local function display()
228
        while true do
229
                updateDisplay()
230
                sleep(1.5)
231
        end
232
end
233
 
234
local function connect()
235
        print("Looking for a tankmon server in wireless Rednet range...")
236
        while true do
237
                local senderID, message, distance = rednet.receive()
238
                serverID = senderID
239
                print("Connected to server " .. tostring(serverID))
240
                sleep(3)
241
  end  
242
end
243
 
244
local function publishTank()
245
      while true do
246
            if serverID then
247
                        term.clear()
248
                        term.setCursorPos(1,1)
249
                print("** Sending out tank information **")
250
                local tank = valve.getTankInfo("unknown")[1]
251
                        -- establish whether redstone signal should be sent
252
                        local amt,size,pctFilled = tankStats(tank)
253
                        on = false
254
                        local filled = pctFilled * 100
255
                        if (filled and redlimit and redlimit==0 and filled==0) then
256
                                on = true
257
                        else
258
                                if(filled and redlimit and filled <= redlimit) then
259
                                        on=true
260
                                end
261
                        end
262
                        if(redside) then
263
                                rs.setOutput(redside, on)
264
                        end
265
                        -- use rednet to update the server with this tank's info.
266
                        local info = {tank, redlimit, on}
267
                        if (redlimit and redside) then
268
                                print("Redstone threshold: " .. tostring(redlimit))
269
                                print("Redstone output side: " .. redside)
270
                                print("Redstone signal on: " .. tostring(on))
271
                                print("")
272
                        end
273
                        term.clearLine()
274
                        write("** Tank contains: " .. tostring(amt))
275
            rednet.send(serverID, textutils.serialize(info), false)            
276
                end
277
                sleep(math.random(1,5))
278
    end
279
end
280
 
281
---------------------------------------
282
--the Main
283
---------------------------------------
284
local modemSide = getDeviceSide("modem");
285
 
286
if (modemSide) then
287
      local modem = peripheral.wrap(modemSide)
288
else
289
      error("A wireless modem must be attached to this computer.")
290
end
291
 
292
local tankSide = getDeviceSide("iron_tank_valve");
293
local tankSide2 = getDeviceSide("steel_tank_valve");
294
local tankSide3 = getDeviceSide("rcsteeltankvalvetile");
295
local tankSide4 = getDeviceSide("rcirontankvalvetile");
296
local finalside = tankSide or tankSide2 or tankSide3 or tankSide4
297
local screenSide = getDeviceSide("monitor");
298
 
299
if (finalside and screenSide) then
300
      error("Either a screen or a tank valve can be connected, not both.")
301
end
302
 
303
if finalside  then
304
      valve = peripheral.wrap(finalside )
305
end
306
 
307
if (screenSide) then
308
      monitor = peripheral.wrap(screenSide)
309
        if(not monitor.isColor()) then
310
                error("The attached monitor must be Advanced.  Get some gold!")
311
        end
312
    screenw, screenh = monitor.getSize()
313
    monitor.clear()
314
end
315
 
316
rednet.open(modemSide)
317
if (valve) then
318
      -- client mode
319
        redlimit = args[1]
320
        redside = args[2]
321
        if (redlimit and not redside) then
322
                print("A threshold and redstone side must both be present.")
323
                print("e.g. tankmon 100 top")
324
                error()
325
        end
326
        if (redlimit) then
327
                redlimit = tonumber(redlimit)
328
                print("")
329
                print("Tank will send redstone signal at or below " .. tostring(redlimit) .. "% on side " .. redside)
330
        end
331
        -- clear outstanding redstone signals.
332
        for i,side in pairs(sides) do
333
                rs.setOutput(side, false)
334
        end
335
    parallel.waitForAll(connect, publishTank)
336
else
337
      -- server mode
338
      parallel.waitForAll(broadcast, receive, display)
339
end
340
rednet.close(modemSide)