Esempio n. 1
0
def parse_location_data_bytes(location_data_bytes):
    if len(location_data_bytes) > 0:
        location_data_content = location_data_bytes[0]
        location_data_bytes = location_data_bytes[1:]
        location_data_content_name = LOCATION_DATA_CONTENT_NAMES[
            location_data_content]
    else:
        location_data_content = None
        location_data_content_name = None
    if (location_data_content == 0 or location_data_content == 2):
        if len(location_data_bytes) < 13:
            raise ValueError(
                'Location data content byte indicated position data was included but less than 13 bytes follow'
            )
        position_bytes = location_data_bytes[:13]
        location_data_bytes = location_data_bytes[13:]
        position_data = bitstruct.unpack_dict(
            's32s32s32u8<',
            ['x_position', 'y_position', 'z_position', 'quality'],
            position_bytes)
    else:
        position_data = None
    if (location_data_content == 1 or location_data_content == 2):
        if len(location_data_bytes) < 1:
            raise ValueError(
                'Location data content byte indicated distance data was included but no bytes follow'
            )
        distance_count = location_data_bytes[0]
        location_data_bytes = location_data_bytes[1:]
        if len(location_data_bytes) < 7 * distance_count:
            raise ValueError(
                'Distance count byte indicated that {} distance values would follow so expected {} bytes but only {} bytes follow'
                .format(distance_count, 7 * distance_count,
                        len(location_data_bytes)))
        distance_data = []
        for distance_data_index in range(distance_count):
            distance_datum_bytes = location_data_bytes[:7]
            location_data_bytes = location_data_bytes[7:]
            distance_datum = bitstruct.unpack_dict(
                'u16u32u8<', ['node_id', 'distance', 'quality'],
                distance_datum_bytes)
            distance_data.append(distance_datum)
    else:
        distance_data = None
    return {
        'location_data_content': location_data_content,
        'location_data_content_name': location_data_content_name,
        'position_data': position_data,
        'distance_data': distance_data
    }
Esempio n. 2
0
def HexToCmd(hex):
    """convert the raw tlf35584 command to physical meaning."""
    unpacked = bitstruct.unpack_dict('u1u6u8u1', ['RW', 'Addr', 'Value', 'P'],
                                     bytearray.fromhex(hex))
    for k, v in unpacked.items():
        print("{:<6} {:#04x}".format(k, v))
    return unpacked
Esempio n. 3
0
    def _parse_location_data_bytes(self, location_data_bytes) -> {}:
        if len(location_data_bytes) > 0:
            location_data_content = location_data_bytes[0]
            location_data_bytes = location_data_bytes[1:]
        else:
            location_data_content = None

        if (location_data_content == 0 or location_data_content == 2):
            if len(location_data_bytes) < AMOUNT_OF_BYTES_FOR_POSITION:
                raise ValueError(
                    'Location data content byte indicated position data but less than 13 bytes follow'
                )
            position_data = bitstruct.unpack_dict(
                's32s32s32u8<', ['x', 'y', 'z', 'quality'],
                location_data_bytes[:AMOUNT_OF_BYTES_FOR_POSITION])
        else:
            position_data = None

        return {
            'location_data_content_name':
            LOCATION_DATA_CONTENT_NAMES[location_data_content]
            if location_data_content else None,
            'position_data':
            position_data
        }
