pinger/pinger.py

218 lines
6.0 KiB
Python
Raw Normal View History

2013-12-16 06:26:43 +00:00
#!/usr/bin/env python
2013-12-16 11:44:58 +00:00
# -*- coding: utf-8 -*-
2013-12-16 06:26:43 +00:00
#
2013-12-16 09:58:00 +00:00
# Pinger.py -- A ping tool that sits in your system tray
# Copyright 2013 Will Bradley
2013-12-16 06:26:43 +00:00
#
2013-12-16 09:58:00 +00:00
# Authors: Will Bradley <bradley.will@gmail.com>
2013-12-16 06:26:43 +00:00
#
# This program is free software: you can redistribute it and/or modify it
# under the terms of either or both of the following licenses:
#
# 1) the GNU Lesser General Public License version 3, as published by the
# Free Software Foundation; and/or
# 2) the GNU Lesser General Public License version 2.1, as published by
# the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranties of
# MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR
# PURPOSE. See the applicable version of the GNU Lesser General Public
# License for more details.
#
# You should have received a copy of both the GNU Lesser General Public
# License version 3 and version 2.1 along with this program. If not, see
# <http://www.gnu.org/licenses/>
#
2013-12-16 10:36:08 +00:00
#
# Dependencies
#
# System Tray Icon
2013-12-16 06:26:43 +00:00
from gi.repository import Gtk
from gi.repository import AppIndicator3 as appindicator
# Timer
from gi.repository import GObject as gobject
2013-12-16 06:26:43 +00:00
# Pinging
import subprocess
# Regex
import re
2013-12-16 10:36:08 +00:00
# Ctrl-c
import signal
2013-12-16 11:44:58 +00:00
# File paths
import os
#Argument parsing
import argparse
#for exit
import sys
2013-12-16 11:44:58 +00:00
# Vars
startup_active_label = "✓ Start Automatically"
startup_inactive_label = "Start Automatically"
home_path = os.path.expanduser("~")
startup_path = home_path+'/.config/autostart/pinger.desktop'
2013-12-16 06:26:43 +00:00
parser = argparse.ArgumentParser()
parser.add_argument("-t", "--target", help="Target to PING against. (IP / Hostname / Domain name). Defaults to 4.2.2.2")
parser.add_argument("-f", "--freq", help="Timeout between pings, in seconds. Defaults to 5")
parser.add_argument("-m", "--maxlog", help="Maximum amount of pings to log. Defaults to 15")
args = parser.parse_args()
#accumulate the arguments for use later
arguments = " "
for arg in sys.argv[1:]:
arguments += arg + " "
# User-editable variables
if args.target:
host = args.target
else:
host = "4.2.2.2" # IP or hostname
print "Using default target IP of 4.2.2.2"
if args.freq:
try:
ping_frequency = int(args.freq)
except ValueError:
sys.stderr.write("Error parsing argument '--freq'\n")
sys.exit(1)
else:
ping_frequency = 5 # in seconds
if args.maxlog:
try:
ping_log_max_size = int(args.maxlog)
except ValueError:
sys.stderr.write("Error parsing argument '--maxlog'\n")
sys.exit(1)
else:
ping_log_max_size = 15
2013-12-16 10:36:08 +00:00
#
# Main Class
#
2013-12-16 06:26:43 +00:00
2013-12-16 10:36:08 +00:00
class Pinger:
2013-12-17 12:50:58 +00:00
ping_log = []
2013-12-16 06:26:43 +00:00
def ping(self, widget=None, data=None):
ping = subprocess.Popen(
["ping", "-c", "1", host],
stdout = subprocess.PIPE,
stderr = subprocess.PIPE
)
out, error = ping.communicate()
m = re.search('time=(.*) ms', out)
if error or m == None:
2013-12-16 10:46:58 +00:00
label = "PING FAIL"
2013-12-17 12:50:58 +00:00
self.log_ping(-1)
else:
label = m.group(1)+" ms"
2013-12-17 12:50:58 +00:00
self.log_ping(m.group(1))
2013-12-16 10:36:08 +00:00
self.ind.set_label (label, "100.0 ms")
#self.ping_menu_item.set_label(out)
2013-12-16 06:26:43 +00:00
gobject.timeout_add_seconds(self.timeout, self.ping)
2013-12-17 12:50:58 +00:00
def log_ping(self, value):
self.ping_log.append(value)
self.update_log_menu()
# limit the size of the log
if len(self.ping_log) >= ping_log_max_size:
2013-12-17 12:50:58 +00:00
# remove the earliest ping, not the latest
self.ping_log.pop(0)
2013-12-16 10:36:08 +00:00
def create_menu_item(self, text, callback):
menu_item = Gtk.MenuItem(text)
self.menu.append(menu_item)
2013-12-17 12:50:58 +00:00
if callback:
menu_item.connect("activate", callback, text)
2013-12-16 10:36:08 +00:00
menu_item.show()
2013-12-16 11:44:58 +00:00
return menu_item
2013-12-16 10:36:08 +00:00
2013-12-16 06:26:43 +00:00
def destroy(self, widget, data=None):
2013-12-16 11:44:58 +00:00
print "Quitting..."
2013-12-16 06:26:43 +00:00
Gtk.main_quit()
2013-12-16 11:44:58 +00:00
def create_autostart(self, widget, data=None):
with open(startup_path,'w') as f:
f.write("[Desktop Entry]\r\n"
"Type=Application\r\n"
"Exec=python "+os.path.abspath( __file__ )+arguments+"\r\n"
2013-12-16 11:44:58 +00:00
"X-GNOME-Autostart-enabled=true\r\n"
"Name=Pinger\r\n"
"Comment=Pings the internet every few seconds")
self.update_startup_menu()
def remove_autostart(self, widget, data=None):
os.remove(startup_path)
self.update_startup_menu()
def update_startup_menu(self):
if os.path.exists(startup_path):
self.startup_menu.set_label(startup_active_label)
self.startup_menu.connect("activate", self.remove_autostart, startup_active_label)
else:
self.startup_menu.set_label(startup_inactive_label)
self.startup_menu.connect("activate", self.create_autostart, startup_inactive_label)
2013-12-17 12:50:58 +00:00
def update_log_menu(self):
graph = ""
print self.ping_log
for p in self.ping_log:
if float(p) == -1:
graph += "E "#u'\u2847' # Error
elif float(p) < 30:
graph += u'\u2840'
elif float(p) < 100:
graph += u'\u2844'
elif float(p) < 100:
graph += u'\u2846'
else:
graph += u'\u2847'
self.log_menu.set_label(graph)
2013-12-16 06:26:43 +00:00
def __init__(self):
2013-12-16 10:36:08 +00:00
# Handle ctrl-c
signal.signal(signal.SIGINT, self.destroy)
2013-12-16 11:48:05 +00:00
# Print welcome message
print "Starting Pinger..."
2013-12-16 10:36:08 +00:00
# Create systray icon
self.ind = appindicator.Indicator.new (
"pinger",
"", # no icon
appindicator.IndicatorCategory.COMMUNICATIONS)
self.ind.set_status (appindicator.IndicatorStatus.ACTIVE)
2013-12-16 10:46:58 +00:00
self.ind.set_label ("Pinger Loading...", "Pinger Loading...")
2013-12-16 10:36:08 +00:00
# create a menu
self.menu = Gtk.Menu()
2013-12-17 12:50:58 +00:00
# with autostart option
2013-12-16 11:44:58 +00:00
self.startup_menu = self.create_menu_item(startup_inactive_label, self.create_autostart)
self.update_startup_menu()
2013-12-17 12:50:58 +00:00
# and log display
self.log_menu = self.create_menu_item("Ping Log", None)
# and exit option
2013-12-16 10:36:08 +00:00
self.create_menu_item("Exit", self.destroy)
self.ind.set_menu(self.menu)
# start the ping process
2013-12-16 06:26:43 +00:00
self.counter = 0
2013-12-16 10:36:08 +00:00
self.timeout = ping_frequency
2013-12-16 09:58:00 +00:00
self.ping()
2013-12-16 06:26:43 +00:00
2013-12-16 11:48:05 +00:00
# Print started message
print "Started."
2013-12-16 10:36:08 +00:00
# Begin runtime loop
Gtk.main()
2013-12-16 06:26:43 +00:00
2013-12-16 10:36:08 +00:00
#
# Runtime
#
2013-12-16 06:38:08 +00:00
2013-12-16 06:26:43 +00:00
if __name__ == "__main__":
2013-12-16 10:36:08 +00:00
pinger = Pinger()