Mercurial > templog
diff old/server/ts.py @ 511:cf52d5817709
merge
author | Matt Johnston <matt@ucc.asn.au> |
---|---|
date | Thu, 26 Jun 2014 23:03:32 +0800 |
parents | 95043860e437 |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/old/server/ts.py Thu Jun 26 23:03:32 2014 +0800 @@ -0,0 +1,239 @@ +#!/usr/bin/env python2.7 + +# time that the bluetooth takes to get going? +EXTRA_WAKEUP = -3 + +FETCH_TRIES = 3 + +# avoid turning off the bluetooth etc. +TESTING = False + +import sys +# for wrt +sys.path.append('/root/python') +import httplib +import time +import traceback +import binascii +import hmac +import zlib +import urllib +import urllib2 +import logging +import socket + +L = logging.info +W = logging.warning +E = logging.error + +import config + +from utils import monotonic_time, retry, readline, crc16 +import utils + +import bluetooth + +def get_socket(addr): + s = bluetooth.BluetoothSocket( bluetooth.RFCOMM ) + L("connecting") + s.connect((addr, 1)) + s.setblocking(False) + s.settimeout(1) + + return s + + +def flush(sock): + ret = [] + while True: + l = readline(sock) + if l: + ret.append(l) + else: + break + return ret + +def encode_extra(extra_lines): + return ['extra%d=%s' % (n, l.strip()) for (n,l) in enumerate(extra_lines)] + +@retry() +def fetch(sock): + extra_lines = flush(sock) + sock.send("fetch\n") + + crc = 0 + + lines = [] + l = readline(sock) + if not l: + return None + + if l != 'START\n': + W("Bad expected START line '%s'\n" % l.rstrip('\n')) + extra_lines.append(l) + return encode_extra(extra_lines) + crc = crc16(l, crc) + + while True: + l = readline(sock) + + crc = crc16(l, crc) + + if l == 'END\n': + break + + lines.append(l.rstrip('\n')) + + lines += encode_extra(extra_lines) + + for d in lines: + L("Received: %s" % d) + + l = readline(sock) + recv_crc = None + try: + k, v = l.rstrip('\n').split('=') + if k == 'CRC': + recv_crc = int(v) + if recv_crc < 0 or recv_crc > 0xffff: + recv_crc = None + except ValueError: + pass + + if recv_crc is None: + W("Bad expected CRC line '%s'\n" % l.rstrip('\n')) + return None + + if recv_crc != crc: + W("Bad CRC: calculated 0x%x vs received 0x%x\n" % (crc, recv_crc)) + return None + + return lines + +@retry() +def turn_off(sock): + if TESTING: + return 99 + L("Sending btoff") + flush(sock) + sock.send("btoff\n"); + # read newline + l = readline(sock) + if not l: + W("Bad response to btoff") + return None + + if not l.startswith('next_wake'): + W("Bad response to btoff '%s'" % l) + return None + L("Next wake line %s" % l) + + toks = dict(v.split('=') for v in l.split(',')) + + rem = int(toks['rem']) + tick_secs = int(toks['tick_secs']) + tick_wake = int(toks['tick_wake']) + 1 + next_wake = int(toks['next_wake']) + + rem_secs = float(rem) / tick_wake * tick_secs + + next_wake_secs = next_wake - rem_secs + L("next_wake_secs %f\n", next_wake_secs) + return next_wake_secs + +@retry() +def clear_meas(sock): + flush(sock) + sock.send("clear\n"); + l = readline(sock) + if l and l.rstrip() == 'cleared': + return True + + E("Bad response to clear '%s'" % str(l)) + return False + +def send_results(lines): + enc_lines = binascii.b2a_base64(zlib.compress('\n'.join(lines))) + mac = hmac.new(config.HMAC_KEY, enc_lines).hexdigest() + + url_data = urllib.urlencode( {'lines': enc_lines, 'hmac': mac} ) + con = urllib2.urlopen(config.UPDATE_URL, url_data) + result = con.read(100) + if result == 'OK': + return True + else: + W("Bad result '%s'" % result) + return False + +def do_comms(sock): + L("do_comms") + d = None + # serial could be unreliable, try a few times + d = fetch(sock) + if not d: + return + + res = send_results(d) + if not res: + return + + clear_meas(sock) + + next_wake = 600 + #next_wake = turn_off(sock) + #sock.close() + return next_wake + +testcount = 0 + +def sleep_for(secs): + until = monotonic_time() + secs + while True: + length = until - monotonic_time() + if length <= 0: + return + time.sleep(length) + +def setup_logging(): + logging.basicConfig(format='%(asctime)s %(message)s', + datefmt='%m/%d/%Y %I:%M:%S %p', + level=logging.INFO) + +def get_net_socket(host, port): + s = socket.create_connection((host, port)) + s.setblocking(False) + s.settimeout(1) + return s + +def main(): + setup_logging() + + L("Running templog rfcomm server") + + if '--daemon' in sys.argv: + utils.cheap_daemon() + + next_wake_time = 0 + + while True: + sock = None + try: + sock = get_net_socket(config.SERIAL_HOST, config.SERIAL_PORT) + except Exception, e: + #logging.exception("Error connecting") + pass + + if not sock: + sleep_for(config.SLEEP_TIME) + continue + + while True: + try: + do_comms(sock) + sleep_for(config.SLEEP_TIME) + except Exception, e: + logging.exception("Error in do_comms") + break + +if __name__ == '__main__': + main()