Advertisement
horsemeat

ComputerCraft Redstone Node

Dec 18th, 2016
70
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 15.49 KB | None | 0 0
  1. --Computer Craft Node Application for redstone interfacing
  2. --By snipy67
  3. --V1.2
  4. --You will need the Master Application at http://pastebin.com/edit/5xnjjYWA
  5. --You will need the Router Application in server mode running on the network http://pastebin.com/BuRcCc2n
  6. --change the nodes
  7. NODE = "node0"--set your node name
  8. REDSTONE_SIDE = "top"
  9. INVERSE = false
  10. --router application
  11.  
  12. BROADCAST_PORT = 2
  13.  
  14. --Computer Craft Router Application
  15. --By snipy67
  16. --V1.0
  17. BROADCAST_PORT = 2
  18.  
  19. --Layer 1
  20. lowLevelListeners = {}
  21. routerComputerId = 0
  22.  
  23. function detectModem()
  24.     return peripheral.find("modem")
  25. end
  26. function lowLevelMessageSplit(message)
  27.     local tab = {}
  28.     local current = ""
  29.     for i = 1, #message, 1 do
  30.         if message:sub(i,i) == ':' then
  31.             table.insert(tab,current)
  32.             current = ""
  33.         else
  34.             current = current .. message:sub(i,i)
  35.         end
  36.     end
  37.     if #current > 0 then
  38.         table.insert(tab,current)
  39.     end
  40.     return tab
  41. end
  42.  
  43. function lowLevelListenerCheckForMethod(modem,port,tab,verbose)
  44.     for k, v in pairs(lowLevelListeners) do
  45.         if v.message == tab[1] then
  46.             if verbose then
  47.                 print("function " .. v.message .. "found")
  48.             end
  49.             if v.func ~= nil then
  50.                 local t = {}
  51.                 t.message = tab[1]
  52.                 t.senderId = tab[2]
  53.                 t.reciverId = tab[3]
  54.                 t.data = tab[4]
  55.                 v.func(t)
  56.                 if t.data ~= nil then
  57.                     local responseText = tab[1] .. "~response:" .. os.getComputerID() .. ":".. tab[2] .. ":".. t.data;
  58.                     modem.transmit(port,port,responseText)
  59.                 else
  60.                     local responseText = tab[1] .. "~response:" .. os.getComputerID() .. ":".. tab[2]
  61.                     modem.transmit(port,port,responseText)
  62.                 end
  63.             else
  64.                 local responseText = tab[1] .. "~response:" .. os.getComputerID() .. ":".. tab[2]
  65.                 modem.transmit(port,port,responseText)
  66.             end
  67.             return true
  68.         else
  69.             if verbose then
  70.                 print("v.message:" .. v.message .. " != tab[1]:"..tab[1])
  71.             end
  72.         end
  73.     end
  74.     return false
  75. end
  76.  
  77. function lowLevelListener(modem,port,verbose)
  78.     while true do
  79.         local event, modemSide, senderChannel, replyChannel, message, senderDistance = os.pullEvent()--listens for a actions
  80.         if event == "modem_message" then--gets the message
  81.             if senderChannel == port then
  82.                 if verbose then
  83.                     print("message recived: " .. message)
  84.                 end
  85.                 local tab = lowLevelMessageSplit(message)
  86.                 if #tab > 2 then
  87.                     if verbose then
  88.                         print("There is more then 2 arguments in the message")
  89.                     end
  90.                     if tonumber(tab[3]) == os.getComputerID() then
  91.                         if verbose then
  92.                             print("id matches")
  93.                         end
  94.                         lowLevelListenerCheckForMethod(modem,port,tab,verbose)
  95.                     elseif tonumber(tab[3]) == -1 then
  96.                         if verbose then
  97.                             print("broadcast")
  98.                         end
  99.                         lowLevelListenerCheckForMethod(modem,port,tab,verbose)
  100.                     end
  101.                 elseif #tab == 2 then
  102.                     lowLevelListenerCheckForMethod(modem,port,tab,verbose)
  103.                 end
  104.             end
  105.         end
  106.     end
  107. end
  108.  
  109. function lowLevelRequest(modem,request,port,maxTimeOut,timeBetweenResend,numberOfResendsBeforeTimeOut,id,data,verbose)
  110.     local str = ""
  111.     if id ~= nil and id ~= -1 then
  112.         str = request .. ":" .. os.getComputerID() .. ":" .. id -- adds the computer id and the id of the reciver
  113.     else
  114.         str = request .. ":" .. os.getComputerID() .. ":" .. -1-- adds the computer id to the requests
  115.     end
  116.    
  117.     if data ~= nil then
  118.         str = str .. ":" .. data
  119.     end
  120.    
  121.     modem.transmit(port,port,str);--transmits the request
  122.     local responseText = request .. "~response"--creates text on how a response will look like
  123.     local count = 0--count is to keep track of how many times the request timed out
  124.     local timer = -1
  125.     if timeBetweenResend > 0 and numberOfResendsBeforeTimeOut > 0 then
  126.         timer = os.startTimer(timeBetweenResend) -- to keep track of the number of seconds before a time out
  127.     end
  128.     local atLeastOne = false--this determines if atleast one computer recived the request
  129.     local timeOutTimer
  130.     if maxTimeOut > 0 then
  131.         timeOutTimer = os.startTimer(maxTimeOut)--this timer is the number of seconds it should wait for return requests
  132.     end
  133.     local all = {} -- this is all the data that will be returned
  134.     all.package = {}--this is where the data from each request is stored
  135.     while true do
  136.         local event, modemSide, senderChannel, replyChannel, message, senderDistance = os.pullEvent()--listens for a actions
  137.         if event == "timer" then--check if the timer is up
  138.             local timerId = modemSide; --modemSide is the timerid when timer event is called (prevents confusion)
  139.             if timerId == timer then--checks if the timer is the timer that handels resends
  140.                 if atLeastOne == false then--checks if there are no records recovered
  141.                     if count ~= numberOfResendsBeforeTimeOut then--check to make sure the count is not at the timeout stage
  142.                         modem.transmit(port,port,str);--transmits the request again
  143.                         count = count + 1 -- adds one to the #of time outs
  144.                         timer = os.startTimer(timeBetweenResend)--resets the timer
  145.                         if verbose then
  146.                             print("Message Transmission failed resending...")
  147.                         end
  148.                     else
  149.                         if verbose then
  150.                             print("Message Transmission failed")
  151.                         end
  152.                         all.sucess = false
  153.                         return all
  154.                     end
  155.                 end
  156.             elseif timerId == timeOutTimer then--this is the maximum amount of time it was going to wait and not it's going to return the data
  157.                 if atLeastone == false then
  158.                     all.sucess = false
  159.                 else
  160.                     all.sucess = true
  161.                 end
  162.                 return all
  163.             end
  164.         elseif event == "modem_message" then--gets the message
  165.             if senderChannel == port then
  166.                 local tab = lowLevelMessageSplit(message)
  167.                 if verbose then
  168.                     print("Modem message: " .. message)
  169.                 end
  170.                 if tab[1] == responseText then
  171.                     if tonumber(tab[3]) == os.getComputerID() then
  172.                         local p = {}
  173.                         p.sucess = true
  174.                         p.tab = tab
  175.                         atLeastOne = true
  176.                         table.insert(all.package,p)
  177.                         if verbose then
  178.                             print("This computer: " .. tab[3] .. ". Request response recived from " .. tab[2])
  179.                         end
  180.                         if timeOutTimer == -1 then
  181.                             all.sucess = true
  182.                             return all;
  183.                         end
  184.                     end
  185.                 end
  186.             end
  187.         end
  188.     end
  189. end
  190.  
  191. MAX_TIME_OUT = 0.8
  192. TIME_BETWEEN_RESENDS = 0.2
  193. NUMBER_OF_RESENDS = 4
  194. VERBOSE = false
  195.  
  196. --easy to use methods
  197. --> the low level lowLevelListener returns true if atleast 1 tramission has been valid and in this case only 1 transmision
  198. function basicListener(modem)
  199.     return lowLevelListener(modem,BROADCAST_PORT,VERBOSE)--this will never finish, it will listen forever
  200. end
  201.  
  202. -->Low level request return
  203. --.sucess
  204. --.package[instance].sucess = true
  205. --.package[instance].tab = tab
  206. function basicBroadcast(modem,request)
  207.    
  208.     return lowLevelRequest(modem,request,BROADCAST_PORT,MAX_TIME_OUT,TIME_BETWEEN_RESENDS,NUMBER_OF_RESENDS,nil,nil,VERBOSE)--A broadcast request which will conenct to everyone
  209. end
  210.  
  211. function basicRequest(modem,request,computer)
  212.     return lowLevelRequest(modem,request,BROADCAST_PORT,MAX_TIME_OUT,TIME_BETWEEN_RESENDS,NUMBER_OF_RESENDS,computer,nil,VERBOSE)-- a message for a certian computer
  213. end
  214.  
  215. function basicBroadcastWithData(modem,request,data)
  216.     return lowLevelRequest(modem,request,BROADCAST_PORT,MAX_TIME_OUT,TIME_BETWEEN_RESENDS,NUMBER_OF_RESENDS,nil,data,VERBOSE)-- this a a broadcast with data
  217. end
  218.  
  219. function basicRequestWithData(modem,request,computer,data)
  220.     return lowLevelRequest(modem,request,BROADCAST_PORT,MAX_TIME_OUT,TIME_BETWEEN_RESENDS,NUMBER_OF_RESENDS,computer,data,VERBOSE) -- this is a message for a certian computer with data
  221. end
  222.  
  223. function addActionListener(message,func)
  224.     --function parameters required (data)
  225.     --.message -- the message that was transmitted
  226.     --.senderId -- the sender of the message
  227.     --.reciverId -- the reciver of the message
  228.     --.data -- the data that might have been passed along
  229.     local tab = {}
  230.     tab.message = message
  231.     tab.func = func
  232.     table.insert(lowLevelListeners,tab)
  233.     return #lowLevelListeners
  234. end
  235.  
  236. function removeActionListener(index)
  237.     table.remove(lowLevelListeners,index)
  238. end
  239. --End Of Layer 1
  240.  
  241. --Routeing layer
  242. portsTaken = {}
  243. computerId = {}
  244.  
  245. function openBroadcastNode(modem)
  246.     portsTaken[BROADCAST_PORT] = true
  247.     modem.open(BROADCAST_PORT)
  248. end
  249.  
  250. function portInit(modem)
  251.     for i = 1, 128, 1 do
  252.         portsTaken[i] = false
  253.         if modem.isOpen(i) then
  254.             modem.close(i)
  255.         end
  256.     end
  257. end
  258.  
  259. function findEmptyPort(modem)
  260.     for i = 1,128, 1 do
  261.         if portsTaken[i] == false then
  262.             return i
  263.         end
  264.     end
  265.     return -1
  266. end
  267.  
  268. function routerServer(modem)
  269.     portInit(modem)
  270.     openBroadcastNode(modem)
  271.     local requestRoute = function(data)
  272.         local port = findEmptyPort(modem)
  273.         computerId[port] = data.senderId
  274.         portsTaken[port] = true
  275.         data.data = tostring(port)
  276.         print("Port Found: " .. port)
  277.     end
  278.     addActionListener("addport",requestRoute)
  279.     local deleteRoute = function(data)
  280.         local port = tonumber(data.data)
  281.         if port ~= nil or port ~= -1 then
  282.             if data.senderId == computerId[port] then
  283.                 computerId[data.senderId] = -1
  284.                 portsTaken[port] = false
  285.                 data.data = "true"
  286.                 print("Port Deleted: " .. port)
  287.             else
  288.                 data.data = "false"
  289.             end
  290.         end    
  291.     end
  292.     addActionListener("removeport",deleteRoute)
  293.     addActionListener("ping",nil)
  294.     basicListener(modem)
  295. end
  296.  
  297. function deletePort(modem,port)
  298.     local d = basicBroadcastWithData(modem,"removeport",tostring(port))
  299.     for k, v in pairs(d.package) do
  300.         if #v.tab > 3 then
  301.             local state = v.tab[4]
  302.             if state ~=nil then
  303.                 if state == "true" then
  304.                     return true
  305.                 else
  306.                     return false
  307.                 end
  308.             end
  309.         end
  310.     end
  311.     print("router error")
  312.     return false
  313. end
  314.  
  315. function getRouterPort(modem)
  316.     local d = basicRequest(modem,"addport",routerComputerId)
  317.     for k, v in pairs(d.package) do
  318.         if #v.tab > 3 then
  319.             local p = v.tab[4]
  320.             if p ~= nil and p ~= "" then
  321.                 return tonumber(p)
  322.             end
  323.         end
  324.     end
  325.     print("router error")
  326.     return -1
  327. end
  328.  
  329. function routerInit(modem)
  330.     portInit(modem)
  331.     openBroadcastNode(modem)
  332.     local d = basicBroadcast(modem,"ping")
  333.     if d.sucess then
  334.         if #d.package > 0 then
  335.             local id = -1
  336.             for k, v in pairs(d.package) do
  337.                 if id == -1 or id == tonumber(v.tab[2]) then
  338.                     id = tonumber(v.tab[2])
  339.                     if id ~= -1 and id < 128 then
  340.                         routerComputerId = id
  341.                         return true
  342.                     end
  343.                 else
  344.                     print("Too many routers")
  345.                     return false
  346.                 end
  347.             end
  348.             print("unknown router Error")
  349.             return false
  350.         elseif #d.package == 0 then
  351.             print("No Routers detected")
  352.             return false
  353.         else
  354.             return false
  355.         end
  356.     else
  357.         print("Router not found")
  358.         return false
  359.     end
  360. end
  361. --End of routeing layer
  362.  
  363.  
  364. function splitText(text)
  365.     local textSplit = {}
  366.     local current = ""
  367.     for i = 1, #text, 1 do
  368.         local currentCharecter = text:sub(i,i)
  369.         if currentCharecter == '\n' then
  370.             table.insert(textSplit,current)
  371.             current = ""
  372.            
  373.         else
  374.             current = current .. currentCharecter
  375.         end
  376.     end
  377.     if current ~= ""  then
  378.         table.insert(textSplit,current)
  379.         current = ""
  380.     end
  381.     return textSplit
  382. end
  383.  
  384. function closeConnection(modem,sendPort,port,transmit)
  385.     if transmit then
  386.         modem.transmit(sendPort,port,"~close-connection")
  387.     end
  388.     if INVERSE then
  389.         redstone.setOutput(REDSTONE_SIDE, true)
  390.     else
  391.         redstone.setOutput(REDSTONE_SIDE, false)
  392.     end
  393.     deletePort(modem,port)
  394. end
  395.  
  396. function connect(modem,port)
  397.     local message = ""
  398.     local sendPort = -1
  399.     local timeout = os.startTimer(2.5)
  400.     modem.transmit(1, port, "~connect~")
  401.     print("Connecting...")
  402.     repeat
  403.         --sender channel is the channel that send the message and the reply channel is the channel that you reply to
  404.         local event, modemSide, senderChannel, replyChannel, message, senderDistance = os.pullEvent()
  405.         if event == "modem_message" then
  406.             if message == "~connection-error~" then
  407.                 print("There is a problem with connecting")
  408.                 break
  409.             elseif message == "~connected~" then
  410.                 sendPort = replyChannel
  411.             end
  412.             print("Connecting...")
  413.         elseif event == "timer" then
  414.             if modemSide == timeout then
  415.                 print("Conection failed, Trying Again...")
  416.                 modem.transmit(1, port, "~connect~")
  417.                 timeout = os.startTimer(2.5)
  418.             end
  419.         elseif event == "key" then
  420.             local key = modemSide
  421.             local held = senderChannel
  422.             if key == 31 then
  423.            
  424.                 print("closeing connections")
  425.                 if sendPort ~= nil and sendPort ~= -1 then
  426.                     closeConnection(modem,sendPort,port,true)
  427.                 end
  428.                 return -1
  429.             end
  430.         end
  431.     until message == "~connected~"
  432.     print("connected")
  433.     return sendPort
  434. end
  435.  
  436. function sendNodeData(modem,sendPort,port)
  437.     local timeout = os.startTimer(2.5)
  438.     modem.transmit(sendPort,port,NODE)
  439.     while true do
  440.         --sender channel is the channel that send the message and the reply channel is the channel that you reply to
  441.         local event, modemSide, senderChannel, replyChannel, message, senderDistance = os.pullEvent()
  442.         if event == "modem_message" then
  443.             if senderChannel == port and replyChannel == sendPort then
  444.                 if message == "~NodeAccepted~" then
  445.                     print("Server Accepted the Node")
  446.                     return true
  447.                 elseif message == "~NodeNotAccepted~" then
  448.                     print("Server Did not accept the Node")
  449.                     return false
  450.                 end
  451.             end
  452.         elseif event == "timer" then
  453.             if modemSide == timeout then
  454.                 print("Node Request failed, Trying Again...")
  455.                 print("Sending node request ServerPort:".. sendPort .. " listenPort:" .. port)
  456.                 modem.transmit(sendPort,port,NODE)
  457.                 timeout = os.startTimer(2.5)
  458.             end
  459.         elseif event == "key" then
  460.             local key = modemSide
  461.             local held = senderChannel
  462.             if key == 31 then
  463.            
  464.                 print("closeing connections")
  465.                 closeConnection(modem,sendPort,port,true)
  466.                 exit()
  467.             end
  468.         end
  469.     end
  470.    
  471. end
  472.  
  473. function run()
  474.     redstone.setOutput(REDSTONE_SIDE, INVERSE)
  475.    
  476.     local modem = detectModem()
  477.     modem.open(3)
  478.    
  479.     if modem == nil then
  480.         return
  481.     end
  482.    
  483.     routerInit(modem)
  484.    
  485.     local port = 1
  486.     while port == 1 do
  487.         port = getRouterPort(modem)
  488.         print("port: " .. port)
  489.         if port == -1 then
  490.             return
  491.         end
  492.     end
  493.    
  494.     modem.open(port)
  495.  
  496.     while true do
  497.         local sendPort = connect(modem,port)--channel you reply to
  498.         if sendPort == nil or sendPort == -1 then
  499.             break
  500.         end
  501.         if sendNodeData(modem,sendPort,port) == true then
  502.             while true do
  503.                 local event, modemSide, senderChannel, replyChannel, message, senderDistance = os.pullEvent()
  504.                 if event == "modem_message" then
  505.                     if senderChannel == port and replyChannel == sendPort then
  506.                         if message == "redstone-on" then
  507.                             if INVERSE then
  508.                                 redstone.setOutput(REDSTONE_SIDE, false)
  509.                             else
  510.                                 redstone.setOutput(REDSTONE_SIDE, true)
  511.                             end
  512.                             modem.transmit(sendPort,port,"~Operation-Complete~")
  513.                         elseif message == "redstone-off" then
  514.                             if INVERSE then
  515.                                 redstone.setOutput(REDSTONE_SIDE, true)
  516.                             else
  517.                                 redstone.setOutput(REDSTONE_SIDE, false)
  518.                             end
  519.                             modem.transmit(sendPort,port,"~Operation-Complete~")
  520.                         elseif message == "~close-connection~" then
  521.                             if INVERSE then
  522.                                 redstone.setOutput(REDSTONE_SIDE, true)
  523.                             else
  524.                                 redstone.setOutput(REDSTONE_SIDE, false)
  525.                             end
  526.                             print("Connection Closed")
  527.                             modem.transmit(sendPort,port,"~Operation-Complete~")
  528.                             closeConnection(modem,sendPort,port,false)
  529.                             break
  530.                         else
  531.                             print("Unknown message recived " .. message)
  532.                         end
  533.                     else
  534.                         print("Unknown transmitter. Transmitter:"..senderChannel.." Message:"..message)
  535.                     end
  536.                 elseif event == "key" then
  537.                     local key = modemSide
  538.                     local held = senderChannel
  539.                     if key == 31 then
  540.                    
  541.                         print("closeing connections")
  542.                         closeConnection(modem,sendPort,port,true)
  543.                         sendPort = -1
  544.                         break
  545.                     end
  546.                 end
  547.             end
  548.         else
  549.             break
  550.         end
  551.         if sendPort == -1 then
  552.             break
  553.         end
  554.     end
  555. end
  556. run()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement