Advertisement
Guest User

tankmon2

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