Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- --Computer Craft Node Application for redstone interfacing
- --By snipy67
- --V1.2
- --You will need the Master Application at http://pastebin.com/edit/5xnjjYWA
- --You will need the Router Application in server mode running on the network http://pastebin.com/BuRcCc2n
- --change the nodes
- NODE = "node0"--set your node name
- REDSTONE_SIDE = "top"
- INVERSE = false
- --router application
- BROADCAST_PORT = 2
- --Computer Craft Router Application
- --By snipy67
- --V1.0
- BROADCAST_PORT = 2
- --Layer 1
- lowLevelListeners = {}
- routerComputerId = 0
- function detectModem()
- return peripheral.find("modem")
- end
- function lowLevelMessageSplit(message)
- local tab = {}
- local current = ""
- for i = 1, #message, 1 do
- if message:sub(i,i) == ':' then
- table.insert(tab,current)
- current = ""
- else
- current = current .. message:sub(i,i)
- end
- end
- if #current > 0 then
- table.insert(tab,current)
- end
- return tab
- end
- function lowLevelListenerCheckForMethod(modem,port,tab,verbose)
- for k, v in pairs(lowLevelListeners) do
- if v.message == tab[1] then
- if verbose then
- print("function " .. v.message .. "found")
- end
- if v.func ~= nil then
- local t = {}
- t.message = tab[1]
- t.senderId = tab[2]
- t.reciverId = tab[3]
- t.data = tab[4]
- v.func(t)
- if t.data ~= nil then
- local responseText = tab[1] .. "~response:" .. os.getComputerID() .. ":".. tab[2] .. ":".. t.data;
- modem.transmit(port,port,responseText)
- else
- local responseText = tab[1] .. "~response:" .. os.getComputerID() .. ":".. tab[2]
- modem.transmit(port,port,responseText)
- end
- else
- local responseText = tab[1] .. "~response:" .. os.getComputerID() .. ":".. tab[2]
- modem.transmit(port,port,responseText)
- end
- return true
- else
- if verbose then
- print("v.message:" .. v.message .. " != tab[1]:"..tab[1])
- end
- end
- end
- return false
- end
- function lowLevelListener(modem,port,verbose)
- while true do
- local event, modemSide, senderChannel, replyChannel, message, senderDistance = os.pullEvent()--listens for a actions
- if event == "modem_message" then--gets the message
- if senderChannel == port then
- if verbose then
- print("message recived: " .. message)
- end
- local tab = lowLevelMessageSplit(message)
- if #tab > 2 then
- if verbose then
- print("There is more then 2 arguments in the message")
- end
- if tonumber(tab[3]) == os.getComputerID() then
- if verbose then
- print("id matches")
- end
- lowLevelListenerCheckForMethod(modem,port,tab,verbose)
- elseif tonumber(tab[3]) == -1 then
- if verbose then
- print("broadcast")
- end
- lowLevelListenerCheckForMethod(modem,port,tab,verbose)
- end
- elseif #tab == 2 then
- lowLevelListenerCheckForMethod(modem,port,tab,verbose)
- end
- end
- end
- end
- end
- function lowLevelRequest(modem,request,port,maxTimeOut,timeBetweenResend,numberOfResendsBeforeTimeOut,id,data,verbose)
- local str = ""
- if id ~= nil and id ~= -1 then
- str = request .. ":" .. os.getComputerID() .. ":" .. id -- adds the computer id and the id of the reciver
- else
- str = request .. ":" .. os.getComputerID() .. ":" .. -1-- adds the computer id to the requests
- end
- if data ~= nil then
- str = str .. ":" .. data
- end
- modem.transmit(port,port,str);--transmits the request
- local responseText = request .. "~response"--creates text on how a response will look like
- local count = 0--count is to keep track of how many times the request timed out
- local timer = -1
- if timeBetweenResend > 0 and numberOfResendsBeforeTimeOut > 0 then
- timer = os.startTimer(timeBetweenResend) -- to keep track of the number of seconds before a time out
- end
- local atLeastOne = false--this determines if atleast one computer recived the request
- local timeOutTimer
- if maxTimeOut > 0 then
- timeOutTimer = os.startTimer(maxTimeOut)--this timer is the number of seconds it should wait for return requests
- end
- local all = {} -- this is all the data that will be returned
- all.package = {}--this is where the data from each request is stored
- while true do
- local event, modemSide, senderChannel, replyChannel, message, senderDistance = os.pullEvent()--listens for a actions
- if event == "timer" then--check if the timer is up
- local timerId = modemSide; --modemSide is the timerid when timer event is called (prevents confusion)
- if timerId == timer then--checks if the timer is the timer that handels resends
- if atLeastOne == false then--checks if there are no records recovered
- if count ~= numberOfResendsBeforeTimeOut then--check to make sure the count is not at the timeout stage
- modem.transmit(port,port,str);--transmits the request again
- count = count + 1 -- adds one to the #of time outs
- timer = os.startTimer(timeBetweenResend)--resets the timer
- if verbose then
- print("Message Transmission failed resending...")
- end
- else
- if verbose then
- print("Message Transmission failed")
- end
- all.sucess = false
- return all
- end
- end
- 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
- if atLeastone == false then
- all.sucess = false
- else
- all.sucess = true
- end
- return all
- end
- elseif event == "modem_message" then--gets the message
- if senderChannel == port then
- local tab = lowLevelMessageSplit(message)
- if verbose then
- print("Modem message: " .. message)
- end
- if tab[1] == responseText then
- if tonumber(tab[3]) == os.getComputerID() then
- local p = {}
- p.sucess = true
- p.tab = tab
- atLeastOne = true
- table.insert(all.package,p)
- if verbose then
- print("This computer: " .. tab[3] .. ". Request response recived from " .. tab[2])
- end
- if timeOutTimer == -1 then
- all.sucess = true
- return all;
- end
- end
- end
- end
- end
- end
- end
- MAX_TIME_OUT = 0.8
- TIME_BETWEEN_RESENDS = 0.2
- NUMBER_OF_RESENDS = 4
- VERBOSE = false
- --easy to use methods
- --> the low level lowLevelListener returns true if atleast 1 tramission has been valid and in this case only 1 transmision
- function basicListener(modem)
- return lowLevelListener(modem,BROADCAST_PORT,VERBOSE)--this will never finish, it will listen forever
- end
- -->Low level request return
- --.sucess
- --.package[instance].sucess = true
- --.package[instance].tab = tab
- function basicBroadcast(modem,request)
- 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
- end
- function basicRequest(modem,request,computer)
- return lowLevelRequest(modem,request,BROADCAST_PORT,MAX_TIME_OUT,TIME_BETWEEN_RESENDS,NUMBER_OF_RESENDS,computer,nil,VERBOSE)-- a message for a certian computer
- end
- function basicBroadcastWithData(modem,request,data)
- return lowLevelRequest(modem,request,BROADCAST_PORT,MAX_TIME_OUT,TIME_BETWEEN_RESENDS,NUMBER_OF_RESENDS,nil,data,VERBOSE)-- this a a broadcast with data
- end
- function basicRequestWithData(modem,request,computer,data)
- 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
- end
- function addActionListener(message,func)
- --function parameters required (data)
- --.message -- the message that was transmitted
- --.senderId -- the sender of the message
- --.reciverId -- the reciver of the message
- --.data -- the data that might have been passed along
- local tab = {}
- tab.message = message
- tab.func = func
- table.insert(lowLevelListeners,tab)
- return #lowLevelListeners
- end
- function removeActionListener(index)
- table.remove(lowLevelListeners,index)
- end
- --End Of Layer 1
- --Routeing layer
- portsTaken = {}
- computerId = {}
- function openBroadcastNode(modem)
- portsTaken[BROADCAST_PORT] = true
- modem.open(BROADCAST_PORT)
- end
- function portInit(modem)
- for i = 1, 128, 1 do
- portsTaken[i] = false
- if modem.isOpen(i) then
- modem.close(i)
- end
- end
- end
- function findEmptyPort(modem)
- for i = 1,128, 1 do
- if portsTaken[i] == false then
- return i
- end
- end
- return -1
- end
- function routerServer(modem)
- portInit(modem)
- openBroadcastNode(modem)
- local requestRoute = function(data)
- local port = findEmptyPort(modem)
- computerId[port] = data.senderId
- portsTaken[port] = true
- data.data = tostring(port)
- print("Port Found: " .. port)
- end
- addActionListener("addport",requestRoute)
- local deleteRoute = function(data)
- local port = tonumber(data.data)
- if port ~= nil or port ~= -1 then
- if data.senderId == computerId[port] then
- computerId[data.senderId] = -1
- portsTaken[port] = false
- data.data = "true"
- print("Port Deleted: " .. port)
- else
- data.data = "false"
- end
- end
- end
- addActionListener("removeport",deleteRoute)
- addActionListener("ping",nil)
- basicListener(modem)
- end
- function deletePort(modem,port)
- local d = basicBroadcastWithData(modem,"removeport",tostring(port))
- for k, v in pairs(d.package) do
- if #v.tab > 3 then
- local state = v.tab[4]
- if state ~=nil then
- if state == "true" then
- return true
- else
- return false
- end
- end
- end
- end
- print("router error")
- return false
- end
- function getRouterPort(modem)
- local d = basicRequest(modem,"addport",routerComputerId)
- for k, v in pairs(d.package) do
- if #v.tab > 3 then
- local p = v.tab[4]
- if p ~= nil and p ~= "" then
- return tonumber(p)
- end
- end
- end
- print("router error")
- return -1
- end
- function routerInit(modem)
- portInit(modem)
- openBroadcastNode(modem)
- local d = basicBroadcast(modem,"ping")
- if d.sucess then
- if #d.package > 0 then
- local id = -1
- for k, v in pairs(d.package) do
- if id == -1 or id == tonumber(v.tab[2]) then
- id = tonumber(v.tab[2])
- if id ~= -1 and id < 128 then
- routerComputerId = id
- return true
- end
- else
- print("Too many routers")
- return false
- end
- end
- print("unknown router Error")
- return false
- elseif #d.package == 0 then
- print("No Routers detected")
- return false
- else
- return false
- end
- else
- print("Router not found")
- return false
- end
- end
- --End of routeing layer
- function splitText(text)
- local textSplit = {}
- local current = ""
- for i = 1, #text, 1 do
- local currentCharecter = text:sub(i,i)
- if currentCharecter == '\n' then
- table.insert(textSplit,current)
- current = ""
- else
- current = current .. currentCharecter
- end
- end
- if current ~= "" then
- table.insert(textSplit,current)
- current = ""
- end
- return textSplit
- end
- function closeConnection(modem,sendPort,port,transmit)
- if transmit then
- modem.transmit(sendPort,port,"~close-connection")
- end
- if INVERSE then
- redstone.setOutput(REDSTONE_SIDE, true)
- else
- redstone.setOutput(REDSTONE_SIDE, false)
- end
- deletePort(modem,port)
- end
- function connect(modem,port)
- local message = ""
- local sendPort = -1
- local timeout = os.startTimer(2.5)
- modem.transmit(1, port, "~connect~")
- print("Connecting...")
- repeat
- --sender channel is the channel that send the message and the reply channel is the channel that you reply to
- local event, modemSide, senderChannel, replyChannel, message, senderDistance = os.pullEvent()
- if event == "modem_message" then
- if message == "~connection-error~" then
- print("There is a problem with connecting")
- break
- elseif message == "~connected~" then
- sendPort = replyChannel
- end
- print("Connecting...")
- elseif event == "timer" then
- if modemSide == timeout then
- print("Conection failed, Trying Again...")
- modem.transmit(1, port, "~connect~")
- timeout = os.startTimer(2.5)
- end
- elseif event == "key" then
- local key = modemSide
- local held = senderChannel
- if key == 31 then
- print("closeing connections")
- if sendPort ~= nil and sendPort ~= -1 then
- closeConnection(modem,sendPort,port,true)
- end
- return -1
- end
- end
- until message == "~connected~"
- print("connected")
- return sendPort
- end
- function sendNodeData(modem,sendPort,port)
- local timeout = os.startTimer(2.5)
- modem.transmit(sendPort,port,NODE)
- while true do
- --sender channel is the channel that send the message and the reply channel is the channel that you reply to
- local event, modemSide, senderChannel, replyChannel, message, senderDistance = os.pullEvent()
- if event == "modem_message" then
- if senderChannel == port and replyChannel == sendPort then
- if message == "~NodeAccepted~" then
- print("Server Accepted the Node")
- return true
- elseif message == "~NodeNotAccepted~" then
- print("Server Did not accept the Node")
- return false
- end
- end
- elseif event == "timer" then
- if modemSide == timeout then
- print("Node Request failed, Trying Again...")
- print("Sending node request ServerPort:".. sendPort .. " listenPort:" .. port)
- modem.transmit(sendPort,port,NODE)
- timeout = os.startTimer(2.5)
- end
- elseif event == "key" then
- local key = modemSide
- local held = senderChannel
- if key == 31 then
- print("closeing connections")
- closeConnection(modem,sendPort,port,true)
- exit()
- end
- end
- end
- end
- function run()
- redstone.setOutput(REDSTONE_SIDE, INVERSE)
- local modem = detectModem()
- modem.open(3)
- if modem == nil then
- return
- end
- routerInit(modem)
- local port = 1
- while port == 1 do
- port = getRouterPort(modem)
- print("port: " .. port)
- if port == -1 then
- return
- end
- end
- modem.open(port)
- while true do
- local sendPort = connect(modem,port)--channel you reply to
- if sendPort == nil or sendPort == -1 then
- break
- end
- if sendNodeData(modem,sendPort,port) == true then
- while true do
- local event, modemSide, senderChannel, replyChannel, message, senderDistance = os.pullEvent()
- if event == "modem_message" then
- if senderChannel == port and replyChannel == sendPort then
- if message == "redstone-on" then
- if INVERSE then
- redstone.setOutput(REDSTONE_SIDE, false)
- else
- redstone.setOutput(REDSTONE_SIDE, true)
- end
- modem.transmit(sendPort,port,"~Operation-Complete~")
- elseif message == "redstone-off" then
- if INVERSE then
- redstone.setOutput(REDSTONE_SIDE, true)
- else
- redstone.setOutput(REDSTONE_SIDE, false)
- end
- modem.transmit(sendPort,port,"~Operation-Complete~")
- elseif message == "~close-connection~" then
- if INVERSE then
- redstone.setOutput(REDSTONE_SIDE, true)
- else
- redstone.setOutput(REDSTONE_SIDE, false)
- end
- print("Connection Closed")
- modem.transmit(sendPort,port,"~Operation-Complete~")
- closeConnection(modem,sendPort,port,false)
- break
- else
- print("Unknown message recived " .. message)
- end
- else
- print("Unknown transmitter. Transmitter:"..senderChannel.." Message:"..message)
- end
- elseif event == "key" then
- local key = modemSide
- local held = senderChannel
- if key == 31 then
- print("closeing connections")
- closeConnection(modem,sendPort,port,true)
- sendPort = -1
- break
- end
- end
- end
- else
- break
- end
- if sendPort == -1 then
- break
- end
- end
- end
- run()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement