예제 #1
0
    def __init__(self, address=None):
        if not address:
            address = "00:00:00:00:00:00"  # TODO: is defaulting this a good idea?
        # expect a string of the format "xx:xx:xx:xx:xx:xx"
        # or a 6 element; tuple, list, bytes or bytearray
        if isinstance(address, str):
            # TODO: regex based check
            if len(address) != 6 * 2 + 5:
                raise ValueError(
                    'Unexpected address length of {} for {}'.format(
                        len(address), address))
            address = address
        elif isinstance(address, list) \
                or isinstance(address, tuple) \
                or isinstance(address, bytes) \
                or isinstance(address, bytearray):
            if len(address) != 6:
                raise ValueError(
                    'Unexpected address length of {} for {}'.format(
                        len(address), address))
            address = ':'.join(
                [format(c, '02x') for c in list(reversed(address))])
        else:
            raise TypeError('Unsupported address type: {}'.format(
                type(address)))

        # TODO:  keep this for hashing but return bytearray for getter (defaulted to little endian)
        self.address = address.upper()
        log.debug(self)
예제 #2
0
 def tlm(self, tlm):
     self._tlm = tlm
     if tlm:
         self.advertisement.raw_data = self.eddystone_type_adv_data(
             tlm, FRAME_TYPE_TLM)
         log.debug("Beacon Adv TLM raw data = {}".format(
             self.advertisement.raw_data))
예제 #3
0
def on_advertisement(advertisement):
    log.debug(advertisement)

    if advertisement.address.address.startswith(GOVEE_BT_mac_OUI_PREFIX):
        mac = advertisement.address.address

        if mac not in govee_devices:
            govee_devices[mac] = {}
        if H5075_UPDATE_UUID16 in advertisement.uuid16s:
            # HACK:  Proper decoding is done in bleson > 0.10
            name = advertisement.name.split("'")[1]

            encoded_data = int(advertisement.mfg_data.hex()[6:12], 16)
            battery = int(advertisement.mfg_data.hex()[12:14], 16)
            govee_devices[mac]["address"] = mac
            govee_devices[mac]["name"] = name
            govee_devices[mac]["mfg_data"] = advertisement.mfg_data
            govee_devices[mac]["data"] = encoded_data

            govee_devices[mac]["tempInC"] = decode_temp_in_c(encoded_data)
            govee_devices[mac]["tempInF"] = decode_temp_in_f(encoded_data)
            govee_devices[mac]["humidity"] = decode_humidity(encoded_data)

            govee_devices[mac]["battery"] = battery
            print_values(mac)
        if advertisement.rssi is not None and advertisement.rssi != 0:
            govee_devices[mac]["rssi"] = advertisement.rssi
            print_rssi(mac)

        log.debug(govee_devices[mac])
예제 #4
0
 def eid(self, eid):
     self._eid = eid
     if eid:
         self.advertisement.raw_data = self.eddystone_type_adv_data(
             eid, FRAME_TYPE_EID)
         log.debug("Beacon Adv EID raw data = {}".format(
             self.advertisement.raw_data))
예제 #5
0
    def __init__(self, uuid, little_endian=True):
        """ Create UUID128, non-int types must be little endian (e.g. 'reversed' order w.r.t. displayed UUID)"""

        # TODO: accept 32bit and convert,  xxxxxxxx-0000-1000-8000-00805F9B34FB
        log.debug(("UUID128 type: {} value={}".format(type(uuid), uuid)))

        if isinstance(uuid, memoryview):
            uuid = uuid.tobytes()

        # Massage 'uuid' into a string that the built-in UUID() contructor accepts
        if isinstance(uuid, int):
            if not 0 <= uuid <= 0xffff:
                raise ValueError('Invalid UUID16 value {} fro UUID128 promotion'.format(uuid))
            uuid = UUID("0000{:04x}-0000-1000-8000-00805F9B34FB".format(uuid)).hex

        elif isinstance(uuid, str):
            if not len(uuid) == 36:
                raise ValueError('Invalid UUID128 value {}'.format(uuid))

        elif isinstance(uuid, list) or isinstance(uuid, tuple) or isinstance(uuid, bytes) or isinstance(uuid, bytearray):
            if len(uuid) != 16:
                raise ValueError('Unexpected address length of {} for {}'.format(len(uuid), uuid))
            uuid = ''.join([format(c, '02x') for c in reversed(uuid)] )
        else:
            raise TypeError('Unsupported UUID128 initialiser type: {}'.format(type(uuid)))


        self._uuid_obj = UUID(uuid)

        if not little_endian:
            self._uuid_obj = UUID(bytes=bytes(reversed(self._uuid_obj.bytes)))


        self._uuid=self._uuid_obj.urn.replace('urn:uuid:', '')
        log.debug(self)
