Пример #1
0
    def process_value(self, value):
        assert value[0] == 0
        opcode = value[1]
        tid = value[2]
        payload = value[7:]

        if opcode == HapBleOpCodes.CHAR_WRITE:
            new_value = dict(TLV.decode_bytes(payload))
            self.do_char_write(tid, new_value[1])

        elif opcode == HapBleOpCodes.CHAR_READ:
            value = self.char.get_value_for_ble()
            value = TLV.encode_list([(TLV.kTLVHAPParamValue, value)])

            response = bytearray([0x02, tid, 0x00])
            tlv = len(value).to_bytes(2, byteorder='little') + value
            response.extend(tlv)
            self.queue_read_response(self.encrypt_value(bytes(response)))

        elif opcode == HapBleOpCodes.CHAR_SIG_READ:
            response = bytearray([0x02, tid, 0x00])

            service_type = list(uuid.UUID(self.service.service.type).bytes)
            service_type.reverse()
            service_type = bytes(bytearray(service_type))

            char_type = list(uuid.UUID(self.char.type).bytes)
            char_type.reverse()
            char_type = bytes(bytearray(char_type))

            fmt = BleCharacteristicFormats.get_reverse(self.char.format, b'\x00').to_bytes(length=1, byteorder='little')
            unit = b'\x00\x00'
            gatt_fmt = fmt + unit

            data = [
                (TLV.kTLVHAPParamHAPCharacteristicPropertiesDescriptor, b'\x00'),
                (TLV.kTLVHAPParamGATTPresentationFormatDescriptor, gatt_fmt),
                (TLV.kTLVHAPParamCharacteristicType, char_type),
                (TLV.kTLVHAPParamServiceInstanceId, self.service.service.iid.to_bytes(length=8, byteorder='little')),
                (TLV.kTLVHAPParamServiceType, service_type),
            ]

            tlv = TLV.encode_list(data)
            response.extend(len(tlv).to_bytes(2, byteorder='little') + tlv)
            self.queue_read_response(self.encrypt_value(bytes(response)))
        else:
            raise RuntimeError('Fake does not implement opcode %s' % opcode)
Пример #2
0
def parse_sig_read_response(data, expected_tid):
    # TODO document me
    # parse header and check stuff
    logger.debug('parse sig read response %s',
                 bytes([int(a) for a in data]).hex())

    # handle the header data
    cf = data[0]
    logger.debug('control field %d', cf)
    tid = data[1]
    logger.debug('transaction id %d (expected was %d)', tid, expected_tid)
    status = data[2]
    logger.debug('status code %d (%s)', status, HapBleStatusCodes[status])
    assert cf == 0x02
    assert tid == expected_tid
    assert status == HapBleStatusCodes.SUCCESS

    # get body length
    length = int.from_bytes(data[3:5], byteorder='little')
    logger.debug('expected body length %d (got %d)', length, len(data[5:]))

    # parse tlvs and analyse information
    tlv = tlv8.decode(bytes([int(a) for a in data[5:]]))

    description = ''
    characteristic_format = ''
    characteristic_range = None
    characteristic_step = None
    for t in tlv:
        if t.type_id == AdditionalParameterTypes.CharacteristicType:
            chr_type = [int(a) for a in t.data]
            chr_type.reverse()
            chr_type = str(uuid.UUID(''.join('%02x' % b for b in chr_type)))
        if t.type_id == AdditionalParameterTypes.ServiceInstanceId:
            svc_id = int.from_bytes(t.data, byteorder='little')
        if t.type_id == AdditionalParameterTypes.ServiceType:
            svc_type = [int(a) for a in t.data]
            svc_type.reverse()
            svc_type = str(uuid.UUID(''.join('%02x' % b for b in svc_type)))
        if t.type_id == AdditionalParameterTypes.HAPCharacteristicPropertiesDescriptor:
            chr_prop_int = int.from_bytes(t.data, byteorder='little')
        if t.type_id == AdditionalParameterTypes.GATTUserDescriptionDescriptor:
            description = t.data.decode()
        if t.type_id == AdditionalParameterTypes.HAPValidValuesDescriptor:
            print('valid values', t.data)
        if t.type_id == AdditionalParameterTypes.HAPValidValuesRangeDescriptor:
            print('valid values range', t.data)
        if t.type_id == AdditionalParameterTypes.GATTPresentationFormatDescriptor:
            unit_bytes = bytearray(t.data[2:4])
            unit_bytes.reverse()
            characteristic_format = BleCharacteristicFormats.get(
                int(t.data[0]), 'unknown')
            unit = BleCharacteristicUnits.get(
                int.from_bytes(unit_bytes, byteorder='big'), 'unknown')
        if t.type_id == AdditionalParameterTypes.GATTValidRange:
            logger.debug('range: %s', t.data.hex())
            lower = None
            upper = None
            if characteristic_format == 'int32' or characteristic_format == 'int':
                (lower, upper) = struct.unpack('ii', t.data)
            if characteristic_format == 'uint8':
                (lower, upper) = struct.unpack('BB', t.data)
            if characteristic_format == 'float':
                (lower, upper) = struct.unpack('ff', t.data)
            # TODO include all formats!
            characteristic_range = (lower, upper)
        if t.type_id == AdditionalParameterTypes.HAPStepValueDescriptor:
            characteristic_step = None
            if characteristic_format == 'int32':
                characteristic_step = struct.unpack('i', t.data)[0]
            if characteristic_format == 'uint8':
                characteristic_step = struct.unpack('B', t.data)[0]
            # TODO include all formats!

    # parse permissions
    # TODO refactor!
    perms = []
    if (chr_prop_int & 0x0001) > 0:
        perms.append('r')
    if (chr_prop_int & 0x0002) > 0:
        perms.append('w')
    if (chr_prop_int & 0x0004) > 0:
        perms.append('aad')
    if (chr_prop_int & 0x0008) > 0:
        perms.append('tw')
    if (chr_prop_int & 0x0010) > 0:
        perms.append('pr')
    if (chr_prop_int & 0x0020) > 0:
        perms.append('pw')
    if (chr_prop_int & 0x0040) > 0:
        perms.append('hd')
    if (chr_prop_int & 0x0080) > 0:
        perms.append('evc')
    if (chr_prop_int & 0x0100) > 0:
        perms.append('evd')

    result = {
        'description': description,
        'perms': perms,
        'format': characteristic_format,
        'unit': unit,
        'range': characteristic_range,
        'step': characteristic_step,
        'type': chr_type.upper(),
        'sid': svc_id,
        'service_type': svc_type
    }
    logger.debug('result: %s', str(result))

    return result
 def test_get_known_key(self):
     self.assertEqual('bool', BleCharacteristicFormats.get(1, 'unknown'))
 def test_get_unknown_key(self):
     self.assertEqual('unknown',
                      BleCharacteristicFormats.get(-0xC0FFEE, 'unknown'))