View difference between Paste ID: 0cQs3X1C and tdQh9KHv
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
	max = max + 1
78
	if (not screenw) then
79
		return nil;
80
		-- monitor has been broken
81
	end
82
       
83
	local starty = screenh -  math.floor((screenh * filled))
84
	local width  = math.ceil(screenw / max + .5)
85
	local offset = math.ceil(width * (count - 1))
86
	local amtw = string.len(amt)
87
	local thresholdy = (threshold and ( screenh - ((threshold / 100) * screenh)))
88
89
	if (count == max) then
90
	--  the final column should use up the remaining space.  A hack!
91
		width = screenw - offset
92
	end
93
	--truncate the label to the width of the bar.
94
	label = string.sub(label, 1, math.max((width - 1), 0))
95
 
96
	if (thresholdy and thresholdy < 1) then
97
		thresholdy = 1
98
	else
99
		if (thresholdy and thresholdy > screenh) then
100
			thresholdy = screenh
101
		end
102
	end
103
 
104
	term.redirect(monitor)
105
	for c=starty, screenh + 1, 1 do
106
		for line=0, width, 1 do
107
			paintutils.drawPixel(line + offset, c, color)
108
		end
109
	end
110
	if (thresholdy) then
111
		local thresholdColor = color
112
		for line=0, width, 1 do
113
			thresholdColor = color
114
			if (signal) then
115
				thresholdColor = colors.red
116
			else
117
				-- makes a dotted line when there is no redstone signal
118
				if (line % 2 == 0) then
119
					thresholdColor = colors.red
120
				end
121
			end
122
			paintutils.drawPixel(line + offset, thresholdy, thresholdColor)
123
        end
124
	end
125
126
	monitor.setBackgroundColor(color)
127
	if (color == colors.white) then
128
		monitor.setTextColor(colors.black)
129
	end
130
131
	labely = math.min((starty + 1), screenh - 1)
132
	monitor.setCursorPos(offset + 1, labely)
133
	write(label)
134
135
	if (amtw <= width) then
136
		amty = math.min(labely + 1, screenh)
137
		monitor.setCursorPos(offset + 1, amty)
138
		write(amt)
139
	end
140
	monitor.setTextColor(colors.white)
141
	-- term.restore()
142
end
143
 
144
local function tankStats(tank)
145
	if(tank) then
146
		local amt = tank["amount"]
147
		local size = tank["capacity"]
148
		local filled = (amt and 1 / (size / amt)) or 0
149
		return amt, size, filled
150
	else
151
		return nil;
152
	end
153
end
154
 
155
local function tableCount(t)
156
	local total=0
157
	for k,v in pairs (t) do
158
		total = total + 1
159
	end
160
	return total
161
end
162
 
163
local function updateDisplay()
164
	local total = tableCount(clients)
165
	local count = 1
166
167
	monitor.setBackgroundColor(colors.black)
168
	monitor.setTextScale(.5)
169
	monitor.clear()
170
171
	for ix,client in pairs (clients) do
172
		local tank = client[1]
173
		local threshold = client[2]
174
		local signalOn = client[3]
175
		local amt,size,filled = tankStats(tank)
176
		local kind = tank["name"]
177
		local color,name = getLiquidColor(kind)
178
		local unit = ""
179
		local amount = math.max(amt or 0, 0)
180
181
		if (amount > 1000000) then
182
			unit="M"
183
			amount=string.format("%.2f", math.floor(amt / 1000) / 1000)
184
		else
185
			if (amount > 0) then
186
				unit="K"
187
				amount=string.format("%.2f", amt / 1000)
188
			else
189
				amount = ""
190
			end
191
		end
192
		amount = amount..unit
193
		showLevel(count, total, filled, color, name or "Empty", amount, threshold, signalOn)
194
		count = count + 1    
195
	end
196
	return nil;
197
end
198
 
199
local function broadcast ()
200
	term.clear()
201
	term.setCursorPos(1,1)
202
	print("_____________ tankmon Server started __________")
203
	print("Broadcasting that tank display is available...")
204
	print("Hold Ctrl+T to Terminate.")
205
	while true do
206
		rednet.broadcast(os.getComputerID())
207
		-- term.setCursorPos(1, 5)
208
		-- term.clearLine()
209
		-- write("Connected tankmon clients: " .. tostring(tableCount(clients)))
210
		sleep(7)
211
	end
212
end
213
 
214
local function receive()
215
	while true do