예제 #6
0
 def url(self, url):
     self._url = url
     if url:
         self.advertisement.raw_data = self.eddystone_type_adv_data(
             url, FRAME_TYPE_URL)
         log.debug("Beacon Adv URL raw data = {}".format(
             self.advertisement.raw_data))
예제 #7
0
    def __init__(self, uuid, little_endian=True):

        log.debug(("UUID16 type: {} value={}".format(type(uuid), uuid)))
        if isinstance(uuid, memoryview):
            uuid = uuid.tolist()

        if isinstance(uuid, int):
            if not 0 <= uuid <= 0xffff:
                raise ValueError('Invalid UUID16 value {}'.format(uuid))

        elif isinstance(uuid, list) or isinstance(uuid, tuple):
            if len(uuid) != 2:
                raise ValueError('Unexpected address length of {} for {}'.format(len(uuid), uuid))
            uuid = (uuid[1] << 8) + (uuid[0] & 0xff)
        elif isinstance(uuid, bytes) or isinstance(uuid, bytearray):
            if len(uuid) != 2:
                raise ValueError('Unexpected address length of {} for {}'.format(len(uuid), uuid))
            uuid = (uuid[1] << 8) + (uuid[0] & 0xff)
        else:
            raise TypeError('Unsupported UUID16 initialiser type: {}'.format(type(uuid)))

        if not little_endian: # swap
            uuid = ( (uuid & 0xff) << 8 )  |  ( (uuid & 0xff00) >>8)
        self._uuid=uuid
        log.debug(self)
예제 #8
0
    def __init__(self, name=None, address=None, rssi=None, tx_power=None, raw_data=None):
        #TODO: use kwargs
        self.flags      =   6   # uint8         # default to LE_GENERAL_DISCOVERABLE | BREDR_NOT_SUPPORTED
        self.type = None
        self.address_type = None
        self.address = address
        self._name = name
        self.name_is_complete   = False     # unsigned
        self.tx_pwr_lvl = tx_power  # unsigned
        self.appearance     = None      # unit16
        self.uuid16s    =   []  # uuid16[]
        self.uuid32s    =   []  # uuid32[]
        self.uuid128s   =   []  # uuid12[]
        self.service_data = None
        #slave_itvl_range
        self.svc_data_uuid16 = None       # uuid16[]
        self.public_tgt_addr = None       #  uint8[]
        self.adv_itvl = None        # uint16
        self.svc_data_uuid32 = None # uint8
        self.svc_data_uuid128 = None # uint8
        self.uri    =   None        # unit8
        self.mfg_data = None        # unit8
        self.rssi = rssi            # really only part of an Advertisement Report...

        self.raw_data = raw_data
        log.debug(self)
