IanHarvey / bluepy

Python interface to Bluetooth LE on Linux
Other
1.6k stars 491 forks source link

Code for notification? #124

Open MarcoSaba opened 8 years ago

MarcoSaba commented 8 years ago

Hi to everyone,

I need help to perform a simple task.

I'm using a BLE Nano to read from an analog pin and then sending via notification the reading. What I want to do is to develop a application that can show on screen the value continuously (I manually change the value using a potentiometer, so when the resistance is maximum the value shown will be e.g 750, when resistance is minimum the value shown will be e.g 7). My BLE device has two characteristics:

Using a Android app developed by RedBearLab I can receive data from the analog pin, so the sketch works. Now I have to receive this data on the computer.

To turn ON the notification I need to write "aa" (0x61,0x61) on characteristic 14, up to now there are no problems. Once the notification is ON I do not receive nothing. BUT if I add the READ property on characteristic 16 I can read the value on it. What I'm trying to say is that after a enter 'aa' on characteristic 14 I can read the value on characteristic 16, but I prefer to receive this data continuously via notification.

I understand this is simple task, but this is my very first time I work with a BLE device and Python programming. I hope someone could help me.

Thank you.

This is the code I wrote, please let me know what I need to do to achieve my goal.

import struct
from bluepy.btle import *

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

    def handleNotification(self, cHandle, data):
        print(data)

per = Peripheral("ea:c7:bd:19:0a:83","random")
per.setDelegate(MyDelegate())

print("Connected")

try:
    per.writeCharacteristic(14,bytes('aa','utf-8'))
    print("writing done")
    while True:
        if per.waitForNotifications(1.0):
            print("Notification")
            continue
    print("Waiting")
finally:
    per.disconnect()
    print ("Disconnected")
IanHarvey commented 8 years ago

The line:

per.writeCharacteristic(14,bytes('aa','utf-8'))

is going to write the two bytes 0x61 0x61 to the characteristic, because bytes(string,encoding) turns a string into a block-of-bytes containing its ASCII (or UTF-8) encoding, and 0x61 is the ASCII encoding of 'a'.

You could use any of the following:

Hope this helps, Ian

MarcoSaba commented 8 years ago

Hi Ian, thank you for replying so quickly.

Indeed I have to write 0x61,0x61 not 0xAA. I told you 'aa' because writing 'aa' I turn ON the notification mechanism (in fact after the line per.writeCharacteristic(14,bytes('aa','utf-8')) if I read the characteristic 16 I can find the value I'm looking for).

So I think something is wrong here:

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

    def handleNotification(self, cHandle, data):
        print(data)

or here:

try:
    per.writeCharacteristic(14,bytes('aa','utf-8'))
    print("writing done")
    while True:
        if per.waitForNotifications(1.0):
            print("Notification")
            continue
    print("Waiting")

Thank you again!

lilingdan commented 7 years ago

if you want to receive notification from characteristic A, you should first write \x01\x00 to A's value+1,like as follows:

def enable_notify(self,  chara_uuid):
    setup_data = b"\x01\x00"
    notify = self.ble_conn.getCharacteristics(uuid=chara_uuid)[0]
    notify_handle = notify.getHandle() + 1
    self.ble_conn.writeCharacteristic(notify_handle, setup_data, withResponse=True)

then you can waitForNotifications.

tautology0 commented 6 years ago

Shouldn't the writing of the notification handle be abstracted properly? I've been stuck on this for ages - even through I know that I had to write to the handle in the raw protocol; I expected the library to abstract this out for me.

A method for Characteristic.startNotification() would be nice; and updating the documentation so the example is valid would be even nicer!

NSLog0 commented 6 years ago

I stucked to get data like below image form service and characteristics

screen shot 2018-06-17 at 11 02 23 am

I used Bluezee on Mac to debug. How to do I get data like the image? I tried many ways to get data but is not working

GammaGames commented 5 years ago

So the data to subscribe to notifications is b"\x01\x00", does anyone know the data to unsubscribe?

(@lilingdan)

Edit: According to this, it's b"\x00\x00". Sorry for the ping!

tautology0 commented 5 years ago

The CCCD is basically a flag: set to 1 (it's little endian) it means subscribe to notifications/indications. Set to 0 it means don't subscribe.

Something I found on a device - the CCCD handle isn't always at (characteristic value +1). The only safe way of discovering it is to enumerative descriptors (there's a BLE method for this). Unfortunately bluepy doesn't have allow management of descriptors, so you need to do this by hand using something like gatttool.

Edit: there is Peripheral.getDescriptor()

rayavarapuvikram1 commented 4 years ago

if you want to receive notification from characteristic A, you should first write \x01\x00 to A's value+1,like as follows:

def enable_notify(self,  chara_uuid):
    setup_data = b"\x01\x00"
    notify = self.ble_conn.getCharacteristics(uuid=chara_uuid)[0]
    notify_handle = notify.getHandle() + 1
    self.ble_conn.writeCharacteristic(notify_handle, setup_data, withResponse=True)

then you can waitForNotifications.

notify = self.ble_conn.getCharacteristics(uuid=chara_uuid)[0] what is self.ble_conn? is it service or peripheral

Why are we adding +1 to notify_handle = notify.getHandle() + 1?

tautology0 commented 4 years ago

Normally the CCCD is at the characteristic handle + 1; normally. Not always. To be safe you should search for a descriptor for the characteristic with a UUID of 0x2902.

I was also wrong above - \x01\x00 is the value for notify; indicate is \x02\x00.

In the above extra self.ble_conn would be the handle returned by a call to Peripheral.

rayavarapuvikram1 commented 4 years ago

thank you

Normally the CCCD is at the characteristic handle + 1; normally. Not always. To be safe you should search for a descriptor for the characteristic with a UUID of 0x2902.

I was also wrong above - \x01\x00 is the value for notify; indicate is \x02\x00.

In the above extra self.ble_conn would be the handle returned by a call to Peripheral.