Esempio n. 4
0
    def load(cls, data, xing_quality):
        encoder = data.read(9)
        if not encoder.startswith(b'LAME'):
            raise InvalidHeader('Valid LAME header not found.')

        version_match = re.search(rb'LAME(\d+)\.(\d+)', encoder)
        if version_match:
            version = tuple(int(part) for part in version_match.groups())
        else:
            version = None

        revision, bitrate_mode_ = bitstruct.unpack('u4 u4', data.read(1))
        bitrate_mode = LAMEBitrateMode(bitrate_mode_)

        # TODO: Decide what, if anything, to do with the different meanings in LAME.
        # quality = (100 - xing_quality) % 10
        # vbr_quality = (100 - xing_quality) // 10

        lowpass_filter = struct.unpack('B', data.read(1))[0] * 100

        replay_gain = LAMEReplayGain.load(data)

        flags_ath = bitstruct.unpack_dict('b1 b1 b1 b1 u4', [
            'nogap_continuation', 'nogap_continued', 'nssafejoint',
            'nspsytune', 'ath_type'
        ], data.read(1))

        ath_type = flags_ath.pop('ath_type')
        encoding_flags = LAMEEncodingFlags(flags_ath['nogap_continuation'],
                                           flags_ath['nogap_continued'],
                                           flags_ath['nssafejoint'],
                                           flags_ath['nspsytune'])

        # TODO: Different representation for VBR minimum bitrate vs CBR/ABR specified bitrate?
        # Can only go up to 255.
        bitrate = struct.unpack('B', data.read(1))[0] * 1000

        delay, padding = bitstruct.unpack('u12 u12', data.read(3))

        source_sample_rate, unwise_settings_used, channel_mode_, noise_shaping = bitstruct.unpack(
            'u2 u1 u3 u2', data.read(1))
        channel_mode = LAMEChannelMode(channel_mode_)

        mp3_gain = bitstruct.unpack('s8', data.read(1))[0]

        surround_info_, preset_used_ = bitstruct.unpack(
            'p2 u3 u11', data.read(2))
        surround_info = LAMESurroundInfo(surround_info_)

        preset = LAMEPreset(preset_used_)

        audio_size, audio_crc, lame_crc = struct.unpack('>I2s2s', data.read(8))

        return cls(lame_crc, version, revision, ath_type, audio_crc,
                   audio_size, bitrate, bitrate_mode, channel_mode, delay,
                   encoding_flags, lowpass_filter, mp3_gain, noise_shaping,
                   padding, preset, replay_gain, source_sample_rate,
                   surround_info, unwise_settings_used)
Esempio n. 5
0
def parse_operation_mode_bytes(operation_mode_bytes):
    operation_mode_data = bitstruct.unpack_dict('u1u2u1b1b1b1b1b1b1b1u4', [
        'device_type', 'uwb_mode', 'fw_version', 'accelerometer_enable',
        'led_enable', 'fw_update_enable', 'reserved_01', 'initiator',
        'low_power_mode', 'location_engine', 'reserved_02'
    ], operation_mode_bytes)
    operation_mode_data['device_type_name'] = DEVICE_TYPE_NAMES[
        operation_mode_data['device_type']]
    operation_mode_data['uwb_mode_name'] = UWB_MODE_NAMES[
        operation_mode_data['uwb_mode']]
    operation_mode_data['fw_version_name'] = FW_VERSION_NAMES[
        operation_mode_data['fw_version']]
    return operation_mode_data
Esempio n. 6
0
def parse_proxy_positions_bytes(proxy_positions_bytes):
    if len(proxy_positions_bytes) > 0:
        num_elements = proxy_positions_bytes[0]
        proxy_positions_bytes = proxy_positions_bytes[1:]
        proxy_positions_data = []
        for element_index in range(num_elements):
            position_bytes = proxy_positions_bytes[:15]
            proxy_positions_bytes = proxy_positions_bytes[15:]
            position_data = bitstruct.unpack_dict('u16s32s32s32u8<', [
                'node_id', 'x_position', 'y_position', 'z_position', 'quality'
            ], position_bytes)
            proxy_positions_data.append(position_data)
        return proxy_positions_data
    else:
        return None
Esempio n. 7
0
    def unpack(cls, packet):
        # the options field may extend into sname/file
        # so we have to extract the options into their own variable
        # TODO: check option overload option before reading options out of sname/file
        options_idx = packet.index(DHCP_OPTIONS_MAGIC_COOKIE,
                                   DHCP_CORE_HEADER_LENGTH)
        header_bytes = packet[:options_idx].rjust(DHCP_FULL_HEADER_LENGTH,
                                                  b"\x00")
        options_bytes = packet[options_idx + len(DHCP_OPTIONS_MAGIC_COOKIE):]

        params = bitstruct.unpack_dict(DHCP_STRUCT, DHCP_NAMES, header_bytes)
        options = list(DHCPOption.parse_multiple(options_bytes))

        params["chaddr"] = params["chaddr"][:params["hlen"]]
        params["sname"] = params["sname"][:params["sname"].index(b"\x00")]
        params["file"] = params["file"][:params["file"].index(b"\x00")]

        return cls(**params, options=options)
