diff options
author | Ben West <bewest@gmail.com> | 2016-05-28 12:30:03 -0700 |
---|---|---|
committer | Ben West <bewest@gmail.com> | 2016-05-28 12:30:03 -0700 |
commit | ea9d852533facf323f251196821c7346e743074c (patch) | |
tree | 274ce4874b577b7f7991cd1afcee664c5898e9b2 | |
parent | 30bd94ce14588b9bb73e6893d00f049b5502978a (diff) |
attempt unifying G5 support, legacy cals
Try throwing in compatibility layer, if a bit hacky, for everything.
-rw-r--r-- | dexcom_reader/database_records.py | 26 | ||||
-rw-r--r-- | dexcom_reader/readdata.py | 26 |
2 files changed, 44 insertions, 8 deletions
diff --git a/dexcom_reader/database_records.py b/dexcom_reader/database_records.py index 3812573..9274d24 100644 --- a/dexcom_reader/database_records.py +++ b/dexcom_reader/database_records.py | |||
@@ -91,7 +91,7 @@ class GenericXMLRecord(GenericTimestampedRecord): | |||
91 | 91 | ||
92 | class InsertionRecord(GenericTimestampedRecord): | 92 | class InsertionRecord(GenericTimestampedRecord): |
93 | FIELDS = ['insertion_time', 'session_state'] | 93 | FIELDS = ['insertion_time', 'session_state'] |
94 | FORMAT = '<3Ic10BH' | 94 | FORMAT = '<3IcH' |
95 | 95 | ||
96 | @property | 96 | @property |
97 | def insertion_time(self): | 97 | def insertion_time(self): |
@@ -111,6 +111,8 @@ class InsertionRecord(GenericTimestampedRecord): | |||
111 | def __repr__(self): | 111 | def __repr__(self): |
112 | return '%s: state=%s' % (self.display_time, self.session_state) | 112 | return '%s: state=%s' % (self.display_time, self.session_state) |
113 | 113 | ||
114 | class G5InsertionRecord (InsertionRecord): | ||
115 | FORMAT = '<3Ic10BH' | ||
114 | 116 | ||
115 | class Calibration(GenericTimestampedRecord): | 117 | class Calibration(GenericTimestampedRecord): |
116 | FORMAT = '<2Iddd3cdb' | 118 | FORMAT = '<2Iddd3cdb' |
@@ -184,6 +186,12 @@ class Calibration(GenericTimestampedRecord): | |||
184 | def crc(self): | 186 | def crc(self): |
185 | return struct.unpack('H', self.raw_data[-2:])[0] | 187 | return struct.unpack('H', self.raw_data[-2:])[0] |
186 | 188 | ||
189 | class LegacyCalibration (Calibration): | ||
190 | @classmethod | ||
191 | def _ClassSize(cls): | ||
192 | |||
193 | return cls.LEGACY_SIZE | ||
194 | |||
187 | 195 | ||
188 | class SubCal (GenericTimestampedRecord): | 196 | class SubCal (GenericTimestampedRecord): |
189 | FORMAT = '<IIIIc' | 197 | FORMAT = '<IIIIc' |
@@ -207,7 +215,7 @@ class SubCal (GenericTimestampedRecord): | |||
207 | return util.ReceiverTimeToTime(self.data[3]) | 215 | return util.ReceiverTimeToTime(self.data[3]) |
208 | 216 | ||
209 | class MeterRecord(GenericTimestampedRecord): | 217 | class MeterRecord(GenericTimestampedRecord): |
210 | FORMAT = '<2IHI5BH' | 218 | FORMAT = '<2IHIH' |
211 | FIELDS = ['meter_glucose', 'meter_time' ] | 219 | FIELDS = ['meter_glucose', 'meter_time' ] |
212 | 220 | ||
213 | @property | 221 | @property |
@@ -221,6 +229,8 @@ class MeterRecord(GenericTimestampedRecord): | |||
221 | def __repr__(self): | 229 | def __repr__(self): |
222 | return '%s: Meter BG:%s' % (self.display_time, self.meter_glucose) | 230 | return '%s: Meter BG:%s' % (self.display_time, self.meter_glucose) |
223 | 231 | ||
232 | class G5MeterRecord (MeterRecord): | ||
233 | FORMAT = '<2IHI5BH' | ||
224 | 234 | ||
225 | class EventRecord(GenericTimestampedRecord): | 235 | class EventRecord(GenericTimestampedRecord): |
226 | # sys_time,display_time,glucose,meter_time,crc | 236 | # sys_time,display_time,glucose,meter_time,crc |
@@ -280,7 +290,7 @@ class EGVRecord(GenericTimestampedRecord): | |||
280 | # uint, uint, ushort, byte, ushort | 290 | # uint, uint, ushort, byte, ushort |
281 | # (system_seconds, display_seconds, glucose, trend_arrow, crc) | 291 | # (system_seconds, display_seconds, glucose, trend_arrow, crc) |
282 | FIELDS = ['glucose', 'trend_arrow'] | 292 | FIELDS = ['glucose', 'trend_arrow'] |
283 | FORMAT = '<2IHBBBBBBBBBcBH' | 293 | FORMAT = '<2IHcH' |
284 | 294 | ||
285 | @property | 295 | @property |
286 | def full_glucose(self): | 296 | def full_glucose(self): |
@@ -288,7 +298,7 @@ class EGVRecord(GenericTimestampedRecord): | |||
288 | 298 | ||
289 | @property | 299 | @property |
290 | def full_trend(self): | 300 | def full_trend(self): |
291 | return self.data[12] | 301 | return self.data[3] |
292 | 302 | ||
293 | @property | 303 | @property |
294 | def display_only(self): | 304 | def display_only(self): |
@@ -318,3 +328,11 @@ class EGVRecord(GenericTimestampedRecord): | |||
318 | else: | 328 | else: |
319 | return '%s: CGM BG:%s (%s) DO:%s' % (self.display_time, self.glucose, | 329 | return '%s: CGM BG:%s (%s) DO:%s' % (self.display_time, self.glucose, |
320 | self.trend_arrow, self.display_only) | 330 | self.trend_arrow, self.display_only) |
331 | |||
332 | class G5EGVRecord (EGVRecord): | ||
333 | FORMAT = '<2IHBBBBBBBBBcBH' | ||
334 | @property | ||
335 | def full_trend(self): | ||
336 | return self.data[12] | ||
337 | |||
338 | |||
diff --git a/dexcom_reader/readdata.py b/dexcom_reader/readdata.py index 5e91499..0f20e71 100644 --- a/dexcom_reader/readdata.py +++ b/dexcom_reader/readdata.py | |||
@@ -266,17 +266,21 @@ class Dexcom(object): | |||
266 | for x in xrange(header[1]): | 266 | for x in xrange(header[1]): |
267 | yield record_type.Create(data, x) | 267 | yield record_type.Create(data, x) |
268 | 268 | ||
269 | def ParsePage(self, header, data): | 269 | PARSER_MAP = { |
270 | record_type = constants.RECORD_TYPES[ord(header[2])] | ||
271 | revision = int(header[3]) | ||
272 | generic_parser_map = { | ||
273 | 'USER_EVENT_DATA': database_records.EventRecord, | 270 | 'USER_EVENT_DATA': database_records.EventRecord, |
274 | 'METER_DATA': database_records.MeterRecord, | 271 | 'METER_DATA': database_records.MeterRecord, |
275 | 'CAL_SET': database_records.Calibration, | 272 | 'CAL_SET': database_records.Calibration, |
273 | # 'CAL_SET': database_records.Calibration, | ||
276 | 'INSERTION_TIME': database_records.InsertionRecord, | 274 | 'INSERTION_TIME': database_records.InsertionRecord, |
277 | 'EGV_DATA': database_records.EGVRecord, | 275 | 'EGV_DATA': database_records.EGVRecord, |
278 | 'SENSOR_DATA': database_records.SensorRecord, | 276 | 'SENSOR_DATA': database_records.SensorRecord, |
279 | } | 277 | } |
278 | def ParsePage(self, header, data): | ||
279 | record_type = constants.RECORD_TYPES[ord(header[2])] | ||
280 | revision = int(header[3]) | ||
281 | generic_parser_map = self.PARSER_MAP | ||
282 | if revision < 2 and record_type == 'CAL_SET': | ||
283 | generic_parser_map.update(CAL_SET=database_records.LegacyCalibration) | ||
280 | xml_parsed = ['PC_SOFTWARE_PARAMETER', 'MANUFACTURING_DATA'] | 284 | xml_parsed = ['PC_SOFTWARE_PARAMETER', 'MANUFACTURING_DATA'] |
281 | if record_type in generic_parser_map: | 285 | if record_type in generic_parser_map: |
282 | return self.GenericRecordYielder(header, data, | 286 | return self.GenericRecordYielder(header, data, |
@@ -310,6 +314,20 @@ class Dexcom(object): | |||
310 | records.extend(self.ReadDatabasePage(record_type, x)) | 314 | records.extend(self.ReadDatabasePage(record_type, x)) |
311 | return records | 315 | return records |
312 | 316 | ||
317 | class DexcomG5 (Dexcom): | ||
318 | PARSER_MAP = { | ||
319 | 'USER_EVENT_DATA': database_records.EventRecord, | ||
320 | 'METER_DATA': database_records.G5MeterRecord, | ||
321 | 'CAL_SET': database_records.Calibration, | ||
322 | 'INSERTION_TIME': database_records.G5InsertionRecord, | ||
323 | 'EGV_DATA': database_records.G5EGVRecord, | ||
324 | 'SENSOR_DATA': database_records.SensorRecord, | ||
325 | } | ||
326 | |||
327 | def GetDevice (port, G5=False): | ||
328 | if G5: | ||
329 | return DexcomG5(port) | ||
330 | return Dexcom(port) | ||
313 | 331 | ||
314 | if __name__ == '__main__': | 332 | if __name__ == '__main__': |
315 | Dexcom.LocateAndDownload() | 333 | Dexcom.LocateAndDownload() |