Exemplo n.º 1
0
    def __init__(self, stream):
        raw = bytearray(stream.read(1024))
        data, crc = raw[0:1022], raw[1022:]
        computed = lib.CRC16CCITT.compute(bytearray(data))
        if lib.BangInt(crc) != computed:
            assert lib.BangInt(crc) == computed, "CRC does not match page data"

        data.reverse()
        self.data = self.eat_nulls(data)
        self.stream = io.BufferedReader(io.BytesIO(self.data))
Exemplo n.º 2
0
 def readStatus(self):
     result = self.link.sendComLink2Command(3)
     commStatus = result[0]  # 0 indicates success
     if commStatus != 0:
         log.error("readStatus: non-zero status: %02x" % commStatus)
         raise BadDeviceCommError("readStatus: non-zero status: %02x" %
                                  commStatus)
     status = result[2]
     lb, hb = result[3], result[4]
     bytesAvailable = lib.BangInt((lb, hb))
     self.status = status
     log.info('status byte: %02x' % status)
     if (status & 0x2) > 0:
         log.info('STATUS: receive in progress!')
     if (status & 0x4) > 0:
         log.info('STATUS: transmit in progress!')
     if (status & 0x8) > 0:
         log.info('STATUS: interface error!')
     if (status & 0x10) > 0:
         log.info('STATUS: recieve overflow!')
     if (status & 0x20) > 0:
         log.info('STATUS: transmit overflow!')
     assert commStatus == 0
     if (status & 0x1) > 0:
         return bytesAvailable
     return 0
Exemplo n.º 3
0
 def decode(self):
   self.parse_time( )
   dose = {
            'amount': self.head[2]/10.0,
            'programmed': self.head[1]/10.0,
            'duration': self.head[3] * 30,
            'type': self.head[3] > 0 and 'square' or 'normal'
          }
   if self.larger:
     duration = self.head[7] * 30
     dose = { 'amount': lib.BangInt(self.head[3:5])/40.0,
              'programmed':  lib.BangInt(self.head[1:3])/40.0,
              'unabsorbed': lib.BangInt(self.head[5:7])/40.0,
              'duration': duration,
              'type': duration > 0 and 'square' or 'normal',
            }
   return dose
Exemplo n.º 4
0
  def decode(self):
    self.parse_time( )
    bg = lib.BangInt([ self.body[1] & 0x0f, self.head[1] ])
    carb_input = int(self.body[0])
    # XXX: I have no idea if this is correct; it seems to produce correct results.
    correction = ( twos_comp( self.body[7], 8 )
                 + twos_comp( self.body[5] & 0x0f, 8 ) ) / 10.0
    wizard = { 'bg': bg, 'carb_input': carb_input,
               'carb_ratio': int(self.body[2]),
               'sensitivity': int(self.body[3]),
               'bg_target_low': int(self.body[4]),
               'bg_target_high': int(self.body[12]),
               'bolus_estimate': int(self.body[11])/10.0,
               'food_estimate': int(self.body[6])/10.0,
               'unabsorbed_insulin_total': int(self.body[9])/10.0,
               'unabsorbed_insulin_count': '??',
               'correction_estimate': correction,
               '_byte[5]': self.body[5],
               '_byte[7]': int(self.body[7]), #
               'unknown_byte[8]': self.body[8],
               'unknown_byte[10]': self.body[10],
               # '??': '??',
               # 'unabsorbed_insulin_total': int(self.body[9])/10.0,
               # 'food_estimate': int(self.body[0]),
             }

    if self.larger:
      # correction = ( twos_comp( self.body[6], (self.body[9] & 0x38) << 5 ) ) / 40.0
      bg = ((self.body[1] & 0x03) << 8) + self.head[1]
      carb_input = ((self.body[1] & 0x0c) << 6) + self.body[0]
      carb_ratio = (((self.body[2] & 0x07) << 8) + self.body[3]) / 10.0
      # xxx: not sure about this
      # https://github.com/ps2/minimed_rf/blob/master/lib/minimed_rf/log_entries/bolus_wizard.rb#L102
      sensitivity = int(self.body[4])
      wizard = { 'bg': bg, 'carb_input': carb_input,
                 'carb_ratio': carb_ratio,
                 'sensitivity': sensitivity,
                 'bg_target_low': int(self.body[5]),
                 'bg_target_high': int(self.body[14]),
                 # 'bolus_estimate': int(self.body[13])/40.0,

                 'correction_estimate': (((self.body[9] & 0x38) << 5) + self.body[6]) / 40.0,
                 # 'correction_maybe_estimate': correction,

                 'food_estimate': insulin_decode(self.body[7], self.body[8]),
                 'unabsorbed_insulin_total': insulin_decode(self.body[10], self.body[11]),
                 'bolus_estimate': insulin_decode(self.body[12], self.body[13]),
                 # 'unknown_bytes': map(int, list(self.body)),
               }

    if self.MMOL_DEFAULT:
      for key in [ 'bg', 'bg_target_high', 'bg_target_low', 'sensitivity' ]:
        wizard[key] = wizard[key] / 10.0
    return wizard
