7

I am new to python and programming the Pi, my aim is to make it ping a server such as a gaming server or website and tell me if it is online or offline.

So far I have looked everywhere but nobody gives detailed instructions on how to do it, it may be that it is so "easy" for someone who already programs in python that they assume it is known.

Is this even possible in python?

Piotr Kula
  • 17,307
  • 6
  • 65
  • 104
Josh Bannister
  • 83
  • 1
  • 2
  • 7
  • 1
    Separate it in two parts. Finding out if the host can be pinged and have that result in a variable, and how to turn the given output on/off. When you have solved both tasks, the problem is then reduced to combining th two solutions. – Thorbjørn Ravn Andersen Aug 02 '13 at 09:48
  • Thank you, I will give PiBorg's one a try tonight it seems the simplest of all three, but thank you to all those who helped. I cant upvote yet because I only have 6 rep. – Josh Bannister Aug 02 '13 at 15:05

4 Answers4

8

The RPi.GPIO library is available in Raspbian for driving GPIO, building on using the requests library you could do something like this:

import requests
import time
import RPi.GPIO as GPIO

GPIO.setmode(GPIO.BCM)
GPIO.setup(17, GPIO.OUT)

while True:
    response = requests.get('http://game-server.com')
    if response.status_code == requests.codes.ok:
        GPIO.output(17, GPIO.LOW)
    else:
        GPIO.output(17, GPIO.HIGH)
    time.sleep(1)

Which will turn GPIO 17 on when there is a problem. off when all is ok.

If you need to install any of these modules do so from the command line (terminal) using:

sudo apt-get -y install python-dev python-setuptools python-rpi.gpio python-pip
sudo pip install requests

Alternative:

If you want to get actual latencies as well, probably the simplest method is to actually call the ping program and parse the results:

import requests
import time
import RPi.GPIO as GPIO

GPIO.setmode(GPIO.BCM)
GPIO.setup(17, GPIO.OUT)

while True:
    # Perform the ping using the system ping command (one ping only)
    rawPingFile = os.popen('ping -c 1 %s' % (pingAddress))
    rawPingData = rawPingFile.readlines()
    rawPingFile.close()
    # Extract the ping time
    if len(rawPingData) < 2:
        # Failed to find a DNS resolution or route
        failed = True
        latency = 0
    else:
        index = rawPingData[1].find('time=')
        if index == -1:
            # Ping failed or timed-out
            failed = True
            latency = 0
        else:
            # We have a ping time, isolate it and convert to a number
            failed = False
            latency = rawPingData[1][index + 5:]
            latency = latency[:latency.find(' ')]
            latency = float(latency)
    # Set our outputs
    if failed:
        # Could not ping
        GPIO.output(17, GPIO.HIGH)
    else:
        # Ping stored in latency in milliseconds
        GPIO.output(17, GPIO.LOW)
        print '%f ms' % (latency)

this way you could use many LEDs and make a bar graph based on the ping time, for example.

PiBorg
  • 1,497
  • 10
  • 11
5

You could use the python-requests library:

import requests

response = requests.get('http://game-server.com')
print(int(response.status_code))

See here for the quick-start guide :http://www.python-requests.org/en/latest/user/quickstart/

dotancohen
  • 302
  • 2
  • 13
5

here's a quick and dirty approach, that checks most of possible outcomes and gives a reasonable output:

import socket
from urllib2 import urlopen, URLError, HTTPError

socket.setdefaulttimeout( 23 )  # timeout in seconds

url = 'http://google.com/'
try :
    response = urlopen( url )
except HTTPError, e:
    print 'The server couldn\'t fulfill the request. Reason:', str(e.code)
except URLError, e:
    print 'We failed to reach a server. Reason:', str(e.reason)
else :
    html = response.read()
    print 'got response!'
    # do something, turn the light on/off or whatever
