# HG changeset patch # User Matt Johnston # Date 1337998647 -28800 # Node ID 46070aaf29ea9c34fdacce19e4abff55513528af # Parent 5639c74f2cbb3609b34d776e34a33a87cad1ec42 A bit of work on the server python diff -r 5639c74f2cbb -r 46070aaf29ea main.c --- a/main.c Tue May 22 23:45:16 2012 +0800 +++ b/main.c Sat May 26 10:17:27 2012 +0800 @@ -34,6 +34,7 @@ #define VALUE_NOSENSOR -9000 #define VALUE_BROKEN -8000 +// limited to uint16_t for now #define COMMS_WAKE 3600 #define WAKE_SECS 30 @@ -69,6 +70,10 @@ static uint16_t n_measurements; // stored as decidegrees static int16_t measurements[NUM_MEASUREMENTS][MAX_SENSORS]; +static uint32_t first_measurement_clock; +// last_measurement_clock is redundant but checks that we're not missing +// samples +static uint32_t last_measurement_clock; // boolean flags static uint8_t need_measurement; @@ -218,7 +223,9 @@ eeprom_read(n_sensors, n_sensors); fprintf_P(crc_stdout, PSTR("START\n")); - fprintf_P(crc_stdout, PSTR("time=%lu\n"), clock_epoch); + fprintf_P(crc_stdout, PSTR("now=%lu\n"), clock_epoch); + fprintf_P(crc_stdout, PSTR("first_time=%lu\n"), first_measurement_clock); + fprintf_P(crc_stdout, PSTR("last_time=%lu\n"), last_measurement_clock); fprintf_P(crc_stdout, PSTR("sensors=%d\n"), n_measurements); for (uint8_t s = 0; s < n_sensors; s++) { @@ -252,7 +259,8 @@ static void cmd_btoff() { - printf_P(PSTR("Turning off\n")); + uint16_t next_wake = COMMS_WAKE - comms_count; + printf_P(PSTR("off:%d\n"), next_wake); _delay_ms(50); comms_timeout = 0; } @@ -462,11 +470,15 @@ { char c = UDR0; uart_putchar(c, NULL); - if (c == '\r') + // XXX move this out of interrupt handler + if (c == '\r' || c == '\n') { - readbuf[readpos] = '\0'; - read_handler(); - readpos = 0; + if (readpos > 0) + { + readbuf[readpos] = '\0'; + read_handler(); + readpos = 0; + } } else { @@ -625,6 +637,13 @@ } measurements[n_measurements][s] = decicelsius; } + + if (n_measurements == 0) + { + first_measurement_clock = clock_epoch; + } + last_measurement_clock = clock_epoch; + n_measurements++; //do_adc_335(); } diff -r 5639c74f2cbb -r 46070aaf29ea server/ts.py --- a/server/ts.py Tue May 22 23:45:16 2012 +0800 +++ b/server/ts.py Sat May 26 10:17:27 2012 +0800 @@ -1,7 +1,14 @@ #!/usr/bin/env python2.7 +BTADDR = "00:12:03:27:70:88" +SLEEP_TIME = 180 + import sys import httplib +import time +import traceback + +from utils import monotonic_time, retry lightblue = None try: @@ -9,8 +16,6 @@ except ImportError: import bluetooth -BTADDR = "00:12:03:27:70:88" - def get_socket(addr): if lightblue: s = lightblue.socket() @@ -19,40 +24,32 @@ s = bluetooth.BluetoothSocket( bluetooth.RFCOMM ) s.connect((addr, 1)) + s.setnonblocking(True) + return s # from http://blog.stalkr.net/2011/04/pctf-2011-32-thats-no-bluetooth.html def crc16(buff, crc = 0, poly = 0x8408): -    l = len(buff) -    i = 0 -    while i < l: -        ch = ord(buff[i]) -        uc = 0 -        while uc < 8: -            if (crc & 1) ^ (ch & 1): -                crc = (crc >> 1) ^ poly -            else: -                crc >>= 1 -            ch >>= 1 -            uc += 1 -        i += 1 -    return crc + l = len(buff) + i = 0 + while i < l: + ch = ord(buff[i]) + uc = 0 + while uc < 8: + if (crc & 1) ^ (ch & 1): + crc = (crc >> 1) ^ poly + else: + crc >>= 1 + ch >>= 1 + uc += 1 + i += 1 + return crc +@retry() def fetch(sock): sock.send("fetch\n") - def readline(self): - buf = '' - while true: - c = self.recv(1) - if c == '\r': - continue - - buf.append(c) - if c == '\n': - return buf - crc = 0 lines = [] @@ -93,3 +90,70 @@ return None return ''.join(lines) + +@retry() +def turn_off(sock): + sock.send("btoff\n"); + # read newline + l = readline(sock) + if not l: + print>>sys.stderr, "Bad response to btoff\n" + return None + + off, next_wake = l.rstrip().split(':') + if off != 'Off': + print>>sys.stderr, "Bad response to btoff '%s'\n" % l + + return int(next_wake) + + +def do_comms(sock): + d = None + # serial could be unreliable, try a few times + for i in range(FETCH_TRIES): + d = fetch(sock) + if d: + break + time.sleep(1) + if not d: + return + + res = send_results() + if not res: + return + + clear_meas(sock) + + 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 main(): + + while True: + sock = get_socket() + sleep_time = SLEEP_TIME + if sock: + next_wake = None + try: + next_wake = do_comms(sock) + except Exception, e: + print>>sys.stderr, "Error in do_comms:" + traceback.print_last(file=sys.stderr) + if next_wake: + sleep_time = min(next_wake, sleep_time) + + sleep_for(sleep_time) + +if __name__ == '__main__': + main() diff -r 5639c74f2cbb -r 46070aaf29ea server/utils.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/server/utils.py Sat May 26 10:17:27 2012 +0800 @@ -0,0 +1,75 @@ +import os +import sys +import ctypes +import time +import select + +DEFAULT_TRIES = 3 + +__all__ = ('monotonic_time', 'retry') + +clock_gettime = None +no_clock_gettime = False +def monotonic_time(): + global clock_gettime + global no_clock_gettime + if no_clock_gettime: + return time.time() + + class timespec(ctypes.Structure): + _fields_ = [ + ('tv_sec', ctypes.c_long), + ('tv_nsec', ctypes.c_long) + ] + if not clock_gettime: + try: + librt = ctypes.CDLL('librt.so.0', use_errno=True) + clock_gettime = librt.clock_gettime + clock_gettime.argtypes = [ctypes.c_int, ctypes.POINTER(timespec)] + except: + print>>sys.stderr, "No clock_gettime(), using fake fallback." + no_clock_gettime = True + return time.time() + + t = timespec() + CLOCK_MONOTONIC = 1 # see + + if clock_gettime(CLOCK_MONOTONIC, ctypes.pointer(t)) != 0: + errno_ = ctypes.get_errno() + raise OSError(errno_, os.strerror(errno_)) + return t.tv_sec + t.tv_nsec * 1e-9 + +# decorator, tries a number of times, returns None on failure, sleeps between +# Must be used as "@retry()" if arguments are defaulted +def retry(retries=DEFAULT_TRIES, try_time = 1): + def inner(func): + print "inner" + def new_f(*args, **kwargs): + print "newf" + for i in range(retries): + print "retry %d" % i + d = func(*args, **kwargs) + if d: + return d + time.sleep(try_time) + new_f.func_name = func.func_name + return new_f + return inner + +def readline(sock): + timeout = READLINE_SELECT_TIMEOUT + buf = '' + while true: + (rlist, wlist, xlist) = select.select([sock], [], [], timeout) + if sock not in rlist: + # hit timeout + return None + + c = sock.recv(1) + if c == '\r': + continue + + buf.append(c) + if c == '\n': + return buf +