コード例 #1
0
ファイル: bluetooth.py プロジェクト: jbouwh/core
 def async_on_advertisement(self, adv: BluetoothLEAdvertisement) -> None:
     """Call the registered callback."""
     now = time.monotonic()
     address = ":".join(TWO_CHAR.findall("%012X" %
                                         adv.address))  # must be upper
     advertisement_data = AdvertisementData(  # type: ignore[no-untyped-call]
         local_name=None if adv.name == "" else adv.name,
         manufacturer_data=adv.manufacturer_data,
         service_data=adv.service_data,
         service_uuids=adv.service_uuids,
     )
     device = BLEDevice(  # type: ignore[no-untyped-call]
         address=address,
         name=adv.name,
         details={},
         rssi=adv.rssi,
     )
     self._discovered_devices[address] = device
     self._discovered_device_timestamps[address] = now
     self._new_info_callback(
         BluetoothServiceInfoBleak(
             name=advertisement_data.local_name or device.name
             or device.address,
             address=device.address,
             rssi=device.rssi,
             manufacturer_data=advertisement_data.manufacturer_data,
             service_data=advertisement_data.service_data,
             service_uuids=advertisement_data.service_uuids,
             source=self._source,
             device=device,
             advertisement=advertisement_data,
             connectable=False,
             time=now,
         ))
コード例 #2
0
def fixture_scanner(hass):
    """Fixture for scanner."""

    devices = [BLEDevice("1.1.1.1", "COOKERHOOD_FJAR")]

    class MockScanner(BaseBleakScanner):
        """Mock Scanner."""

        async def start(self):
            """Start scanning for devices."""
            for device in devices:
                self._callback(device, AdvertisementData())

        async def stop(self):
            """Stop scanning for devices."""

        @property
        def discovered_devices(self) -> list[BLEDevice]:
            """Return discovered devices."""
            return devices

        def set_scanning_filter(self, **kwargs):
            """Set the scanning filter."""

    with patch(
        "homeassistant.components.fjaraskupan.config_flow.BleakScanner", new=MockScanner
    ), patch(
        "homeassistant.components.fjaraskupan.config_flow.CONST_WAIT_TIME", new=0.01
    ):
        yield devices
コード例 #3
0
    async def get_discovered_devices(self) -> List[BLEDevice]:
        found = []
        peripherals = cbapp.central_manager_delegate.peripheral_list

        for i, peripheral in enumerate(peripherals):
            address = peripheral.identifier().UUIDString()
            name = peripheral.name() or "Unknown"
            details = peripheral

            advertisementData = cbapp.central_manager_delegate.advertisement_data_list[i]
            manufacturer_binary_data = advertisementData.get("kCBAdvDataManufacturerData")
            manufacturer_data = {}
            if manufacturer_binary_data:
                manufacturer_id = int.from_bytes(
                    manufacturer_binary_data[0:2], byteorder="little"
                )
                manufacturer_value = bytes(manufacturer_binary_data[2:])
                manufacturer_data = {manufacturer_id: manufacturer_value}

            uuids = [
                # converting to lower case to match other platforms
                str(u).lower()
                for u in advertisementData.get("kCBAdvDataServiceUUIDs", [])
            ]

            found.append(
                BLEDevice(
                    address, name, details, uuids=uuids, manufacturer_data=manufacturer_data
                )
            )

        return found
コード例 #4
0
 def discovered_devices(self) -> List[BLEDevice]:
     # Reduce output.
     discovered_devices = []
     for path, props in self._devices.items():
         if not props:
             logger.debug(
                 "Disregarding %s since no properties could be obtained." % path
             )
             continue
         name, address, _, path = _device_info(path, props)
         if address is None:
             continue
         uuids = props.get("UUIDs", [])
         manufacturer_data = props.get("ManufacturerData", {})
         discovered_devices.append(
             BLEDevice(
                 address,
                 name,
                 {"path": path, "props": props},
                 props.get("RSSI", 0),
                 uuids=uuids,
                 manufacturer_data=manufacturer_data,
             )
         )
     return discovered_devices
コード例 #5
0
ファイル: scanner.py プロジェクト: scsims/bleak
 def parse_eventargs(event_args):
     bdaddr = _format_bdaddr(event_args.BluetoothAddress)
     uuids = []
     for u in event_args.Advertisement.ServiceUuids:
         uuids.append(u.ToString())
     data = {}
     for m in event_args.Advertisement.ManufacturerData:
         with BleakDataReader(m.Data) as reader:
             data[m.CompanyId] = reader.read()
     local_name = event_args.Advertisement.LocalName
     return BLEDevice(bdaddr,
                      local_name,
                      event_args,
                      uuids=uuids,
                      manufacturer_data=data)
コード例 #6
0
    def discovered_devices(self) -> List[BLEDevice]:
        found = []
        peripherals = self._manager.central_manager.retrievePeripheralsWithIdentifiers_(
            NSArray(self._identifiers.keys()),
        )

        for peripheral in peripherals:
            address = peripheral.identifier().UUIDString()
            name = peripheral.name() or "Unknown"
            details = peripheral
            rssi = self._manager.devices[address].rssi

            advertisementData = self._identifiers[peripheral.identifier()]
            manufacturer_binary_data = advertisementData.get(
                "kCBAdvDataManufacturerData"
            )
            manufacturer_data = {}
            if manufacturer_binary_data:
                manufacturer_id = int.from_bytes(
                    manufacturer_binary_data[0:2], byteorder="little"
                )
                manufacturer_value = bytes(manufacturer_binary_data[2:])
                manufacturer_data = {manufacturer_id: manufacturer_value}

            uuids = [
                cb_uuid_to_str(u)
                for u in advertisementData.get("kCBAdvDataServiceUUIDs", [])
            ]

            service_data = {}
            adv_service_data = advertisementData.get("kCBAdvDataServiceData", [])
            for u in adv_service_data:
                service_data[cb_uuid_to_str(u)] = bytes(adv_service_data[u])

            found.append(
                BLEDevice(
                    address,
                    name,
                    details,
                    rssi=rssi,
                    uuids=uuids,
                    manufacturer_data=manufacturer_data,
                    service_data=service_data,
                    delegate=self._manager.central_manager.delegate(),
                )
            )

        return found
