Posted 10 July 2014 - 04:47 PM
Greetings,
I'm rather new to the community here, and wouldn't be too surprised if I were to get trout slapped by a professional developer looking to prove to the world that I'm an idiot. In all fairness, I am an idiot.
I figure posting my code here will allow me to move into a greater realm of CC systems design as I get further into the yogspack and continue to grow my facility.
So here it goes, my first, nooby, incorrect syntax post:
This isn't specifically an API, more over a solution for those just getting into the meat and potatoes of networking in CC.
First, let me explain it's use.
Simply put, I needed a way to get the current status of my various servers and control computers around my facility. I have computers controlling power output, emergency power storage, reactors, ME computers, and various other systems I plan to add.
For the start, I have a control room, with a large screen (GO NASA!). This screen is controlled by a screen server, and pings the various control computers to check their statuses. I decided to use the modem API because it was new and had fancy channels, but as I got into it, I found rednet may have been a better choice. Either way, I am sticking with modem.
My first task in the system was to get a solution built that would ping the control servers, of which I have six.
Now, to any beginner, this isn't as easy as it seems. It can be challenging to grasp the idea of networking, sending data and receiving data. I often get stuck at trying to receive data. It will wait and wait and wait… and wait… forever. I needed to find a way to receive data whilst continuing to control screens and communicate with other systems. The code below is my first step in this direction. It isn't perfect, but it's, what I believe, a great step in the right direction.
Here we go:
This link will make it easier to read: http://pastebin.com/RjdXMsbS
Alright, so that is my main screen, it will send a ping to all 6 servers and listen for a few seconds for a return ping. If there is no ping return, if assumes it is offline, and moves to the next server.
Let's look at the code a little closer and move away from some of these non-interesting functions…
First let's take a look at the send function, pretty simple:
It's pretty basic, really just a way for me to simplify typing in my main body, nothing more really. chan is the desired channel to send, reply is the response channel, and m represents the message to send.
Next, the more complicated get function:
So one step at a time…
First we decide if the timer is needed or not. A listener may never need to timeout, but a ping may only want to listen for a few seconds.
I was lazy and just put a large number in. I will eventually change this to a version without a timer at all. Just lazy.
Next we open the channel we wish to listen on, and check that it opened… If it failed to open we throw an error. If it succeeds, we then begin the message listening. We open an event named event, upon opening the event, we listen for two things. First, was the event modem_message? If so we then define the message and break the loop. The ping was received, yay! However, assuming a timer was set, if we get the timer event, our timer has timed out and it is time to move on, a ping was not received. Boo :(/>
… Will continue when I return from lunch :)/>)
Alright… back :D/>… So we've used a timer to limit our listening time (if we choose to).
So how do we use get? In the end, it's really simple, get(chan,tmout) where chan represents channel and tmout represents the time, in seconds, we want to listen before timing out and moving on.
That concludes send and get. We now have some functions to allow us to get and send messages.
But how can we use this?
I specifically built this function:
It will send a ping on the chosen channel, and offer a response channel, then listen for "gettmout" amount of time to get a return ping. If it gets a return ping, it uses my writing function to write the status to the big screen. If it times out, it will display that server x is down.
The combination to make this revolve through several servers can be seen in my main program:
Essentially, I clear the screen, move the cursor to the top left, display that the control system is online, then use a while loop to check server 1,2 and 3 on channel 1,3, and 5. I originally planned to have multiple return channels for each server, but decided to only use channel 2. You can also see in my comments that I plan to also check some other servers and also have a screen check. I will update this post once I have completed that.
Also very quickly I will discuss my listening code on the server to show how it works:
So basically what I've done on each server is use a get function with no timeout to listen for the initial ping from the screen server. It will reply and begin to listen again. Parallel it will also complete the test() function. This does limit me to using non-interactive functions :(/>. IE I can't run one function that listens for user input (io.read()) because it will wait for the input before running the listen function. :(/> Does anyone have a better solution?
Is this code total junk? If you have suggestions, questions, comments etc, please feel free to share. Just remember, I'm a beginner, and I like learning, but please don't be a jerk. No one likes a jerk.
Thanks guys!
I'm rather new to the community here, and wouldn't be too surprised if I were to get trout slapped by a professional developer looking to prove to the world that I'm an idiot. In all fairness, I am an idiot.
I figure posting my code here will allow me to move into a greater realm of CC systems design as I get further into the yogspack and continue to grow my facility.
So here it goes, my first, nooby, incorrect syntax post:
This isn't specifically an API, more over a solution for those just getting into the meat and potatoes of networking in CC.
First, let me explain it's use.
Simply put, I needed a way to get the current status of my various servers and control computers around my facility. I have computers controlling power output, emergency power storage, reactors, ME computers, and various other systems I plan to add.
For the start, I have a control room, with a large screen (GO NASA!). This screen is controlled by a screen server, and pings the various control computers to check their statuses. I decided to use the modem API because it was new and had fancy channels, but as I got into it, I found rednet may have been a better choice. Either way, I am sticking with modem.
My first task in the system was to get a solution built that would ping the control servers, of which I have six.
Now, to any beginner, this isn't as easy as it seems. It can be challenging to grasp the idea of networking, sending data and receiving data. I often get stuck at trying to receive data. It will wait and wait and wait… and wait… forever. I needed to find a way to receive data whilst continuing to control screens and communicate with other systems. The code below is my first step in this direction. It isn't perfect, but it's, what I believe, a great step in the right direction.
Here we go:
--Modem Communication Numbering
-- 1/2 Screen to Server 1
-- 2/1 Server 1 to Screen
--3/4 Screen to Power Emergency PC
-- 4/3 Pwr Em. PC to Screen
local modem = peripheral.wrap('back')
local screen = peripheral.wrap('top')
function ps(n) --similar to print
screen.write(n)
x,y=screen.getCursorPos()
y=y+1
screen.setCursorPos(1,y)
end
function w(n) --write same line
x1,y1=screen.getCursorPos()
screen.setCursorPos(1,y1)
screen.clearLine()
screen.write(n)
end
function reset() --places cursor to left again
x1,y1=screen.getCursorPos()
screen.setCursorPos(1,y1)
end
function send(chan,reply,m) --transmits a message
modem.transmit(chan,reply,m)
end
function get(chan,tmout)--listener
if tmout==nil then
tmout=100000000000000000000000000000 --change to call event w/o timer
end
modem.open(chan) --opens port
chk=modem.isOpen(chan) --checks to make sure it is open
if chk==true then --will set listener
--mm = os.pullEvent("modem_message")
timeout = os.startTimer(tmout)
while true do
event = {os.pullEvent()}
if event[1] == "modem_message" then
--print'Worked'
--print(event[1].." "..event[2].." "..event[3].." "..event[4].." "..event[5].." "..event[6])
msg=event[5]
returnchan=event[4]
chan=event[3]
success=1
break
elseif event[1] == "timer" and event[2] == timeout then
success=0
break
end
end
end
if chk==false then
--send error# to screen
print('Error 100: Failed to Bind Port '..chan..'.')
end
end
function chksvr(sendchan,svrnum,gettmout)
send(sendchan,2,"ping")
get(2,gettmout)
if success==1 then
screen.setCursorPos(1,svrnum+2)
w("Server "..svrnum..": Online")
end
if success==0 then
screen.setCursorPos(1,svrnum+2)
w("Server "..svrnum..": DOWN")
end
--sleep(5)
end
--main
screen.clear()
screen.setCursorPos(1,1)
ps("Kizz Tower Control: ONLINE")
ps("")
--MAIN LOOP for REFRESH
while true do
--Screen choice chk
--Power system checks/screen
--Server Checks/Screen
chksvr(1,1,2)
chksvr(3,2,2)
chksvr(5,3,2)
--loop refresh pause (removed due to timer in get function)
end
--end main
This link will make it easier to read: http://pastebin.com/RjdXMsbS
Alright, so that is my main screen, it will send a ping to all 6 servers and listen for a few seconds for a return ping. If there is no ping return, if assumes it is offline, and moves to the next server.
Let's look at the code a little closer and move away from some of these non-interesting functions…
First let's take a look at the send function, pretty simple:
function send(chan,reply,m) --transmits a message
modem.transmit(chan,reply,m)
end
It's pretty basic, really just a way for me to simplify typing in my main body, nothing more really. chan is the desired channel to send, reply is the response channel, and m represents the message to send.
Next, the more complicated get function:
function get(chan,tmout)--listener
if tmout==nil then
tmout=100000000000000000000000000000 --change to call event w/o timer
end
modem.open(chan) --opens port
chk=modem.isOpen(chan) --checks to make sure it is open
if chk==true then --will set listener
--mm = os.pullEvent("modem_message")
timeout = os.startTimer(tmout)
while true do
event = {os.pullEvent()}
if event[1] == "modem_message" then
--print'Worked'
--print(event[1].." "..event[2].." "..event[3].." "..event[4].." "..event[5].." "..event[6])
msg=event[5]
returnchan=event[4]
chan=event[3]
success=1
break
elseif event[1] == "timer" and event[2] == timeout then
success=0
break
end
end
end
if chk==false then
--send error# to screen
print('Error 100: Failed to Bind Port '..chan..'.')
end
end
So one step at a time…
First we decide if the timer is needed or not. A listener may never need to timeout, but a ping may only want to listen for a few seconds.
I was lazy and just put a large number in. I will eventually change this to a version without a timer at all. Just lazy.
Next we open the channel we wish to listen on, and check that it opened… If it failed to open we throw an error. If it succeeds, we then begin the message listening. We open an event named event, upon opening the event, we listen for two things. First, was the event modem_message? If so we then define the message and break the loop. The ping was received, yay! However, assuming a timer was set, if we get the timer event, our timer has timed out and it is time to move on, a ping was not received. Boo :(/>
Alright… back :D/>… So we've used a timer to limit our listening time (if we choose to).
So how do we use get? In the end, it's really simple, get(chan,tmout) where chan represents channel and tmout represents the time, in seconds, we want to listen before timing out and moving on.
That concludes send and get. We now have some functions to allow us to get and send messages.
But how can we use this?
I specifically built this function:
function chksvr(sendchan,svrnum,gettmout)
send(sendchan,2,"ping")
get(2,gettmout)
if success==1 then
screen.setCursorPos(1,svrnum+2)
w("Server "..svrnum..": Online")
end
if success==0 then
screen.setCursorPos(1,svrnum+2)
w("Server "..svrnum..": DOWN")
end
--sleep(5)
end
It will send a ping on the chosen channel, and offer a response channel, then listen for "gettmout" amount of time to get a return ping. If it gets a return ping, it uses my writing function to write the status to the big screen. If it times out, it will display that server x is down.
The combination to make this revolve through several servers can be seen in my main program:
screen.clear()
screen.setCursorPos(1,1)
ps("Kizz Tower Control: ONLINE")
ps("")
--MAIN LOOP for REFRESH
while true do
--Screen choice chk
--Power system checks/screen
--Server Checks/Screen
chksvr(1,1,2) --channel,server,timeout
chksvr(3,2,2)
chksvr(5,3,2)
--loop refresh pause (removed due to timer in get function)
end
--end main
Essentially, I clear the screen, move the cursor to the top left, display that the control system is online, then use a while loop to check server 1,2 and 3 on channel 1,3, and 5. I originally planned to have multiple return channels for each server, but decided to only use channel 2. You can also see in my comments that I plan to also check some other servers and also have a screen check. I will update this post once I have completed that.
Also very quickly I will discuss my listening code on the server to show how it works:
local modem = peripheral.wrap('back')
function send(chan,reply,m)
modem.transmit(chan,reply,m)
end
function get(chan,tmout)--listener
if tmout==nil then
tmout=100000000000000000000000000000 --change to call event w/o timer
end
modem.open(chan) --opens port
chk=modem.isOpen(chan) --checks to make sure it is open
if chk==true then --will set listener
--mm = os.pullEvent("modem_message")
timeout = os.startTimer(tmout)
while true do
event = {os.pullEvent()}
if event[1] == "modem_message" then
--print'Worked'
--print(event[1].." "..event[2].." "..event[3].." "..event[4].." "..event[5].." "..event[6])
msg=event[5]
returnchan=event[4]
chan=event[3]
break
elseif event[1] == "timer" and event[2] == timeout then
break
end
end
end
if chk==false then
--send error# to screen
print('Error 100: Failed to Bind Port '..chan..'.')
end
end
function listen()
while true do
get(1)
--print(msg)
send(2,1,"ping")
--sleep(.5)
--os.reboot()
end
end
function test()
print'Welcome to Server 1.'
print'System online.'
end
parallel.waitForAny(test(),listen())
So basically what I've done on each server is use a get function with no timeout to listen for the initial ping from the screen server. It will reply and begin to listen again. Parallel it will also complete the test() function. This does limit me to using non-interactive functions :(/>. IE I can't run one function that listens for user input (io.read()) because it will wait for the input before running the listen function. :(/> Does anyone have a better solution?
Is this code total junk? If you have suggestions, questions, comments etc, please feel free to share. Just remember, I'm a beginner, and I like learning, but please don't be a jerk. No one likes a jerk.
Thanks guys!
Edited on 10 July 2014 - 04:34 PM