BLE subscribe to notification using gatttool or bluepy

只愿长相守 提交于 2019-12-07 04:15:21

问题


I am writing a program using bluepy that listen for a characteristic sent by a bluetooth device. I can also use any library or language, the only constraint is to run on Linux and not in mobile environment (it seems is widely used only in mobile devices, no one use BLE with desktop). Using bluepy I register the delegate and after trying to register for notification calling write('\x01\x00') as described in the bluetooth rfc. But it doesn't work, any notification for the characteristic is received. Maybe I am wrong in writing the message for subscribing. Is there an error in the small snippet I wrote? Thank you so much.

class MyDelegate(btle.DefaultDelegate):

    def __init__(self, hndl):
        btle.DefaultDelegate.__init__(self)
   self.hndl=hndl;

   def handleNotification(self, cHandle, data):
   if (cHandle==self.hndl):
            val = binascii.b2a_hex(data)
            val = binascii.unhexlify(val)
            val = struct.unpack('f', val)[0]
            print str(val) + " deg C"


p = btle.Peripheral("xx:xx:xx:xx", "random")

try:
   srvs = (p.getServices());
   chs=srvs[2].getCharacteristics();
   ch=chs[1];
   print(str(ch)+str(ch.propertiesToString()));
   p.setDelegate(MyDelegate(ch.getHandle()));
   # Setup to turn notifications on, e.g.
   ch.write("\x01\x00");

   # Main loop --------
   while True:
      if p.waitForNotifications(1.0):
      continue

      print "Waiting..."
finally:
    p.disconnect();

回答1:


I was struggling with this myself, and jgrant's comment really helped. I'd like to share my solution, if it could help anyone.

Note that I needed indication, hence the x02 rather than x01.

If it were possible to read the descriptors using bluepy, I would do that, but it doesn't seem to work (bluepy v 1.0.5). The method in the service class appears to be missing, and the method in the peripheral class gets stuck when I try to use it.

from bluepy import btle

class MyDelegate(btle.DefaultDelegate):
    def __init__(self):
        btle.DefaultDelegate.__init__(self)

    def handleNotification(self, cHandle, data):
        print("A notification was received: %s" %data)


p = btle.Peripheral(<MAC ADDRESS>, btle.ADDR_TYPE_RANDOM)
p.setDelegate( MyDelegate() )

# Setup to turn notifications on, e.g.
svc = p.getServiceByUUID( <UUID> )
ch = svc.getCharacteristics()[0]
print(ch.valHandle)

p.writeCharacteristic(ch.valHandle+1, "\x02\x00")

while True:
    if p.waitForNotifications(1.0):
        # handleNotification() was called
        continue

    print("Waiting...")
    # Perhaps do something else here



回答2:


It looks like the problem is that you're trying to write \x01\x00 to the characteristic itself. You need to write it to the Client Characteristic Configuration descriptor that proceeds it (0x2902). The handle is likely 1 greater than the characteristic (but you may want to confirm by reading the descriptors).

ch=chs[1]
cccd = ch.valHandle + 1
cccd.write("\x01\x00")



回答3:


What was confusing for me was that in https://ianharvey.github.io/bluepy-doc/notifications.html the part that enabled the notifications was in comments, so it didn't look obligatory to me.

the bare minimum (given you know the MAC-adress already an you included everything and declared the Delegateclass) for me is

p1 = Peripheral(<MAC>)
ch1 = p1.getCharacteristics()[3]
p1.setDelegate(MyDelegate())
p1.writeCharacteristic(ch1.valHandle + 1, b"\x01\x00")

Note that I already knew I wanted to get notifications from characteristic#3. Also, without the 'b'-bytesprefix infront of "\x0\x00", it wouldn't work for me.



来源:https://stackoverflow.com/questions/32807781/ble-subscribe-to-notification-using-gatttool-or-bluepy

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!