コード例 #7
0
        def callback(p: CBPeripheral, a: Dict[str, Any], r: int) -> None:
            # update identifiers for scanned device
            self._identifiers.setdefault(p.identifier(), {}).update(a)

            if not self._callback:
                return

            # Process service data
            service_data_dict_raw = a.get("kCBAdvDataServiceData", {})
            service_data = {
                cb_uuid_to_str(k): bytes(v) for k, v in service_data_dict_raw.items()
            }

            # Process manufacturer data into a more friendly format
            manufacturer_binary_data = a.get("kCBAdvDataManufacturerData")
            manufacturer_data = {}
            if manufacturer_binary_data:
                manufacturer_id = int.from_bytes(
                    manufacturer_binary_data[0:2], byteorder="little"
                )
                manufacturer_value = bytes(manufacturer_binary_data[2:])
                manufacturer_data[manufacturer_id] = manufacturer_value

            service_uuids = [
                cb_uuid_to_str(u) for u in a.get("kCBAdvDataServiceUUIDs", [])
            ]

            advertisement_data = AdvertisementData(
                local_name=p.name(),
                manufacturer_data=manufacturer_data,
                service_data=service_data,
                service_uuids=service_uuids,
                platform_data=(p, a, r),
            )

            device = BLEDevice(
                p.identifier().UUIDString(),
                p.name(),
                p,
                r,
                uuids=service_uuids,
                manufacturer_data=manufacturer_data,
                service_data=service_data,
                delegate=self._manager.central_manager.delegate(),
            )

            self._callback(device, advertisement_data)
コード例 #8
0
ファイル: btinspect.py プロジェクト: cwi-dis/lissabon
async def main():
    devices = [BLEDevice(addr, None) for addr in sys.argv[1:]]
    tasks = []
    for device in devices:
        tasks.append(asyncio.create_task(get_device_services(device)))
    if tasks:
        results = await asyncio.gather(*tasks)
    else:
        results = []

    for device, services in results:
        print(f'Device {device}')
        if services:
            for service in services:
                print(f'\tService {services}')
        else:
            print(f'\tunknown')
    print('all done')
コード例 #9
0
ファイル: __init__.py プロジェクト: jbouwh/core
def make_advertisement(address: str,
                       payload: bytes) -> BluetoothServiceInfoBleak:
    """Make a dummy advertisement."""
    return BluetoothServiceInfoBleak(
        name="Test Device",
        address=address,
        device=BLEDevice(address, None),
        rssi=-56,
        manufacturer_data={},
        service_data={
            "0000181c-0000-1000-8000-00805f9b34fb": payload,
        },
        service_uuids=["0000181c-0000-1000-8000-00805f9b34fb"],
        source="local",
        advertisement=AdvertisementData(local_name="Test Device"),
        time=0,
        connectable=False,
    )
コード例 #10
0
ファイル: scanner.py プロジェクト: pybricks/bleak
 def parse_eventargs(event_args):
     bdaddr = _format_bdaddr(event_args.BluetoothAddress)
     uuids = []
     for u in event_args.Advertisement.ServiceUuids:
         uuids.append(u.ToString())
     data = {}
     for m in event_args.Advertisement.ManufacturerData:
         md = IBuffer(m.Data)
         b = Array.CreateInstance(Byte, md.Length)
         reader = DataReader.FromBuffer(md)
         reader.ReadBytes(b)
         data[m.CompanyId] = bytes(b)
     local_name = event_args.Advertisement.LocalName
     return BLEDevice(bdaddr,
                      local_name,
                      event_args,
                      uuids=uuids,
                      manufacturer_data=data)
コード例 #11
0
ファイル: scanner.py プロジェクト: sreerajpunnoli/bleak
    def _invoke_callback(self, path: str, message: Message) -> None:
        """Invokes the advertising data callback.

        Args:
            message: The D-Bus message that triggered the callback.
        """
        if self._callback is None:
            return

        props = self._devices[path]

        # Get all the information wanted to pack in the advertisement data
        _local_name = props.get("Name")
        _manufacturer_data = {
            k: bytes(v)
            for k, v in props.get("ManufacturerData", {}).items()
        }
        _service_data = {
            k: bytes(v)
            for k, v in props.get("ServiceData", {}).items()
        }
        _service_uuids = props.get("UUIDs", [])

        # Pack the advertisement data
        advertisement_data = AdvertisementData(
            local_name=_local_name,
            manufacturer_data=_manufacturer_data,
            service_data=_service_data,
            service_uuids=_service_uuids,
            platform_data=(props, message),
        )

        device = BLEDevice(
            props["Address"],
            props["Alias"],
            {
                "path": path,
                "props": props
            },
            props.get("RSSI", 0),
        )

        self._callback(device, advertisement_data)
コード例 #12
0
ファイル: scanner.py プロジェクト: devbis/bleak
 def _parse_event_args(event_args):
     bdaddr = _format_bdaddr(event_args.bluetooth_address)
     uuids = []
     try:
         for u in event_args.advertisement.service_uuids:
             uuids.append(str(u))
     except NotImplementedError as e:
         # Cannot get service uuids for this device...
         pass
     data = {}
     for m in event_args.advertisement.manufacturer_data:
         data[m.company_id] = bytes(m.data)
     local_name = event_args.advertisement.local_name
     rssi = event_args.raw_signal_strength_in_d_bm
     return BLEDevice(bdaddr,
                      local_name,
                      event_args,
                      rssi,
                      uuids=uuids,
                      manufacturer_data=data)
コード例 #13
0
ファイル: scanner_windows.py プロジェクト: hulttis/ruuvigw
 def AdvertisementWatcher_Received(sender, e):
     if sender == watcher:
         # logger.debug("Received {0}.".format(_format_event_args(e)))
         l_bdaddr = _format_bdaddr(e.BluetoothAddress)
         l_uuids = []
         for l_u in e.Advertisement.ServiceUuids:
             l_uuids.append(l_u.ToString())
         l_data = {}
         for l_m in e.Advertisement.ManufacturerData:
             l_md = IBuffer(l_m.Data)
             l_b = Array.CreateInstance(Byte, l_md.Length)
             l_reader = DataReader.FromBuffer(l_md)
             l_reader.ReadBytes(l_b)
             l_data[l_m.CompanyId] = bytes(l_b)
         local_name = e.Advertisement.LocalName
         logger.debug(f'>>> bdaddr:{l_bdaddr} local_name:{local_name} mfdata:{l_data}')
         if q:
             q.put(BLEDevice(
                 l_bdaddr,
                 local_name,
                 e,
                 uuids=l_uuids,
                 manufacturer_data=l_data,
             ))
