Strict Standards: Non-static method Text_Highlighter::factory() should not be called statically in /home2/rwy/public_html/airquality/colorize.php on line 13
#!/usr/bin/env python
# indicatorAQI.py
# written by XrussellX@young-0X.com (remove all 'X's)
# Open source, feel free to use, please leave in attribution
# It also might be nice to drop me an email if anyone ever does use this :-)
#
# This works by getting data from the aqi application described at young-0.com/airquality/page2.html.
# That page has an isp function that cron runs a couple times an hour that scrapes the AQI data off
# the twitter feed and puts it in the file young-0.com/airquality/mostRecent.dat.
#
# To install it locally:
#  - get the indicator-sysmonitor package  (sudo apt-get install indicator-sysmonitor)
#  - set up a cron job to fetch the data off my server. It should run the script GET_CMD (see below).
#    The new data shows up on twitter at about 15 after the hour, so make sure it runs arond X:20
#  - edit the code below: make sure GET_CMD points to the cron command file.
#  - Run this file, or add it to your startup files
#
# HERE IS THE COMMAND FILE TO BE RUN BY CRON
#
# #!/bin/bash
# 
# wget -T 600 -O /tmp/currentaqi.new http://young-0.com/airquality/mostRecent.dat 2> /dev/null
# 
# case `wc -c /tmp/currentaqi.new` in
# 0*) echo;;
# *) mv /tmp/currentaqi.new /tmp/currentaqi
# esac
 
 
import sys
import os
import thread
import threading
from threading import Thread
import time
import subprocess
 
import gtk
import appindicator
 
import Tkinter
from Tkinter import *
 
GET_CMD = '/home/russell/airquality/aqi.cron'
 
gtk.gdk.threads_init()
 
class History:
    def close_window (self, event = ''): 
        self.window.destroy()
 
    def popup(self, ignore):
        self.window = Tk()
        self.window.protocol("WM_DELETE_WINDOW", self.close_window)
        self.window.bind("<Button-1>", self.close_window)
        self.window.geometry('+1100+40')    # place near status location
        f = Frame(self.window, width=180)
        f.pack()
 
        top = Frame(self.window)
        self.window.title('AQI History')
        with file('/tmp/currentaqi') as f:
            lines = f.readlines()
        expected = -1
        frame = Frame(top)
        for line in lines:
            reading = line.split()[1:4]
            bg, fg = getColors(int(reading[1]))
            if expected >= 0 and not expected == int(reading[0]):
                frame.pack(pady=3, fill=X)
                frame = Frame(top)
            expected = (int(reading[0]) - 1) % 24
            Label(frame, text="%s:00 : %s (%s)" % tuple(reading), anchor=W, fg=fg, bg=bg).pack(fill=X)
        frame.pack(pady=3, fill=X)
        top.pack()
        mainloop()
 
colorDesc = ((50,  '#00e400', '#000000'),
             (100, '#ffff00', '#000000'),
             (150, '#ff7e00', '#ffffff'),
             (200, '#ff0000', '#ffffff'),
             (300, '#7e0023', '#ffffff'),
             (500, '#99004c', '#ffffff'),
             (999, '#000000', '#ffffff'))
 
def getColors(aqi):
    global colorDesc
    for level in colorDesc:
        if aqi < level[0]:
            return level[1:3]
    return colorDesc[-1][1:3]
 
class AqiFetcher(Thread):
    REFRESH_INTERVAL = 60
    def __init__(self, parent):
        Thread.__init__(self)
        self.parent = parent
 
    def run(self):
        while(self.parent.alive.isSet()):
            self.parent.update(self.display())
            time.sleep(self.REFRESH_INTERVAL)
 
    def display(self):
        if not os.path.exists('/tmp/currentaqi'):
            return '(none)'
        with file('/tmp/currentaqi') as f:
            line = f.readline()
        parsed = line.split()
        if len(parsed) >= 3:
            return "%s (%s:00)" % (parsed[2], parsed[1])
        return '(none)'
 
class ShowAQI:
    def __init__(self):
        self.ind = appindicator.Indicator ("indicator-aqi", "aqi", appindicator.CATEGORY_SYSTEM_SERVICES)
        self.ind.set_status (appindicator.STATUS_ACTIVE)
        self.ind.set_label("AQI init...")
        self.menu = gtk.Menu()
        self.history = History()
        self.fetching = False
 
        menuitem = gtk.MenuItem('History')
        menuitem.connect('activate', self.history.popup)
        self.menu.add(menuitem)
 
        menuitem = gtk.MenuItem('Fetch data')
        menuitem.connect('activate', self.fetchdata)
        self.menu.add(menuitem)
 
        self.menu.add(gtk.SeparatorMenuItem())
 
        exit_menu = gtk.ImageMenuItem(stock_id=gtk.STOCK_QUIT)
        exit_menu.connect('activate', self.on_exit)
        self.menu.add(exit_menu)
       
        self.menu.show_all()
        self.ind.set_menu(self.menu)
 
        self.alive = threading.Event()
        self.alive.set()
        self.fetch = AqiFetcher(self)
        self.fetch.start()
 
    def update(self, string, force=False):
        if not string == False:
            if self.fetching:
                active = '*'
            else:
                active = ''
            self.ind.set_label("AQI: %s%s" % (active, string))
            if force:
                while gtk.events_pending():
                    gtk.main_iteration(False)
 
 
    def fetchdata(self, ignore):
        if not self.fetching:
            self.fetching = True
            self.update(self.fetch.display())
            thread.start_new_thread(self._fetchdata, ())
 
    def _fetchdata(self):
        subprocess.Popen(GET_CMD, stdout=subprocess.PIPE, shell=True).communicate()
        self.fetching = False
        self.update(self.fetch.display())
 
    def on_exit(self, event=None):
        self.alive.clear()
        self.update('exiting...', True)
        try: gtk.main_quit()
        except RuntimeError: pass
 
 
if __name__ == "__main__":
    aqiObj = ShowAQI()
    try:
        gtk.main()
    except KeyboardInterrupt:
        aqiObj.on_exit()