virantha / bricknil

Control LEGO Bluetooth Sensors and Motors with Python
https://virantha.github.io/bricknil
Apache License 2.0
142 stars 39 forks source link

Windows 10 not reporting BLE UUID #3

Closed Entalyan closed 5 years ago

Entalyan commented 5 years ago

On my machine (Win10) the UUID is not actually showing, instead a MAC-like address is given. This has made it hard to select a specific device. From inside the main run() method in Train I have added

self.message_info("BLE_ID:"+self.ble_id)

which outputs

INFO:GreenCargoTrain.2:BLE_ID:90:84:2B:0B:DD:BF

I have tried setting the logging to DEBUG, and using all the UUID's that are in there, including the Device advertised UUID, but no luck. For example, without setting a specific UUID it finds the train:

INFO:BLE Event Q.0:checking manufacturer ID for device named Unknown for HUB NO.4
INFO:BLE Event Q.0:found device Unknown
INFO:BLE Event Q.0:Device advertised: {'00002a00-0000-1000-8000-00805f9b34fb': <Windows.Devices.Bluetooth.GenericAttributeProfile.GattCharacteristic object at 0x071A27D0>, '00002a01-0000-1000-8000-00805f9b34fb': <Windows.Devices.Bluetooth.GenericAttributeProfile.GattCharacteristic object at 0x071A2D50>, '00002a04-0000-1000-8000-00805f9b34fb': <Windows.Devices.Bluetooth.GenericAttributeProfile.GattCharacteristic object at 0x071A2D70>, '00002a05-0000-1000-8000-00805f9b34fb': <Windows.Devices.Bluetooth.GenericAttributeProfile.GattCharacteristic object at 0x071A2A70>, '00001624-1212-efde-1623-785feabcd123': <Windows.Devices.Bluetooth.GenericAttributeProfile.GattCharacteristic object at 0x071A2870>}
INFO:BLE Event Q.0:Connected to device HUB NO.4:90:84:2B:0B:DD:BF

But when putting any of those UUID's in there (the first one in this example) I get:

hub = Train("GreenCargoTrain", ble_id="00002a05-0000-1000-8000-00805f9b34fb")
INFO:BLE Event Q.0:checking manufacturer ID for device named Unknown for HUB NO.4
INFO:BLE Event Q.0:Address 90:84:2B:0B:DD:BF is not a match

A debug log file of a successful connect and execution to the same device looks like this: PUP_Debug_Success.log

This is on Microsoft Windows [Version 10.0.17763.379], using Python 3.7.3

dlech commented 5 years ago

