-
-
Notifications
You must be signed in to change notification settings - Fork 7
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Bug] Hub took too long to respond #256
Comments
Can you capture the Bluetooth traffic when this happens? https://bleak.readthedocs.io/en/latest/troubleshooting.html#capture |
Will do. I'm stuck on the decoding step though (This app can't run on your PC); will have to try it later. |
I can decode it if that helps. |
Here's the etl file if I've done it right. Not sure this type of file contains any sysinfo? Feel free to delete if so. |
For some reason, it looks like Windows is hitting a 30 second timeout waiting for the write response. At this point, tries to disconnect the device. But as soon as the disconnect request is made, we get the write response and the notification that we were expecting. It's like they are stuck in the Bluetooth stack or something (would need to get a proper Bluetooth sniffer to see for sure). |
Decoded file for the record. |
Does this still happen after rebooting Windows? |
Yes. Still occurs consistently in |
Need to go through old builds of Pybricks Code to see if it worked before. |
Can you also share the output of |
|
Hmm... not much useful there. I was at least expecting to see a disconnect after 30 seconds like we did in the packet capture. |
Does flashing with pybricksdev work on the same hardware? Either way, can you do a Bluetooth packet capture while doing this as well so we can compare it to what Edge does? |
Same hardware yes and no --- I'm running Windows on a VM. And indeed, it seems to go wrong there with Pybricksdev as well, so I could dig a bit deeper.
|
Does it work if you change the erase command to write without response? |
Also, the light does turn off briefly, so the hub appears to receive the erase command. |
Without response, it mostly still doesn't work, but I saw it work once... In that case it mostly just gets stuck awaiting the reply:
|
Hmm, looks like write without response EDIT: It seems we always wait for a reply of some sort, maybe that's worth skipping. Update: yes, see post below. |
So indeed, this quick hack does the trick on Technic Hub: diff --git a/pybricksdev/flash.py b/pybricksdev/flash.py
index 8ee5e5f..da8ecd5 100644
--- a/pybricksdev/flash.py
+++ b/pybricksdev/flash.py
@@ -11,6 +11,8 @@ from typing import Dict, Tuple
from tqdm import tqdm
import typing
import zipfile
+import asyncio
+
from .ble import BLERequestsConnection
from .compile import save_script, compile_file
@@ -203,6 +205,8 @@ class BootloaderRequest():
self.reply_len = struct.calcsize(data_format)
if request_reply:
self.reply_len += 1
+ if command == 0x11: # Hack to skip waiting for reply altogether, not even the echo of the command.
+ self.reply_len = 0
self.write_with_response = write_with_response
def make_request(self, payload=None):
@@ -223,7 +227,7 @@ class BootloaderConnection(BLERequestsConnection):
# Static BootloaderRequest instances for particular messages
ERASE_FLASH = BootloaderRequest(
- 0x11, 'Erase', ['result'], '<B'
+ 0x11, 'Erase', ['result'], '<B', False, False
)
PROGRAM_FLASH_BARE = BootloaderRequest(
0x22, 'Flash', [], '', False, False
@@ -273,7 +277,6 @@ class BootloaderConnection(BLERequestsConnection):
return request.parse_reply(reply)
async def flash(self, firmware, metadata, delay):
-
# Firmware information
firmware_io = io.BytesIO(firmware)
firmware_size = len(firmware)
@@ -299,6 +302,7 @@ class BootloaderConnection(BLERequestsConnection):
self.logger.debug("Erasing flash.")
response = await self.bootloader_request(self.ERASE_FLASH)
self.logger.debug(response)
+ await asyncio.sleep(4) # wait for flash erase to complete, guess enough time instead of waiting for reply with success
# Get the bootloader ready to accept the firmware
self.logger.debug('Request begin update.')
On City Hub I do get something back |
Does Move hub work? Can you do a Bluetooth packet capture for all hubs with the hack in place? |
Yes, it works in Pybricks Code. |
Notes:
|
Thanks for this. In bth_hci_technichub_pybricksdev_default, it looks like the bootloader is sending the wrong response to Find By Type Value Request. This probably confuses the Windows Bluetooth stack since it is getting responses to commands it didn't send and not getting responses to commands that it did send. I recall that this request was added in a newer version of Windows and caused problems and had to be fixed in our firmware. However, we can't fix it in the bootloader. The capture doesn't even get to the point of starting to send the first bootloader command to the LWP3 characteristic, so I imagine that if you were to capture again, you might get different results. |
On City Hub, when changing the flash request to write without response it does proceed, and we're seeing the same as before, the reply
Then fails with
Could we send a bogus message (get checksum?) just to clear up any pending replies before starting to send the firmware? |
Workaround for pybricks/support#256
Yes, that works. I've pushed a patch here. So the flash erase command is now the same again for all hubs (write without response); this just moves the workaround instead of adding another one, so hopefully this isn't too bad. It can probably be improved by proper handling of the responses instead of sending something and waiting two seconds. If Pybricks Code already does this, then maybe the bogus message isn't needed. |
Also, looking at the log above it's almost as if the hub does send that reply, since the script gets it back before the backend send the next one. But just the act of writing to the stack appears to unload that data. |
Did you try this patch on Linux? I'm pretty sure that it will cause BlueZ to disconnect (it did in the past). If that is the case, we need to do write without response (and the checksum hack) only on Windows. Does it work on Windows if we just add an async sleep before sending the next message? I wonder if there is some other way we could "poke" the Windows Bluetooth stack to get it to see the notification or if the message really is getting held back on the hub. |
Could you also do a packet capture of City Hub on Windows with "write with response". |
Also, what Bluetooth adapter are you using? |
Patch has only been tested on windows so far, hence pushed to a windows branch for now. I also tried a plain async sleep (and a longer timeout, 10s), but this didn't seem to work. The old/bad response always came when attempting the next write. I'll get back with captures and info on the adapter when I'm back at the PC. |
I think I have this one: https://www.trust.com/en/product/18187-manga-bluetooth-4-0-adapter |
With the current Pybricksdev master: |
Indeed:
|
USB VID:PID? |
Decoded captures from #256 (comment) bth_hci_pybricksdev_hack (2).zip Decoded capture from #256 (comment) |
What happened when this ran? It looks like it got cut off before it ever to the point of sending LWP3 commands (probably due to other misbehavior due to buggy implementation of Bluetooth in the bootloader). EDIT: I now see that this capture contains 2 connections, so the interesting part is in the middle. |
This addresses additional quirks seen on a specific Windows setup with the city hub. Issue: pybricks/support#256
I pushed a branch with a different workaround that shouldn't break Linux. |
Same as throughout this whole issue; got stuck on trying to erase flash with response. That patch (pybricks/pybricksdev@c227f02) works too 👍 So does this not break on other Windows machines, given that those were working before the patch?
|
It seems to be working fine on my Windows laptop. |
I have a dongle with the same VID:PID. My Windows laptop doesn't seem to be able to load the driver for it, but I was able to use it in a Windows VM without problem (driver worked and pybricksdev worked without hacks). What is the driver info for this dongle in your Windows VM? |
After disabling the built-in adapter, I was able to get this dongle to work on my laptop as well. I didn't not encounter any problems with it when flashing firmware in Pybricks Code. |
This works around some issues that have been observed on a specific Windows computer. Issue: pybricks/support#256
I have pushed a branch to |
This addresses additional quirks seen on a specific Windows setup with the city hub. Issue: pybricks/support#256
I can confirm that pybricks/pybricks-code@956b6f3 is working for me on Windows for City Hub, Technic Hub, and Move Hub 🎉 Also works on Ubuntu 18.04 with City Hub, Technic Hub, and Move Hub. |
Hopefully you aren't the only person in the world that had this strange problem. 😉 |
If we merge it, we'll never know 😄 |
Is there anything left to do on this issue? |
Reading the messages above, I guess not. |
Describe the bug
Cannot install Technic Hub firmware in Microsoft Edge and Google Chrome on Windows.
It pairs just fine, and appears to erase the flash as usual. The light is off for a bit, then starts blinking red/green/blue. But Pybricks Code does not appear to pick it up after.
Expected behavior
Start installation after erasing flash.
Screenshots
The text was updated successfully, but these errors were encountered: