Ejemplo n.º 1
0
 def _read_parameter(self, parameter_key):
   response = self._send_message(
     _READ_PARAMETER_REQUEST + parameter_key, 4)
   if response[0:2] != b'\x03\x06':
     raise lifescan.MalformedCommand(
       'invalid response, expected 03 06, received %02x %02x' % (
         response[0], response[1]))
   return response[2:]
Ejemplo n.º 2
0
 def get_datetime(self):
   response = self._send_message(_READ_RTC_REQUEST, 3)
   if response[0:2] != b'\x04\06':
     raise lifescan.MalformedCommand(
       'invalid response, expected 04 06, received %02x %02x' % (
         response[0], response[1]))
   (timestamp,) = _STRUCT_TIMESTAMP.unpack(response[2:])
   return _convert_timestamp(timestamp)
Ejemplo n.º 3
0
  def read_from(self, serial):
    self.cmd.extend(serial.read(3))

    if self.cmd[_IDX_STX] != _STX:
      raise lifescan.MalformedCommand(
        'at position %s expected %02x, received %02x' % (
          _IDX_STX, _STX, self.cmd[_IDX_STX]))

    # the length includes prelude and appendix, which are six bytes total.
    if self.length > 6:
      self.cmd.extend(serial.read(self.length - 6))

    self.cmd.extend(serial.read(3))

    if self.cmd[_IDX_ETX] != _ETX:
      raise lifescan.MalformedCommand(
        'at position %s expected %02x, received %02x' % (
          _IDX_ETX, _ETX, self.cmd[_IDX_ETX]))
Ejemplo n.º 4
0
  def _get_reading_count(self):
    response = self._send_message(_READ_RECORD_COUNT_REQUEST, 3)
    if response[0:2] != b'\x04\06':
      raise lifescan.MalformedCommand(
        'invalid response, expected 04 06, received %02x %02x' % (
          response[0], response[1]))

    (record_count,) = _STRUCT_RECORDID.unpack(response[2:])
    return record_count
Ejemplo n.º 5
0
 def _query_string(self, query_key):
   response = self._send_message(_QUERY_REQUEST + query_key, 3)
   if response[0:2] != b'\x04\06':
     raise lifescan.MalformedCommand(
       'invalid response, expected 04 06, received %02x %02x' % (
         response[0], response[1]))
   # Strings are encoded in wide characters (LE), but they should
   # only contain ASCII characters. Note that the string is
   # null-terminated, so the last character should be dropped.
   return response[2:].decode('utf-16-le')[:-1]
Ejemplo n.º 6
0
    def _send_request(self, request_format, request_obj, response_format):
        try:
            request = request_format.build(request_obj)
            self._send_packet(request)

            response_pkt = self._read_packet()

            return response_format.parse(response_pkt.message)
        except construct.ConstructError as e:
            raise lifescan.MalformedCommand(str(e))
Ejemplo n.º 7
0
  def get_glucose_unit(self):
    result = self._send_command(_READ_GLUCOSE_UNIT)
    response = self._read_response()

    if response.data[2] == 0:
      return common.UNIT_MGDL
    elif response.data[2] == 1:
      return common.UNIT_MMOLL
    else:
      raise lifescan.MalformedCommand(
        'at position PM1 invalid value %02x for unit' % response.data[2])
Ejemplo n.º 8
0
def _extract_message(register):
    """Parse the message preamble and verify checksums."""
    stx, length = _STRUCT_PREAMBLE.unpack_from(register)
    if stx != _STX:
        raise lifescan.MalformedCommand('invalid STX byte: %02x' % stx)
    if length > _REGISTER_SIZE:
        raise lifescan.MalformedCommand('invalid length: %d > REGISTER_SIZE' %
                                        length)

    # 2 is the length of the checksum, so it should be ignored.
    calculated_checksum = lifescan.crc_ccitt(register[:(length - 2)])

    coda_offset = length - _STRUCT_CODA.size
    etx, encoded_checksum = _STRUCT_CODA.unpack_from(register[coda_offset:])
    if etx != _ETX:
        raise lifescan.MalformedCommand('invalid ETX byte: %02x' % etx)
    if encoded_checksum != calculated_checksum:
        raise exceptions.InvalidChecksum(encoded_checksum, calculated_checksum)

    response = register[_STRUCT_PREAMBLE.size:coda_offset]
    return response
Ejemplo n.º 9
0
    def _read_packet(self) -> construct.Container:
        raw_pkt = self.buffered_reader_.parse_stream(self.serial_).data
        logging.debug("received packet: %r", raw_pkt)

        # discard the checksum and copy
        pkt = raw_pkt.value

        if not pkt.link_control.disconnect and (
                pkt.link_control.sequence_number != self.expect_receive_):
            raise lifescan.MalformedCommand(
                f"at position 2[0b] expected {self.expect_receive_:02x}, received {pkt.link_connect.sequence_count:02x}"
            )

        return pkt
Ejemplo n.º 10
0
    def _read_packet(self):
        raw_pkt = self.buffered_reader_.parse_stream(self.serial_).data
        logging.debug('received packet: %r', raw_pkt)

        # discard the checksum and copy
        pkt = raw_pkt.value

        if not pkt.link_control.disconnect and (
                pkt.link_control.sequence_number != self.expect_receive_):
            raise lifescan.MalformedCommand(
                'at position 2[0b] expected %02x, received %02x' %
                (self.expect_receive_, pkt.link_connect.sequence_count))

        return pkt
