#!/usr/bin/python # Web interface to my home automation stuff import sys sys.path.append('/data/src/stillhq_public/trunk/python/') import asyncore import copy import datetime import os import re import time import uuid import urllib import MySQLdb import gflags import mhttp import mplugin import substitute from mpygooglechart import Chart from mpygooglechart import SimpleLineChart from mpygooglechart import Axis FLAGS = gflags.FLAGS MIN_Y = -30.0 MAX_Y = 100.0 MAX_READINGS_PER_GRAPH = 580 POWER_COST = 0.138 PLUGIN_DIR = '/data/src/stillhq_public/trunk/homeautomation/plugins/' sensor_names = {} running = True uuid = uuid.uuid4() requests = {} skips = {} bytes = 0 wiggle = [0] backwards = range(-150, 0, 1) forwards = range(150, 0, -1) while backwards: wiggle.append(backwards.pop()) wiggle.append(forwards.pop()) wiggle.append(None) bom_wiggle = [0] backwards = range(-1800, 0, 1) forwards = range(1800, 0, -1) while backwards: bom_wiggle.append(backwards.pop()) bom_wiggle.append(forwards.pop()) bom_wiggle.append(None) class http_server(mhttp.http_server): def client_init(self): """Do local setup.""" self.http_handler_class = http_handler class http_handler(mhttp.http_handler): def dispatch(self, urlpath, post_data, chunk=None): if urlpath == '/': now_tuple = datetime.datetime.now().timetuple() self.sendredirect('/dashboard') elif urlpath.startswith('/sensor/'): self.sendredirect(urlpath.replace('/sensor/', '/chart/')) elif urlpath.startswith('/chart'): self.handleurl_chart(urlpath, post_data) elif urlpath.startswith('/flash'): self.handleurl_flash(urlpath, post_data) elif urlpath.startswith('/image'): self.handleurl_image(urlpath, post_data) elif urlpath.startswith('/table'): self.handleurl_table(urlpath, post_data) elif urlpath.startswith('/csv'): self.handleurl_csv(urlpath, post_data) elif urlpath.startswith('/json'): self.handleurl_json(urlpath, post_data) elif urlpath.startswith('/chilltime'): self.handleurl_chilltime(urlpath, post_data) elif urlpath.startswith('/dashboard'): self.handleurl_dashboard(urlpath, post_data) # TODO(mikal): this should be in mhttp elif urlpath.startswith('/local/'): self.handleurl_local(urlpath, post_data) else: self.senderror(404, '%s file not found' % urlpath) self.close() def handleurl_local(self, file, post_data): """Return a local file needed by the user interface.""" ent = file.split('/')[-1] self.sendfile(ent) def timewindow(self, time_field): """Given a time arguement, work out what epoch second window to use.""" day_field = time_field[0].split('.') self.log('Time field is %s, day field is %s' %(time_field, day_field)) if day_field == ['today']: day_field = datetime.datetime.now().timetuple()[0:3] self.log('Time field is %s, day field is %s' %(time_field, day_field)) elif day_field == ['yesterday']: one_day = datetime.timedelta(days=1) yesterday = datetime.datetime.now() - one_day day_field = yesterday.timetuple()[0:3] self.log('Time field is %s, day field is %s' %(time_field, day_field)) day = datetime.datetime(int(day_field[0]), int(day_field[1]), int(day_field[2]), 0, 0, 0) day_tuple = day.timetuple() start_epoch = time.mktime(day_tuple) end_epoch = start_epoch + (60 * 60 * 24) self.log('Day started at epoch seconds: %d' % start_epoch) # They _might_ have passed a time window in the time_field if len(time_field) > 1: start_epoch -= int(time_field[1]) * (60 * 60 * 24) end_epoch += int(time_field[2]) * (60 * 60 * 24) self.log('Event window is: %d to %d' %(start_epoch, end_epoch)) return (start_epoch, end_epoch, day_field) def summarizingjoin(self, space, skip, values): """space.join(values) with skip instead of repeated values.""" out = [] previous = None for v in values: if v != previous: out.append(v) elif out[-1] != skip: out.append(skip) previous = v return space.join(out) def handleurl_chilltime(self, urlpath, post_data): """Analyse the expense of running a fridge.""" args = urlpath.split('/') (start_epoch, end_epoch, day_field) = self.timewindow(args[2].split(',')) data = ['

Chiller use summary