Open tkrmnz opened 5 months ago
If the LE device's handles are always the same, then this is the simplest implementation. Use the handle of the value (001D) then it is not necessary to run find_ctics() to find the handle. Just set the ADDRESS= of the LE device in the devices.txt info.
/**** devices.txt file - set ADDRESS *****/
DEVICE=My Pi ..... local device info
DEVICE=BLE device TYPE=LE NODE=2 ADDRESS=11:22:33:44:55:66
LECHAR=Data HANDLE=001D PERMIT=14 SIZE=3 UUID=FEC26EC46D7144429F8155BC21D658D6 ; index 0
/***** C code file ******/
int notify_callback(int lenode,int cticn,unsigned char *buf,int nread);
int main()
{
if(init_blue("devices.txt") == 0)
return(0);
// connect to node 2
connect_node(2,CHANNEL_LE,0);
// enable notifications for characteristic index 0
notify_ctic(2,0,NOTIFY_ENABLE,notify_callback);
// read notifications for 1 minute
read_notify(60000);
disconnect_node(2);
close_all();
return(0);
}
int notify_callback(int lenode,int cticn,unsigned char *buf,int nread)
{
// LE device lenode has sent notification of characteristic index cticn
// data in buf[0] to buf[nread-1]
printf("Notify %02X %02X %02X\n",buf[0],buf[1],buf[2]);
return(0);
}
Didn't work. The callback was never called. The Notificaton was never triggered. This is the same with btferret as well.
If notify_ctic is not returning an error, then notifications are being enabled, but the device must decide to send one - the client cannot request it. You can check if the BLE device is sending notifications as follows. The Bluetooth traffic will be saved to a file "monitor.txt". If notifications are being sent, there will be packets listed as:
> CHANNEL 0004 Opcode = 1B
1B is the opcode for a notification.
int main()
{
if(init_blue("devices.txt") == 0)
return(0);
set_print_flag(PRINT_VERBOSE);
// connect to node 2
connect_node(2,CHANNEL_LE,0);
// enable notifications for characteristic index 0
notify_ctic(2,0,NOTIFY_ENABLE,notify_callback);
// read notifications for 1 minute
read_notify(60000);
output_file("monitor.txt");
disconnect_node(2);
close_all();
return(0);
}
Based on your recommendation, I added a CCC section to the devices.txt
DEVICE=BLE device TYPE=LE NODE=2 ADDRESS=B4:3A:31:EB:4C:01
LECHAR=Data HANDLE=001D PERMIT=14 SIZE=3 UUID=FEC26EC46D7144429F8155BC21D658D6 ; index 0
LECHAR=CCC HANDLE=001E PERMIT=14 SIZE=2 UUID=2902 ; index 1
Also, for gattool this is what I have to do. sudo gatttool -i hci0 -b B4:3A:31:EB:4C:01 --char-write-req -a 0x001e -n 0100 --listen
However, a W into ctic 1 (0x001e) with 01 or 01 00 did not start the notification from the BLE device. BTW, I'm using btferret as a quick test. Any other recommendations?
That is exactly what notify_ctic does - it writes 01 00 to handle 001E. If this appears in monitor.txt without an error return, then notifications are being enabled. There are maybe two things to look at:
connect_node(2,CHANNEL_LE,0);
set_le_wait(5000);
le_pair(2,JUST_WORKS,0);
Otherwise, the solution should be apparent by using btmon to get a listing of the Bluetooth traffic when running the procedures that do generate notifications.
This is the closest that I can get btferret btmon logs to match the working gatttool comman. Note there is a difference in the Attn:Write Request. Note, right after the Notiffy Enable was sent to the BLE device, BTFerret just sits there waiting from the BLE device to send data.
That's interesting. There are two types of write.
PERMIT OPCODE
04 52 Write no acknowledge
08 12 Write with ack
Gatttool is using the acknowledge version. To replicate this, use your method of defining the notification as a separate characteristic, but with PERMIT=08. Then write 01 00 to it and do not call notify_ctic. Btferret will then use opcode 12.
LECHAR=CCC HANDLE=001E PERMIT=08 SIZE=2 UUID=2902 ; index 1
buf[0] = 1;
buf[1] = 0;
write_ctic(2,1,buf,2);
Yup, that did the trick. Thank you very much.
Here is the working solution for others with the same issue. The UUID is what Silabs used to emulate serial terminal.
;DEVICE=BLE device TYPE=LE NODE=2 ADDRESS=B4:3A:31:EB:4C:01
; LECHAR=Data HANDLE=001D PERMIT=14 SIZE=3 UUID=FEC26EC46D7144429F8155BC21D658D6 ; index 0
; LECHAR=CCC1 HANDLE=001E PERMIT=08 SIZE=2 UUID=2902 ; index 1
int notify_callback(int lenode,int cticn,unsigned char *buf,int nread);
int main()
{
unsigned char data[8];
data[0] = 0x01;
data[1] = 0x00;
if(init_blue("devices.txt") == 0) return(0);
// connect to node 2
connect_node(2,CHANNEL_LE,0);
write_ctic(2,1,data,0);
// enable notifications for characteristic index 0
notify_ctic(2,0,NOTIFY_ENABLE,notify_callback);
// read notifications for 1 minute
read_notify(60000); output_file("monitor.txt");
disconnect_node(2); close_all(); return(0); }
int notify_callback(int lenode,int cticn,unsigned char *buf,int nread) { // LE device lenode has sent notification of characteristic index cticn // data in buf[0] to buf[nread-1]
printf("Notify %02X %02X %02X\n",buf[0],buf[1],buf[2]);
return(0); }
OK, good. Thanks for flagging this up. It's the first time I've seen notification enable work this way. I'll have to consider updates to the code.
I've uploaded a new version 16.1 of btlib.c to fix this problem. Now notify_ctic should work with your LE device.
I can confirm that btlib.c v16.1 works with Silabs SPP demo without the write_ctic hack. Thank you.
I'm currently using a silabs BLE device emulating the SPP mode. SPP data is transmitted as notified packet with UUID FEC26EC46D7144429F8155BC21D658D6. I can see the data on Android BLE terminal app, RaspberryPi Gatttool and RaspberryPi bluez/btgatt-client example code. However, I cannot get the notify to work via Btferret and the btferret/le_client example code. I think the problem has to do with my understanding of the device.txt configuration of the device. Below is the capture of the BLE services using CySmart.
Any help would be greatly appreciated.