Ejemplo n.º 11
0
    def _send_request(
        self,
        request_format: construct.struct,
        request_obj: Optional[Dict[str, Any]],
        response_format: construct.Struct,
    ) -> construct.Container:
        try:
            request = request_format.build(request_obj)
            self._send_packet(request)

            response_pkt = self._read_packet()

            return response_format.parse(response_pkt.message)
        except construct.ConstructError as e:
            raise lifescan.MalformedCommand(str(e))
Ejemplo n.º 12
0
  def _get_reading(self, record_number):
    request = (_READ_RECORD_REQUEST_PREFIX +
               _STRUCT_RECORDID.pack(record_number) +
               _READ_RECORD_REQUEST_SUFFIX)
    response = self._send_message(request, 3)
    if response[0:2] != b'\x04\06':
      raise lifescan.MalformedCommand(
        'invalid response, expected 04 06, received %02x %02x' % (
          response[0], response[1]))

    (unused_const1, unused_const2, unused_counter, unused_const3,
     unused_counter2, timestamp, value, unused_flags, unused_const4,
     unused_const5) = _STRUCT_RECORD.unpack(response)

    return common.Reading(_convert_timestamp(timestamp), float(value))
Ejemplo n.º 13
0
    def _send_request(
        self,
        lba: int,
        request_format: construct.Struct,
        request_obj: Optional[Dict[str, Any]],
        response_format: construct.Struct,
    ) -> construct.Container:
        """Send a request to the meter, and read its response.

        Args:
          lba: the address of the block register to use, known
            valid addresses are 3, 4 and 5.
          request_format: a construct format identifier of the request to send
          request_obj: the object to format with the provided identifier
          response_format: a construct format identifier to parse the returned
            message with.

        Returns:
          The Container object parsed from the response received by the meter.

        Raises:
          lifescan.MalformedCommand if Construct fails to build the request or
            parse the response.

        """
        try:
            request = request_format.build(request_obj)
            request_raw = _PACKET.build(
                {"data": {
                    "value": {
                        "message": request
                    }
                }})
            logging.debug("Request sent: %s", binascii.hexlify(request_raw))
            self.scsi_.write10(lba, 1, request_raw)

            response_raw = self.scsi_.read10(lba, 1)
            logging.debug("Response received: %s",
                          binascii.hexlify(response_raw.datain))
            response_pkt = _PACKET.parse(response_raw.datain).data
            logging.debug("Response packet: %r", response_pkt)

            response = response_format.parse(response_pkt.value.message)
            logging.debug("Response parsed: %r", response)

            return response
        except construct.ConstructError as e:
            raise lifescan.MalformedCommand(str(e))
Ejemplo n.º 14
0
  def set_datetime(self, date=datetime.datetime.now()):
    epoch = datetime.datetime.utcfromtimestamp(_EPOCH_BASE)
    delta = date - epoch
    timestamp = int(delta.total_seconds())

    timestamp_bytes = _STRUCT_TIMESTAMP.pack(timestamp)
    response = self._send_message(_WRITE_RTC_REQUEST + timestamp_bytes, 3)

    if response[0:2] != b'\x04\06':
      raise lifescan.MalformedCommand(
        'invalid response, expected 04 06, received %02x %02x' % (
          response[0], response[1]))

    # The device does not return the new datetime, so confirm by
    # calling READ RTC again.
    return self.get_datetime()
Ejemplo n.º 15
0
    def _send_request(self, request_format, request_obj, response_format):
        try:
            request = request_format.build(request_obj)
            self._send_packet(request, acknowledge=False, disconnect=False)

            self.sent_counter_ = not self.sent_counter_
            self._read_ack()

            response_pkt = self._read_packet()
            assert not response_pkt.link_control.acknowledge

            self.expect_receive_ = not self.expect_receive_
            self._send_ack()

            return response_format.parse(response_pkt.message)
        except construct.ConstructError as e:
            raise lifescan.MalformedCommand(str(e))
Ejemplo n.º 16
0
  def _read_response(self):
    response = _Packet()

    response.read_from(self.serial_)

    if not response.disconnect and response.sent_counter != self.expect_receive_:
      raise lifescan.MalformedCommand(
        'at position 2[0b] expected %02x, received %02x' % (
          self.expect_receive_, response.expect_receive))

    if not response.acknowledge:
      self.expect_receive_ = not self.expect_receive_

    response.validate_checksum()

    if not response.acknowledge:
      self._send_command('', acknowledge=True)

    return response
Ejemplo n.º 17
0
 def zero_log(self):
   response = self._send_message(_MEMORY_ERASE_REQUEST, 3)
   if response[0:2] != b'\x04\06':
     raise lifescan.MalformedCommand(
       'invalid response, expected 04 06, received %02x %02x' % (
         response[0], response[1]))
Ejemplo n.º 18
0
 def connect(self):
     try:
         self._send_packet(b'', disconnect=True)
         self._read_ack()
     except construct.ConstructError as e:
         raise lifescan.MalformedCommand(str(e))