diff options
author | Andrew Cady <d@jerkface.net> | 2017-01-27 07:55:49 +0000 |
---|---|---|
committer | Andrew Cady <d@jerkface.net> | 2017-01-27 07:55:49 +0000 |
commit | 1dbf49a63d126e63e15d5e426e1faf2140b97c5d (patch) | |
tree | e89d9f8e515b1f2857b1367bedbab8b9090a514f | |
parent | c60a203b350272c08d7bcc0d31bce43e7cd825db (diff) |
Use synchronization instead of pushing updates
When a BG reading needs to be pushed, the server is contacted to determine
the latest BG reading it has. Then the Dexcom is queried to find all
readings since that latest one.
This could be made more efficient by avoiding double-querying the Dexcom.
-rw-r--r-- | dexcom_reader/dexcom_dumper.py | 109 |
1 files changed, 53 insertions, 56 deletions
diff --git a/dexcom_reader/dexcom_dumper.py b/dexcom_reader/dexcom_dumper.py index 2694b83..f4cf7c5 100644 --- a/dexcom_reader/dexcom_dumper.py +++ b/dexcom_reader/dexcom_dumper.py | |||
@@ -81,27 +81,27 @@ def recent(t): | |||
81 | now = dr.ReadSystemTime() | 81 | now = dr.ReadSystemTime() |
82 | return t.system_time > now - timedelta(minutes=5) | 82 | return t.system_time > now - timedelta(minutes=5) |
83 | 83 | ||
84 | def print_verbose(s): | 84 | def print_verbose(s, newline=True): |
85 | global VERBOSE | 85 | global VERBOSE |
86 | if VERBOSE: | 86 | if VERBOSE: |
87 | stderr.write('%s\n' % str(s)) | 87 | stderr.write('%s%s' % (str(s), '\n' if newline else '')) |
88 | 88 | ||
89 | def read_recent_egv_data(): | 89 | def read_recent_egv_data(): |
90 | try: | 90 | global dr |
91 | r = dr.ReadRecords('EGV_DATA', 1)[-1] | 91 | try: |
92 | if recent(r) and not r.is_special and not r.display_only: | 92 | now = dr.ReadSystemTime() |
93 | return r | 93 | r = dr.ReadRecords('EGV_DATA', 1)[-1] |
94 | else: | 94 | if recent(r) and not r.is_special and not r.display_only: |
95 | return None | 95 | return (r, now) |
96 | except ValueError as v: | 96 | else: |
97 | if (v.args[0] == 'Attempting to use a port that is not open'): | 97 | return (None, now) |
98 | return False | 98 | except ValueError as v: |
99 | else: | 99 | if (v.args[0] != 'Attempting to use a port that is not open'): |
100 | print_verbose(v) | 100 | print_verbose(v) |
101 | return None | 101 | dr = get_dexcom_reader() |
102 | except: | 102 | except: |
103 | print_verbose(sys.exc_info) | 103 | print_verbose(sys.exc_info()) |
104 | return None | 104 | return (None, None) |
105 | 105 | ||
106 | def time_fmt(t): | 106 | def time_fmt(t): |
107 | global HUMAN | 107 | global HUMAN |
@@ -128,10 +128,20 @@ def sleep_verbose(n): | |||
128 | print_verbose('sleep(%d)' % n) | 128 | print_verbose('sleep(%d)' % n) |
129 | sleep(n) | 129 | sleep(n) |
130 | 130 | ||
131 | imported_requests = None | ||
132 | def import_requests(): | ||
133 | global imported_requests | ||
134 | if not imported_requests: | ||
135 | print_verbose("Loading 'requests' HTTP client library... ", newline=False) | ||
136 | import requests | ||
137 | print_verbose("done.") | ||
138 | imported_requests = requests | ||
139 | return imported_requests | ||
140 | |||
131 | def POST(path, json_str): | 141 | def POST(path, json_str): |
132 | msg = None | 142 | msg = None |
133 | try: | 143 | try: |
134 | import requests | 144 | requests = import_requests() |
135 | resp = requests.post(HOST + path, data=json_str, | 145 | resp = requests.post(HOST + path, data=json_str, |
136 | headers={'Content-type': 'application/json'}) | 146 | headers={'Content-type': 'application/json'}) |
137 | msg = resp.text | 147 | msg = resp.text |
@@ -149,9 +159,7 @@ def send_ping(now): | |||
149 | 159 | ||
150 | def print_cgm_bg(now, r): | 160 | def print_cgm_bg(now, r): |
151 | if HOST: | 161 | if HOST: |
152 | r.trend_arrow.replace('45_', 'DIAGONAL_', 1) | 162 | remote_update('EGV_DATA') |
153 | if not r.is_special: | ||
154 | POST('/egv_data', toJSON(r)) | ||
155 | send_ping(now) | 163 | send_ping(now) |
156 | return | 164 | return |
157 | elif JSON: | 165 | elif JSON: |
@@ -163,61 +171,50 @@ def print_cgm_bg(now, r): | |||
163 | def poll(): | 171 | def poll(): |
164 | print_localtime('dexcom_dumper started') | 172 | print_localtime('dexcom_dumper started') |
165 | while True: | 173 | while True: |
166 | r = read_recent_egv_data() | 174 | (r, now) = read_recent_egv_data() |
167 | if r is None: | 175 | if now is None: |
168 | connected(True) | ||
169 | if HOST: | ||
170 | now = dr.ReadSystemTime() | ||
171 | send_ping(now) | ||
172 | sleep_verbose(10) | ||
173 | elif r is False: | ||
174 | connected(False) | 176 | connected(False) |
175 | sleep_verbose(10) | 177 | sleep_verbose(10) |
178 | elif r is None: | ||
179 | connected(True) | ||
180 | send_ping(now) | ||
181 | sleep_verbose(10) | ||
176 | else: | 182 | else: |
177 | now = dr.ReadSystemTime() | 183 | connected(True) |
178 | print_cgm_bg(now, r) | 184 | print_cgm_bg(now, r) |
179 | next_reading = (r.system_time - now + timedelta(minutes=5, seconds=2)).total_seconds() | 185 | next_reading = (r.system_time - now + timedelta(minutes=5, seconds=2)).total_seconds() |
180 | if (next_reading > 0): | 186 | if (next_reading > 0): |
181 | sleep_verbose(next_reading) | 187 | sleep_verbose(next_reading) |
182 | 188 | ||
183 | def since(when, rectype='EGV_DATA'): | 189 | def since(when, rectype): |
184 | return reversed(list(takewhile(lambda r: r.system_time > when, dr.iter_records(rectype)))) | 190 | filt = lambda r: (r.system_time > when) if when else True |
191 | return reversed(list(takewhile(filt, dr.iter_records(rectype)))) | ||
185 | 192 | ||
186 | def parsetime(s): | 193 | def parsetime(s): |
187 | return datetime.strptime(s, "%Y-%m-%dT%H:%M:%SZ") | 194 | return datetime.strptime(s, "%Y-%m-%dT%H:%M:%SZ") |
188 | 195 | ||
189 | def test(): | 196 | def remote_update(rectype): |
190 | now = dr.ReadSystemTime() | 197 | requests = import_requests() |
191 | POST('/ping', toJSON(now)) | 198 | url_path = '/' + rectype |
192 | 199 | ||
193 | import requests | 200 | resp = requests.get(HOST + url_path + '/1') |
194 | rectype = 'EGV_DATA' | ||
195 | resp = requests.get(HOST + '/egv_data/1') | ||
196 | resp.raise_for_status() | 201 | resp.raise_for_status() |
197 | rs = None | 202 | when = None |
198 | if len(resp.json()): | 203 | if len(resp.json()): |
199 | when = parsetime(resp.json()[0]['contents']['system_time']) | 204 | when = parsetime(resp.json()[0]['contents']['system_time']) |
200 | print when | 205 | print_verbose("Latest record on server: %s" % when.isoformat()) |
201 | rs = list(since(when, rectype)) | ||
202 | else: | ||
203 | #rs = list(reversed(list(dr.iter_records(rectype)))) | ||
204 | now = dr.ReadSystemTime() | ||
205 | when = now - timedelta(days=5) | ||
206 | rs = list(since(when, rectype)) | ||
207 | 206 | ||
208 | print len(rs) | 207 | rs = list(since(when, rectype)) |
209 | print POST('/egv_datas', toJSON(rs)) | 208 | if len(rs): |
209 | 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))) | ||
210 | 211 | ||
211 | def test0(): | 212 | def test(): |
212 | now = dr.ReadSystemTime() | 213 | remote_update('EGV_DATA') |
213 | POST('/ping', toJSON(now)) | ||
214 | 214 | ||
215 | def test0(): | ||
215 | for t in parseable_record_types(): | 216 | for t in parseable_record_types(): |
216 | rs = dr.ReadRecords(t, 1) | 217 | remote_update(t) |
217 | if not rs: | ||
218 | continue | ||
219 | r=rs[-1] | ||
220 | print toJSON([t,r]) | ||
221 | 218 | ||
222 | class JSON_Time(json.JSONEncoder): | 219 | class JSON_Time(json.JSONEncoder): |
223 | def default(self, o): | 220 | def default(self, o): |