예제 #9
0
    def peripheral_didDiscoverCharacteristicsForService_error_(
            self, peripheral, service, error):
        log.debug("peripheral_didDiscoverCharacteristicsForService_error_")

        for characteristic in self.service.characteristics():
            if characteristic.UUID().UUIDString(
            ) == crtp_characteristic.UUIDString():
                self.crtp_characteristic = characteristic
                self.peripheral.setNotifyValue_forCharacteristic_(
                    True, self.crtp_characteristic)
    def test_parse_heartrate_advertisment_report(self):

        hci_packet = parse_hci_event_packet(HEARTRATE_ADV_REPORT)
        log.debug(hci_packet)
        advertisement = AdvertisingDataConverters.from_hcipacket(hci_packet)
        self.assertEqual(0x1a, advertisement.flags)
        self.assertEqual(-55, advertisement.rssi)
        self.assertEqual('Heart Rate', advertisement.name)
        self.assertEqual(True, advertisement.name_is_complete)
        self.assertEqual(True, UUID16(0x180a) in advertisement.uuid16s)
        self.assertEqual(True, UUID16(0x180d) in advertisement.uuid16s)
        self.assertEqual(2, len(advertisement.uuid16s))
예제 #11
0
    def _handle_meta_event(self, hci_packet):

        log.debug("EVT_LE_META_EVENT")

        if hci_packet.subevent_code == EVT_LE_ADVERTISING_REPORT:
            log.debug('LE Advertising Report')
            if self.on_advertising_data:

                advertisement = AdvertisingDataConverters.from_hcipacket(
                    hci_packet)
                self.on_advertising_data(advertisement)
        else:
            log.warning(
                "TODO: unhandled HCI Meta Event packet, type={}".format(
                    hci_packet))
    def test_parse_nrf5x_lefacy_dfu_advertisement_report(self):

        hci_packet = parse_hci_event_packet(NRF51X_LEGACY_DFU_ADV_REPORT)
        log.debug(hci_packet)

        advertisement = AdvertisingDataConverters.from_hcipacket(hci_packet)
        self.assertEqual(0x1a, advertisement.flags)
        self.assertEqual(-71, advertisement.rssi)
        self.assertEqual('nRF5x', advertisement.name)
        log.debug(advertisement.uuid128s)
        self.assertEqual(
            True,
            UUID128('00001530-1212-efde-1523-785feabcd123')
            in advertisement.uuid128s)
        self.assertEqual(1, len(advertisement.uuid128s))
    def test_parse_thermometer_advertisment_report(self):

        hci_packet = parse_hci_event_packet(THERMOMETER_ADV_REPORT)
        log.debug(hci_packet)
        advertisement = AdvertisingDataConverters.from_hcipacket(hci_packet)
        self.assertEqual(0x1a, advertisement.flags)
        self.assertEqual(-74, advertisement.rssi)
        self.assertEqual('Health Thermometer', advertisement.name)
        self.assertEqual(True, advertisement.name_is_complete)

        log.debug(advertisement.uuid16s)

        self.assertEqual(True, UUID16(0x180a) in advertisement.uuid16s)
        self.assertEqual(True, UUID16(0x1809) in advertisement.uuid16s)
        self.assertEqual(2, len(advertisement.uuid16s))
예제 #14
0
    def test_all_examples(self):
        path = os.path.abspath(__file__)
        dir_path = os.path.dirname(path)
        examples_path = os.path.join(dir_path, '..', 'examples')
        examples_glob = os.path.join(examples_path, '*.py')

        scripts = glob.glob(examples_glob)
        log.debug(scripts)

        for script in scripts:
            log.info("Running {}".format(script))
            sys.argv = ['', str(TEST_DURATION)]

            # if sys.platform.lower().startswith('darwin'):
            #     log.warning("Remove workaround for macOS native teardown issue")
            #     os.system("python3 {} {}".format(script, TEST_DURATION))
            # else:
            #     runpy.run_path(script)
            runpy.run_path(script)
