import crc16 import constants import struct import util import binascii class BaseDatabaseRecord(object): FORMAT = None @classmethod def _CheckFormat(cls): if cls.FORMAT is None or not cls.FORMAT: raise NotImplementedError("Subclasses of %s need to define FORMAT" % cls.__name__) @classmethod def _ClassFormat(cls): cls._CheckFormat() return struct.Struct(cls.FORMAT) @classmethod def _ClassSize(cls): return cls._ClassFormat().size @property def FMT(self): self._CheckFormat() return _ClassFormat() @property def SIZE(self): return self._ClassSize() @property def crc(self): return self.data[-1] def __init__(self, data, raw_data): self.raw_data = raw_data self.data = data self.check_crc() def check_crc(self): local_crc = self.calculate_crc() if local_crc != self.crc: raise constants.CrcError('Could not parse %s' % self.__class__.__name__) def dump(self): return ''.join('\\x%02x' % ord(c) for c in self.raw_data) def calculate_crc(self): return crc16.crc16(self.raw_data[:-2]) @classmethod def Create(cls, data, record_counter): offset = record_counter * cls._ClassSize() raw_data = data[offset:offset + cls._ClassSize()] unpacked_data = cls._ClassFormat().unpack(raw_data) return cls(unpacked_data, raw_data) class GenericTimestampedRecord(BaseDatabaseRecord): FIELDS = [ ] BASE_FIELDS = [ 'system_time', 'display_time' ] @property def system_time(self): return util.ReceiverTimeToTime(self.data[0]) @property def display_time(self): return util.ReceiverTimeToTime(self.data[1]) def to_dict (self): d = dict( ) for k in self.BASE_FIELDS + self.FIELDS: d[k] = getattr(self, k) if callable(getattr(d[k], 'isoformat', None)): d[k] = d[k].isoformat( ) return d class GenericXMLRecord(GenericTimestampedRecord): FORMAT = '> 4 def __repr__(self): if self.is_special: return '%s: %s' % (self.display_time, self.glucose_special_meaning) else: return '%s: CGM BG:%s (%s) DO:%s' % (self.display_time, self.glucose, self.trend_arrow, self.display_only) class G5EGVRecord (EGVRecord): FORMAT = '<2IHBBBBBBBBBcBH' @property def full_trend(self): return self.data[12]