User avatar
procrasty
Posts: 3
Joined: Thu Dec 10, 2015 12:45 pm

Pi UPS and Connectivity Monitor

Wed May 08, 2019 4:26 am

Hi Guys. I know I'm being a little bit ambitious here (basically being a total noob and all) but I want to build the following project I've had in mind for a while and would appreciate all the help I can get. I've tried to elaborate each individual goal (TL/DR warning) and, in my understanding, the Pi should be more than capable of doing all of the following. (Of course, whether I'm quite up to building it all is a big question :D )

Aim: To set up a Pi powered UPS and internet connectivity monitor to ensure smart home devices are available remotely

Issue: Frequent internet connection drops and intermittent power outages

Things I would like to achieve:
  • 1. Need to connect adequately powered battery to power Pi, modem and smart network switch at the correct voltages and currents (can provide specific power requirements for these devices)
  • 2. Pi needs to be able to tell when mains is on and the battery is charging
  • 3. Pi needs to be able to shut off battery when it is done charging (or interrupt the charging process at pre-set intervals, in case the Pi does not draw power directly from the mains, to ensure maximum battery life)
  • 4. Pi needs to be able to seamlessly switch from mains power to battery power when the power fails (alternatively, it can directly be powered by the battery, but this is the less preferred option since battery longevity will be compromised)
  • 5. Pi needs to be able to monitor battery levels and shut down - both itself and other devices connected to the battery - when battery is low (predefined value). It is okay to hard shutdown the other devices (modem and smart network switch)
  • 6. Pi needs to be able to monitor access to a predefined IP address (to monitor internet connectivity) and log when the connection is down
  • 7. Pi needs to be able to shut off and start up power to a modem (essentially, hard restart it) when it detects that internet access is not available
  • 8. Pi needs to query the above mentioned predefined IP address after a set period of time (allowing for any delays in reconnecting) after restarting the modem to ensure internet access is resumed, else repeat shutdown procedure. After it repeats the shutdown procedure for a prefixed number of times (ten times?), if internet access does not resume, Pi shuts down modem and remains on standby. It again restarts the modem after a predefined interval (1 hour?) and checks for internet availability (It logs every failed attempt). In case the battery reaches the above mentioned critical level, it shuts down the entire setup
  • 9. ALSO: If possible, the Pi should be able to run some sort of speed test program/protocol periodically and locally log all the results as well as send a notification (through email and/or a custom mobile app) when the speeds fall below predefined limits
  • 10. ALSO: If possible, set up some sort of notification on any mobile device through an app for when the Pi is unable to access/ping a preset server/IP address for a set period of time (if I can set up something of the sort on a personal website or something) - not sure if this last is even possible

I look forward to any and all inputs, even of the concept. I think this is something - if I can manage to build it - that many people can DIY themselves and actually put to use.
Noob. Has had a couple of Pi 2b+ boards for a couple of years. Looking to do more than set up Kodi media centres :)

IanS
Posts: 225
Joined: Wed Jun 20, 2012 2:51 pm
Location: Southampton, England

Re: Pi UPS and Connectivity Monitor

Wed May 08, 2019 9:41 am