예제 #15
0
    def centralManager_didDiscoverPeripheral_advertisementData_RSSI_(
            self, manager, peripheral, data, rssi):
        try:
            log.debug('Found: name={} rssi={} data={} '.format(
                peripheral.name(), rssi, data))

            if self.on_advertising_data:
                advertisement = Advertisement()
                advertisement.flags = 0  # Not available
                advertisement.name = peripheral.name()
                advertisement.rssi = rssi
                advertisement.raw_data = data

                if 'kCBAdvDataTxPowerLevel' in data:
                    advertisement.tx_pwr_lvl = int(
                        data['kCBAdvDataTxPowerLevel'])

                if data['kCBAdvDataIsConnectable']:
                    # TODO: handle: kCBAdvDataIsConnectable correctly
                    advertisement.type = 0x01  # BLE_GAP_ADV_TYPE_ADV_DIRECT_IND

                if 'kCBAdvDataServiceUUIDs' in data:
                    log.debug('kCBAdvDataServiceUUIDs:')
                    for cbuuid in data['kCBAdvDataServiceUUIDs']:
                        uuid_bytes = cbuuid.data().bytes().tobytes()

                        if 2 == len(uuid_bytes):
                            uuid = UUID16(uuid_bytes, little_endian=False)
                            advertisement.uuid16s.append(uuid)

                        elif 16 == len(uuid_bytes):
                            uuid = UUID128(uuid_bytes, little_endian=False)
                            advertisement.uuid128s.append(uuid)
                        else:
                            log.error(
                                "Unsupporten UUID length for UUID bytes={}".
                                format(uuid_bytes))

                        log.debug('Service UUID: {} {}'.format(
                            type(cbuuid), cbuuid))

                if 'kCBAdvDataManufacturerData' in data:
                    mfg_data = data['kCBAdvDataManufacturerData']
                    log.debug('kCBAdvDataManufacturerData={}'.format(mfg_data))
                    advertisement.mfg_data = mfg_data

                self.on_advertising_data(advertisement)

        except Exception as e:
            log.exception(e)
예제 #16
0
    def _on_data(self, data):
        log.debug(
            "----------------------------------------------------------------------"
        )
        log.debug("Socket data: len={}, data={}".format(
            len(data), hex_string(data)))

        if data[0] == HCI_EVENT_PKT:
            hci_event_packet = parse_hci_event_packet(data[1:-1])
            log.debug(hci_event_packet)

            if data[1] == EVT_CMD_COMPLETE:
                self._handle_command_complete(data)

            elif data[1] == EVT_DISCONN_COMPLETE:
                self._handle_disconnection_complete(data)

            elif data[1] == EVT_LE_META_EVENT:
                self._handle_meta_event(hci_event_packet)

            else:
                log.warning("TODO: unhandled HCI Event packet, type={}".format(
                    hci_event_packet))
        else:
            log.warning("TODO: Unhandled HCI packet, type={}".format(data[0]))
예제 #17
0
    def _on_advertising_data(self, data):
        try:
            log.debug('Found: {}'.format(data))

            if self.on_advertising_data:
                advertisement = Advertisement()
                advertisement.flags = 0
                advertisement.rssi = data['RSSI']

                if 'ADDRESS' in data:
                    advertisement.address = BDAddress(data['ADDRESS'])

                if 'LOCALNAME' in data:
                    advertisement.name = data['LOCALNAME']

                if 'TXPOWER' in data:
                    advertisement.tx_pwr_lvl = int(data['TXPOWER'])

                self.on_advertising_data(advertisement)

        except Exception as e:
            log.exception(e)
예제 #18
0
def get_provider():

    global _provider

    if _provider is None:
        if sys.platform.startswith('linux'):
            from bleson.providers.linux.linux_provider import LinuxProvider
            _provider = LinuxProvider()
        elif sys.platform.startswith('darwin'):
            from bleson.providers.macos.macos_provider import MacOSProvider
            _provider = MacOSProvider()

        elif sys.platform.startswith('win32'):
            from bleson.providers.win32.win32_provider import Win32Provider
            _provider = Win32Provider()
        else:
            raise RuntimeError('Platform {0} is not supported!'.format(
                sys.platform))

    log.debug("Provider is {}".format(_provider))

    return _provider
예제 #19
0
 def centralManager_didDisconnectPeripheral_error_(self, manager,
                                                   peripheral, error):
     log.debug("centralManager_didDisconnectPeripheral_error_")
     self.connected = False
