summaryrefslogtreecommitdiff
path: root/dexcom_reader
diff options
context:
space:
mode:
authorBen West <bewest@gmail.com>2016-05-28 12:30:03 -0700
committerBen West <bewest@gmail.com>2016-05-28 12:30:03 -0700
commitea9d852533facf323f251196821c7346e743074c (patch)
tree274ce4874b577b7f7991cd1afcee664c5898e9b2 /dexcom_reader
parent30bd94ce14588b9bb73e6893d00f049b5502978a (diff)
attempt unifying G5 support, legacy cals
Try throwing in compatibility layer, if a bit hacky, for everything.
Diffstat (limited to 'dexcom_reader')
-rw-r--r--dexcom_reader/database_records.py26
-rw-r--r--dexcom_reader/readdata.py26
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
92class InsertionRecord(GenericTimestampedRecord): 92class 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
114class G5InsertionRecord (InsertionRecord):
115 FORMAT = '<3Ic10BH'
114 116
115class Calibration(GenericTimestampedRecord): 117class 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
189class LegacyCalibration (Calibration):
190 @classmethod
191 def _ClassSize(cls):
192
193 return cls.LEGACY_SIZE
194
187 195
188class SubCal (GenericTimestampedRecord): 196class 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
209class MeterRecord(GenericTimestampedRecord): 217class 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
232class G5MeterRecord (MeterRecord):
233 FORMAT = '<2IHI5BH'
224 234
225class EventRecord(GenericTimestampedRecord): 235class 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
332class 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
317class 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
327def GetDevice (port, G5=False):
328 if G5:
329 return DexcomG5(port)
330 return Dexcom(port)
313 331
314if __name__ == '__main__': 332if __name__ == '__main__':
315 Dexcom.LocateAndDownload() 333 Dexcom.LocateAndDownload()