# HG changeset patch # User Matt Johnston # Date 1428766379 -28800 # Node ID 9b1d71310c831464f057a17b138be325427d7597 # Parent fd0fd9f947a1993d288a78e29ec0481c773f245b better arg parser. seems close to ready diff -r fd0fd9f947a1 -r 9b1d71310c83 py/fridge.py --- a/py/fridge.py Sat Apr 11 21:09:13 2015 +0800 +++ b/py/fridge.py Sat Apr 11 23:32:59 2015 +0800 @@ -81,6 +81,8 @@ if fridge is None: W("Invalid fridge sensor") + D("fridge on %s" % self.is_on()) + if self.is_on(): turn_off = False on_time = self.server.now() - self.fridge_on_clock @@ -109,6 +111,7 @@ else: # fridge is off turn_on = False + D("fridge %(fridge)f max %(fridge_max)f wort %(wort)f wort_max %(wort_max)f" % locals()) if not params.nowort \ and wort is not None \ and wort >= wort_max: diff -r fd0fd9f947a1 -r 9b1d71310c83 py/params.py --- a/py/params.py Sat Apr 11 21:09:13 2015 +0800 +++ b/py/params.py Sat Apr 11 23:32:59 2015 +0800 @@ -33,13 +33,7 @@ self[k] self[k] = v - def load(self, f = None): - if not f: - try: - f = open(config.PARAMS_FILE, 'r') - except IOError as e: - W("Missing parameter file, using defaults. %s", e) - return + def _do_load(self, f): try: u = json.load(f) except Exception as e: @@ -55,14 +49,29 @@ L("Loaded parameters") L(self.save_string()) + def load(self, f = None): + if f: + return self._do_load(f) + else: + with open(config.PARAMS_FILE, 'r') as f: + try: + return self._do_load(f) + except IOError as e: + W("Missing parameter file, using defaults. %s" % str(e)) + return - def save(self, f = None): - if not f: - f = file(config.PARAMS_FILE, 'w') + def _do_save(self, f): json.dump(self, f, sort_keys=True, indent=4) f.write('\n') f.flush() + def save(self, f = None): + if f: + return self._do_save(f) + else: + with file(config.PARAMS_FILE, 'w') as f: + return self._do_save(f) + def save_string(self): s = io.StringIO() self.save(s) diff -r fd0fd9f947a1 -r 9b1d71310c83 py/tempserver.py --- a/py/tempserver.py Sat Apr 11 21:09:13 2015 +0800 +++ b/py/tempserver.py Sat Apr 11 23:32:59 2015 +0800 @@ -6,6 +6,7 @@ import time import signal import asyncio +import argparse import lockfile.pidlockfile import daemon @@ -20,11 +21,12 @@ class Tempserver(object): - def __init__(self): + def __init__(self, test_mode): self.readings = [] self.current = (None, None) self.fridge = None - self._wakeup = asyncio.Condition() + self._wakeup = asyncio.Event() + self._test_mode = test_mode def __enter__(self): self.params = params.Params() @@ -53,9 +55,15 @@ ) loop = asyncio.get_event_loop() - result_tasks = loop.run_until_complete(asyncio.wait(tasks, return_when=asyncio.FIRST_EXCEPTION)) - # use the results so that exceptions get thrown - [t.result() for x in result_tasks for t in x] + try: + result_tasks = loop.run_until_complete(asyncio.wait(tasks, return_when=asyncio.FIRST_EXCEPTION)) + # use the results so that exceptions get thrown + [t.result() for x in result_tasks for t in x] + except KeyboardInterrupt: + print('ctrl-c') + pass + finally: + loop.close() def now(self): return utils.monotonic_time() @@ -98,42 +106,58 @@ # XXX fixme - we should wake on _wakeup but asyncio Condition with wait_for is a bit broken? # https://groups.google.com/forum/#!topic/python-tulip/eSm7rZAe9LM # For now we just sleep, ignore the _wakeup - yield from asyncio.sleep(timeout) + try: + yield from asyncio.wait_for(self._wakeup.wait(), timeout=timeout) + except asyncio.TimeoutError: + pass - @asyncio.coroutine def _reload_signal(self): try: self.params.load() L("Reloaded.") - yield from self._wakeup.acquire() - self._wakeup.notify_all() - self._wakeup.release() + self._wakeup.set() + self._wakeup.clear() except Error as e: W("Problem reloading: %s" % str(e)) -def setup_logging(): + def test_mode(self): + return self._test_mode + +def setup_logging(debug = False): + level = logging.INFO + if debug: + level = logging.DEBUG logging.basicConfig(format='%(asctime)s %(message)s', datefmt='%m/%d/%Y %I:%M:%S %p', - level=logging.DEBUG) - logging.getLogger("asyncio").setLevel(logging.DEBUG) + level=level) + #logging.getLogger("asyncio").setLevel(logging.DEBUG) -def start(): - with Tempserver() as server: +def start(test_mode): + with Tempserver(test_mode) as server: server.run() def main(): - setup_logging() + parser = argparse.ArgumentParser() + parser.add_argument('--hup', action='store_true') + parser.add_argument('--new', action='store_true') + parser.add_argument('--daemon', action='store_true') + parser.add_argument('-d', '--debug', action='store_true') + parser.add_argument('-t', '--test', action='store_true') + args = parser.parse_args() + + setup_logging(args.debug) heredir = os.path.abspath(os.path.dirname(__file__)) pidpath = os.path.join(heredir, 'tempserver.pid') pidf = lockfile.pidlockfile.PIDLockFile(pidpath, threaded=False) - do_hup = '--hup' in sys.argv + + try: pidf.acquire(1) pidf.release() except (lockfile.AlreadyLocked, lockfile.LockTimeout) as e: pid = pidf.read_pid() - if do_hup: + if args.hup: try: os.kill(pid, signal.SIGHUP) print("Sent SIGHUP to process %d" % pid, file=sys.stderr) @@ -146,7 +170,7 @@ stale = False if pid > 0: - if '--new' in sys.argv: + if args.new: try: os.kill(pid, 0) except OSError: @@ -171,18 +195,18 @@ print("Unlinking stale lockfile %s for pid %d" % (pidpath, pid), file=sys.stderr) pidf.break_lock() - if do_hup: + if args.hup: print("Doesn't seem to be running", file=sys.stderr) sys.exit(1) - if '--daemon' in sys.argv: + if args.daemon: logpath = os.path.join(os.path.dirname(__file__), 'tempserver.log') logf = open(logpath, 'a+') with daemon.DaemonContext(pidfile=pidf, stdout=logf, stderr = logf): - start() + start(args.test) else: with pidf: - start() + start(args.test) if __name__ == '__main__': main() diff -r fd0fd9f947a1 -r 9b1d71310c83 py/uploader.py --- a/py/uploader.py Sat Apr 11 21:09:13 2015 +0800 +++ b/py/uploader.py Sat Apr 11 23:32:59 2015 +0800 @@ -1,5 +1,6 @@ import json import hmac +import hashlib import zlib import binascii import logging @@ -44,8 +45,11 @@ @asyncio.coroutine def send(self, tosend): js = json.dumps(tosend) + if self.server.test_mode(): + D("Would upload %s to %s" % (js, config.UPDATE_URL)) + return js_enc = binascii.b2a_base64(zlib.compress(js.encode())) - mac = hmac.new(config.HMAC_KEY.encode(), js_enc).hexdigest() + mac = hmac.new(config.HMAC_KEY.encode(), js_enc, hashlib.sha1).hexdigest() send_data = {'data': js_enc, 'hmac': mac} r = yield from asyncio.wait_for(aiohttp.request('post', config.UPDATE_URL, data=send_data), 60) result = yield from asyncio.wait_for(r.text(), 60)