Esempio n. 8
0
    def load(cls, data):
        if data.read(3) != b"ID3":
            raise InvalidHeader("Valid ID3v2 header not found.")

        major, revision, flags_, sync_size = struct.unpack(
            'BBs4s', data.read(7))

        try:
            version = ID3Version((2, major))
        except ValueError:
            raise ValueError(f"Unsupported ID3 version (2.{major}).")

        flags = bitstruct.unpack_dict(
            'b1 b1 b1 b1',
            ['unsync', 'extended', 'experimental', 'footer', 'ath_type'],
            flags_)

        size = decode_synchsafe_int(sync_size, 7)

        return cls(size, version, flags)
Esempio n. 9
0
 def unpack(cls, bytes):
     params = bitstruct.unpack_dict(IP_HEADER_STRUCT, IP_HEADER_NAMES,
                                    bytes[:IP_HEADER_LENGTH])
     return cls(**params, data=bytes[params["ihl"] * 4:])
Esempio n. 10
0
    def load(cls, data, xing_quality):
        if not isinstance(data, DataReader):  # pragma: nocover
            data = DataReader(data)

        encoder = data.read(9)
        if not encoder.startswith(b'LAME'):
            raise InvalidHeader('Valid LAME header not found.')

        version_match = re.search(rb'LAME(\d+)\.(\d+)', encoder)
        if version_match:
            version = tuple(int(part) for part in version_match.groups())
        else:
            version = None

        revision, bitrate_mode_ = bitstruct.unpack('u4 u4', data.read(1))
        bitrate_mode = LAMEBitrateMode(bitrate_mode_)

        # TODO: Decide what, if anything, to do with the different meanings in LAME.
        # quality = (100 - xing_quality) % 10
        # vbr_quality = (100 - xing_quality) // 10

        lowpass_filter = struct.unpack('B', data.read(1))[0] * 100

        gain_data = struct.unpack('4s2s2s', data.read(8))
        track_gain = LAMEReplayGain.load(gain_data[0] + gain_data[1])
        album_gain = LAMEReplayGain.load(gain_data[0] + gain_data[2])

        flags_ath = bitstruct.unpack_dict('b1 b1 b1 b1 u4', [
            'nogap_continuation', 'nogap_continued', 'nssafejoint',
            'nspsytune', 'ath_type'
        ], data.read(1))

        encoding_flags = {
            k: v
            for k, v in flags_ath.items() if k != 'ath_type'
        }

        ath_type = flags_ath['ath_type']

        # TODO: Different representation for VBR minimum bitrate vs CBR/ABR specified bitrate?
        # Can only go up to 255.
        bitrate = struct.unpack('B', data.read(1))[0] * 1000

        delay, padding = bitstruct.unpack('u12 u12', data.read(3))

        source_sample_rate, unwise_settings_used, channel_mode_, noise_shaping = bitstruct.unpack(
            'u2 u1 u3 u2', data.read(1))
        channel_mode = LAMEChannelMode(channel_mode_)

        # lame_header_data = struct.unpack('>IHH', data.read(36))

        mp3_gain = bitstruct.unpack('s8', data.read(1))[0]
        # mp3_gain = lame_header_data[12] & 127
        # if lame_header_data[12] & 1:
        # 	mp3_gain *= -1

        surround_info_, preset_used_ = bitstruct.unpack(
            'p2 u3 u11', data.read(2))
        surround_info = LAMESurroundInfo(surround_info_)

        try:
            preset = LAMEPreset(preset_used_)
        except ValueError:  # 8-320 are used for bitrates and aren't defined in LAMEPreset.
            preset = f"{preset_used_} Kbps"

        audio_size, audio_crc, lame_crc = struct.unpack('>I2s2s', data.read(8))

        return cls(lame_crc, version, revision, album_gain, ath_type,
                   audio_crc, audio_size, bitrate, bitrate_mode, channel_mode,
                   delay, encoding_flags, lowpass_filter, mp3_gain,
                   noise_shaping, padding, preset, source_sample_rate,
                   surround_info, track_gain, unwise_settings_used)
Esempio n. 11
0
 def unpack(cls, packet):
     params = bitstruct.unpack_dict(UDP_HEADER_STRUCT, UDP_HEADER_NAMES, packet[:8])
     return cls(**params, data=packet[8:params["length"]])
