summaryrefslogtreecommitdiff
path: root/dexcom_reader
diff options
context:
space:
mode:
authorAndrew Cady <d@jerkface.net>2017-01-27 14:09:19 +0000
committerAndrew Cady <d@jerkface.net>2017-01-27 14:09:31 +0000
commit8108af95b1f698986415a941c4d9b1db2488da51 (patch)
treefa354217ad0e1a3e522928afd98969207f8ba2b1 /dexcom_reader
parent1dbf49a63d126e63e15d5e426e1faf2140b97c5d (diff)
dexcom_dumper: improved server update logic
Diffstat (limited to 'dexcom_reader')
-rw-r--r--dexcom_reader/dexcom_dumper.py81
1 files changed, 72 insertions, 9 deletions
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):
158 POST('/ping', toJSON(now)) 158 POST('/ping', toJSON(now))
159 159
160def print_cgm_bg(now, r): 160def print_cgm_bg(now, r):
161 if HOST: 161 if JSON:
162 remote_update('EGV_DATA')
163 send_ping(now)
164 return
165 elif JSON:
166 print toJSON(r) 162 print toJSON(r)
167 else: 163 else:
168 print '%s: %s %s' % (format_times(now, r.system_time), r.glucose, r.trend_arrow) 164 print '%s: %s %s' % (format_times(now, r.system_time), r.glucose, r.trend_arrow)
169 stdout.flush() 165 stdout.flush()
170 166
167def dexcom_reconnect():
168 global dr
169 dr = get_dexcom_reader()
170
171def poll(): 171def poll():
172 if HOST:
173 poll_remote()
174 else:
175 poll_stdout()
176
177def poll_remote():
178 print_localtime('dexcom_dumper started')
179 connected = False
180 while True:
181 try:
182 (n, r) = remote_update('EGV_DATA')
183 if n is None:
184 sleep_verbose(10)
185 continue
186
187 now = dr.ReadSystemTime()
188 if n == 0:
189 send_ping(now)
190 if r:
191 next_reading = (r.system_time - now + timedelta(minutes=5, seconds=2)).total_seconds()
192 sleep_verbose(max(10, next_reading))
193 else:
194 sleep_verbose(10)
195 connected = True
196 except ValueError as v:
197 if connected:
198 print_verbose('Dexcom is disconnected.')
199 connected = False
200 sleep(10)
201 if (v.args[0] != 'Attempting to use a port that is not open'):
202 dexcom_reconnect()
203 except KeyboardInterrupt:
204 print_verbose('Exiting.')
205 return
206 except:
207 print_verbose(sys.exc_info())
208 sleep(10)
209
210def poll_stdout():
172 print_localtime('dexcom_dumper started') 211 print_localtime('dexcom_dumper started')
173 while True: 212 while True:
174 (r, now) = read_recent_egv_data() 213 (r, now) = read_recent_egv_data()
@@ -177,7 +216,6 @@ def poll():
177 sleep_verbose(10) 216 sleep_verbose(10)
178 elif r is None: 217 elif r is None:
179 connected(True) 218 connected(True)
180 send_ping(now)
181 sleep_verbose(10) 219 sleep_verbose(10)
182 else: 220 else:
183 connected(True) 221 connected(True)
@@ -188,11 +226,32 @@ def poll():
188 226
189def since(when, rectype): 227def since(when, rectype):
190 filt = lambda r: (r.system_time > when) if when else True 228 filt = lambda r: (r.system_time > when) if when else True
191 return reversed(list(takewhile(filt, dr.iter_records(rectype)))) 229 return list(reversed(list(takewhile(filt, dr.iter_records(rectype)))))
230
231def since_and_first(when, rectype):
232 class closure:
233 fst = None
234 def filt(r):
235 closure.fst = closure.fst or r
236 return (r.system_time > when) if when else True
237 return (list(reversed(list(takewhile(filt, dr.iter_records(rectype))))), closure.fst)
192 238
193def parsetime(s): 239def parsetime(s):
194 return datetime.strptime(s, "%Y-%m-%dT%H:%M:%SZ") 240 return datetime.strptime(s, "%Y-%m-%dT%H:%M:%SZ")
195 241
242# Update the remote site with any records of 'rectype' that are missing.
243# The server is queried to determine its last update.
244#
245# Returns (a,b) where:
246#
247# a = the number of records sent to the server (possibly zero), or None for a server error
248#
249# b = the latest record available on the Dexcom
250#
251# TODO: This has a race condition if you imagine multiple clients,
252# server restarts, etc.; it should send back the value it got in the
253# query to the server, so that the server can verify that the updates
254# are consecutive.
196def remote_update(rectype): 255def remote_update(rectype):
197 requests = import_requests() 256 requests = import_requests()
198 url_path = '/' + rectype 257 url_path = '/' + rectype
@@ -204,10 +263,14 @@ def remote_update(rectype):
204 when = parsetime(resp.json()[0]['contents']['system_time']) 263 when = parsetime(resp.json()[0]['contents']['system_time'])
205 print_verbose("Latest record on server: %s" % when.isoformat()) 264 print_verbose("Latest record on server: %s" % when.isoformat())
206 265
207 rs = list(since(when, rectype)) 266 (rs, r) = since_and_first(when, rectype)
208 if len(rs): 267 if len(rs):
209 print_verbose("Sending %d record%s... " % (len(rs), '' if len(rs) == 1 else 's'), newline=False) 268 print_verbose("Sending %d record%s... " % (len(rs), '' if len(rs) == 1 else 's'), newline=False)
210 print_verbose("done. (Result: %s)" % POST(url_path, toJSON(rs))) 269 result = POST(url_path, toJSON(rs))
270 print_verbose("done. (Result: %s)" % result)
271 return (len(rs) if result else None, r)
272 else:
273 return (0, r)
211 274
212def test(): 275def test():
213 remote_update('EGV_DATA') 276 remote_update('EGV_DATA')