This project is amazingly useful and incredibly simple to duplicate. If you already have a Raspberry PI it is very cheap to implement.
-----
What it does and how it works:
The Raspberry PI runs a Python program that test pings 10 internet sites that you to determine to provide the status of your internet connection.
GREEN: 7 or more sites return a successful ping.
Green LED on. Updates the stats.
YELLOW: 6 to 4 sites return a successful ping.
Yellow LED on. Updates the stats.
RED: 3 or fewer sites return a successful ping.
Red LED on. Updates the stats.
To make the program run faster and not burden the network with outgoing pings, all 10 sites are not pinged on each run. The ping test rotates through the 10 sites. If the selected site does fail the ping test, the program goes into "Deep Probe" and checks all 10 sites to determine the connection status. "Deep Probe" runs are tracked for the status report that prints to the screen.
Each hour a status report is appended to a Google Drive spreadsheet via the Maker channel at IFTTT.Com.
-----
For a visual output we went with a device that anyone can identify with, a simple $8 toy traffic light from Amazon. For $8 you get a lot. The light is well build, looks great, and is a full 7" tall with three LEDs already installed. It also comes with 12 little toy cars that you can give away; you don't need those. Next remove the four screws at the bottom of the base. You are going to see four wires that lead up to the three LEDs in the traffic light. Cut those wires and free them from the little ON/OFF switch and microcontroller that was meant to control the blink patterns for the non-hacker. Now you should only be left with four wires. The LEDs are wired common athode (+). The simple schematic below shows the hookup for each LED and their connection to the Raspberry PI. Double check the wiring for your traffic light with a button cell battery to see what wire lights each LED.
-----
You don't need to open the back, but if you did it would look like this:
-----
After you wire in the toy traffic light it will look something like this:
-----
Now you will need to load the Python source code provided below, but before you do, a few simple edits are required:
- Find in the code where it says "# Identify ten PING 'friendly' sites". In that section put in ten IP addresses or DNS names that are "ping friendly". Not all sites allow you to ping them, so test ping them manually first from a command line.
- Find the variable named "Delay_between_tests". In the program it is set to 15 (for 15 seconds). Adjust this if you want to test more or less frequently.
-----
That's about it, now run the program. The RasPI will take the traffic light through an LED self test. Then it will do an initial first run deep probe ping test on all ten of the test sites; the LEDs will self test during this as well.
From then on the little toy traffic light will answer that all too common "Is the internet up?" question. In addition, as the local IT Support Manager, you will have access to a running history in a Google Drive spreadsheet and the status output table below to impress your friends:
Here is the Python code that makes it all work. Of course, as mentioned above, you will need to supply your own list of ten ping friendly internet sites instead of "yourtestsite-1.com", etc.
# Is the Internet UP? / August 2015
#
# Project details at:
# http://whiskeytangohotel.com/internetup
#
# Using a Raspberry PI we ping a 10 IP addresses and light up a Red, Yellow, or Green LED
# to display the 'health' of our internet connection.
#
# SEPT 3, 2015: Adding IFTTT.com Maker channel to log status to Google Drive each hour.
#
# At least 7 of 10 successful pings to light the Green LED
# 3 or fewer of 10 successful pings for Red LED
# Anything in between and light the Yellow LED
#
# Program does not ping all 10 sites each time. For speed, etc. one of the sites
# is tested at each run. If that ping fails, 'deep probe' mode involkes and all sites are tested
# to determine latest Red/Yellow/Green status.
#
# As an output device we used a $7 toy stoplight from Amazon.com. Search:
# "Dazzling Toys Racer Cars and Traffic Set - 7" Traffic Light with 12 Pull Back 2" Racer Cars"
#
# In addition to the LED stop light status. The details below are screen printed on each run.
#
# Tue, 01 Sep 2015 05:03:32. Update interval: 15 seconds.
# Status report: GREEN. Runs: 1812. DeepProbes: 6. Runtime: 8:42:44.448047
# -----------------------------------------------------------------------------------
# Last check: UP pingfriendlysite-1.com was UP 188 of 189 pings. 99% uptime.
# >>>Last check: UP pingfriendlysite-2.com was UP 189 of 189 pings. 100% uptime.
# Last check: UP pingfriendlysite-3.com was UP 187 of 188 pings. 99% uptime.
# Last check: UP pingfriendlysite-4.com was UP 187 of 188 pings. 99% uptime.
# Last check: UP pingfriendlysite-5.com was UP 188 of 188 pings. 100% uptime.
# Last check: UP pingfriendlysite-6.com was UP 188 of 188 pings. 100% uptime.
# Last check: UP pingfriendlysite-7.com was UP 188 of 188 pings. 100% uptime.
# Last check: UP pingfriendlysite-8.com was UP 188 of 188 pings. 100% uptime.
# Last check: UP pingfriendlysite-9.com was UP 188 of 188 pings. 100% uptime.
# Last check: UP pingfriendlysite-10.com was UP 185 of 188 pings. 98% uptime.
# ------------------------------------------------------------------------------------
#
# RED: 0 events. Last event: none detected
# YELLOW: 0 events. Last event: none detected
# GREEN: 1812 events. Last event: Tue, 01 Sep 2015 05:03:32
#
from __future__ import division # don't round interger division to 'zero'
import time
import datetime # used for timestamp math
t0 = datetime.datetime.now() # for timestamp math. t0 is the time the program run started
runtime = 0 # localtime minus t0 = total runtime of the program
# Set up for IFTTT triggering
import requests # needed to get https request to IFTTT web page
Current_hr = time.strftime("%H", time.localtime()) # use this var to update trigger IFTTT at each hour change
IFTTT_hr = "999" # we will only trigger IFTTT if this is diffent from Current_hr
MAKER_SECRET_KEY = "xxxx-my-maker-ifft-key-xxx" #this is my IFTTT Maker Channel secret key
Delay_between_tests = 15 #in seconds. Delay is in last line of code
Loop_count = 0 # track how many times the Red/Yellow/Green status was updated.
Deep_probe = 0 # how many times was a deep probe required; Single_test_site ping test failed
Single_test_site = 0 # used to select non deep probe ping test. Rotates thru the 10 IPs
Last_Red = "none detected" # timestamps for when condition happened for screen report
Red_Event_Counter = 0 #also count number of time condition occured
Last_Yellow = "none detected"
Yellow_Event_Counter = 0
Last_Green = "none detected"
Green_Event_Counter = 0
import os # allows for the ping calls
import RPi.GPIO as GPIO # We will be using the RasPI GPIO to control the three LEDss
GPIO.setwarnings(False) # suppress screen from showing GPIO errors
# to use Raspberry Pi board pin numbers
GPIO.setmode(GPIO.BOARD)
# set up GPIO output channel
# I/O 15 = RED
# I/O 18 = YELLOW
# I/O 22 = GREEN
# NOTE: LOGIC LOW TURNS ON THE LEDs (they are active LOW)
GPIO.setup(15, GPIO.OUT)
GPIO.setup(18, GPIO.OUT)
GPIO.setup(22, GPIO.OUT)
#Turn off all the LEDs
GPIO.output(15,GPIO.HIGH)
GPIO.output(18,GPIO.HIGH)
GPIO.output(22,GPIO.HIGH)
SiteStatus = [1,2,3,4,5,6,7,8,9,10,11] # Pass/Fail of the site ping
UpTally = [1,2,3,4,5,6,7,8,9,10,11] # count succesful pings for each site
PingCount = [1,2,3,4,5,6,7,8,9,10,11] # count how many times each site is pinged
PingSite = [1,2,3,4,5,6,7,8,9,10,11] # holds the IP or DNS name of the site being pinged
# Identify ten PING 'friendly' sites
PingSite[1] = "pingfriendlysite-1.com"
PingSite[2] = "pingfriendlysite-2.com"
PingSite[3] = "pingfriendlysite-3.com"
PingSite[4] = "pingfriendlysite-4.com"
PingSite[5] = "pingfriendlysite-5.com"
PingSite[6] = "pingfriendlysite-6.com"
PingSite[7] = "pingfriendlysite-7.com"
PingSite[8] = "pingfriendlysite-8.com"
PingSite[9] = "pingfriendlysite-.9com"
PingSite[10] = "pingfriendlysite-10.com"
print " " # print startime, self test, etc...
print time.strftime("%a, %d %b %Y %H:%M:%S", time.localtime())
print "-------------------------"
print "LED Self Test in process..."
print " "
print "Test Pings Sites are:"
print "-------------------------"
for checksite in range (1,11): #init some vars, display sites on screen during self test.
UpTally[checksite] = 0 # if site is UP when tested then incremented
PingCount[checksite] = 0 # if site is tested then increment
SiteStatus[checksite] = "---"
print checksite, PingSite[checksite]
# Self test the LEDs by blinking them. Remember; active LOW.
st_delay = 0.20
for st in range (0, 5):
GPIO.output(15,GPIO.LOW) # Red
time.sleep(st_delay)
GPIO.output(15,GPIO.HIGH)
GPIO.output(18,GPIO.LOW) # Yellow
time.sleep(st_delay)
GPIO.output(18,GPIO.HIGH)
GPIO.output(22,GPIO.LOW) #Green
time.sleep(st_delay)
GPIO.output(22,GPIO.HIGH)
print " "
print "Test pinging all sites for first run..."
print " "
# get a 1st run baseline so the status printout looks normal/clean
LED_status = 0 # LED_Status keeps score of the successful pings on the test sites
for checksite in range (1,11):
# All LEDs on during the 1st run pings; flash effect
print " "
print "All LEDs on..."
GPIO.output(15,GPIO.LOW)
GPIO.output(18,GPIO.LOW)
GPIO.output(22,GPIO.LOW)
hostname = PingSite[checksite]
PingCount[checksite] = PingCount[checksite] + 1
response = os.system("ping -c 1 " + hostname)
if response == 0:
#hostname 'is up!'
SiteStatus[checksite] = "UP"
LED_status = LED_status + 1
UpTally[checksite] = UpTally[checksite] + 1
else:
#hostname 'is down!'
SiteStatus[checksite] = "DOWN"
# All LEDs off; flash effect
print " "
print "All LEDs off..."
GPIO.output(15,GPIO.HIGH)
GPIO.output(18,GPIO.HIGH)
GPIO.output(22,GPIO.HIGH)
time.sleep(.5) # little delay for the LED off
print " "
print "Self Test complete..."
print " "
while True: #Loop forever to check and display ping test status
Loop_count = Loop_count + 1
# Only test ping all sites if the one site tested sites fails the ping
# Here we test ping a single site. Next time we ping test the next site on our list of 10.
if Single_test_site < 10: # single test site selection
Single_test_site = Single_test_site + 1
else:
Single_test_site = 1
hostname = PingSite[Single_test_site] # OK, now the have selected one of our ping test sites
print "Ping site: " + hostname # so let's test ping it with os.system command
print " "
time.sleep(1.5)
PingCount[Single_test_site] = PingCount[Single_test_site] + 1
response = os.system("ping -c 1 " + hostname)
if response == 0:
# tested site is up. all is fine. don't deep probe, but update the tally stats
SiteStatus[Single_test_site] = "UP"
UpTally[Single_test_site] = UpTally[Single_test_site] + 1
Led_status = 10 # insure GREEN condition
else: # If selected site is down, so now we call for a vote by testing all sites. Let's deep probe.
print " "
print "Selected site failed ping test. Intiating deep probe..."
print " "
Deep_probe = Deep_probe + 1
LED_status = 0
for checksite in range (1,11):
hostname = PingSite[checksite]
PingCount[checksite] = PingCount[checksite] + 1
response = os.system("ping -c 1 " + hostname)
if response == 0:
#hostname 'is up!'
SiteStatus[checksite] = "UP"
LED_status = LED_status + 1
UpTally[checksite] = UpTally[checksite] + 1
else:
#hostname 'is down!'
SiteStatus[checksite] = "DOWN"
time.sleep(.1)
#Adjust the LED status light and screen print a report
if (LED_status >= 7): #Hurray, looking good. Turn on Green LED. All others off
GPIO.output(15,GPIO.HIGH) #Red OFF
GPIO.output(18,GPIO.HIGH) #Yellow OFF
GPIO.output(22,GPIO.LOW) #Green ON
Status_Color = "GREEN"
Last_Green = time.strftime("%a, %d %b %Y %H:%M:%S", time.localtime())
Green_Event_Counter = Green_Event_Counter + 1
if 3 < LED_status < 7: #Things are shakey. Yellow LED on. All others off
GPIO.output(15,GPIO.HIGH) #Red OFF
GPIO.output(18,GPIO.LOW) #Yellow ON
GPIO.output(22,GPIO.HIGH) #Green OFF
Status_Color = "YELLOW"
Last_Yellow = time.strftime("%a, %d %b %Y %H:%M:%S", time.localtime())
Yellow_Event_Counter = Yellow_Event_Counter + 1
if (LED_status <= 3): #Oh no, looking bad. Turn on Red LED. All others off
GPIO.output(15,GPIO.LOW) #Red ON
GPIO.output(18,GPIO.HIGH) #Yellow OFF
GPIO.output(22,GPIO.HIGH) #Green OFF
Status_Color = "RED"
Last_Red = time.strftime("%a, %d %b %Y %H:%M:%S", time.localtime())
Red_Event_Counter = Red_Event_Counter + 1
os.system('clear') # clear the screen for the report
print " "
print time.strftime("%a, %d %b %Y %H:%M:%S", time.localtime()) + ". Update interval: " + str(Delay_between_tests) + " seconds."
runtime = datetime.datetime.now() - t0
print "Status report: " + Status_Color + ". Runs: " + str(Loop_count) + ". DeepProbes: " + str(Deep_probe) + ". Runtime: " + str(runtime)
print "--------------------------------------------------------------------------"
for checksite in range (1,11):
if Single_test_site == checksite:
LastCheck = ">>>Last check:"
else:
LastCheck = " Last check:"
Red_print = " RED:" + "%6s" % str(Red_Event_Counter) + " events. Last event: " + Last_Red
Yellow_print = " YELLOW:" + "%6s" % str(Yellow_Event_Counter) + " events. Last event: " + Last_Yellow
Green_print = " GREEN:" + "%6s" % str(Green_Event_Counter) + " events. Last event: " + Last_Green
print "--------------------------------------------------------------------------"
print " "
print Red_print
print Yellow_print
print Green_print
print " "
# At each hour trigger IFTTT and update Google Drive Spreadsheet. Will always trigger on 1st run
Current_hr = time.strftime("%H", time.localtime())
if (Current_hr != IFTTT_hr):
IFTTT_hr = Current_hr
url = url = "https://maker.ifttt.com/trigger/trigger_stat/with/key/" + MAKER_SECRET_KEY + "?value1=" + Red_print + "&value2=" + Yellow_print + "&value3=" + Green_print
res = requests.get(url)
#print str(res) + " is web request result for BT device: " #used only for debug
time.sleep(5)
time.sleep(Delay_between_tests) #wait some before next ping test
-----
If you're still with us, thanks and if you duplicate the build let us know!