lenik
  • 11,541
  • 1
  • 30
  • 37
  • This one works well to turn on a light when i add on the end GPIO.output(18, True). however i can not seem to make it turn the light off when it can not find the server? any suggestions – Josh Bannister Aug 02 '13 at 20:17
  • you may add GPIO.output(18, False) in the beginning (before try: statement), the LED will shortly blink when the web-site is accessed and turn back on if everything is alright (or not, if something is wrong). – lenik Aug 03 '13 at 02:56
  • Alternatively add GPIO.output(18, False) at the end of the two except blocks, this will prevent it blinking (if not desirable) – PiBorg Aug 03 '13 at 09:26
0

Here are some programs I use to monitor my systems. Any variation of these would be able to be used as the basis for a program which acts on the results via PiGPIO as described below.


fping in Python to monitor delays and to see if systems are alive.

sudo apt-get update
sudo apt-get install fping

from subprocess import Popen, PIPE
.
.
.
cmd = 'fping -C 1 -q www.myaddress.com'
p = Popen(cmd,stdout=PIPE, stderr=PIPE, shell=True)
stdout, stderr = p.communicate()

NOTE THAT THE OUTPUT IS IN stderr AND LOOKS LIKE THIS:

50.87.249.67 : 6.30       for a positive response

or

50.87.249.67 : -          for a non response

OR

You can use this alternate cmd command string in the same code:

from subprocess import Popen, PIPE
.
.
.
cmd = 'fping www.myaddress.com'
p = Popen(cmd,stdout=PIPE, stderr=PIPE, shell=True)
stdout, stderr = p.communicate()

NOTE THAT THE OUTPUT IS IN stderr AND LOOKS LIKE THIS:

where the result is either

www.myaddress.com is alive

or

www.myaddress.com: Name or service not known

-----------------------------------------------

Then to control outside devices I always recommend piGPIO

piGPIO Library Interface

piGPIO Library Examples


I use a similar method for a ping-delay monitor:

#!/usr/bin/python
import os 
import time 
from subprocess import Popen, PIPE
from datetime import datetime
os.system('clear') 
os.chdir("/home/pi/pymon"
tab = "\t"

while True :

tt = datetime.now()
ts = " "
ts = str(getattr(tt,'hour')) + ":"
if getattr(tt,'minute')<10: 
    ts = ts + '0'
ss = ts + str(getattr(tt,'minute')) + ":"
if getattr(tt,'second')<10: 
  ts = ts + '0'
ts = ts + str(getattr(tt,'second'))
td = datetime.today()
ds = " "
ds = str(td.year)
if td.month<10 :
    ds = ds +"0"
ds = ds + str(td.month)
if td.day<10 :
    ds = ds + "0"
ds = ds + str(td.day) 
datestr   = str(datetime.now().date())
datestr   = datestr[:10]            
timestr   = str(datetime.now().time())
timestr   = timestr[:8]

cmd = 'fping -C 1 -q www.SDsolarBlog.com'
p = Popen(cmd,stdout=PIPE, stderr=PIPE, shell=True)
stdout, stderr = p.communicate()

outline = datestr + tab + timestr + tab + stderr

f = open("/home/pi/pymon/today.dat","a")
f.write(outline)
f.close()

os.system("tail -n 1 today.dat")
print

time.sleep(60.0)

which produces a datafile that looks like:

2018-04-04  00:17:52    50.87.249.67 : 6.56
2018-04-04  00:18:52    50.87.249.67 : -
2018-04-04  00:19:52    50.87.249.67 : 7.41
2018-04-04  00:20:52    50.87.249.67 : 10.99

The line with the - is a line where there was no response in 3 seconds.

I use this output with a gnuplot program to plot it all out.

set title "Ping Times"
set xlabel "Time"
set ylabel "Ping Times"
set yrange [0:*]
set grid
set timestamp
unset mouse
unset log
set key top left
set xdata time
set timefmt '%H:%M:%S'
set xtics format '%H:%M'
set datafile missing "-"
set y2tics
set terminal x11
set style fill solid 1.0
plot 50 lw 1 lc rgb "black" notitle, \
    100 lw 1 lc rgb "gray" notitle, \
    "today.dat" using 2:5 skip 2 with lines lc rgb "red" t "Delay"
pause 11
reread     

to get a live plot:

enter image description here


This is similar to the code I use for a different command:

What's the maximum / minimum running temperature?

SDsolar
  • 2,348
  • 8
  • 25
  • 43