Esempio n. 12
0
def parse_update_rate_bytes(update_rate_bytes):
    update_rate_data = bitstruct.unpack_dict(
        'u32u32<', ['moving_update_rate', 'stationary_update_rate'],
        update_rate_bytes)
    return update_rate_data
Esempio n. 13
0
def parse_device_info_bytes(device_info_bytes):
    device_info_data = bitstruct.unpack_dict('u64u32u32u32u32u32b1u7<', [
        'node_id', 'hw_version', 'fw1_version', 'fw2_version', 'fw1_checksum',
        'fw2_checksum', 'bridge', 'unknown'
    ], device_info_bytes)
    return device_info_data
Esempio n. 14
0
    def __init__(self, buf):
        self.rx_epoch = int(time.time())
        self.logger = logging.getLogger(__file__)
        self.adv = tuple()
        self.rsp = tuple()
        self.flags_dict = dict()
        self.bd_addr = ""
        self.name = ""
        self.adv_valid = False
        self.rsp_valid = False
        self.rsp_has_versions = False
        if (len(buf) % 2) == 0:
            b = bytes.fromhex(buf)
        else:
            b = bytes()
        self.logger.debug(f"Advertisement Length {len(buf)} -> {len(b)}")
        try:
            self.adv = namedtuple("adv", FOB_ADV_FIELDS)._make(
                struct.unpack_from(FOB_ADV_FORMAT, b))
            self.adv_valid = self._validate_ad()
            h = self.adv.bluetooth_address.hex()
            self.bd_addr = h[10:12] + h[8:10] + \
                h[6:8] + h[4:6] + h[2:4] + h[0:2]
        except:
            self.logger.info("Error in parsing advertisement")

        if self.adv_valid:
            if verbose:
                self.logger.debug(self.adv.flags)
            try:
                x = struct.pack('>H', self.adv.flags)
                if verbose:
                    self.logger.debug(x)
                self.flags_dict = bitstruct.unpack_dict(
                    FOB_FLAGS_FORMAT, FOB_FLAGS_NAMES, (x))
                self.logger.debug(self.flags_dict)
            except:
                self.logger.debug("Unable to unpack flags in advertisement")

        #
        # Adv and Scan response are done individually for debug reasons
        #
        try:
            rsp_format = namedtuple("format_type", "type")._make(
                struct.unpack_from('<B', b, RSP_START_INDEX))
            if rsp_format.type == VSP_ADTYPE_LENGTH:
                self.rsp = namedtuple("rsp", FOB_RSP_FIELDS1)._make(
                    struct.unpack_from(FOB_RSP_FORMAT1, b, RSP_START_INDEX))
                self.rsp_valid = self._validate_rsp1()
            else:
                self.rsp = namedtuple("rsp", FOB_RSP_FIELDS2)._make(
                    struct.unpack_from(FOB_RSP_FORMAT2, b, RSP_START_INDEX))
                self.rsp_valid = self._validate_rsp2()
                self.rsp_has_versions = self.rsp_valid

            # The length of the name is variable
            length = self.rsp.name_length - 1
            self.name = namedtuple("name", "name")._make(
                struct.unpack_from(f'<{length}s', b,
                                   (RSP_START_INDEX + rsp_format.type +
                                    RSP_NAME_OFFSET))).name.decode('utf-8')
        except:
            self.logger.info("Error in parsing scan response")
Esempio n. 15
0
 def unpack(cls, packet):
     params = bitstruct.unpack_dict(ARP_STRUCT, ARP_NAMES, packet)
     return cls(**params)
Esempio n. 16
0
 def unpack(cls, packet):
     params = bitstruct.unpack_dict(TCP_HEADER_STRUCT, TCP_HEADER_NAMES,
                                    packet[:TCP_HEADER_LENGTH])
     return cls(**params, data=packet[params["offset"] * 4:])
Esempio n. 17
0
 def unpack(cls, packet):
     params = bitstruct.unpack_dict(ETHERNET_HEADER_STRUCT,
                                    ETHERNET_HEADER_NAMES,
                                    packet[:ETHERNET_HEADER_LENGTH])
     return cls(**params, data=packet[ETHERNET_HEADER_LENGTH:])