diff options
Diffstat (limited to 'dexcom_reader/dexcom_dumper.py')
-rw-r--r-- | dexcom_reader/dexcom_dumper.py | 81 |
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 | ||
160 | def print_cgm_bg(now, r): | 160 | def 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 | ||
167 | def dexcom_reconnect(): | ||
168 | global dr | ||
169 | dr = get_dexcom_reader() | ||
170 | |||
171 | def poll(): | 171 | def poll(): |
172 | if HOST: | ||
173 | poll_remote() | ||
174 | else: | ||
175 | poll_stdout() | ||
176 | |||
177 | def 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 | |||
210 | def 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 | ||
189 | def since(when, rectype): | 227 | def 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 | |||
231 | def 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 | ||
193 | def parsetime(s): | 239 | def 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. | ||
196 | def remote_update(rectype): | 255 | def 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 | ||
212 | def test(): | 275 | def test(): |
213 | remote_update('EGV_DATA') | 276 | remote_update('EGV_DATA') |