Open grahaminnovations opened 6 years ago
The error message:
Traceback (most recent call last):
File "/home/pi/GI-bleNotify/demo.py", line 111, in <module>
if p.waitForNotifications(1.0):
File "/usr/local/lib/python3.4/dist-packages/bluepy/btle.py", line 516, in waitForNotifications
resp = self._getResp(['ntfy','ind'], timeout)
File "/usr/local/lib/python3.4/dist-packages/bluepy/btle.py", line 369, in _getResp
resp = self._waitResp(wantType + ['ntfy', 'ind'], timeout)
File "/usr/local/lib/python3.4/dist-packages/bluepy/btle.py", line 337, in _waitResp
raise BTLEException(BTLEException.INTERNAL_ERROR, "Unexpected response (%s)" % respType)
bluepy.btle.BTLEException: Unexpected response (wr)```
I received the same error and as it looks when we are waiting for notifications and in my case another thread is going to write a value to a characteristic, a response is produced, as the error says ,and in the _waitResp() in the source code of btle.py which is called from waitForNotifications(),the last else is fired and produces this error.The thing is that in my case the write operation is always executed but then this error comes up.I don't know if it is too simple but maybe in the last else of this function if the response type is 'wr' then you can just skip it and wait again for the correct response instead of throwing an exception,but since we can't modify the code we hope it will be fixed
If you're using multithreading or some setup where multiple BLE functions can be called in "parallel" then what can happen is that the write() function will send a write command, and then wait to receive the write response "wr". One possible problem is, if there's another thread that's also waiting for a response (like calling waitForNotifications()) then when that response 'wr' is received, it can mistakenly get passed to waitForNotifications instead, and that function isn't expecting such a response type and will throw an error. One way to workaround this is to call write() with the withResponse argument set to True (.write(value, withResponse=True) ), which will queue the write request instead so you get everything in the right order? (not exactly sure what's going on in this case, I didn't bother to go deeper than this).
If you instead update the code to "ignore" the 'wr' response, then you could potentially block your code indefinitely.
Oh wait, no no ignore that I found the problem: int the btle.py the following code snippet has an indentation error replace:
def _getResp(self, wantType, timeout=None):
if isinstance(wantType, list) is not True:
wantType = [wantType]
while True:
resp = self._waitResp(wantType + ['ntfy', 'ind'], timeout)
if resp is None:
return None
respType = resp['rsp'][0]
if respType == 'ntfy' or respType == 'ind':
hnd = resp['hnd'][0]
data = resp['d'][0]
if self.delegate is not None:
self.delegate.handleNotification(hnd, data)
if respType not in wantType: # [ERROR] indented one more level than it should be
continue # [ERROR] this will never happen
return resp
with:
def _getResp(self, wantType, timeout=None):
if isinstance(wantType, list) is not True:
wantType = [wantType]
while True:
resp = self._waitResp(wantType + ['ntfy', 'ind'], timeout)
if resp is None:
return None
respType = resp['rsp'][0]
if respType == 'ntfy' or respType == 'ind':
hnd = resp['hnd'][0]
data = resp['d'][0]
if self.delegate is not None:
self.delegate.handleNotification(hnd, data)
if respType not in wantType:
continue
return resp
the part that's suppose to continue the loop if the expected response isn't received yet, is mistakenly indented one more tab, making it a redundant statement that never gets executed. Just make that fix and all will be good. I'm gonna submit a pull request soon.
Ok, well it seems that my first comment was more accurate, the issue still presists, and it definitely seems to be a multithreading (non linear code execution, in your case the use of interrupts) issue where the 'wr' response is propagated to waitForNotifications() instead of .write(). Like I said, just set withResponse to True and you should be fine. The only downside is a slowdown due to using write with response.
Hi, The code I used is based on the ble notify example. I have a separate function to deal with the GPIO button interrupt response. It will call the writeCharacteristic and send a short command to the peripheral device. The peripheral device will send back an ACK notification. Sometimes it cause the ble to disconnect. Any idea why is that?