For the UPS side, it might be easier to find a small UPS that is supported by NUT (https://networkupstools.org/). There are small UPS devices specifically targeted at the Pi, but I do not know if they support anything like battery level querying.
For the modem reset you could use a GPIO controlled relay board and route the low voltage side (probably 12V) of the modem power supply through it. Not the mains side unless you really know what you are doing! Alternatively you could use something like https://shop.pimoroni.com/products/pi-m ... 1066571265 to power cycle it at the mains supply.

pcmanbob
Posts: 5893
Joined: Fri May 31, 2013 9:28 pm
Location: Mansfield UK

Re: Pi UPS and Connectivity Monitor

Wed May 08, 2019 2:34 pm

For internet connection monitoring I use this code.

Code: Select all

#!/usr/bin/env python
# Speed test Pi Internet monitor V5.00 27 may 2017
import subprocess
import sys
import time
import RPi.GPIO as GPIO


GPIO_GREEN_LIGHT = 33      # led for internet working
GPIO_AMBER_LIGHT = 35      # led for internet marginally working
GPIO_RED_LIGHT = 37        # led for internet is not working



DELAY_BETWEEN_PINGS = 1    # delay in seconds
DELAY_BETWEEN_TESTS = 120  # delay in seconds
siteinerror = ""

SITES = ["google.co.uk", "bbc.co.uk" , "raspberrypi.org" , "no-ip.com"]

# possible test sites "grc.com" "talktalk.co.uk" "uk.yahoo.com" "google.co.uk" "bbc.co.uk" "raspberrypi.org" "no-ip.com"

# print messages for debugging when indicator is set
def debug_message(debug_indicator, output_message):
  if debug_indicator:
    print output_message

# issue Linux ping command to determine internet connection status
def ping(site):
  global siteinerror
  cmd = "/bin/ping -c 1 " + site
  try:
    output = subprocess.check_output(cmd, stderr=subprocess.STDOUT, shell=True)
  except subprocess.CalledProcessError, e:
    siteinerror = siteinerror + site + " "
    debug_message(debug, site + ": not reachable")
    return 0
  else:
    debug_message(debug, site + ": reachable")
    return 1

# ping the sites in the site list the specified number of times
# and calculate the percentage of successful pings
def ping_sites(site_list, wait_time, times):
  successful_pings = 0
  attempted_pings = times * len(site_list)
  for t in range(0, times):
    for s in site_list:
      successful_pings += ping(s)
      time.sleep(wait_time)
  debug_message(debug, "Percentage successful: " + str(int(100 * (successful_pings / float(attempted_pings)))) + "%")
  return successful_pings / float(attempted_pings)   # return percentage successful 

# turn the amber lamp on   
def lamp_amber_on():
  debug_message(debug, ">>> Turn Red OFF; Turn Amber ON; Turn Green OFF")
  GPIO.output(GPIO_RED_LIGHT, False)
  GPIO.output(GPIO_AMBER_LIGHT, True)
  GPIO.output(GPIO_GREEN_LIGHT, False)

# turn the green lamp on
def lamp_green_on():
  debug_message(debug, ">>> Turn Red OFF; Turn Amber OFF; Turn Green ON")
  GPIO.output(GPIO_RED_LIGHT, False)
  GPIO.output(GPIO_AMBER_LIGHT, False)
  GPIO.output(GPIO_GREEN_LIGHT, True)

# turn the red lamp on
def lamp_red_on():
  debug_message(debug, ">>> Turn Red ON; Turn Amber OFF; Turn Green OFF")
  GPIO.output(GPIO_RED_LIGHT, True)
  GPIO.output(GPIO_AMBER_LIGHT, False)
  GPIO.output(GPIO_GREEN_LIGHT, False)

# turn all of the lamps off
def lamp_all_off():
  debug_message(debug, ">>> Turn Red OFF; Turn Amber OFF; Turn Green OFF")
  GPIO.output(GPIO_RED_LIGHT, False)
  GPIO.output(GPIO_AMBER_LIGHT, False)
  GPIO.output(GPIO_GREEN_LIGHT, False)

# flash all of the lamps in sequence 10 times
def lamp_test():
  debug_message(debug, "Testing Lights")
  TEST_DELAY = 0.1           # tenth of a second delay   
  for i in range(0, 10):
    time.sleep(TEST_DELAY)
    lamp_red_on()
    time.sleep(TEST_DELAY)
    lamp_amber_on()
    time.sleep(TEST_DELAY)
    lamp_green_on()
  lamp_all_off()
  debug_message(debug, "Light test completed")
      
# main program starts here

# check to see if the user wants to print debugging messages
debug = False
if len(sys.argv) > 1:
  if sys.argv[1] == "-debug":
    debug = True
  else:
    print "unknown option specified: " + sys.argv[1]
    sys.exit(1)

# setup the GPIO pins
GPIO.setmode(GPIO.BOARD)
GPIO.setup(GPIO_GREEN_LIGHT, GPIO.OUT)
GPIO.setup(GPIO_AMBER_LIGHT, GPIO.OUT)
GPIO.setup(GPIO_RED_LIGHT, GPIO.OUT)

# flash the lamps to indicate the program is starting
lamp_all_off()
lamp_test()
time.sleep(0.5)
lamp_amber_on()     # turn amber lamp on during the first test
time.sleep(20)

# main loop: ping sites, turn appropriate lamp on, wait, repeat
test = 0
while True:
  test+=1
  debug_message(debug, "----- Test " + str(test) + " -----")
  success = ping_sites(SITES, DELAY_BETWEEN_PINGS, 2)
 
  state = ('%3.0f' % (success * 100))

  if success == 0:
    lamp_red_on()
  elif success <= .50:  
    lamp_amber_on()
  else:
    lamp_green_on()
	
  debug_message(debug, "Waiting " + str(DELAY_BETWEEN_TESTS) + " seconds until next test.")
  when = (time.strftime("%H:%M:%S"))
  result = open("/home/pi/connection-results.csv","a")
  result.write(str(state) + "," + when + "," + siteinerror + "\n")
  result.close()
  siteinerror = ""
  time.sleep(DELAY_BETWEEN_TESTS)

which is based on the code in this tutorial https://www.instructables.com/id/Raspbe ... t-Monitor/
with added logging of results, you could just remove all the gpio references if you don't need the LED outputs.
We want information… information… information........................no information no help
The use of crystal balls & mind reading are not supported

Return to “Networking and servers”