Ejemplo n.º 1
0
    def write_characteristic(self, sender: GattLocalCharacteristic,
                             args: GattWriteRequestedEventArgs):
        """
        Called by pythonnet when a write request is submitted

        Parameters
        ----------
        sender : GattLocalCharacteristic
            The object representation of the gatt characteristic whose value we
            should write to
        args : GattWriteRequestedEventArgs
            The event arguments for the write request
        """

        deferral: Deferral = args.GetDeferral()
        request: GattWriteRequest = sync_async_wrap(GattWriteRequest,
                                                    args.GetRequestAsync)
        logger.debug("Request value: {}".format(request.Value))
        reader: DataReader = DataReader.FromBuffer(request.Value)
        n_bytes: int = reader.UnconsumedBufferLength
        value: bytearray = bytearray()
        for n in range(0, n_bytes):
            next_byte: int = reader.ReadByte()
            value.append(next_byte)

        logger.debug("Written Value: {}".format(value))
        self.write_request(str(sender.Uuid), value)

        if request.Option == GattWriteOption.WriteWithResponse:
            request.Respond()

        logger.debug("Write Complete")
        deferral.Complete()
Ejemplo n.º 2
0
    def dotnet_notification_parser(sender: Any, args: Any):
        # Return only the UUID string representation as sender.
        # Also do a conversion from System.Bytes[] to bytearray.
        reader = DataReader.FromBuffer(args.CharacteristicValue)
        output = Array.CreateInstance(Byte, reader.UnconsumedBufferLength)
        reader.ReadBytes(output)

        return func(sender.Uuid.ToString(), bytearray(output))
Ejemplo n.º 3
0
def ProcessWriteCharacteristic(request, opCode):
    if (request.Value.Length != 4):
        print("Error with length in request!")
        exit()
    else:
        reader = DataReader.FromBuffer(request.Value)
        #reader.ByteOrder = ByteOrder.LittleEndian
        val = reader.ReadInt32()
        print(val)
Ejemplo n.º 4
0
    async def read_gatt_char(self,
                             char_specifier: Union[BleakGATTCharacteristic,
                                                   int, str, uuid.UUID],
                             use_cached=False,
                             **kwargs) -> bytearray:
        """Perform read operation on the specified GATT characteristic.

        Args:
            char_specifier (BleakGATTCharacteristic, int, str or UUID): The characteristic to read from,
                specified by either integer handle, UUID or directly by the
                BleakGATTCharacteristic object representing it.
            use_cached (bool): `False` forces Windows to read the value from the
                device again and not use its own cached value. Defaults to `False`.

        Returns:
            (bytearray) The read data.

        """
        if not isinstance(char_specifier, BleakGATTCharacteristic):
            characteristic = self.services.get_characteristic(char_specifier)
        else:
            characteristic = char_specifier
        if not characteristic:
            raise BleakError(
                "Characteristic {0} was not found!".format(char_specifier))

        read_result = await wrap_IAsyncOperation(
            IAsyncOperation[GattReadResult](characteristic.obj.ReadValueAsync(
                BluetoothCacheMode.
                Cached if use_cached else BluetoothCacheMode.Uncached)),
            return_type=GattReadResult,
            loop=self.loop,
        )
        if read_result.Status == GattCommunicationStatus.Success:
            reader = DataReader.FromBuffer(IBuffer(read_result.Value))
            output = Array.CreateInstance(Byte, reader.UnconsumedBufferLength)
            reader.ReadBytes(output)
            value = bytearray(output)
            logger.debug("Read Characteristic {0} : {1}".format(
                characteristic.uuid, value))
        else:
            if read_result.Status == GattCommunicationStatus.ProtocolError:
                raise BleakDotNetTaskError(
                    "Could not get GATT characteristics for {0}: {1} (Error: 0x{2:02X})"
                    .format(
                        characteristic.uuid,
                        _communication_statues.get(read_result.Status, ""),
                        read_result.ProtocolError,
                    ))
            else:
                raise BleakError(
                    "Could not read characteristic value for {0}: {1}".format(
                        characteristic.uuid,
                        _communication_statues.get(read_result.Status, ""),
                    ))
        return value
