# HG changeset patch # User Matt Johnston # Date 1358724352 -28800 # Node ID a40f30fad8f64e3b106bf60f2429a3b096be2730 # Parent c3926e7cfb0cfe539189b055597e00e51c496078# Parent a91adc95543d71d96e567ba533fd986c936d6a15 Merge diff -r c3926e7cfb0c -r a40f30fad8f6 py/config.py --- a/py/config.py Mon Jan 21 07:25:29 2013 +0800 +++ b/py/config.py Mon Jan 21 07:25:52 2013 +0800 @@ -1,12 +1,16 @@ +import os.path -FRIDGE_SLEEP = 10 +FRIDGE_SLEEP = 60 SENSOR_SLEEP = 15 -UPLOAD_SLEEP = 300 +UPLOAD_SLEEP = 80 -FRIDGE_DELAY = 3 # 10 mins +FRIDGE_DELAY = 600 # 10 mins FRIDGE_WORT_INVALID_TIME = 300 # 5 mins -PARAMS_FILE = './tempserver.conf' +# 12 hours +MAX_READINGS = 12*60*60 / SENSOR_SLEEP + +PARAMS_FILE = os.path.join(os.path.dirname(__file__), 'tempserver.conf') SENSOR_BASE_DIR = '/sys/devices/w1_bus_master1' FRIDGE_GPIO = '/sys/devices/virtual/gpio/gpio17' @@ -14,3 +18,11 @@ FRIDGE_NAME = '28-0000042cccc4' AMBIENT_NAME = '28-0000042c6dbb' INTERNAL_TEMPERATURE = '/sys/class/thermal/thermal_zone0/temp' + +HMAC_KEY = "a key" +UPDATE_URL = 'https://matt.ucc.asn.au/test/templog/update' + +try: + from localconfig import * +except ImportError: + pass diff -r c3926e7cfb0c -r a40f30fad8f6 py/fridge.py --- a/py/fridge.py Mon Jan 21 07:25:29 2013 +0800 +++ b/py/fridge.py Mon Jan 21 07:25:52 2013 +0800 @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -from utils import L,W,E,EX +from utils import L,W,E,EX,D import config import gevent @@ -50,6 +50,8 @@ # greenlet subclassed def _run(self): + if self.server.params.disabled: + L("Fridge is disabled") while True: self.do() gevent.sleep(config.FRIDGE_SLEEP) @@ -71,6 +73,12 @@ L("fridge skipping, too early") return + if params.disabled: + if self.is_on(): + L("Disabled, turning fridge off") + self.off() + return + # handle broken wort sensor if wort is not None: self.wort_valid_clock = self.server.now() @@ -93,7 +101,7 @@ overshoot = params.overshoot_factor \ * min(self.OVERSHOOT_MAX_DIV, on_time) \ / self.OVERSHOOT_MAX_DIV - L("on_time %(on_time)f, overshoot %(overshoot)f" % locals()) + D("on_time %(on_time)f, overshoot %(overshoot)f" % locals()) if wort is not None: if (wort - overshoot) < params.fridge_setpoint: @@ -115,7 +123,7 @@ turn_on = False if wort is not None: if wort >= wort_max: - L("Wort is too hot") + L("Wort is too hot %f, max %f" % (wort, wort_max)) turn_on = True else: # wort sensor is broken @@ -126,4 +134,4 @@ if turn_on: L("Turning fridge on") self.on() - fridge_on_clock = self.server.now() + self.fridge_on_clock = self.server.now() diff -r c3926e7cfb0c -r a40f30fad8f6 py/params.py --- a/py/params.py Mon Jan 21 07:25:29 2013 +0800 +++ b/py/params.py Mon Jan 21 07:25:52 2013 +0800 @@ -2,6 +2,7 @@ import collections import json import signal +import StringIO import gevent @@ -13,6 +14,7 @@ 'fridge_difference': 0.2, 'overshoot_delay': 720, # 12 minutes 'overshoot_factor': 1, # ÂșC + 'disabled': False, } class Params(dict): @@ -48,6 +50,10 @@ raise self.Error("Unknown parameter %s=%s in file '%s'" % (str(k), str(u[k]), getattr(f, 'name', '???'))) self.update(u) + L("Loaded parameters") + L(self.save_string()) + + def save(self, f = None): if not f: f = file(config.PARAMS_FILE, 'w') @@ -55,9 +61,14 @@ f.write('\n') f.flush() + def save_string(self): + s = StringIO.StringIO() + self.save(s) + return s.getvalue() + def reload_signal(self): try: self.load() - L("Reloaded params") + L("Reloaded.") except self.Error, e: W("Problem reloading: %s" % str(e)) diff -r c3926e7cfb0c -r a40f30fad8f6 py/sensor_ds18b20.py --- a/py/sensor_ds18b20.py Mon Jan 21 07:25:29 2013 +0800 +++ b/py/sensor_ds18b20.py Mon Jan 21 07:25:52 2013 +0800 @@ -75,7 +75,6 @@ """ Returns a sequence of sensorname """ slaves_path = os.path.join(self.master_dir, "w1_master_slaves") names = open(slaves_path, 'r').read().split() - D("returning names %s" % names) return names def wort_name(self): diff -r c3926e7cfb0c -r a40f30fad8f6 py/tempserver.py --- a/py/tempserver.py Mon Jan 21 07:25:29 2013 +0800 +++ b/py/tempserver.py Mon Jan 21 07:25:52 2013 +0800 @@ -6,6 +6,8 @@ import gevent import gevent.monkey +import lockfile +import daemon import utils from utils import L,D,EX,W @@ -13,6 +15,7 @@ import config import sensor_ds18b20 import params +import uploader class Tempserver(object): @@ -27,6 +30,7 @@ def __enter__(self): self.params = params.Params() self.fridge = fridge.Fridge(self) + self.uploader = uploader.Uploader(self) self.params.load() self.set_sensors(sensor_ds18b20.DS18B20s(self)) return self @@ -44,6 +48,7 @@ self.start_time = self.now() self.fridge.start() self.sensors.start() + self.uploader.start() # won't return. while True: @@ -69,7 +74,7 @@ def pushfront(self, readings): """ used if a caller of take_readings() fails """ - self.readings = pushback + self.readings + self.readings = readings + self.readings # a reading is a map of {sensorname: value}. temperatures # are float degrees @@ -79,6 +84,8 @@ self.readings.append( (reading, self.now())) self.current = (reading.get(self.wort_name, None), reading.get(self.fridge_name, None)) + if len(self.readings) > config.MAX_READINGS: + self.readings = self.readings[-config.MAX_READINGS:] def current_temps(self): """ returns (wort_temp, fridge_temp) tuple """ @@ -87,15 +94,27 @@ def setup_logging(): logging.basicConfig(format='%(asctime)s %(message)s', datefmt='%m/%d/%Y %I:%M:%S %p', - level=logging.DEBUG) + level=logging.INFO) + +def start(): + with Tempserver() as server: + server.run() def main(): setup_logging() + pidpath = os.path.join(os.path.dirname(__file__), 'tempserver-lock') + pidf = lockfile.FileLock(pidpath, threaded=False) + pidf.acquire(0) + if '--daemon' in sys.argv: - utils.cheap_daemon() - with Tempserver() as server: - server.run() + logpath = os.path.join(os.path.dirname(__file__), 'tempserver.log') + logf = open(logpath, 'a+') + with daemon.DaemonContext(pidfile=pidf, stdout=logf, stderr = logf): + start() + else: + with pidf: + start() if __name__ == '__main__': main() diff -r c3926e7cfb0c -r a40f30fad8f6 py/uploader.py --- a/py/uploader.py Mon Jan 21 07:25:29 2013 +0800 +++ b/py/uploader.py Mon Jan 21 07:25:52 2013 +0800 @@ -1,8 +1,15 @@ -import config - import json import hmac import zlib +import binascii +import urllib +import urllib2 + +import gevent + +import config +from utils import L,D,EX,W,E +import utils class Uploader(gevent.Greenlet): def __init__(self, server): @@ -10,6 +17,7 @@ self.server = server def _run(self): + gevent.sleep(5) while True: self.do() gevent.sleep(config.UPLOAD_SLEEP) @@ -23,7 +31,7 @@ tosend['readings'] = readings tosend['wort_name'] = self.server.wort_name - tosend['fridge_name'] = self.server.wort_fridge_name + tosend['fridge_name'] = self.server.wort_name tosend.update(dict(self.server.params)) @@ -42,14 +50,18 @@ if result != 'OK': raise Exception("Server returned %s" % result) - def do(): + def do(self): readings = self.server.take_readings() try: tosend = self.get_tosend(readings) - readings = None + nreadings = len(readings) self.send(tosend) + readings = None + D("Sent updated %d readings" % nreadings) + except urllib2.HTTPError, e: + E("Error in uploader: %s" % str(e)) except Exception, e: - EX"Error in uploader: %s" % str(e)) + EX("Error in uploader: %s" % str(e)) finally: if readings is not None: self.server.pushfront(readings) diff -r c3926e7cfb0c -r a40f30fad8f6 requirements.txt --- a/requirements.txt Mon Jan 21 07:25:29 2013 +0800 +++ b/requirements.txt Mon Jan 21 07:25:52 2013 +0800 @@ -1,5 +1,7 @@ argparse==1.2.1 gevent==1.0rc2 greenlet==0.4.0 +lockfile==0.9.1 +python-daemon==1.6 smbus==1.1 wsgiref==0.1.2