예제 #20
0
 def __init__(self, address:BDAddress=None, name=None, rssi=None):
     self.address = address
     self.name = name
     self.rssi = rssi
     log.debug(self)
예제 #21
0
    def from_hcipayload(cls, data):
        data_info = "Data: {}".format(hex_string(data))
        pos_info = "POS : {}".format(''.join('{:02} '.format(x)
                                             for x in range(0, len(data))))
        log.debug(data_info)
        log.debug(pos_info)

        num_reports = data[0]
        log.debug("Num Reports {}".format(num_reports))

        if num_reports != 1:
            log.error(
                "TODO: Only 1 Advertising report is supported, creating emtpy Advertisement"
            )
            # don't make it fatal
            return Advertisement()

        # TODO: move these 2 LUTs to a better place
        gap_adv_type = [
            'ADV_IND', 'ADV_DIRECT_IND', 'ADV_SCAN_IND', 'ADV_NONCONN_IND',
            'SCAN_RSP'
        ][data[1]]
        gap_addr_type = [
            'PUBLIC', 'RANDOM', 'PUBLIC_IDENTITY', 'RANDOM_STATIC'
        ][data[2]]
        gap_addr = data[3:9]
        rssi = rssi_from_byte(data[-1])

        advertisement = Advertisement(address=BDAddress(gap_addr), rssi=rssi)
        advertisement.type = gap_adv_type
        advertisement.address_type = gap_addr_type

        pos = 10
        while pos < len(data) - 1:
            log.debug("POS={}".format(pos))
            length = data[pos]
            gap_type = data[pos + 1]
            payload = data[pos + 2:pos + 2 + length - 1]
            log.debug("Pos={} Type=0x{:02x} Len={} Payload={}".format(
                pos, gap_type, length, hex_string(payload)))

            if GAP_FLAGS == gap_type:
                advertisement.flags = payload[0]
                log.debug("Flags={:02x}".format(advertisement.flags))

            elif GAP_UUID_16BIT_COMPLETE == gap_type:
                uuids = []
                byte_pos = 0
                if len(payload) % 2 != 0:
                    raise ValueError(
                        "PAyload is not divisible by 2 for UUID16")

                while byte_pos < len(payload):
                    log.debug('byte_pos={}'.format(byte_pos))
                    byte_pair = payload[byte_pos:byte_pos + 2]
                    log.debug('byte pair = {}'.format(byte_pair))
                    uuid = UUID16(byte_pair)
                    uuids.append(uuid)
                    byte_pos += 2

                advertisement.uuid16s = uuids

            elif GAP_UUID_128BIT_COMPLETE == gap_type:

                # if length-1 > 16:
                #     log.warning("TODO: >1 UUID128's found, not yet split into individual elements")
                #advertisement.uuid128s=[UUID128(payload)]
                uuids = []
                byte_pos = 0
                if len(payload) % 16 != 0:
                    raise ValueError(
                        "Payload is not divisible by 16 for UUID128")

                while byte_pos < len(payload):
                    log.debug('byte_pos={}'.format(byte_pos))
                    byte_list = payload[byte_pos:byte_pos + 16]
                    log.debug('byte_list = {}'.format(byte_list))
                    uuid = UUID128(byte_list)
                    uuids.append(uuid)
                    byte_pos += 16

                advertisement.uuid128s = uuids

                log.debug(advertisement.uuid128s)

            elif GAP_NAME_INCOMPLETE == gap_type:
                advertisement.name = payload
                advertisement.name_is_complete = False
                log.debug("Incomplete Name={}".format(advertisement.name))

            elif GAP_NAME_COMPLETE == gap_type:
                advertisement.name = payload
                advertisement.name_is_complete = True
                log.debug("Complete Name={}".format(advertisement.name))

            elif GAP_SERVICE_DATA == gap_type:
                advertisement.service_data = payload
                log.debug("Service Data={}".format(advertisement.service_data))

            elif GAP_MFG_DATA == gap_type:
                advertisement.mfg_data = payload
                log.debug("Manufacturer Data={}".format(
                    advertisement.mfg_data))

            else:
                log.warning(
                    "TODO: Unhandled GAP type, pos={} type=0x{:02x} len={}".
                    format(pos, gap_type, length))
                log.warning(data_info)
                log.warning(pos_info)

            pos += length + 1

        log.debug(advertisement)
        return advertisement
