From 8108af95b1f698986415a941c4d9b1db2488da51 Mon Sep 17 00:00:00 2001 From: Andrew Cady Date: Fri, 27 Jan 2017 14:09:19 +0000 Subject: dexcom_dumper: improved server update logic --- dexcom_reader/dexcom_dumper.py | 81 +++++++++++++++++++++++++++++++++++++----- 1 file changed, 72 insertions(+), 9 deletions(-) (limited to 'dexcom_reader') diff --git a/dexcom_reader/dexcom_dumper.py b/dexcom_reader/dexcom_dumper.py index f4cf7c5..95d1bee 100644 --- a/dexcom_reader/dexcom_dumper.py +++ b/dexcom_reader/dexcom_dumper.py @@ -158,17 +158,56 @@ def send_ping(now): POST('/ping', toJSON(now)) def print_cgm_bg(now, r): - if HOST: - remote_update('EGV_DATA') - send_ping(now) - return - elif JSON: + if JSON: print toJSON(r) else: print '%s: %s %s' % (format_times(now, r.system_time), r.glucose, r.trend_arrow) stdout.flush() +def dexcom_reconnect(): + global dr + dr = get_dexcom_reader() + def poll(): + if HOST: + poll_remote() + else: + poll_stdout() + +def poll_remote(): + print_localtime('dexcom_dumper started') + connected = False + while True: + try: + (n, r) = remote_update('EGV_DATA') + if n is None: + sleep_verbose(10) + continue + + now = dr.ReadSystemTime() + if n == 0: + send_ping(now) + if r: + next_reading = (r.system_time - now + timedelta(minutes=5, seconds=2)).total_seconds() + sleep_verbose(max(10, next_reading)) + else: + sleep_verbose(10) + connected = True + except ValueError as v: + if connected: + print_verbose('Dexcom is disconnected.') + connected = False + sleep(10) + if (v.args[0] != 'Attempting to use a port that is not open'): + dexcom_reconnect() + except KeyboardInterrupt: + print_verbose('Exiting.') + return + except: + print_verbose(sys.exc_info()) + sleep(10) + +def poll_stdout(): print_localtime('dexcom_dumper started') while True: (r, now) = read_recent_egv_data() @@ -177,7 +216,6 @@ def poll(): sleep_verbose(10) elif r is None: connected(True) - send_ping(now) sleep_verbose(10) else: connected(True) @@ -188,11 +226,32 @@ def poll(): def since(when, rectype): filt = lambda r: (r.system_time > when) if when else True - return reversed(list(takewhile(filt, dr.iter_records(rectype)))) + return list(reversed(list(takewhile(filt, dr.iter_records(rectype))))) + +def since_and_first(when, rectype): + class closure: + fst = None + def filt(r): + closure.fst = closure.fst or r + return (r.system_time > when) if when else True + return (list(reversed(list(takewhile(filt, dr.iter_records(rectype))))), closure.fst) def parsetime(s): return datetime.strptime(s, "%Y-%m-%dT%H:%M:%SZ") +# Update the remote site with any records of 'rectype' that are missing. +# The server is queried to determine its last update. +# +# Returns (a,b) where: +# +# a = the number of records sent to the server (possibly zero), or None for a server error +# +# b = the latest record available on the Dexcom +# +# TODO: This has a race condition if you imagine multiple clients, +# server restarts, etc.; it should send back the value it got in the +# query to the server, so that the server can verify that the updates +# are consecutive. def remote_update(rectype): requests = import_requests() url_path = '/' + rectype @@ -204,10 +263,14 @@ def remote_update(rectype): when = parsetime(resp.json()[0]['contents']['system_time']) print_verbose("Latest record on server: %s" % when.isoformat()) - rs = list(since(when, rectype)) + (rs, r) = since_and_first(when, rectype) if len(rs): print_verbose("Sending %d record%s... " % (len(rs), '' if len(rs) == 1 else 's'), newline=False) - print_verbose("done. (Result: %s)" % POST(url_path, toJSON(rs))) + result = POST(url_path, toJSON(rs)) + print_verbose("done. (Result: %s)" % result) + return (len(rs) if result else None, r) + else: + return (0, r) def test(): remote_update('EGV_DATA') -- cgit v1.2.3