Ejemplo n.º 5
0
    async def read_gatt_descriptor(self,
                                   handle: int,
                                   use_cached=False,
                                   **kwargs) -> bytearray:
        """Perform read operation on the specified GATT descriptor.

        Args:
            handle (int): The handle of the descriptor to read from.
            use_cached (bool): `False` forces Windows to read the value from the
                device again and not use its own cached value. Defaults to `False`.

        Returns:
            (bytearray) The read data.

        """
        descriptor = self.services.get_descriptor(handle)
        if not descriptor:
            raise BleakError(
                "Descriptor with handle {0} was not found!".format(handle))

        read_result = await wrap_IAsyncOperation(
            IAsyncOperation[GattReadResult](descriptor.obj.ReadValueAsync(
                BluetoothCacheMode.
                Cached if use_cached else BluetoothCacheMode.Uncached)),
            return_type=GattReadResult,
            loop=self.loop,
        )
        if read_result.Status == GattCommunicationStatus.Success:
            reader = DataReader.FromBuffer(IBuffer(read_result.Value))
            output = Array.CreateInstance(Byte, reader.UnconsumedBufferLength)
            reader.ReadBytes(output)
            value = bytearray(output)
            logger.debug("Read Descriptor {0} : {1}".format(handle, value))
        else:
            if read_result.Status == GattCommunicationStatus.ProtocolError:
                raise BleakDotNetTaskError(
                    "Could not get GATT characteristics for {0}: {1} (Error: 0x{2:02X})"
                    .format(
                        descriptor.uuid,
                        _communication_statues.get(read_result.Status, ""),
                        read_result.ProtocolError,
                    ))
            else:
                raise BleakError(
                    "Could not read Descriptor value for {0}: {1}".format(
                        descriptor.uuid,
                        _communication_statues.get(read_result.Status, ""),
                    ))

        return value
Ejemplo n.º 6
0
        def write(sender: GattLocalCharacteristic,
                  args: GattWriteRequestedEventArgs):
            deferral: Deferral = args.GetDeferral()
            request: GattWriteRequest = sync_async_wrap(
                GattWriteRequest, args.GetRequestAsync)
            reader: DataReader = DataReader.FromBuffer(request.Value)
            n_bytes: int = reader.UnconsumedBufferLength
            value: bytearray = bytearray()
            for n in range(0, n_bytes):
                next_byte: int = reader.ReadByte()
                value.append(next_byte)
            self.val = value

            if request.Option == GattWriteOption.WriteWithResponse:
                request.Respond()

            deferral.Complete()
Ejemplo n.º 7
0
 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)
Ejemplo n.º 8
0
    async def read_gatt_char(self, _uuid: str, use_cached=False, **kwargs) -> bytearray:
        """Perform read operation on the specified GATT characteristic.

        Args:
            _uuid (str or UUID): The uuid of the characteristics to read from.
            use_cached (bool): `False` forces Windows to read the value from the
                device again and not use its own cached value. Defaults to `False`.

        Returns:
            (bytearray) The read data.

        """
        characteristic = self.services.get_characteristic(str(_uuid))
        if not characteristic:
            raise BleakError("Characteristic {0} was not found!".format(_uuid))

        read_result = await wrap_IAsyncOperation(
            IAsyncOperation[GattReadResult](
                characteristic.obj.ReadValueAsync(
                    BluetoothCacheMode.Cached
                    if use_cached
                    else BluetoothCacheMode.Uncached
                )
            ),
            return_type=GattReadResult,
            loop=self.loop,
        )
        if read_result.Status == GattCommunicationStatus.Success:
            reader = DataReader.FromBuffer(IBuffer(read_result.Value))
            output = Array.CreateInstance(Byte, reader.UnconsumedBufferLength)
            reader.ReadBytes(output)
            value = bytearray(output)
            logger.debug("Read Characteristic {0} : {1}".format(_uuid, value))
        else:
            raise BleakError(
                "Could not read characteristic value for {0}: {1}".format(
                    characteristic.uuid, read_result.Status
                )
            )
        return value
Ejemplo n.º 9
0
 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,
             ))
Ejemplo n.º 10
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:
        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)

    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

    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, 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 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:
            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
Ejemplo n.º 11
0
 def __enter__(self):
     self.reader = DataReader.FromBuffer(self.buffer)
     return self
Ejemplo n.º 12
0
async def discover(timeout: float = 5.0,
                   loop: AbstractEventLoop = None,
                   **kwargs) -> List[BLEDevice]:
    """Perform a Bluetooth LE Scan.

    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 = {}

    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.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 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)
        found.append(
            BLEDevice(bdaddr,
                      d.Advertisement.LocalName,
                      d,
                      uuids=uuids,
                      manufacturer_data=data))

    return found