예제 #22
0
 def stop_scanning(self):
     log.debug("")
     if self._manager:
         self._manager.stopScan()
예제 #23
0
 def on(self):
     log.debug("TODO: adatper on")
예제 #24
0
 def peripheral_didUpdateValueForCharacteristic_error_(
         self, peripheral, characteristic, error):
     log.debug("peripheral_didUpdateValueForCharacteristic_error_")
     log.debug(repr(characteristic.value().bytes().tobytes()))
예제 #25
0
 def peripheral_didUpdateNotificationStateForCharacteristic_error_(
         self, peripheral, characteristic, error):
     log.debug(
         "peripheral_didUpdateNotificationStateForCharacteristic_error_")
예제 #26
0
    def peripheral_didWriteValueForCharacteristic_error_(
            self, peripheral, characteristic, error):
        log.debug("peripheral_didWriteValueForCharacteristic_error_")

        if error != None:
            log.error(repr(error))
예제 #27
0
 def centralManagerDidUpdateState_(self, manager):
     state = manager.state()
     log.debug("State: {}".format(state))
예제 #28
0
 def centralManager_didConnectPeripheral_(self, manager, peripheral):
     log.debug('Connected: ' + peripheral.name())
     self.connected = True
     self.peripheral.setDelegate_(self)
     self.peripheral.readRSSI()
