def _save_charecteristic_callback(self, event): match = event["match"] try: value_handle = int(match.group(2), 16) char_uuid = match.group(3).strip().decode('ascii') self._characteristics[UUID(char_uuid)] = Characteristic( char_uuid, value_handle) log.debug("Found characteristic %s, value handle: 0x%x", char_uuid, value_handle) except AttributeError: pass
def setUp(self): super(GATTToolBLEDeviceTests, self).setUp() self.address = "11:22:33:44:55:66" self.backend = MagicMock() self.device = GATTToolBLEDevice(self.address, self.backend) self.expected_handle = 99 self.char_uuid = uuid.uuid4() self.backend.discover_characteristics.return_value = { self.char_uuid: Characteristic(self.char_uuid, self.expected_handle) }
def _ble_evt_attclient_find_information_found(self, args): """ Handles the event for characteristic discovery. Adds the characteristic to the dictionary of characteristics or adds the descriptor to the dictionary of descriptors in the current characteristic. These events will be occur in an order similar to the following: 1) primary service uuid 2) 0 or more descriptors 3) characteristic uuid 4) 0 or more descriptors 5) repeat steps 3-4 args -- dictionary containing the characteristic handle ('chrhandle'), and characteristic UUID ('uuid') """ raw_uuid = bytearray(reversed(args['uuid'])) # Convert 4-byte UUID shorthand to a full, 16-byte UUID uuid_type = self._get_uuid_type(raw_uuid) if uuid_type != UUIDType.custom: uuid = uuid16_to_uuid( int(bgapi_address_to_hex(args['uuid']).replace(':', ''), 16)) else: uuid = UUID(bytes=bytes(raw_uuid)) # TODO is there a way to get the characteristic from the packet instead # of having to track the "current" characteristic? if uuid_type == UUIDType.descriptor: log.info("Found descriptor %s" % uuid) if self._current_characteristic is not None: self._current_characteristic.add_descriptor( uuid, args['chrhandle']) elif self._current_service is not None: self._current_service.add_descriptor(uuid, args['chrhandle']) elif (uuid_type == UUIDType.custom or uuid_type == UUIDType.nonstandard or uuid_type == UUIDType.characteristic): if uuid_type == UUIDType.custom: log.info("Found custom characteristic %s" % uuid) elif uuid_type == UUIDType.characteristic: log.info("Found approved characteristic %s" % uuid) elif uuid_type == UUIDType.nonstandard: log.info("Found nonstandard 4-byte characteristic %s" % uuid) new_char = Characteristic(uuid, args['chrhandle']) self._current_characteristic = new_char if self._current_service is not None: self._current_service.add_characteristic(new_char)
def _save_charecteristic_callback(self, event): match = event["match"] print("day _save_char match:'{}'".format( repr(match)[:80])) try: value_handle = int(match.group(2), 16) char_uuid = match.group(3).strip().decode('ascii') self._characteristics[UUID(char_uuid)] = Characteristic( char_uuid, value_handle ) log.debug( "Found characteristic %s, value handle: 0x%x", char_uuid, value_handle ) except AttributeError: print("day has a AttributeError") pass
def _save_charecteristic_callback(self, event): match = event["match"] unmatched = event["before"] + event["after"] m = re.findall( ur"handle: 0x([a-fA-F0-9]{4}), char properties: 0x[a-fA-F0-9]{2}, char value handle: 0x([a-fA-F0-9]{4}), uuid: ([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})", repr(unmatched)) match = m try: for m in match: value_handle = int(m[1], 16) char_uuid = m[2].strip().decode('ascii') self._characteristics[UUID(char_uuid)] = Characteristic( char_uuid, value_handle) log.debug("Found characteristic %s, value handle: 0x%x", char_uuid, value_handle) except AttributeError: pass
def run(self): """Thread that keeps connection alive.""" # pylint: disable=import-error import pygatt from pygatt.backends import Characteristic from pygatt.exceptions import ( BLEError, NotConnectedError, NotificationTimeout) cached_char = Characteristic(BLE_TEMP_UUID, BLE_TEMP_HANDLE) adapter = pygatt.backends.GATTToolBackend() while True: try: _LOGGER.debug("Connecting to %s", self.name) # We need concurrent connect, so lets not reset the device adapter.start(reset_on_start=False) # Seems only one connection can be initiated at a time with CONNECT_LOCK: device = adapter.connect(self.mac, CONNECT_TIMEOUT, pygatt.BLEAddressType.random) if SKIP_HANDLE_LOOKUP: # HACK: inject handle mapping collected offline # pylint: disable=protected-access device._characteristics[UUID(BLE_TEMP_UUID)] = cached_char # Magic: writing this makes device happy device.char_write_handle(0x1b, bytearray([255]), False) device.subscribe(BLE_TEMP_UUID, self._update) _LOGGER.info("Subscribed to %s", self.name) while self.keep_going: # protect against stale connections, just read temperature device.char_read(BLE_TEMP_UUID, timeout=CONNECT_TIMEOUT) self.event.wait(60) break except (BLEError, NotConnectedError, NotificationTimeout) as ex: _LOGGER.error("Exception: %s ", str(ex)) finally: adapter.stop()
def discover_characteristics(self): characteristics = {} with self._connection_lock: self._con.sendline('characteristics') timeout = 6 while True: try: self._con.expect( r"handle: 0x([a-fA-F0-9]{4}), " "char properties: 0x[a-fA-F0-9]{2}, " "char value handle: 0x([a-fA-F0-9]{4}), " "uuid: ([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})\r\n", # noqa timeout=timeout) except pexpect.TIMEOUT: break except pexpect.EOF: break else: try: value_handle = int(self._con.match.group(2), 16) char_uuid = ( self._con.match.group(3).strip().decode('ascii')) characteristics[UUID(char_uuid)] = Characteristic( char_uuid, value_handle) log.debug( "Found characteristic %s, value handle: 0x%x", char_uuid, value_handle) # The characteristics all print at once, so after # waiting 1-2 seconds for them to all fetch, you can # load the rest without much delay at all. timeout = .01 except AttributeError: pass return characteristics
def discover_characteristics(self): return { self.CHAR_UUID: Characteristic(self.CHAR_UUID, self.EXPECTED_HANDLE) }