216
		local senderID, message, distance = rednet.receive()
217
		if (message) then
218
			local data = textutils.unserialize(message)
219
			clients[senderID] = data
220
		end
221
	end
222
end
223
 
224
local function display()
225
	while true do
226
		updateDisplay()
227
		sleep(1.5)
228
	end
229
end
230
 
231
local function connect()
232
	print("Looking for a tankmon server in wireless Rednet range...")
233
	while true do
234
		local senderID, message, distance = rednet.receive()
235
		serverID = senderID
236
		print("Connected to server " .. tostring(serverID))
237
		sleep(3)
238
	end
239
end
240
 
241
local function publishTank()
242
	while true do
243
		if serverID then
244
			term.clear()
245
			term.setCursorPos(1,1)
246
			print("** Sending out tank information **")
247
			local tank = valve.getTankInfo("unknown")[1]
248
249
			-- establish whether redstone signal should be sent
250
			local amt,size,pctFilled = tankStats(tank)
251
			on = false
252
			local filled = pctFilled * 100
253
			if (filled and redlimit and redlimit==0 and filled==0) then
254
				on = true
255
			else
256
				if (filled and redlimit and filled <= redlimit) then
257
					on=true
258
				end
259
			end
260
			if (redside) then
261
				rs.setOutput(redside, on)
262
			end
263
264
			-- use rednet to update the server with this tank's info.
265
			local info = {tank, redlimit, on}
266
			if (redlimit and redside) then
267
				print("Redstone threshold: " .. tostring(redlimit))
268
				print("Redstone output side: " .. redside)
269
				print("Redstone signal on: " .. tostring(on))
270
				print("")
271
			end
272
			term.clearLine()
273
			write("** Tank contains: " .. tostring(amt))
274
			rednet.send(serverID, textutils.serialize(info), false)            
275
		end
276
		sleep(math.random(1,5))
277
	end
278
end
279
280
---------------------------------------
281
-- Main
282
---------------------------------------
283
local modemSide = getDeviceSide("modem");
284
285
if (modemSide) then
286
	local modem = peripheral.wrap(modemSide)
287
else
288
	error ("A wireless modem must be attached to this computer.")
289
end
290
291
local tankSide = getDeviceSide("iron_tank_valve");
292
local tankSide2 = getDeviceSide("steel_tank_valve");
293
local tankSide3 = getDeviceSide("rcsteeltankvalvetile");
294
local tankSide4 = getDeviceSide("rcirontankvalvetile");
295
local finalside = tankSide or tankSide2 or tankSide3 or tankSide4
296
local screenSide = getDeviceSide("monitor");
297
 
298
if (finalside and screenSide) then
299
      error("Either a screen or a tank valve can be connected, not both.")
300
end
301
302
if finalside  then
303
	valve = peripheral.wrap(finalside )
304
end
305
 
306
if (screenSide) then
307
	monitor = peripheral.wrap(screenSide)
308
	local screenw, screenh = monitor.getSize()
309
	screenw = screenw / 2
310
	screenh = screenh / 2
311
	if (not monitor.isColor()) then
312
		error("The attached monitor must be Advanced. Get some gold!")
313
	end
314
	monitor.clear()
315
end
316
 
317
rednet.open(modemSide)
318
if (valve) then
319
	-- client mode
320
	redlimit = args[1]
321
	redside = args[2]
322
	if (redlimit and not redside) then
323
		print ("A threshold and redstone side must both be present.")
324
		print ("e.g. tankmon 100 top")
325
		error ()
326
	end
327
	if (redlimit) then
328
		redlimit = tonumber(redlimit)
329
		print("")
330
		print("Tank will send redstone signal at or below " .. tostring(redlimit) .. "% on side " .. redside)
331
	end
332
	-- clear outstanding redstone signals.
333
	for i,side in pairs(sides) do
334
		rs.setOutput(side, false)
335
	end
336
	parallel.waitForAll(connect, publishTank)
337
else
338
	-- server mode
339-
	paintutils.drawLine(screenw, 0, screenw, 2 * screenh)
339+
	if (screenh and screenw) then
340-
	paintutils.drawLine(0, screenh, 2 * screenw, screenh)
340+
		paintutils.drawLine(screenw, 0, screenw, 2 * screenh)
341
		paintutils.drawLine(0, screenh, 2 * screenw, screenh)
342
	end	
343
344
	parallel.waitForAll(broadcast, receive, display)
345
end
346
rednet.close(modemSide)