How to send data to characteristic over BLE
-
I could use some help. I can connect to the service and characteristic, been able to receive data from another device I'm using. What I don't know is how to send over data to the device that should receive data. Is there a command for that? I'm using Windows 7 and Atom.
I've been looking at the documentation for the LoPy and it should be characteristic.write that sends the data.
# Handler for data Received (Working on Send) def characteristic_callback(char): #v = int.from_bytes(char.value(), "little") #print("Data: {}".format(chr(v))) i = 25 characteristic.write(i) characteristic.callback(trigger=Bluetooth.CHAR_NOTIFY_EVENT, handler=None, arg=None)```
-
@codemaniac64
Umm I'm not sure, do you have any debug visibility on your PSoC code?Seems like it's rejecting something. Can you see if the BLE connection is still up when you try the .write(b'x0f')?
It really helps to have a BLE sniffer like this https://www.nordicsemi.com/eng/Products/Bluetooth-low-energy/nRF-Sniffer
-
So I've tried both using
bytes([4])
andpayload = struct.pack("<H", 2048)
and I get this error everytime. What am I doing wrong? Is it because I'm not doing anything in mycharacteristic_callback
?Also I did change
char
tocharacteristic
just as Seb said.
-
bytes([]) really expects an array of one byte integer to convert, if you try to covert something larger than one byte you'll get an error.
To do it properly you should use struct.pack functions() where you can specify the byte order, for example to get the byte representation of 2048 as a little endian 16 bit short you''d use:
import struct payload = struct.pack("<H", 2048) characteristic.write(payload)
For Strings you can use
payload_str = mystring.encode('ascii')
(or Unicode, etc)Finally you can simple concatenate bytes with
+
e.g.payload + payload_str
-
@jmarcelino
Thank you so much! This has helped a lot.
Is it also possible that I store it in a variable and print it out, that way I can enter numbers and letters I want to send over.bytes([value])
-
@codemaniac64
Yes that should do it.As explained on the documentation "For now it only accepts bytes object representing the value to be written." so you need to covert your integer to a bytes type with (for example to write one byte with the number 4):
bytes([4])
-
Should it be like this? Also what does the error I get mean?
-
If the PSoC 4 is your GATT Server and you’ve already connected and found the characteristic it should just be a matter of doing characteristic.write(value)
But do this outside of the callback function. Just use the characteristic you found via service.characteristics()
-
@jmarcelino
My LoPy would be my GATT Client that I will send to my PSoC 4 BLE that will be my GATT Server.Another thing, in your trigger you have
Bluetooth.CHAR_READ_EVENT
, but the documentation says that it can must beBluetooth.CHAR_NOTIFY_EVENT
.So if I want to write something wouldn't it be:
char.callback(trigger=Bluetooth.CHAR_WRITE_EVENT, handler=char_cb_handler)
-
I already have the connection established to the desired characteristic, so that step is not needed. I also already know that the characteristic has a writable bit set because I've already programmed it that way and done tests.
I have tried the
characteristic.write(value)
aswell but it doesn't work. The only step I want to know is how to send something to the GATT server.
-
Can you clarify what is your GATT Server and Client in your setup?
If the LoPy is your GATT Server you'd trigger on a CHAR_READ_EVENT in order to send data to the remote device
def char_cb_handler(chr): global some_number return some_number char.callback(trigger=Bluetooth.CHAR_READ_EVENT, handler=char_cb_handler)
-
So firstly you need to find the desired characteristic from the device using code like:
from network import Bluetooth import time bluetooth = Bluetooth() bluetooth.start_scan(10) while True: adv = bluetooth.get_adv() if adv and binascii.hexlify(adv.mac) == 'XXXXXXXXXX': try: print('1') conn = bluetooth.connect(adv.mac) except: bluetooth.start_scan(5) continue break wanted_char = None services = conn.services() for service in services: print("Service: {}".format(service.uuid())) if service.uuid() == b'XXXXXXXXXXXXX': characteristics = service.characteristics() for characteristic in characteristics: print("Characteristic: {}".format(characteristic.uuid())) if characteristic.uuid() == b'XXXXXXXXXXXX': wanted_char = characteristic
You will then need to check the
wanted_char.properties()
to see if it has the writable bit set, if it does you can then dowanted_char.write(b'x0f')
-
@seb
It's not a LoPy, I'm using a PSoC 4 BLE
-
Are you sending to another LoPy or a third party device?
-
I want to send something over BLE from LoPy. That is all. A simple 'Hello' or a value that I can enter in putty.
-
What exactly are you trying to achieve?
-
@seb
Do I need to change every char to characteristic?
Nothing changed when I changed the char in the characteristic_callback
-
In the code you have posted the callback parameter is called
char
notcharacteristic
so please adjust your code accordingly.