summaryrefslogtreecommitdiff
path: root/dexcom_reader
diff options
context:
space:
mode:
authorBen West <bewest@gmail.com>2016-05-28 11:22:52 -0700
committerBen West <bewest@gmail.com>2016-05-28 11:22:52 -0700
commitcf10d70fe0c724286d6e84c869d63eefd077e331 (patch)
tree10c8bc446b74833076b213eabeed154486399ea0 /dexcom_reader
parentff9e632209317d1c16ceb3d78f77c244504be474 (diff)
support fetching cal_set
Many thanks to @LorelaiL for putting up with some my remedial questions.
Diffstat (limited to 'dexcom_reader')
-rw-r--r--dexcom_reader/database_records.py90
-rw-r--r--dexcom_reader/readdata.py4
2 files changed, 91 insertions, 3 deletions
diff --git a/dexcom_reader/database_records.py b/dexcom_reader/database_records.py
index 8d471f4..6d5b37b 100644
--- a/dexcom_reader/database_records.py
+++ b/dexcom_reader/database_records.py
@@ -111,13 +111,99 @@ class InsertionRecord(GenericTimestampedRecord):
111 111
112 112
113class Calibration(GenericTimestampedRecord): 113class Calibration(GenericTimestampedRecord):
114 FORMAT = '<2Iddd3cdb'
115 # CAL_FORMAT = '<2Iddd3cdb'
116 FIELDS = [ 'slope', 'intercept', 'scale', 'decay', 'numsub', 'raw' ]
114 @property 117 @property
115 def raw(self): 118 def raw (self):
116 return binascii.hexlify(bytearray(self.data)) 119 return binascii.hexlify(self.raw_data)
120 @property
121 def slope (self):
122 return self.data[2]
123 @property
124 def intercept (self):
125 return self.data[3]
126 @property
127 def scale (self):
128 return self.data[4]
129 @property
130 def decay (self):
131 return self.data[8]
132 @property
133 def numsub (self):
134 return int(self.data[9])
117 135
118 def __repr__(self): 136 def __repr__(self):
119 return '%s: CAL SET:%s' % (self.display_time, self.raw) 137 return '%s: CAL SET:%s' % (self.display_time, self.raw)
120 138
139 LEGACY_SIZE = 148
140 REV_2_SIZE = 249
141 @classmethod
142 def _ClassSize(cls):
143
144 return cls.REV_2_SIZE
145
146 @classmethod
147 def Create(cls, data, record_counter):
148 offset = record_counter * cls._ClassSize()
149 cal_size = struct.calcsize(cls.FORMAT)
150 raw_data = data[offset:offset + cls._ClassSize()]
151
152 cal_data = data[offset:offset + cal_size]
153 unpacked_data = cls._ClassFormat().unpack(cal_data)
154 return cls(unpacked_data, raw_data)
155
156 def __init__ (self, data, raw_data):
157 self.page_data = raw_data
158 self.raw_data = raw_data
159 self.data = data
160 subsize = struct.calcsize(SubCal.FORMAT)
161 offset = self.numsub * subsize
162 calsize = struct.calcsize(self.FORMAT)
163 caldata = raw_data[:calsize]
164 subdata = raw_data[calsize:calsize + offset]
165 crcdata = raw_data[calsize+offset:calsize+offset+2]
166
167 subcals = [ ]
168 for i in xrange(self.numsub):
169 offset = i * subsize
170 raw_sub = subdata[offset:offset+subsize]
171 sub = SubCal(raw_sub, self.data[1])
172 subcals.append(sub)
173
174 self.subcals = subcals
175
176 self.check_crc()
177 def to_dict (self):
178 res = super(Calibration, self).to_dict( )
179 res['subrecords'] = [ sub.to_dict( ) for sub in self.subcals ]
180 return res
181 @property
182 def crc(self):
183 return struct.unpack('H', self.raw_data[-2:])[0]
184
185
186class SubCal (GenericTimestampedRecord):
187 FORMAT = '<IIIIc'
188 BASE_FIELDS = [ ]
189 FIELDS = [ 'entered', 'meter', 'sensor', 'applied', ]
190 def __init__ (self, raw_data, displayOffset=None):
191 self.raw_data = raw_data
192 self.data = self._ClassFormat().unpack(raw_data)
193 self.displayOffset = displayOffset
194 @property
195 def entered (self):
196 return util.ReceiverTimeToTime(self.data[0])
197 @property
198 def meter (self):
199 return int(self.data[1])
200 @property
201 def sensor (self):
202 return int(self.data[2])
203 @property
204 def applied (self):
205 return util.ReceiverTimeToTime(self.data[3])
206
121class MeterRecord(GenericTimestampedRecord): 207class MeterRecord(GenericTimestampedRecord):
122 FORMAT = '<2IHIH' 208 FORMAT = '<2IHIH'
123 FIELDS = ['meter_glucose', 'meter_time' ] 209 FIELDS = ['meter_glucose', 'meter_time' ]
diff --git a/dexcom_reader/readdata.py b/dexcom_reader/readdata.py
index cc02de3..5e91499 100644
--- a/dexcom_reader/readdata.py
+++ b/dexcom_reader/readdata.py
@@ -251,7 +251,7 @@ class Dexcom(object):
251 assert ord(packet.command) == 1 251 assert ord(packet.command) == 1
252 # first index (uint), numrec (uint), record_type (byte), revision (byte), 252 # first index (uint), numrec (uint), record_type (byte), revision (byte),
253 # page# (uint), r1 (uint), r2 (uint), r3 (uint), ushort (Crc) 253 # page# (uint), r1 (uint), r2 (uint), r3 (uint), ushort (Crc)
254 header_format = '<2I2c4IH' 254 header_format = '<2IcB4IH'
255 header_data_len = struct.calcsize(header_format) 255 header_data_len = struct.calcsize(header_format)
256 header = struct.unpack_from(header_format, packet.data) 256 header = struct.unpack_from(header_format, packet.data)
257 header_crc = crc16.crc16(packet.data[:header_data_len-2]) 257 header_crc = crc16.crc16(packet.data[:header_data_len-2])
@@ -268,9 +268,11 @@ class Dexcom(object):
268 268
269 def ParsePage(self, header, data): 269 def ParsePage(self, header, data):
270 record_type = constants.RECORD_TYPES[ord(header[2])] 270 record_type = constants.RECORD_TYPES[ord(header[2])]
271 revision = int(header[3])
271 generic_parser_map = { 272 generic_parser_map = {
272 'USER_EVENT_DATA': database_records.EventRecord, 273 'USER_EVENT_DATA': database_records.EventRecord,
273 'METER_DATA': database_records.MeterRecord, 274 'METER_DATA': database_records.MeterRecord,
275 'CAL_SET': database_records.Calibration,
274 'INSERTION_TIME': database_records.InsertionRecord, 276 'INSERTION_TIME': database_records.InsertionRecord,
275 'EGV_DATA': database_records.EGVRecord, 277 'EGV_DATA': database_records.EGVRecord,
276 'SENSOR_DATA': database_records.SensorRecord, 278 'SENSOR_DATA': database_records.SensorRecord,