BLE subscribe to notification using gatttool or bl

2019-04-29 16:46发布

问题:

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")