On Windows and Linux, the "id" will be a Bluetooth address (looks like MAC, but technically not the same thing). Only on macOS will the the "id" be a UUID. (Apple thinks that for security/privacy reasons that they should not let us know the Bluetooth address, so we can't make it work the same on all OSes).

So, I think this should work for you:

hub = Train("GreenCargoTrain", ble_id="90:84:2B:0B:DD:BF")

Although there is one place in the code where it looks like it might try to convert this to a UUID and cause an error.

https://github.com/virantha/bricknil/blob/9bd772369a2721c83901263595ce8c47bc9a55ba/bricknil/ble_queue.py#L209

virantha commented 5 years ago

I was thinking about putting that uuid conversion into a try block, and then falling back to just using the ble_id if it throws a ValueError, but that's starting to get a little hacky. I could've sworn bleak under Linux could also return UUIDs (device.id, as opposed to device.address), but I need to go back and refresh my memory. I've started refactoring the whole ble_queue code to make it into sub classes based on the platform, which is something I was hoping to avoid, but I think the current code in that class is starting to turn into a bit of kludge if I don't. I'm trying to update a windows 10 tablet right now, so hopefully I will be able to test whatever change I make before pushing a new release. Perhaps a few more days before it's ready.

dlech commented 5 years ago

How about?

        if sys.platform == 'darwin':
            # Apple uses UUID instead of Bluetooth address
            ble_id = uuid.UUID(hub.ble_id) if hub.ble_id else None
        else:
            # Bluetooth address
            ble_id = hub.ble_id.upper()
dlech commented 5 years ago

Also just double-checked Linux and it uses Bluetooth address, not UUID.

virantha commented 5 years ago

@dlech @Entalyan I have pushed a new version with this fix (cough hack) as v0.8.1 to PyPI. On Linux and Win, just use a string containing the 6 bytes of network ID as mentioned above by @dlech:

hub = Train("GreenCargoTrain", ble_id="90:84:2B:0B:DD:BF")

Let me know if it works, and I'll close this.

As an aside, ideally, I'd prefer a way to make it consistently use the BLE address across all platforms, so I'm just jotting down this idea for the future: It looks like the hub can be queried for its network address after connecting to its characteristic. My initial thought is to have the ble_queue object create a pool of hubs by connecting to all available devices with the Lego service, then query the hub for the network address, and then assign the hub object to the matching device. The connection and messaging logic would need some updates to handle this type of flow. But it would enable Mac hosts to connect to BLE addresses instead of UUIDs.

Entalyan commented 5 years ago

I can confirm this now works with the new version. When using the correct ID it finds my device, and with the wrong ID it gracefully ignores it. This can be closed on my account, thanks very much!

ElTentakel commented 5 years ago

Hello,

i still have the issue using Windows 10

C:\Users\User\Downloads>python poweredup.py
started thread for curio
INFO:curio.monitor:Starting Curio monitor at 127.0.0.1:48802
inside curio run loop
INFO:BLE Event Q.0:using bleak
INFO:BLE Event Q.0:Starting scan for UART 00001623-1212-efde-1623-785feabcd123
INFO:BLE Event Q.0:ble_id 90:84:2B:03:xx:xx is not a parseable UUID, so assuming it's a BLE network addresss
INFO:BLE Event Q.0:Looking for specific hub id 90:84:2B:03:xx:xx
Awaiting on bleak discover
DEBUG:bleak.backends.dotnet.discovery:Added 90:84:2b:03:xx:xx: HUB NO.4.
DEBUG:bleak.backends.dotnet.discovery:Added 4a:ad:d6:d8:xx:xx: Unknown.
DEBUG:bleak.backends.dotnet.discovery:Updated 90:84:2b:03:xx:xx: HUB NO.4.
DEBUG:bleak.backends.dotnet.discovery:Updated 4a:ad:d6:d8:xx:xx: Unknown.
DEBUG:bleak.backends.dotnet.discovery:Could not remove event handlers: unknown event handler...
Done Awaiting on bleak discover
DEBUG:bleak.backends.dotnet.discovery:2 devices found. Watcher status: 4.
ERROR:curio.kernel:Task Crash: Task(id=7, name='BLEventQ.connect', state='TERMINATED')
Traceback (most recent call last):
  File "C:\Python37\lib\site-packages\curio\kernel.py", line 736, in _run_coro
    trap = current._send(current.next_value)
  File "C:\Python37\lib\site-packages\curio\task.py", line 167, in _task_runner
    return await coro
  File "C:\Python37\lib\site-packages\bricknil\ble_queue.py", line 228, in connect
    await self._ble_connect(hub.uart_uuid, hub.ble_name, hub.manufacturer_id, ble_id)
  File "C:\Python37\lib\site-packages\bricknil\ble_queue.py", line 171, in _ble_connect
    devices = [d for d in devices if str(uart_uuid) in d.uuids]
  File "C:\Python37\lib\site-packages\bricknil\ble_queue.py", line 171, in <listcomp>
    devices = [d for d in devices if str(uart_uuid) in d.uuids]
AttributeError: 'BLEDevice' object has no attribute 'uuids'
ERROR:curio.kernel:Task Crash: Task(id=3, name='_run_all', state='TERMINATED')
Traceback (most recent call last):
  File "C:\Python37\lib\site-packages\curio\kernel.py", line 736, in _run_coro
    trap = current._send(current.next_value)
  File "C:\Python37\lib\site-packages\curio\task.py", line 167, in _task_runner
    return await coro
  File "C:\Python37\lib\site-packages\bricknil\ble_queue.py", line 228, in connect
    await self._ble_connect(hub.uart_uuid, hub.ble_name, hub.manufacturer_id, ble_id)
  File "C:\Python37\lib\site-packages\bricknil\ble_queue.py", line 171, in _ble_connect
    devices = [d for d in devices if str(uart_uuid) in d.uuids]
  File "C:\Python37\lib\site-packages\bricknil\ble_queue.py", line 171, in <listcomp>
    devices = [d for d in devices if str(uart_uuid) in d.uuids]
AttributeError: 'BLEDevice' object has no attribute 'uuids'

here is my code


from curio import sleep
from bricknil import attach, start
from bricknil.hub import PoweredUpHub
from bricknil.sensor import TrainMotor
from bricknil.process import Process
import logging

@attach(TrainMotor, name='motor')
class Train(PoweredUpHub):

    async def run(self):
        self.message_info("Running")
        for i in range(2):
            self.message_info('Increasing speed')
            await self.motor.ramp_speed(80,5000)
            await sleep(5)
            self.message_info('Coming to a stop')
            await self.motor.ramp_speed(0,1000)
            await sleep(2)

async def system():
#    train = Train('My train')
    train = Train('My train', ble_id="90:84:2B:03:xx:xx") 

if __name__ == '__main__':
    logging.basicConfig(level=logging.INFO)
    start(system)
pip freeze
bleak==0.4.0
bluebrick-Adafruit-BluefruitLE==0.9.13
bricknil==0.9.1
bricknil-bleak==0.3.1
curio==0.9
cycler==0.10.0
enum-compat==0.0.2
future==0.17.1
gatt==0.2.7
iso8601==0.1.12
kiwisolver==1.0.1
matplotlib==3.0.2
numpy==1.16.0
PyAudio==0.2.11
pygame==1.9.4
pygatt==3.2.0
pyparsing==2.3.1
pyserial==3.4
python-dateutil==2.7.5
pythonnet==2.4.0
PyYAML==3.13
scipy==1.2.0
serial==0.0.96
six==1.12.0
dlech commented 5 years ago

For now, uninstall bleak==0.4.0 and use only bricknil-bleak==0.3.1.

ElTentakel commented 5 years ago

Thank you, I'll try this the next days..

ElTentakel commented 5 years ago

I removed bleak / bricknil-bleak and bricknil and reinstalled bricknil. Than following error occours:

C:\Users\User\Downloads\BLED112>python poweredup.py
Traceback (most recent call last):
  File "poweredup.py", line 3, in <module>
    import bricknil
  File "C:\Python37\lib\site-packages\bricknil\__init__.py", line 39, in <module>
    from .bricknil import attach, start
  File "C:\Python37\lib\site-packages\bricknil\bricknil.py", line 38, in <module>
    from .bleak import Bleak
  File "C:\Python37\lib\site-packages\bricknil\bleak.py", line 20, in <module>
    import bleak
  File "C:\Python37\lib\site-packages\bleak\__init__.py", line 68, in <module>
    from bleak.backends.dotnet.discovery import discover  # noqa
  File "C:\Python37\lib\site-packages\bleak\backends\dotnet\discovery.py", line 17, in <module>
    from Windows.Devices.Bluetooth.Advertisement import BluetoothLEAdvertisementWatcher
ModuleNotFoundError: No module named 'Windows'

This Error caused me to install bleak, since it fixed the other issue :).