Exemplo n.º 5
0
    def __init__(self, stream, larger=False):
        raw = bytearray(stream.read(1024))
        data, crc = raw[0:1022], raw[1022:]
        computed = lib.CRC16CCITT.compute(bytearray(data))
        self.larger = larger
        if lib.BangInt(crc) != computed:
            raise DataTransferCorruptionError("CRC does not match page data")

        data.reverse()
        self.data = self.eat_nulls(data)
        self.stream = io.BufferedReader(io.BytesIO(self.data))
Exemplo n.º 6
0
    def readDeviceDataIO(self):
        results = self.readData()
        lb, hb = results[5] & 0x7F, results[6]
        self.eod = (results[5] & 0x80) > 0
        resLength = lib.BangInt((lb, hb))
        log.info('XXX resLength: %s' % resLength)
        #assert resLength < 64, ("cmd low byte count:\n%s" % lib.hexdump(results))

        data = results[13:13 + resLength]
        assert len(data) == resLength
        crc = results[-1]
        # crc check
        log.info('readDeviceDataIO:msgCRC:%r:expectedCRC:%r:data:%s' %
                 (crc, CRC8(data), lib.hexdump(data)))
        assert crc == CRC8(data)
        return data
Exemplo n.º 7
0
    def decode(self):
        self.parse_time()
        bg = lib.BangInt([self.body[1] & 0x0f, self.head[1]])
        carb_input = int(self.body[0])
        # XXX: I have no idea if this is correct; it seems to produce correct results.
        correction = (twos_comp(self.body[7], 8) +
                      twos_comp(self.body[5] & 0x0f, 8)) / 10.0
        wizard = {
            'bg': bg,
            'carb_input': carb_input,
            'carb_ratio': int(self.body[2]),
            'sensitivity': int(self.body[3]),
            'bg_target_low': int(self.body[4]),
            'bg_target_high': int(self.body[12]),
            'bolus_estimate': int(self.body[11]) / 10.0,
            'food_estimate': int(self.body[6]) / 10.0,
            'unabsorbed_insulin_total': int(self.body[9]) / 10.0,
            'unabsorbed_insulin_count': '??',
            'correction_estimate': correction,
            '_byte[5]': self.body[5],
            '_byte[7]': int(self.body[7]),  #
            'unknown_byte[8]': self.body[8],
            'unknown_byte[10]': self.body[10],
            # '??': '??',
            # 'unabsorbed_insulin_total': int(self.body[9])/10.0,
            # 'food_estimate': int(self.body[0]),
        }

        if self.larger:
            correction = (twos_comp(self.body[6], 8)) / 40.0
            wizard = {
                'bg': bg,
                'carb_input': carb_input,
                'carb_ratio': int(self.body[14]) / 10.0,
                'sensitivity': int(self.body[4]),
                'bg_target_low': int(self.body[5]),
                'bg_target_high': int(self.body[3]),
                'bolus_estimate': int(self.body[13]) / 40.0,

                # 'correction_estimate': int(self.body[6])/40.0,
                'correction_estimate': correction,
                'food_estimate': int(self.body[8]) / 40.0,
                'unabsorbed_insulin_total': int(self.body[11]) / 40.0,
                # 'unknown_bytes': map(int, list(self.body)),
            }

        return wizard
