【问题标题】:BLE subscribe to notification using gatttool or bluepyBLE 使用 gatttool 或 bluepy 订阅通知
【发布时间】:2015-12-24 19:08:11
【问题描述】:

我正在使用 bluepy 编写一个程序,用于侦听蓝牙设备发送的特征。我也可以使用任何库或语言,唯一的限制是在 Linux 上运行而不是在移动环境中运行(似乎只在移动设备中广泛使用,没有人在桌面上使用 BLE)。 使用 bluepy 我注册了委托,并在尝试注册通知后调用write('\x01\x00'),如蓝牙 rfc 中所述。 但它不起作用,收到任何有关该特征的通知。 也许我在写订阅消息时是错误的。 我写的小sn-p有错误吗?非常感谢。

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();

【问题讨论】:

    标签: python linux bluetooth-lowenergy gatt


    【解决方案1】:

    bluepy 类文档和示例很疯狂,而且不完整。要了解更多详情,请查看 bluepy source(它并不大且易于阅读)

    但是,作为起点,您可以使用此通知代码示例,使用心率服务(在 bluepy 1.3.0 上测试)

    不要忘记在 Peripheral 中将设备 MAC 替换为您自己的!

    from bluepy import btle
    from bluepy.btle import AssignedNumbers
    
    import binascii
    
    class MyDelegate(btle.DefaultDelegate):
        def __init__(self, handle):
            btle.DefaultDelegate.__init__(self)
            self.handle = handle
            print "Created delegate for handle", self.handle
            # ... more initialise here
    
        def handleNotification(self, cHandle, data):
            if(cHandle == self.handle):
                print "handleNotification for handle: ", cHandle, "; Raw data: ", binascii.b2a_hex(data)
                #Found somewhere. Not tested is this working, but leave here as decode example
                #val = binascii.b2a_hex(data)
                #val = binascii.unhexlify(val)
                #val = struct.unpack('f', val)[0]
                #print str(val) + " deg C"
    
    print "Connecting..."
    dev = btle.Peripheral("c8:2b:96:a3:d4:76")
    
    try:
        print "Device services list:"
        for svc in dev.services:
            print str(svc)
    
    
        HRService = dev.getServiceByUUID(AssignedNumbers.heartRate)
        print "HRService", HRService
    
        print "HRService characteristics list: "
        for char in HRService.getCharacteristics():
            print "HRService char[", char.getHandle(), "]: ", char
    
        HRMeasurementChar = HRService.getCharacteristics(AssignedNumbers.heart_rate_measurement)[0] #Notice! Check is characteristic found before usage in production code!
        print "HRMeasurementChar", HRMeasurementChar, HRMeasurementChar.propertiesToString();
    
        # Assign delegate to target characteristic
        dev.setDelegate(MyDelegate(HRMeasurementChar.getHandle()));
    
        # We need to write into org.bluetooth.descriptor.gatt.client_characteristic_configuration descriptor to enabe notifications
        # to do so, we must get this descriptor from characteristic first
        # more details you can find in bluepy source (def getDescriptors(self, forUUID=None, hndEnd=0xFFFF))
        desc = HRMeasurementChar.getDescriptors(AssignedNumbers.client_characteristic_configuration);
        print "desc", desc
    
        print "Writing \"notification\" flag to descriptor with handle: ", desc[0].handle
        dev.writeCharacteristic(desc[0].handle, b"\x01\x00")# Notice! Do not use [0] in production. Check is descriptor found first!
    
        print "Waiting for notifications..."
    
        while True:
            if dev.waitForNotifications(1.0):
                # handleNotification() was called
                continue
    
    finally:
        dev.disconnect();
    

    【讨论】:

      【解决方案2】:

      让我感到困惑的是https://ianharvey.github.io/bluepy-doc/notifications.html 启用通知的部分在 cmets 中,所以我觉得它不是必须的。

      对我来说,最低限度(假设你已经知道 MAC 地址并且你包含了所有内容并声明了 Delegateclass)是

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

      请注意,我已经知道我想从特征#3 获取通知。 另外,如果没有 "\x0\x00" 前面的 'b'-bytesprefix,它对我不起作用。

      【讨论】:

        【解决方案3】:

        我自己也在为此苦苦挣扎,而 jgrant 的评论确实很有帮助。我想分享我的解决方案,如果它可以帮助任何人。

        请注意,我需要指示,因此需要 x02 而不是 x01。

        如果可以使用 bluepy 读取描述符,我会这样做,但它似乎不起作用(bluepy v 1.0.5)。服务类中的方法好像丢失了,外围类中的方法在我尝试使用时卡住了。

        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
        

        【讨论】:

        • 为什么是“\x02\x00”?而不是“\x01\x00”?
        【解决方案4】:

        看起来问题在于您正在尝试将\x01\x00 写入特征本身。您需要将其写入执行它的客户端特征配置描述符 (0x2902)。句柄可能比特征大 1(但您可能需要通过阅读描述符来确认)。

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

        【讨论】:

          猜你喜欢
          • 2015-01-20
          • 2015-07-17
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2019-11-07
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多