dlech commented 5 years ago

It sounds like pythonnet is not working. I don't think pythonnet supports Python 3.7 yet, so you need to use Python 3.6 on Windows.

Entalyan commented 5 years ago

I had huge problems getting pythonnet installed in the first place, so I had to use an alternative build of it. The alternative/unofficial build I am using came from here: https://www.lfd.uci.edu/~gohlke/pythonlibs/#pythonnet

On my machine this all works, with Python 3.7.3 (32-bit I think) and:

bluebrick-Adafruit-BluefruitLE==0.9.13 bricknil==0.8.2 bricknil-bleak==0.3.1 curio==0.9 enum-compat==0.0.2 future==0.17.1 paho-mqtt==1.4.0 pygatt==4.0.1 pylgbst==0.10 pyserial==3.4 pythonnet==2.4.0.dev0 PyYAML==5.1

I also tested with bricknil 0.9.1, just not on this machine. Same result though.

virantha commented 5 years ago

FWIW, the following works on my Win10 tablet (32-bit) with Python 3.6.8:

bluebrick-Adafruit-BluefruitLE==0.9.13 bricknil==0.9.1 bricknil-bleak==0.3.1 curio==0.9 future==0.17.1 pythonnet==2.3.0 PyYAML==5.1

positron96 commented 4 years ago

I removed bleak / bricknil-bleak and bricknil and reinstalled bricknil. Than following error occours: C:\Users\User\Downloads\BLED112>python poweredup.py Traceback (most recent call last): File "poweredup.py", line 3, in import bricknil File "C:\Python37\lib\site-packages\bricknil__init.py", line 39, in from .bricknil import attach, start File "C:\Python37\lib\site-packages\bricknil\bricknil.py", line 38, in from .bleak import Bleak File "C:\Python37\lib\site-packages\bricknil\bleak.py", line 20, in import bleak File "C:\Python37\lib\site-packages\bleak\init__.py", line 68, in from bleak.backends.dotnet.discovery import discover # noqa File "C:\Python37\lib\site-packages\bleak\backends\dotnet\discovery.py", line 17, in from Windows.Devices.Bluetooth.Advertisement import BluetoothLEAdvertisementWatcher ModuleNotFoundError: No module named 'Windows'

This Error caused me to install bleak, since it fixed the other issue :).

I am having that same issue, have you fixed this? BTW, pythonnet 2.4.0 supports python 3.7, so my versions are:

System is Windows 10 latest x64, python 3.7.6

bluebrick-Adafruit-BluefruitLE==0.9.13 bricknil==0.9.3 bricknil-bleak==0.3.1 curio==0.9 future==0.18.2 pythonnet==2.4.0 PyYAML==5.2

DavidPowell commented 4 years ago

I am experiencing the same problem as @positron96. I have tried updating my packages to match above suggestions, but no luck so far. I would really love to try out this library (and I'm sure many other Windows users would too!), so adding a reliable installation procedure for windows to the documentation would be greatly appreciated.

In the mean time, I will see if I can get it working on my raspberry pi, as this has a clear set of instructions to follow.

BERLIE77 commented 4 years ago

I experience also the same issue. Unfortunately I am not experienced enough with python to drill down to the source of the issue but I am happy to provide information or testing when instructed. Thanks in advance - I'd like to use the module.

bartekmotyl commented 2 years ago

I am attaching patch to make Bricknil compatible with Bleak 0.13 (latest up to date) on Windows 10. Tested with latest Bricknil code base (commit a908b98938ee1028373186e31cb2d43c68f54b76) on Windows 10 with Python 3.10.0 0001-Issue-3-Compatibility-with-Bleak-0.13-on-Windows-10.txt