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