-
Notifications
You must be signed in to change notification settings - Fork 177
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
Correcting connection issue #37
Conversation
Thanks a lot ! @hubertjb can you review and merge if this work ? |
Awesome work @sylvchev :) @alexandrebarachant yes, I'll take a look asap |
@@ -70,6 +71,11 @@ def connect(self, interface=None, backend='auto'): | |||
self.address = address | |||
self.device = self.adapter.connect(self.address) | |||
|
|||
self.ask_reset() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Instead of having it reset everytime, just wrap this code block in a try catch.
For example:
try:
self.device = self.adapter.connect(self.address)
# subscribes to EEG stream
if self.enable_eeg:
self._subscribe_eeg()
if self.enable_control:
self._subscribe_control()
if self.enable_telemetry:
self._subscribe_telemetry()
if self.enable_acc:
self._subscribe_acc()
if self.enable_gyro:
self._subscribe_gyro()
except pygatt.exceptions.BLEError as error:
if("characteristic" in str(error)):
self.ask_reset()
sleep(2)
self.device = self.adapter.connect(self.address)
self.select_preset(preset=21)
# subscribes to EEG stream
if self.enable_eeg:
self._subscribe_eeg()
if self.enable_control:
self._subscribe_control()
if self.enable_telemetry:
self._subscribe_telemetry()
if self.enable_acc:
self._subscribe_acc()
if self.enable_gyro:
self._subscribe_gyro()
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree doing an ask_device_info callback would be the best way to handle this bootloader mode issue. However, @sylvchev's right in that it's kind of tricky to do that kind of async/await logic in Python
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unfortunately, I have currently no access to a Muse band. I could not test your solution but it seems a better solution than to reset everytime.
@alexandrebarachant, @hubertjb, if you agree, I'll update my PR with the code proposed by @jdpigeon.
I found that my Muse headband could not connect directly after a night charging up. I should start the Muse app on my phone, connect the band and then I could use muse-lsl. This happens each time that I fully charge my headband with a phone charger. I did some tests with different chargers and in different places, this does not happen in certain configurations, but I could not get the bottom of it. Nonetheless, it systematically happens in the building where I need the headband, hence this PR.
I activated the developer mode on my android Phone to "Enable Bluetooth HCI snoop log" and I analyzed the exchanges with Wireshark between the Muse phone app and the headband (when it could not connect). I found out that the Muse app sends an
ask_device_info
sequence (0x03 76 31 0a
) and that, in its response, the 'ap' field of the headband is set to 'bootloader' (instead of 'headset' in a functional headband). When the headband is in 'bootloader' mode, the Muse app sends a special sequence that I identified as a "reset to headset mode" order (0x03 2a 31 0a
, or*1
in ASCII). The headband then reboots, cutting the Bluetooth connection. Once reconnected, theask_device_info
returns now the correct 'headset' value in the 'ap' field.I also spotted that, after "resetting", the headband preset mode is indicated as "32" which seems to map to preset 20 from the official documentation. The Muse app then change the preset to 21, with the sequence `0x04 70 32 31 0a, which is also documented here.
I proposed the following update in this PR:
select_preset
to set the preset to indicated value (default is 21)connect
function: I send a reset order, wait for 2 sec, reconnect, then change the preset. The 2 second delay could be shortened, it is 5 second on the Muse app. Compared to the main branch, and assuming a headband already working well with muse-lsl, this adds a small inconvenience as the muse-lsl take 2 more seconds before starting to stream. But then again, it could be cut to half a second or less without taking any risk. The fact that the Muse headband is reset at each connection does not seem to have any effect.Instead of making a reset at each connection, a better approach could be to use an internal callback responding to
ask_device_info
and to triggers the reset depending on the 'ap' field value. Unfortunately, with the concurrent programming, I did not find a correct way to do that.