コード例 #14
0
async def discover(timeout: float = 5.0, **kwargs) -> List[BLEDevice]:
    """Perform a Bluetooth LE Scan using Windows.Devices.Bluetooth.Advertisement

    Args:
        timeout (float): Time to scan for.

    Keyword Args:
        SignalStrengthFilter (Windows.Devices.Bluetooth.BluetoothSignalStrengthFilter): A
          BluetoothSignalStrengthFilter object used for configuration of Bluetooth
          LE advertisement filtering that uses signal strength-based filtering.
        AdvertisementFilter (Windows.Devices.Bluetooth.Advertisement.BluetoothLEAdvertisementFilter): A
          BluetoothLEAdvertisementFilter object used for configuration of Bluetooth LE
          advertisement filtering that uses payload section-based filtering.
        string_output (bool): If set to false, ``discover`` returns .NET
            device objects instead.

    Returns:
        List of strings or objects found.

    """
    signal_strength_filter = kwargs.get("SignalStrengthFilter", None)
    advertisement_filter = kwargs.get("AdvertisementFilter", None)

    watcher = BluetoothLEAdvertisementWatcher()

    devices = {}
    scan_responses = {}

    def _format_bdaddr(a):
        return ":".join("{:02X}".format(x)
                        for x in a.to_bytes(6, byteorder="big"))

    def _format_event_args(e):
        try:
            return "{0}: {1}".format(
                _format_bdaddr(e.BluetoothAddress),
                e.Advertisement.LocalName or "Unknown",
            )
        except Exception:
            return e.BluetoothAddress

    def AdvertisementWatcher_Received(sender, e):
        if sender == watcher:
            logger.debug("Received {0}.".format(_format_event_args(e)))
            if e.AdvertisementType == BluetoothLEAdvertisementType.ScanResponse:
                if e.BluetoothAddress not in scan_responses:
                    scan_responses[e.BluetoothAddress] = e
            else:
                if e.BluetoothAddress not in devices:
                    devices[e.BluetoothAddress] = e

    def AdvertisementWatcher_Stopped(sender, e):
        if sender == watcher:
            logger.debug("{0} devices found. Watcher status: {1}.".format(
                len(devices), watcher.Status))

    watcher.Received += AdvertisementWatcher_Received
    watcher.Stopped += AdvertisementWatcher_Stopped

    watcher.ScanningMode = BluetoothLEScanningMode.Active

    if signal_strength_filter is not None:
        watcher.SignalStrengthFilter = signal_strength_filter
    if advertisement_filter is not None:
        watcher.AdvertisementFilter = advertisement_filter

    # Watcher works outside of the Python process.
    watcher.Start()
    await asyncio.sleep(timeout)
    watcher.Stop()

    try:
        watcher.Received -= AdvertisementWatcher_Received
        watcher.Stopped -= AdvertisementWatcher_Stopped
    except Exception as e:
        logger.debug("Could not remove event handlers: {0}...".format(e))

    found = []
    for d in list(devices.values()):
        bdaddr = _format_bdaddr(d.BluetoothAddress)
        uuids = []
        for u in d.Advertisement.ServiceUuids:
            uuids.append(u.ToString())
        data = {}
        for m in d.Advertisement.ManufacturerData:
            with BleakDataReader(m.Data) as reader:
                data[m.CompanyId] = reader.read()
        local_name = d.Advertisement.LocalName
        if not local_name and d.BluetoothAddress in scan_responses:
            local_name = scan_responses[
                d.BluetoothAddress].Advertisement.LocalName
        found.append(
            BLEDevice(
                bdaddr,
                local_name,
                d,
                uuids=uuids,
                manufacturer_data=data,
            ))

    return found
コード例 #15
0
ファイル: __init__.py プロジェクト: jbouwh/core
"""Tests for the Fjäråskupan integration."""


from bleak.backends.device import BLEDevice
from bleak.backends.scanner import AdvertisementData

from homeassistant.components.bluetooth import BluetoothServiceInfoBleak