예제 #29
0
    def from_hcipayload(cls, data):
        data_info = "Data: {}".format(hex_string(data))
        pos_info = "POS : {}".format("".join("{:02} ".format(x)
                                             for x in range(0, len(data))))
        log.debug(data_info)
        log.debug(pos_info)

        num_reports = data[0]
        log.debug("Num Reports {}".format(num_reports))

        if num_reports != 1:
            log.error(
                "TODO: Only 1 Advertising report is supported, creating empty Advertisement"
            )
            # don't make it fatal
            return Advertisement()

        # TODO: move these 2 LUTs to a better place
        gap_adv_type = [
            "ADV_IND",
            "ADV_DIRECT_IND",
            "ADV_SCAN_IND",
            "ADV_NONCONN_IND",
            "SCAN_RSP",
        ][data[1]]
        gap_addr_type = [
            "PUBLIC", "RANDOM", "PUBLIC_IDENTITY", "RANDOM_STATIC"
        ][data[2]]
        gap_addr = data[3:9]
        rssi = rssi_from_byte(data[-1])

        advertisement = Advertisement(address=BDAddress(gap_addr),
                                      rssi=rssi,
                                      raw_data=data)
        advertisement.type = gap_adv_type
        advertisement.address_type = gap_addr_type

        pos = 10
        while pos < len(data) - 1:
            log.debug("POS={}".format(pos))
            length = data[pos]
            gap_type = data[pos + 1]
            payload = data[pos + 2:pos + 2 + length - 1]
            log.debug("Pos={} Type=0x{:02x} Len={} Payload={}".format(
                pos, gap_type, length, hex_string(payload)))

            if GAP_FLAGS == gap_type:
                advertisement.flags = payload[0]
                log.debug("Flags={:02x}".format(advertisement.flags))

            elif GAP_UUID_16BIT_COMPLETE == gap_type:
                uuids = []
                byte_pos = 0
                if len(payload) % 2 != 0:
                    raise ValueError(
                        "PAyload is not divisible by 2 for UUID16")

                while byte_pos < len(payload):
                    log.debug("byte_pos={}".format(byte_pos))
                    byte_pair = payload[byte_pos:byte_pos + 2]
                    log.debug("byte pair = {}".format(byte_pair))
                    uuid = UUID16(byte_pair)
                    uuids.append(uuid)
                    byte_pos += 2

                advertisement.uuid16s = uuids

            elif GAP_UUID_128BIT_INCOMPLETE == gap_type:
                # if length-1 > 16:
                #     log.warning("TODO: >1 UUID128's found, not yet split into individual elements")
                # advertisement.uuid128s=[UUID128(payload)]
                uuids = []
                byte_pos = 0
                if len(payload) % 16 != 0:
                    raise ValueError(
                        "Payload is not divisible by 16 for UUID128")

                while byte_pos < len(payload):
                    log.debug("byte_pos={}".format(byte_pos))
                    byte_list = payload[byte_pos:byte_pos + 16]
                    log.debug("byte_list = {}".format(byte_list))
                    uuid = UUID128(byte_list)
                    uuids.append(uuid)
                    byte_pos += 16

                advertisement.uuid128s_incomplete = uuids

                log.debug(advertisement.uuid128s_incomplete)

            elif GAP_UUID_128BIT_COMPLETE == gap_type:

                # if length-1 > 16:
                #     log.warning("TODO: >1 UUID128's found, not yet split into individual elements")
                # advertisement.uuid128s=[UUID128(payload)]
                uuids = []
                byte_pos = 0
                if len(payload) % 16 != 0:
                    raise ValueError(
                        "Payload is not divisible by 16 for UUID128")

                while byte_pos < len(payload):
                    log.debug("byte_pos={}".format(byte_pos))
                    byte_list = payload[byte_pos:byte_pos + 16]
                    log.debug("byte_list = {}".format(byte_list))
                    uuid = UUID128(byte_list)
                    uuids.append(uuid)
                    byte_pos += 16

                advertisement.uuid128s = uuids

                log.debug(advertisement.uuid128s)

            elif GAP_NAME_INCOMPLETE == gap_type:
                advertisement.name = payload
                advertisement.name_is_complete = False
                log.debug("Incomplete Name={}".format(advertisement.name))

            elif GAP_NAME_COMPLETE == gap_type:
                advertisement.name = payload
                advertisement.name_is_complete = True
                log.debug("Complete Name={}".format(advertisement.name))

            elif GAP_SERVICE_DATA == gap_type:
                advertisement.service_data = payload
                log.debug("Service Data={}".format(advertisement.service_data))

            elif GAP_MFG_DATA == gap_type:
                advertisement.mfg_data = payload
                log.debug("Manufacturer Data={}".format(
                    advertisement.mfg_data))

            elif GAP_TX_POWER == gap_type:
                if payload == None:
                    advertisement.tx_pwr_lvl = payload
                else:
                    advertisement.tx_pwr_lvl = int.from_bytes(
                        payload, byteorder="little")
                log.debug("TX Power={}".format(advertisement.tx_pwr_lvl))

            elif GAP_APPEARANCE == gap_type:
                # https://www.bluetooth.com/wp-content/uploads/Sitecore-Media-Library/Gatt/Xml/Characteristics/org.bluetooth.characteristic.gap.appearance.xml
                # "The external appearance of this device. The values are composed of a category (10-bits) and sub-categories (6-bits)."
                # TODO: Add Appearance Names as well as IDs likey as "appearance: {id: , description:}"
                advertisement.appearance = int.from_bytes(payload,
                                                          byteorder="little")
                log.debug("GAP Appearance={}".format(advertisement.appearance))

            else:
                log.warning(
                    "TODO: Unhandled GAP type, pos={} type=0x{:02x} len={}".
                    format(pos, gap_type, length))
                log.warning(data_info)
                log.warning(pos_info)

            pos += length + 1

        log.debug(advertisement)
        return advertisement
예제 #30
0
 def peripheral_didDiscoverServices_(self, peripheral, error):
     log.debug("peripheral_didDiscoverServices_")
     if (error == None):
         self.service = self.peripheral.services()[0]