Exemplo n.º 8
0
  def decode (self):
    """
      XXX: buggy code

        * fails to acknowledge gaps in time
        * fails to acknowledge SensorSync
    """
    records = [ ]
    prefix_records = []
    for B in iter(lambda: self.stream.read(1), ""):
      B = bytearray(B)
      record = self.suggest(B[0])
      record['_tell'] = self.stream.tell( )
      # read packet if needed
      if not record is None and record['packet_size'] > 0:
        raw_packet = bytearray(self.stream.read(record['packet_size']))

      if record['name'] == 'DataEnd':
        prefix_records.append(record)
        continue
      
      elif record['name'] == 'GlucoseSensorData' or record['name'] == 'SensorWeakSignal' \
        or record['name'] == 'SensorCal' or record['name'] == '19-Something':
        # add to prefixed records to add to the next sensor minute timestamped record
        if record['name'] == 'SensorCal':
          record.update(raw=self.byte_to_str(raw_packet))
          if int(raw_packet[0]) == 1:
            record.update(waiting='waiting')
          else:
            record.update(waiting='meter_bg_now')
        prefix_records.append(record)

      elif record['name'] == 'SensorTimestamp' or record['name'] == 'SensorCalFactor' or record['name'] in ['10-Something' ]:
        # TODO: maybe this is like a ResetGlucose base command
        # these are sensor minute timestamped records thus create the record
        # and map prefixed elements based on the timedelta
        record.update(raw=self.byte_to_str(raw_packet))
        date, body = raw_packet[:4], raw_packet[4:]  
        date.reverse()
        date = parse_date(date)
        if date:
          record.update(date=date.isoformat())
        else:
          print "@@@", self.stream.tell( )
          pprint(dict(raw=hexlify(raw_packet)))
          pprint(dict(date=hexlify(date or bytearray( ))))
          pprint(dict(body=hexlify(body)))
          break
        prefix_records.reverse()
        mapped_glucose_records = self.map_glucose(prefix_records, start=date, delta=self.delta_ago(reverse=True))
        mapped_glucose_records.reverse()
        # And this ResetGlucose has a payload indicating calibration factor
        # Update sensor cal factor
        if record['name'] == 'SensorCalFactor': 
          factor = lib.BangInt([ body[0], body[1] ]) / 1000.0
          record.update(factor=factor) 
        records.extend(mapped_glucose_records)
        records.append(record)
        prefix_records = []


      elif record['name'] in ['SensorStatus', 'DateTimeChange', 'SensorSync', '10-Something', 'CalBGForGH', 'BatteryChange' ]:
        # independent record => parse and add to records list
        record.update(raw=self.byte_to_str(raw_packet))
        if record['name'] in ['SensorStatus', 'SensorSync', 'CalBGForGH', 'BatteryChange', 'DateTimeChange']:
          date, body = raw_packet[:4], raw_packet[4:]
          date.reverse()
          date = parse_date(date)
          if date is not None:
            record.update(date=date.isoformat())
          else:
            record.update(_date=str(raw_packet[:4]).encode('hex'))
          record.update(body=self.byte_to_str(body))
          # Update cal amount
          if record['name'] == 'DateTimeChange':
            """
            changed = body[1:5]
            changed.reverse( )
            changed = parse_date(changed)
            record.update(change=changed.isoformat( ), body=self.byte_to_str(body[5:]))
            """
          if record['name'] == 'CalBGForGH':
            amount = lib.BangInt([ (raw_packet[2] & 0b00100000) >> 5, body[0] ])
            record.update(body=self.byte_to_str(body))
            record.update(amount=amount)
        records.append(record)
      else:
        # could not decode
        records.append(record)
      # End For  
    records.reverse()
    self.records = records
    return self.records