COOKER_SERVICE_INFO = BluetoothServiceInfoBleak(
    name="COOKERHOOD_FJAR",
    address="AA:BB:CC:DD:EE:FF",
    rssi=-60,
    manufacturer_data={},
    service_uuids=[],
    service_data={},
    source="local",
    device=BLEDevice(address="AA:BB:CC:DD:EE:FF", name="COOKERHOOD_FJAR"),
    advertisement=AdvertisementData(),
    time=0,
    connectable=True,
)
コード例 #16
0
async def discover_by_enumeration(timeout: float = 5.0,
                                  **kwargs) -> List[BLEDevice]:
    """Perform a Bluetooth LE Scan using Windows.Devices.Enumeration

    Args:
        timeout (float): Time to scan for.

    Keyword Args:
        string_output (bool): If set to false, ``discover`` returns .NET
            device objects instead.

    Returns:
        List of strings or objects found.

    """
    requested_properties = Array[str]([
        "System.Devices.Aep.DeviceAddress",
        "System.Devices.Aep.IsConnected",
        "System.Devices.Aep.Bluetooth.Le.IsConnectable",
        "System.ItemNameDisplay",
        "System.Devices.Aep.Manufacturer",
        "System.Devices.Manufacturer",
        "System.Devices.Aep.ModelName",
        "System.Devices.ModelName",
        "System.Devices.Aep.SignalStrength",
    ])
    aqs_all_bluetooth_le_devices = ('(System.Devices.Aep.ProtocolId:="'
                                    '{bb7bb05e-5972-42b5-94fc-76eaa7084d49}")')
    watcher = Enumeration.DeviceInformation.CreateWatcher(
        aqs_all_bluetooth_le_devices,
        requested_properties,
        Enumeration.DeviceInformationKind.AssociationEndpoint,
    )

    devices = {}

    def _format_device_info(d):
        try:
            return "{0}: {1}".format(
                d.Id.split("-")[-1], d.Name if d.Name else "Unknown")
        except Exception:
            return d.Id

    def DeviceWatcher_Added(sender, dinfo):
        if sender == watcher:

            logger.debug("Added {0}.".format(_format_device_info(dinfo)))
            if dinfo.Id not in devices:
                devices[dinfo.Id] = dinfo

    def DeviceWatcher_Updated(sender, dinfo_update):
        if sender == watcher:
            if dinfo_update.Id in devices:
                logger.debug("Updated {0}.".format(
                    _format_device_info(devices[dinfo_update.Id])))
                devices[dinfo_update.Id].Update(dinfo_update)

    def DeviceWatcher_Removed(sender, dinfo_update):
        if sender == watcher:
            logger.debug("Removed {0}.".format(
                _format_device_info(devices[dinfo_update.Id])))
            if dinfo_update.Id in devices:
                devices.pop(dinfo_update.Id)

    def DeviceWatcher_EnumCompleted(sender, obj):
        if sender == watcher:
            logger.debug(
                "{0} devices found. Enumeration completed. Watching for updates..."
                .format(len(devices)))

    def DeviceWatcher_Stopped(sender, obj):
        if sender == watcher:
            logger.debug("{0} devices found. Watcher status: {1}.".format(
                len(devices), watcher.Status))

    watcher.Added += DeviceWatcher_Added
    watcher.Updated += DeviceWatcher_Updated
    watcher.Removed += DeviceWatcher_Removed
    watcher.EnumerationCompleted += DeviceWatcher_EnumCompleted
    watcher.Stopped += DeviceWatcher_Stopped

    # Watcher works outside of the Python process.
    watcher.Start()
    await asyncio.sleep(timeout)
    watcher.Stop()

    try:
        watcher.Added -= DeviceWatcher_Added
        watcher.Updated -= DeviceWatcher_Updated
        watcher.Removed -= DeviceWatcher_Removed
        watcher.EnumerationCompleted -= DeviceWatcher_EnumCompleted
        watcher.Stopped -= DeviceWatcher_Stopped
    except Exception as e:
        logger.debug("Could not remove event handlers: {0}...".format(e))

    found = []
    for d in devices.values():
        properties = {p.Key: p.Value for p in d.Properties}
        found.append(
            BLEDevice(
                properties["System.Devices.Aep.DeviceAddress"],
                d.Name,
                d,
                uuids=[],
                manufacturer_data=b"",
            ))

    return found
コード例 #17
0
ファイル: discovery.py プロジェクト: workaroundgmbh/bleak
async def discover(timeout: float = 5.0,
                   loop: AbstractEventLoop = None,
                   **kwargs) -> List[BLEDevice]:
    """Perform a Bluetooth LE Scan.

    Args:
        timeout (float): duration of scaning period
        loop (Event Loop): Event Loop to use

    """
    loop = loop if loop else asyncio.get_event_loop()

    devices = {}

    if not cbapp.central_manager_delegate.enabled:
        raise BleakError("Bluetooth device is turned off")

    scan_options = {"timeout": timeout}

    await cbapp.central_manager_delegate.scanForPeripherals_(scan_options)

    # CoreBluetooth doesn't explicitly use MAC addresses to identify peripheral
    # devices because private devices may obscure their MAC addresses. To cope
    # with this, CoreBluetooth utilizes UUIDs for each peripheral. We'll use
    # this for the BLEDevice address on macOS

    found = []

    peripherals = cbapp.central_manager_delegate.peripheral_list

    for i, peripheral in enumerate(peripherals):
        address = peripheral.identifier().UUIDString()
        name = peripheral.name() or "Unknown"
        details = peripheral

        advertisementData = cbapp.central_manager_delegate.advertisement_data_list[
            i]
        manufacturer_binary_data = (
            advertisementData["kCBAdvDataManufacturerData"] if
            "kCBAdvDataManufacturerData" in advertisementData.keys() else None)
        manufacturer_data = {}
        if manufacturer_binary_data:
            manufacturer_id = int.from_bytes(manufacturer_binary_data[0:2],
                                             byteorder="little")
            manufacturer_value = "".join(
                list(
                    map(
                        lambda x: format(x, "x")
                        if len(format(x, "x")) == 2 else "0{}".format(
                            format(x, "x")),
                        list(manufacturer_binary_data)[2:],
                    )))
            manufacturer_data = {manufacturer_id: manufacturer_value}

        found.append(
            BLEDevice(address,
                      name,
                      details,
                      manufacturer_data=manufacturer_data))

    return found
コード例 #18
0
from homeassistant.components.bluetooth import BluetoothServiceInfoBleak

YALE_ACCESS_LOCK_DISCOVERY_INFO = BluetoothServiceInfoBleak(
    name="M1012LU",
    address="AA:BB:CC:DD:EE:FF",
    rssi=-60,
    manufacturer_data={
        465: b"\x00\x00\xd1\xf0b;\xd8\x1dE\xd6\xba\xeeL\xdd]\xf5\xb2\xe9",
        76:
        b"\x061\x00Z\x8f\x93\xb2\xec\x85\x06\x00i\x00\x02\x02Q\xed\x1d\xf0",
    },
    service_uuids=[],
    service_data={},
    source="local",
    device=BLEDevice(address="AA:BB:CC:DD:EE:FF", name="M1012LU"),
    advertisement=AdvertisementData(),
    time=0,
    connectable=True,
)

LOCK_DISCOVERY_INFO_UUID_ADDRESS = BluetoothServiceInfoBleak(
    name="M1012LU",
    address="61DE521B-F0BF-9F44-64D4-75BBE1738105",
    rssi=-60,
    manufacturer_data={
        465: b"\x00\x00\xd1\xf0b;\xd8\x1dE\xd6\xba\xeeL\xdd]\xf5\xb2\xe9",
        76:
        b"\x061\x00Z\x8f\x93\xb2\xec\x85\x06\x00i\x00\x02\x02Q\xed\x1d\xf0",
    },
    service_uuids=[],
コード例 #19
0
ファイル: __init__.py プロジェクト: jbouwh/core
WOHAND_SERVICE_INFO = BluetoothServiceInfoBleak(
    name="WoHand",
    manufacturer_data={89: b"\xfd`0U\x92W"},
    service_data={"00000d00-0000-1000-8000-00805f9b34fb": b"H\x90\xd9"},
    service_uuids=["cba20d00-224d-11e6-9fb8-0002a5d5c51b"],
    address="aa:bb:cc:dd:ee:ff",
    rssi=-60,
    source="local",
    advertisement=AdvertisementData(
        local_name="WoHand",
        manufacturer_data={89: b"\xfd`0U\x92W"},
        service_data={"00000d00-0000-1000-8000-00805f9b34fb": b"H\x90\xd9"},
        service_uuids=["cba20d00-224d-11e6-9fb8-0002a5d5c51b"],
    ),
    device=BLEDevice("aa:bb:cc:dd:ee:ff", "WoHand"),
    time=0,
    connectable=True,
)

WOHAND_SERVICE_INFO_NOT_CONNECTABLE = BluetoothServiceInfoBleak(
    name="WoHand",
    manufacturer_data={89: b"\xfd`0U\x92W"},
    service_data={"00000d00-0000-1000-8000-00805f9b34fb": b"H\x90\xd9"},
    service_uuids=["cba20d00-224d-11e6-9fb8-0002a5d5c51b"],
    address="aa:bb:cc:dd:ee:ff",
    rssi=-60,
    source="local",
    advertisement=AdvertisementData(
        local_name="WoHand",
        manufacturer_data={89: b"\xfd`0U\x92W"},
コード例 #20
0
ファイル: __init__.py プロジェクト: jbouwh/core
"""Tests for the LED BLE Bluetooth integration."""
from bleak.backends.device import BLEDevice
from bleak.backends.scanner import AdvertisementData

from homeassistant.components.bluetooth import BluetoothServiceInfoBleak

LED_BLE_DISCOVERY_INFO = BluetoothServiceInfoBleak(
    name="Triones:F30200000152C",
    address="AA:BB:CC:DD:EE:FF",
    rssi=-60,
    manufacturer_data={},
    service_uuids=[],
    service_data={},
    source="local",
    device=BLEDevice(address="AA:BB:CC:DD:EE:FF", name="Triones:F30200000152C"),
    advertisement=AdvertisementData(),
    time=0,
    connectable=True,
)

UNSUPPORTED_LED_BLE_DISCOVERY_INFO = BluetoothServiceInfoBleak(
    name="LEDnetWFF30200000152C",
    address="AA:BB:CC:DD:EE:FF",
    rssi=-60,
    manufacturer_data={},
    service_uuids=[],
    service_data={},
    source="local",
    device=BLEDevice(address="AA:BB:CC:DD:EE:FF", name="LEDnetWFF30200000152C"),
    advertisement=AdvertisementData(),
    time=0,
コード例 #21
0
ファイル: scanner.py プロジェクト: jsotogaviard/bleak-1
    def parse_msg(self, message):
        if message.member == "InterfacesAdded":
            msg_path = message.body[0]
            try:
                device_interface = message.body[1].get(defs.DEVICE_INTERFACE,
                                                       {})
            except Exception as e:
                raise e
            self._devices[msg_path] = ({
                **self._devices[msg_path],
                **device_interface
            } if msg_path in self._devices else device_interface)
        elif message.member == "PropertiesChanged":
            iface, changed, invalidated = message.body
            if iface != defs.DEVICE_INTERFACE:
                return

            msg_path = message.path
            # the PropertiesChanged signal only sends changed properties, so we
            # need to get remaining properties from cached_devices. However, we
            # don't want to add all cached_devices to the devices dict since
            # they may not actually be nearby or powered on.
            if msg_path not in self._devices and msg_path in self._cached_devices:
                self._devices[msg_path] = self._cached_devices[msg_path]
            self._devices[msg_path] = ({
                **self._devices[msg_path],
                **changed
            } if msg_path in self._devices else changed)

            if self._callback is None:
                return

            props = self._devices[msg_path]

            # Get all the information wanted to pack in the advertisement data
            _local_name = props.get("Name")
            _manufacturer_data = {
                k: bytes(v)
                for k, v in props.get("ManufacturerData", {}).items()
            }
            _service_data = {
                k: bytes(v)
                for k, v in props.get("ServiceData", {}).items()
            }
            _service_uuids = props.get("UUIDs", [])

            # Pack the advertisement data
            advertisement_data = AdvertisementData(
                local_name=_local_name,
                manufacturer_data=_manufacturer_data,
                service_data=_service_data,
                service_uuids=_service_uuids,
                platform_data=(props, message),
            )

            device = BLEDevice(props["Address"], props["Alias"], props,
                               props.get("RSSI", 0))

            self._callback(device, advertisement_data)

        elif (message.member == "InterfacesRemoved"
              and message.body[1][0] == defs.BATTERY_INTERFACE):
            logger.debug("{0}, {1} ({2}): {3}".format(message.member,
                                                      message.interface,
                                                      message.path,
                                                      message.body))
            return
        else:
            msg_path = message.path
            logger.debug("{0}, {1} ({2}): {3}".format(message.member,
                                                      message.interface,
                                                      message.path,
                                                      message.body))

        logger.debug("{0}, {1} ({2} dBm), Object Path: {3}".format(
            *_device_info(msg_path, self._devices.get(msg_path))))
コード例 #22
0
async def discover(timeout: float = 5.0,
                   loop: AbstractEventLoop = None,
                   **kwargs) -> List[BLEDevice]:
    """Perform a Bluetooth LE Scan using Windows.Devices.Bluetooth.Advertisement

    Args:
        timeout (float): Time to scan for.
        loop (Event Loop): The event loop to use.

    Keyword Args:
        string_output (bool): If set to false, ``discover`` returns .NET
            device objects instead.

    Returns:
        List of strings or objects found.

    """
    loop = loop if loop else asyncio.get_event_loop()

    watcher = BluetoothLEAdvertisementWatcher()

    devices = {}
    scan_responses = {}

    def _format_bdaddr(a):
        return ":".join("{:02X}".format(x)
                        for x in a.to_bytes(6, byteorder="big"))

    def _format_event_args(e):
        try:
            return "{0}: {1}".format(
                _format_bdaddr(e.BluetoothAddress),
                e.Advertisement.LocalName or "Unknown",
            )
        except Exception:
            return e.BluetoothAddress

    def AdvertisementWatcher_Received(sender, e):
        if sender == watcher:
            logger.debug("Received {0}.".format(_format_event_args(e)))
            if e.AdvertisementType == BluetoothLEAdvertisementType.ScanResponse:
                if e.BluetoothAddress not in scan_responses:
                    scan_responses[e.BluetoothAddress] = e
            else:
                if e.BluetoothAddress not in devices:
                    devices[e.BluetoothAddress] = e

    def AdvertisementWatcher_Stopped(sender, e):
        if sender == watcher:
            logger.debug("{0} devices found. Watcher status: {1}.".format(
                len(devices), watcher.Status))

    watcher.Received += AdvertisementWatcher_Received
    watcher.Stopped += AdvertisementWatcher_Stopped

    watcher.ScanningMode = BluetoothLEScanningMode.Active

    # Watcher works outside of the Python process.
    watcher.Start()
    await asyncio.sleep(timeout, loop=loop)
    watcher.Stop()

    try:
        watcher.Received -= AdvertisementWatcher_Received
        watcher.Stopped -= AdvertisementWatcher_Stopped
    except Exception as e:
        logger.debug("Could not remove event handlers: {0}...".format(e))

    found = []
    for d in devices.values():
        bdaddr = _format_bdaddr(d.BluetoothAddress)
        uuids = []
        for u in d.Advertisement.ServiceUuids:
            uuids.append(u.ToString())
        data = {}
        for m in d.Advertisement.ManufacturerData:
            md = IBuffer(m.Data)
            b = Array.CreateInstance(Byte, md.Length)
            reader = DataReader.FromBuffer(md)
            reader.ReadBytes(b)
            data[m.CompanyId] = bytes(b)
        local_name = d.Advertisement.LocalName
        if not local_name and d.BluetoothAddress in scan_responses:
            local_name = scan_responses[
                d.BluetoothAddress].Advertisement.LocalName
        found.append(
            BLEDevice(
                bdaddr,
                local_name,
                d,
                uuids=uuids,
                manufacturer_data=data,
            ))

    return found
コード例 #23
0
ファイル: __init__.py プロジェクト: jbouwh/core
"""Tests for the BThome integration."""

from bleak.backends.device import BLEDevice
from bleak.backends.scanner import AdvertisementData

from homeassistant.components.bluetooth import BluetoothServiceInfoBleak

TEMP_HUMI_SERVICE_INFO = BluetoothServiceInfoBleak(
    name="ATC 8D18B2",
    address="A4:C1:38:8D:18:B2",
    device=BLEDevice("A4:C1:38:8D:18:B2", None),
    rssi=-63,
    manufacturer_data={},
    service_data={
        "0000181c-0000-1000-8000-00805f9b34fb": b"#\x02\xca\t\x03\x03\xbf\x13"
    },
    service_uuids=["0000181c-0000-1000-8000-00805f9b34fb"],
    source="local",
    advertisement=AdvertisementData(local_name="Not it"),
    time=0,
    connectable=False,
)

TEMP_HUMI_ENCRYPTED_SERVICE_INFO = BluetoothServiceInfoBleak(
    name="TEST DEVICE 8F80A5",
    address="54:48:E6:8F:80:A5",
    device=BLEDevice("54:48:E6:8F:80:A5", None),
    rssi=-63,
    manufacturer_data={},
    service_data={
        "0000181e-0000-1000-8000-00805f9b34fb":
コード例 #24
0
ファイル: discovery.py プロジェクト: tlongeri/bleak
async def discover(timeout=5.0, loop=None, **kwargs):
    """Discover nearby Bluetooth Low Energy devices.

    Args:
        timeout (float): Duration to scan for.
        loop (asyncio.AbstractEventLoop): Optional event loop to use.

    Keyword Args:
        device (str): Bluetooth device to use for discovery.

    Returns:
        List of tuples containing name, address and signal strength
        of nearby devices.

    """
    device = kwargs.get("device", "hci0")
    loop = loop if loop else asyncio.get_event_loop()
    cached_devices = {}
    devices = {}
    rules = list()

    def parse_msg(message):
        if message.member == "InterfacesAdded":
            msg_path = message.body[0]
            try:
                device_interface = message.body[1].get("org.bluez.Device1", {})
            except Exception as e:
                raise e
            devices[msg_path] = (
                {**devices[msg_path], **device_interface}
                if msg_path in devices
                else device_interface
            )
        elif message.member == "PropertiesChanged":
            iface, changed, invalidated = message.body
            if iface != defs.DEVICE_INTERFACE:
                return

            msg_path = message.path
            # the PropertiesChanged signal only sends changed properties, so we
            # need to get remaining properties from cached_devices. However, we
            # don't want to add all cached_devices to the devices dict since
            # they may not actually be nearby or powered on.
            if msg_path not in devices and msg_path in cached_devices:
                devices[msg_path] = cached_devices[msg_path]
            devices[msg_path] = (
                {**devices[msg_path], **changed} if msg_path in devices else changed
            )
        elif (
            message.member == "InterfacesRemoved"
            and message.body[1][0] == defs.BATTERY_INTERFACE
        ):
            logger.info(
                "{0}, {1} ({2}): {3}".format(
                    message.member, message.interface, message.path, message.body
                )
            )
            return
        else:
            msg_path = message.path
            logger.info(
                "{0}, {1} ({2}): {3}".format(
                    message.member, message.interface, message.path, message.body
                )
            )

        logger.info(
            "{0}, {1} ({2} dBm), Object Path: {3}".format(
                *_device_info(msg_path, devices.get(msg_path))
            )
        )

    bus = await client.connect(reactor, "system").asFuture(loop)

    # Add signal listeners
    rules.append(
        await bus.addMatch(
            parse_msg,
            interface="org.freedesktop.DBus.ObjectManager",
            member="InterfacesAdded",
        ).asFuture(loop)
    )
    rules.append(
        await bus.addMatch(
            parse_msg,
            interface="org.freedesktop.DBus.ObjectManager",
            member="InterfacesRemoved",
        ).asFuture(loop)
    )
    rules.append(
        await bus.addMatch(
            parse_msg,
            interface="org.freedesktop.DBus.Properties",
            member="PropertiesChanged",
        ).asFuture(loop)
    )

    # Find the HCI device to use for scanning and get cached device properties
    objects = await bus.callRemote(
        "/",
        "GetManagedObjects",
        interface=defs.OBJECT_MANAGER_INTERFACE,
        destination=defs.BLUEZ_SERVICE,
    ).asFuture(loop)
    adapter_path, interface = _filter_on_adapter(objects, device)
    cached_devices = dict(_filter_on_device(objects))

    # dd = {'objectPath': '/org/bluez/hci0', 'methodName': 'StartDiscovery',
    # 'interface': 'org.bluez.Adapter1', 'destination': 'org.bluez',
    # 'signature': '', 'body': (), 'expectReply': True, 'autoStart': True,
    # 'timeout': None, 'returnSignature': ''}
    # Running Discovery loop.
    await bus.callRemote(
        adapter_path,
        "SetDiscoveryFilter",
        interface="org.bluez.Adapter1",
        destination="org.bluez",
        signature="a{sv}",
        body=[{"Transport": "le"}],
    ).asFuture(loop)
    await bus.callRemote(
        adapter_path,
        "StartDiscovery",
        interface="org.bluez.Adapter1",
        destination="org.bluez",
    ).asFuture(loop)
    await asyncio.sleep(timeout)
    await bus.callRemote(
        adapter_path,
        "StopDiscovery",
        interface="org.bluez.Adapter1",
        destination="org.bluez",
    ).asFuture(loop)

    # Reduce output.
    # out = []
    # for path, props in devices.items():
    #    properties = await cli.callRemote(
    #        path, 'GetAll',
    #        interface=defs.PROPERTIES_INTERFACE,
    #        destination=defs.BLUEZ_SERVICE,
    #        signature='s',
    #        body=[defs.DEVICE_INTERFACE, ],
    #        returnSignature='a{sv}').asFuture(loop)
    #    print(properties)
    #
    discovered_devices = []
    for path, props in devices.items():
        if not props:
            logger.debug(
                "Disregarding %s since no properties could be obtained." % path
            )
            continue
        name, address, _, path = _device_info(path, props)
        uuids = props.get("UUIDs", [])
        manufacturer_data = props.get("ManufacturerData", {})
        discovered_devices.append(
            BLEDevice(
                address,
                name,
                {"path": path, "props": props},
                uuids=uuids,
                manufacturer_data=manufacturer_data,
            )
        )

    for rule in rules:
        await bus.delMatch(rule).asFuture(loop)

    bus.disconnect()

    return discovered_devices
コード例 #25
0
ファイル: discovery.py プロジェクト: cteqeu/bleak
async def discover(timeout=5.0, loop=None, **kwargs):
    """Discover nearby Bluetooth Low Energy devices.

    Args:
        timeout (float): Duration to scan for.
        loop (asyncio.AbstractEventLoop): Optional event loop to use.

    Keyword Args:
        device (str): Bluetooth device to use for discovery.

    Returns:
        List of tuples containing name, address and signal strength
        of nearby devices.

    """
    device = kwargs.get("device", "hci0")
    loop = loop if loop else asyncio.get_event_loop()
    devices = {}

    def parse_msg(message):
        if message.member in ("InterfacesAdded", "InterfacesRemoved"):
            msg_path = message.body[0]
            device_interface = message.body[1].get("org.bluez.Device1", {})
            devices[msg_path] = {
                **devices[msg_path],
                **device_interface
            } if msg_path in devices else device_interface
        elif message.member == "PropertiesChanged":
            iface, changed, invalidated = message.body
            if iface != defs.DEVICE_INTERFACE:
                return

            msg_path = message.path
            devices[msg_path] = {
                **devices[msg_path],
                **changed
            } if msg_path in devices else changed
        else:
            msg_path = message.path
            logger.info("{0}, {1} ({2}): {3}".format(message.member,
                                                     message.interface,
                                                     message.path,
                                                     message.body))

        logger.info("{0}, {1} ({2} dBm), Object Path: {3}".format(
            *_device_info(msg_path, devices.get(msg_path))))

    # Find the HCI device to use for scanning.
    bus = await client.connect(reactor, "system").asFuture(loop)
    objects = await bus.callRemote(
        "/",
        "GetManagedObjects",
        interface=defs.OBJECT_MANAGER_INTERFACE,
        destination=defs.BLUEZ_SERVICE,
    ).asFuture(loop)
    adapter_path, interface = _filter_on_adapter(objects, device)

    # Add signal listeners
    await bus.addMatch(
        parse_msg,
        interface="org.freedesktop.DBus.ObjectManager",
        member="InterfacesAdded",
    ).asFuture(loop)
    await bus.addMatch(
        parse_msg,
        interface="org.freedesktop.DBus.ObjectManager",
        member="InterfacesRemoved",
    ).asFuture(loop)
    await bus.addMatch(
        parse_msg,
        interface="org.freedesktop.DBus.Properties",
        member="PropertiesChanged",
    ).asFuture(loop)
    await bus.addMatch(parse_msg,
                       interface="org.bluez.Adapter1",
                       member="PropertyChanged").asFuture(loop)

    # dd = {'objectPath': '/org/bluez/hci0', 'methodName': 'StartDiscovery',
    # 'interface': 'org.bluez.Adapter1', 'destination': 'org.bluez',
    # 'signature': '', 'body': (), 'expectReply': True, 'autoStart': True,
    # 'timeout': None, 'returnSignature': ''}
    # Running Discovery loop.
    await bus.callRemote(
        adapter_path,
        "StartDiscovery",
        interface="org.bluez.Adapter1",
        destination="org.bluez",
    ).asFuture(loop)
    await asyncio.sleep(timeout)
    await bus.callRemote(
        adapter_path,
        "StopDiscovery",
        interface="org.bluez.Adapter1",
        destination="org.bluez",
    ).asFuture(loop)

    # Reduce output.
    # out = []
    # for path, props in devices.items():
    #    properties = await cli.callRemote(
    #        path, 'GetAll',
    #        interface=defs.PROPERTIES_INTERFACE,
    #        destination=defs.BLUEZ_SERVICE,
    #        signature='s',
    #        body=[defs.DEVICE_INTERFACE, ],
    #        returnSignature='a{sv}').asFuture(loop)
    #    print(properties)
    #
    discovered_devices = []
    for path, props in devices.items():
        name, address, _, path = _device_info(path, props)
        discovered_devices.append(BLEDevice(address, name, path))
    return discovered_devices
コード例 #26
0
ファイル: discovery.py プロジェクト: satyajitghana/bleak
async def discover(timeout=5.0, loop=None, **kwargs):
    """Discover nearby Bluetooth Low Energy devices.

    For possible values for `filters`, see the parameters to the
    ``SetDiscoveryFilter`` method in the `BlueZ docs
    <https://git.kernel.org/pub/scm/bluetooth/bluez.git/tree/doc/adapter-api.txt?h=5.48&id=0d1e3b9c5754022c779da129025d493a198d49cf>`_

    The ``Transport`` parameter is always set to ``le`` by default in Bleak.

    Args:
        timeout (float): Duration to scan for.
        loop (asyncio.AbstractEventLoop): Optional event loop to use.

    Keyword Args:
        device (str): Bluetooth device to use for discovery.
        filters (dict): A dict of filters to be applied on discovery.

    Returns:
        List of tuples containing name, address and signal strength
        of nearby devices.

    """
    device = kwargs.get("device", "hci0")
    loop = loop if loop else asyncio.get_event_loop()
    cached_devices = {}
    devices = {}
    rules = list()
    reactor = get_reactor(loop)

    # Discovery filters
    filters = kwargs.get("filters", {})
    filters["Transport"] = "le"

    def parse_msg(message):
        if message.member == "InterfacesAdded":
            msg_path = message.body[0]
            try:
                device_interface = message.body[1].get("org.bluez.Device1", {})
            except Exception as e:
                raise e
            devices[msg_path] = ({
                **devices[msg_path],
                **device_interface
            } if msg_path in devices else device_interface)
        elif message.member == "PropertiesChanged":
            iface, changed, invalidated = message.body
            if iface != defs.DEVICE_INTERFACE:
                return

            msg_path = message.path
            # the PropertiesChanged signal only sends changed properties, so we
            # need to get remaining properties from cached_devices. However, we
            # don't want to add all cached_devices to the devices dict since
            # they may not actually be nearby or powered on.
            if msg_path not in devices and msg_path in cached_devices:
                devices[msg_path] = cached_devices[msg_path]
            devices[msg_path] = ({
                **devices[msg_path],
                **changed
            } if msg_path in devices else changed)
        elif (message.member == "InterfacesRemoved"
              and message.body[1][0] == defs.BATTERY_INTERFACE):
            logger.info("{0}, {1} ({2}): {3}".format(message.member,
                                                     message.interface,
                                                     message.path,
                                                     message.body))
            return
        else:
            msg_path = message.path
            logger.info("{0}, {1} ({2}): {3}".format(message.member,
                                                     message.interface,
                                                     message.path,
                                                     message.body))

        logger.info("{0}, {1} ({2} dBm), Object Path: {3}".format(
            *_device_info(msg_path, devices.get(msg_path))))

    bus = await client.connect(reactor, "system").asFuture(loop)

    # Add signal listeners
    rules.append(await bus.addMatch(
        parse_msg,
        interface="org.freedesktop.DBus.ObjectManager",
        member="InterfacesAdded",
        path_namespace="/org/bluez",
    ).asFuture(loop))

    rules.append(await bus.addMatch(
        parse_msg,
        interface="org.freedesktop.DBus.ObjectManager",
        member="InterfacesRemoved",
        path_namespace="/org/bluez",
    ).asFuture(loop))

    rules.append(await bus.addMatch(
        parse_msg,
        interface="org.freedesktop.DBus.Properties",
        member="PropertiesChanged",
        path_namespace="/org/bluez",
    ).asFuture(loop))

    # Find the HCI device to use for scanning and get cached device properties
    objects = await bus.callRemote(
        "/",
        "GetManagedObjects",
        interface=defs.OBJECT_MANAGER_INTERFACE,
        destination=defs.BLUEZ_SERVICE,
    ).asFuture(loop)
    adapter_path, interface = _filter_on_adapter(objects, device)
    cached_devices = dict(_filter_on_device(objects))

    # Running Discovery loop.
    await bus.callRemote(
        adapter_path,
        "SetDiscoveryFilter",
        interface="org.bluez.Adapter1",
        destination="org.bluez",
        signature="a{sv}",
        body=[filters],
    ).asFuture(loop)

    await bus.callRemote(
        adapter_path,
        "StartDiscovery",
        interface="org.bluez.Adapter1",
        destination="org.bluez",
    ).asFuture(loop)

    await asyncio.sleep(timeout)

    await bus.callRemote(
        adapter_path,
        "StopDiscovery",
        interface="org.bluez.Adapter1",
        destination="org.bluez",
    ).asFuture(loop)

    # Reduce output.
    discovered_devices = []
    for path, props in devices.items():
        if not props:
            logger.debug(
                "Disregarding %s since no properties could be obtained." %
                path)
            continue
        name, address, _, path = _device_info(path, props)
        if address is None:
            continue
        uuids = props.get("UUIDs", [])
        manufacturer_data = props.get("ManufacturerData", {})
        discovered_devices.append(
            BLEDevice(
                address,
                name,
                {
                    "path": path,
                    "props": props
                },
                uuids=uuids,
                manufacturer_data=manufacturer_data,
            ))

    for rule in rules:
        await bus.delMatch(rule).asFuture(loop)

    # Try to disconnect the System Bus.
    try:
        bus.disconnect()
    except Exception as e:
        logger.error("Attempt to disconnect system bus failed: {0}".format(e))

    return discovered_devices
コード例 #27
0
"""Tests for the SensorPush integration."""

from bleak.backends.device import BLEDevice
from bleak.backends.scanner import AdvertisementData

from homeassistant.components.bluetooth import BluetoothServiceInfoBleak

NOT_SENSOR_PUSH_SERVICE_INFO = BluetoothServiceInfoBleak(
    name="Not it",
    address="00:00:00:00:00:00",
    device=BLEDevice("00:00:00:00:00:00", None),
    rssi=-63,
    manufacturer_data={3234: b"\x00\x01"},
    service_data={},
    service_uuids=[],
    source="local",
    advertisement=AdvertisementData(local_name="Not it"),
    time=0,
    connectable=False,
)

LYWSDCGQ_SERVICE_INFO = BluetoothServiceInfoBleak(
    name="LYWSDCGQ",
    address="58:2D:34:35:93:21",
    device=BLEDevice("00:00:00:00:00:00", None),
    rssi=-63,
    manufacturer_data={},
    service_data={
        "0000fe95-0000-1000-8000-00805f9b34fb":
        b"P \xaa\x01\xda!\x9354-X\r\x10\x04\xfe\x00H\x02"
    },