Exemplo n.º 9
0
    def decode(self):
        self.parse_time()
        year_bits = extra_year_bits(self.date[4])

        return {'amount': int(lib.BangInt([year_bits[0], self.head[1]]))}
        pass
Exemplo n.º 10
0
    def decode(self):
        """
      XXX: buggy code

        * fails to acknowledge gaps in time
        * fails to acknowledge SensorSync
    """
        records = []
        prefix_records = []
        for B in iter(lambda: self.stream.read(1), ""):
            B = bytearray(B)
            record = self.suggest(B[0])
            # read packet if needed
            if not record is None and record['packet_size'] > 0:
                raw_packet = bytearray(self.stream.read(record['packet_size']))

            if record['name'] == 'DataEnd':
                prefix_records.append(record)
                continue

            elif record['name'] == 'GlucoseSensorData' or record['name'] == 'SensorWeakSignal' \
              or record['name'] == 'SensorCal' or record['name'] == '19-Something':
                # add to prefixed records to add to the next sensor minute timestamped record
                if record['name'] == 'SensorCal':
                    record.update(raw=self.byte_to_str(raw_packet))
                    if int(raw_packet[0]) == 1:
                        record.update(waiting='waiting')
                    else:
                        record.update(waiting='meter_bg_now')
                prefix_records.append(record)

            elif record['name'] == 'SensorTimestamp' or record[
                    'name'] == 'SensorCalFactor':
                # TODO: maybe this is like a ResetGlucose base command
                # these are sensor minute timestamped records thus create the record
                # and map prefixed elements based on the timedelta
                record.update(raw=self.byte_to_str(raw_packet))
                date, body = raw_packet[:4], raw_packet[4:]
                date.reverse()
                date = parse_date(date)
                record.update(date=date.isoformat())
                prefix_records.reverse()
                mapped_glucose_records = self.map_glucose(
                    prefix_records,
                    start=date,
                    delta=self.delta_ago(reverse=True))
                #       mapped_glucose_records.reverse()
                # And this ResetGlucose has a payload indicating calibration factor
                # Update sensor cal factor
                if record['name'] == 'SensorCalFactor':
                    factor = lib.BangInt([body[0], body[1]]) / 1000.0
                    record.update(factor=factor)
                records.append(mapped_glucose_records)
                records.append(record)
                prefix_records = []

            elif record['name'] == 'SensorStatus' or record['name'] == 'DateTimeChange' \
              or record['name'] == 'SensorSync' or record['name'] == '10-Something' \
              or record['name'] == 'CalBGForGH' :
                # independent record => parse and add to records list
                record.update(raw=self.byte_to_str(raw_packet))
                if record['name'] == 'SensorStatus' or record['name'] == 'SensorSync'\
                or record['name'] == 'CalBGForGH' :
                    date, body = raw_packet[:4], raw_packet[4:]
                    date.reverse()
                    date = parse_date(date)
                    record.update(date=date.isoformat())
                    record.update(body=self.byte_to_str(body))
                    # Update cal amount
                    if record['name'] == 'CalBGForGH':
                        amount = int(body[0])
                        if amount < 32:
                            amount = 0x100 + amount
                        record.update(body=self.byte_to_str(body))
                        record.update(amount=amount)
                records.append(record)
            else:
                # could not decode
                records.append(record)
            # End For
        records.reverse()
        self.records = records
        return self.records