GithubHelp home page GithubHelp logo

petzval / btferret Goto Github PK

View Code? Open in Web Editor NEW
92.0 4.0 19.0 1023 KB

Python and C Bluetooth Library

License: MIT License

C 96.40% Python 3.60%
ble bluetooth bluetooth-le c linux python raspberry-pi ubuntu hid obex

btferret's People

Contributors

petzval avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

btferret's Issues

notification callbacks get only 20 bytes

I want to use your nice C package to connect from my PC to a BLE chessboard (Chessnut Air). All communications to the board work well, except the notifiaction callbacks always receive only 20 bytes from the actually sent 38 bytes by the board.
I am sure that the board is OK, since it works well with an USB cable & Android apps.

Some lines of my code:
cticn = 5;
int flag = 1; // inputint("0=Disable 1=Enable");
char *s = "enabled";
if (ctic_ok(node,cticn) == 0) { printf("Invalid index\n"); return 1; }
if (notify_ctic(node,cticn,flag, conf_callback) == 0) s = "failed";
printf("notifyle %s %s %s cticn=%d\n",device_name(node),ctic_name(node,cticn),s,cticn);

cticn = 3;
if (notify_ctic(node,cticn,flag,board_notify_callback) == 0) s = "failed";
printf("notifyle %s %s %s cticn=%d\n",device_name(node),ctic_name(node,cticn),s,cticn);

Version 10 breaks best connection interval

Those are Android logs. Note that my Android app requests the high connection priority.

Version 9 (with //paramreply[PAKHEADSIZE+j+6] = insdat[n+j+3];) ends in 7.5ms:

2023-04-13 20:42:37.331 32740-405   bt_stack                pid-32740                            I  [INFO:le_scanning_manager.cc(318)] SetScanParameters: scan_type=1, scan_interval=6553, scan_window=6553
2023-04-13 20:42:37.495 32740-405   bt_stack                pid-32740                            I  [INFO:le_scanning_manager.cc(318)] SetScanParameters: scan_type=1, scan_interval=2977, scan_window=324
2023-04-13 20:42:39.444  9443-9576  BluetoothGatt           sport.inout.inout                    D  onConnectionUpdated() - Device=702C1F_A interval=6 latency=0 timeout=500 status=0
2023-04-13 20:42:39.599  9443-9576  BluetoothGatt           sport.inout.inout                    D  onConnectionUpdated() - Device=702C1F_A interval=6 latency=0 timeout=500 status=59
2023-04-13 20:42:39.722  9443-9443  Capacitor/Console       sport.inout.inout                    I  File: http://localhost/main.js - Line 377 - Msg: Request HIGH ConnectionPriority for interval
2023-04-13 20:42:39.749  9443-9458  BluetoothGatt           sport.inout.inout                    D  onConnectionUpdated() - Device=702C1F_A interval=6 latency=0 timeout=500 status=30

Version 10 ends in 45ms:

2023-04-13 20:38:08.310 32740-405   bt_stack                pid-32740                            I  [INFO:le_scanning_manager.cc(318)] SetScanParameters: scan_type=1, scan_interval=6553, scan_window=6553
2023-04-13 20:38:08.449 32740-405   bt_stack                pid-32740                            I  [INFO:le_scanning_manager.cc(318)] SetScanParameters: scan_type=1, scan_interval=2977, scan_window=324
2023-04-13 20:38:09.445  9443-9559  BluetoothGatt           sport.inout.inout                    D  onConnectionUpdated() - Device=702C1F_A interval=6 latency=0 timeout=500 status=0
2023-04-13 20:38:09.667  9443-9559  BluetoothGatt           sport.inout.inout                    D  onConnectionUpdated() - Device=702C1F_A interval=36 latency=0 timeout=500 status=0
2023-04-13 20:38:09.773  9443-9443  Capacitor/Console       sport.inout.inout                    I  File: http://localhost/main.js - Line 377 - Msg: Request HIGH ConnectionPriority for interval
2023-04-13 20:38:09.850  9443-9576  BluetoothGatt           sport.inout.inout                    D  onConnectionUpdated() - Device=702C1F_A interval=36 latency=0 timeout=500 status=30

Version 10 + "if(op == LE_CONNECT) set_le_interval_server(clientnode,6,6);" ends in 11.25ms:

2023-04-13 20:50:55.174 32740-405   bt_stack                pid-32740                            I  [INFO:le_scanning_manager.cc(318)] SetScanParameters: scan_type=1, scan_interval=6553, scan_window=6553
2023-04-13 20:50:55.414 32740-405   bt_stack                pid-32740                            I  [INFO:le_scanning_manager.cc(318)] SetScanParameters: scan_type=1, scan_interval=2977, scan_window=324
2023-04-13 20:50:56.419  9443-9459  BluetoothGatt           sport.inout.inout                    D  onConnectionUpdated() - Device=702C1F_A interval=9 latency=0 timeout=500 status=0
2023-04-13 20:50:56.598  9443-9459  BluetoothGatt           sport.inout.inout                    D  onConnectionUpdated() - Device=702C1F_A interval=6 latency=0 timeout=500 status=0
2023-04-13 20:50:56.721  9443-10133 BluetoothGatt           sport.inout.inout                    D  onConnectionUpdated() - Device=702C1F_A interval=9 latency=0 timeout=500 status=0
2023-04-13 20:50:56.776  9443-9443  Capacitor/Console       sport.inout.inout                    I  File: http://localhost/main.js - Line 377 - Msg: Request HIGH ConnectionPriority for interval
2023-04-13 20:50:56.801  9443-10133 BluetoothGatt           sport.inout.inout                    D  onConnectionUpdated() - Device=702C1F_A interval=9 latency=0 timeout=500 status=30

How can I get back my 7.5ms?

read_notify consumes 100% CPU

When I call 'read_notify' in my C-program, after all initialisations to the device have been properly done, it consumes 100% of CPU time of my Ubuntu-Notebook (1 thread is completely busy). Easy to see with 'top'.
The same effect occurs with the test program btferret.

Is there any way to prevent this behaviour?

Giving parameter pointer to callback function of LE server

Hi, me again!

I would like to know if you could give a void pointer to the callback so I can send a structure to the callback (as I need an object from the main function).
So when calling le_server it would receive a third void pointer parameter.
le_server(le_callback,0,(void *)myStruct);
And the callback function would then receive this pointer when called:

int le_callback(int clientnode,int operation,int cticn,void *pvParameter)
{
  struct sObject *myStruct = (struct sObject*) pvParameter;
  //some more code...
}

LE and Classic server

Hi,
Thank you for sharing this extremely useful tool!
Is there a way to run both a LE and Classic server at the same time on the same RPI device?
Will I have to start to independently threaded instances of LE_Server and Node_Server?
Many Thanks!

Is it possible to increase MTU size?

Hi,
In file btlib.c the LEDATLEN is defined as 20. Does that mean the MTU size, right?
I want to send and receive data up to 128 byte. Is it possible? If yes how?
I changed LEDATLEN to 128, and in my nRF52840 firmware also, but it sends/receives still only 20 byte.
I think in btlib.c lots of arraysizes are hardcoded with 20.

Save addresses in device.txt

I have problems with saving found LE-devices in the file 'device.txt'. First I do a scan of LE-devices with btferret. First I do a LE-scan with btferret:
'> b'

.... This is my device:

3 FOUND 00:1B:10:4F:FFFFF - Fixed
    Flags = 06
    Manuf specific = 50 44 43 53 CB 54 77 64 00 00 B8 AD 4F 10 1B 00
    Tx Power Level = 0A
    No name so set = LE node 1003
    New device LE node 1003
....

Then connect to node 1003 and all the rest works correctly.
But if I try to save the device in 'devices.txt' as

DEVICE = Chessnut  TYPE=LE node=1 ADDRESS =  00:1B:10:4F:FFFFF

I get an format error:

Device data from devices.txt file
DEVICE = Chessnut  TYPE=LE node=1 ADDRESS =  00:1B:10:4F:FFFFF
Hex format error - odd number of digits
   ERROR **** Device address must be 6 bytes
************ initblue() FAILED ************

So I have to scan for LE-devices each time at program start, which is a little bit annoying🙁.
Can you tell me what would be the correct entry for this?

Multiple BLE Services and Change Current One

Hey, BLE noobie here...I don't see a way to add more than one BLE service using either the documented methods or the Devices.txt file. I would also like to change the one that is used by default to something else on the fly. Is this a possibility and I am just missing something?
I have the multiple characteristics within the default service seemingly working great. Thanks

Second run issue

Hi!
Thank you for sharing this very useful library & brilliant explanation (readme).
Nice low-level approach.
But I encountered some problems, main is that after first run (>b ; >g) , PC (Ubuntu16) where program is running lost BT-mouse.
​​​​​​​Attempting to run a btferrent once more leads to : 
    Unknown device 52:24:94:23:C7:A5 connected - rejecting.. // that is my mouse
    Unable to read local board address
    Device data from devices.txt file

I suppose that is because Bluez — «off».
ioctl with HCIDEVUP before exit has no effect.
I run vers.12. Any ideas?

Bluetooth Classic server listening to any client?

This is a great library. I have a case that doesn't seem to be fully supported: I would like to connect from an Android app using Bluetooth Classic. More important, the connection/pairing procedure needs to be initiated by the Android app. From my experiment, classic_server needs to know the Android remote address that it will accept connection from.

Why isn't it there a "classic_server(-1, ..." that would accept connection from any client?

The only strategy I see is to have Android to connect to BLE to btfferret, write to a characteristic or something so that btferret is aware of the Android address. Then connect from Android to classic_server(known_android_node,...)

Am I misunderstanding the library?

Cannot connect to LE node (Unknown Connection Identifier)

Hi,
I try to establish a communication to my nRF52840 Module. With btferret I can see my device in the list, I can connect to it and can list the characteristics, I can subscribe to notification and I can receive the notification from nRF52840. Everything works as expected.

However, I wrote a minimal code to connect to nRF52840 but the code gives always error: Unknown Connection Identifier
My nRF52840 sends advertisement every 200ms.
What is wrong in my code?
Thanks.

devices.txt:

DEVICE = My Rpi   TYPE = MESH   NODE = 1001   ADDRESS = <bt address of pi> 
DEVICE = CO2 Sensor Module    TYPE = LE     NODE = 1002   ADDRESS = <address of nRF52840>

main.c:

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include "btlib.h"

int main(int argc, char *argv[])
{
	int retval = 0;
	if (init_blue("devices.txt") == 0) {
		return (0);
	}
	set_print_flag(PRINT_VERBOSE);
	//le_scan();
	set_le_wait(12000); //ms
	
	retval = connect_node(1002, CHANNEL_LE, 0);

	while (1)
	{
		/* code */
	}
	
	printf("ret:%d\nDisconnecting everything and exit..\n",retval);

	close_all();

	return (0);
}

Console output:

Initialising...
Device data from devices.txt file
DEVICE = Tunnel Air Quality   TYPE = MESH   NODE = 1   ADDRESS =  <bt address of pi>
DEVICE = CO2 Sensor Module    TYPE = LE     NODE = 2   ADDRESS =  <address of nRF52840>
SEND LE connect to CO2 Sensor Module
  Set [10].. board address reversed 05..E0
< HCI OGF=08 OCF=0D
      0000  01 0D 20 19 60 00 60 00 - 00 00 05 C6 27 97 D0 E0 
      0010  00 18 00 28 00 00 00 11 - 01 00 00 00 00 
> Event 0F = 00 01 0D 20
      0000  04 0F 04 00 01 0D 20 
Timed out waiting for expected packet
< HCI OGF=08 OCF=0E
      0000  01 0E 20 00 
> Event 0E = 01 0E 20 00
      0000  04 0E 04 01 0E 20 00 
Unknown Connection Identifier
> Event 3E = 01 02 40 00 00 00 05 C6 27 97...
      0000  04 3E 13 01 02 40 00 00 - 00 05 C6 27 97 D0 E0 27 
      0010  00 00 00 11 01 00 
STATUS OK
Fail - no handle
This device may have a random board address which changes
Scan for LE devices to find the current address
leconnect: 0

Compilation error with gcc 11.4.0

Compilation of btferret following the instructions in the README results in the following two errors:

mmourier@optiplex:~/BLE/btferret$ gcc btferret.c btlib.c -o btferret
btferret.c: In function ‘getstring’:
btferret.c:1777:5: warning: format not a string literal and no format arguments [-Wformat-security]
 1777 |     printf(prompt);
      |     ^~~~~~
btlib.c: In function ‘localctics’:
btlib.c:2047:36: warning: ' ' flag used with ‘%o’ gnu_printf format [-Wformat=]
 2047 |         NPRINT "%shandle must be % or greater\n",errs,starthandle);
      |                                    ^

The fix is pretty straightforward, as shown by the diff's below:

mmourier@optiplex:~/BLE/btferret$ git diff
diff --git a/btferret.c b/btferret.c
index bec3d51..15e442c 100644
--- a/btferret.c
+++ b/btferret.c
@@ -1774,7 +1774,7 @@ void getstring(char *prompt,char *s,int len)
   
   do
     {
-    printf(prompt);
+    printf("%s",prompt);
     fgets(s,len,stdin);
     }
   while(s[0] == 10);
diff --git a/btlib.c b/btlib.c
index 8b07ad3..e62a10d 100644
--- a/btlib.c
+++ b/btlib.c
@@ -2044,7 +2044,7 @@ int localctics(int starthandle)
       {
       if(cp->chandle < starthandle)
         {
-        NPRINT "%shandle must be % or greater\n",errs,starthandle);
+        NPRINT "%s handle must be %d or greater\n",errs,starthandle);
         return(0);
         }
    

And when compilation warnings are enabled, gcc prints lots of them, many related to mixing up pointers of different sign: e.g. "char *" and "unsigned char *". I think it would be "a good thing" if the code could compile warning-free ...

Broadcast data and Listen for data at the same time (mesh)

Hi petzval, I am trying to make a mesh from 3 Raspberry Pis. One node will broadcast data to the two other nodes, this part works, but at the same time, I want them to also listen to the other Raspberry Pis for data. However, I am having a problem with the latter. For example, when the mesh server starts listening in raspi A, I tried to send data to other raspi but there is an error like this.

Initialising...
Bluez down failed
Bind failed
HCI socket ERROR - no Bluetooth?

Is it possible to make the node broadcast data and listen for data from the other nodes at the same time? If possible, How can I do it? I'm sorry I am a beginner at this topic. Thank you so much!

Another issue I am facing right now is I tried to code the MESH BROADCASTER but when I try to run it, I cannot receive the data that it sends to other nodes. This is my code:

#include <stdio.h>
#include <stdlib.h>
#include "btlib.h"

int main()
  {
  if(init_blue("devices.txt") == 0)
    return(0);
  
  char buf[4];

  buf[0] = 0x12;
  buf[1] = 0x34;
   // broadcast two-byte mesh packet
  write_mesh(buf,2);
   // broadcast D disconnect command
  write_mesh("D",1);
  return(0);
  }

Error binding socket

trying the sample i get an error while binding the socket to the local adapter in VM, did't change anything just tried to run sample.c and btferret.c

How to modify BLE mininterval,maxinterval and supervision?

During advertisement of a BLE server, the peripheral can suggest some values for min-interval, max-interval and supervision to the central. The central who usually plays the role of client decides in the end. It would be great to be able to modify those values especially the recommending ones on server side?

High traffic BLE write_ctic

I have a scenario of high traffic data going from a device/BLE/peripheral/GATT_server to a Linux_PC/BLE/central/GATT_receiver, both using btferret. The device sender uses write_ctic, the PC receiver uses notification on the same characteristic. High traffic means packet every 10ms.

How can I know that the device sender can write new data to write_ctic? Right now, I need to put a large usleep before writing to write_ctic otherwise btferret goes wild and the hci kernel stack is screwed up, requiring a reboot. The PC receiver listening to the notification is working fine whatever the library (btferret, bluez, webBluetooth) is used.

(Note1: the same scenario works with bluez on both sides though it's not optimal and it has its own set of problems. But at least, it shows that the scenario is possible from a BLE hardware point of view.
Note2: the same scenario works even better using Bluetooth Classic with or without btferret. That's not surprising taking into account the bandwidth of Classic vs. BLE. But I need to make work my scenario with BLE.)

Simultaneously connections to 2 BLE devices

Hello,
at first thank you very much for nice library. I would like to ask you if I can connect 2 BLE devices simultaneously?
I tried to create 2 pthread_t threads and have each process of BLE device under 1 thread, but it doesn't work.
It seems that only 1 connection is allowed.
I'm not skilled at Bluetooth. Can I use it for this purpose?
Thanks

Using the library as "daemon" without stdin

I'm trying to integrate this library in an application that already uses stdin. It would be great to add a daemon option to the library so that there is no conflict about stdin.

Accessory, I would be interested to know how I should patch btlib.c to prevent stdin usage. Should I return 0 in setkeymode and readkey?

Using mutliple adapters

I'm trying to connect to 15 BLE devices by splitting up the connections between three adapters. I can see that I should use init_blue_ex to specify the hci number of the adapter but this seems to set some global state. Is there a way that I can initialize three separate adapters such that I can work with all of them?

Compile for Windows and macOS?

Hello --
I just stumbled across your excellent library, and I'm curious to try to compile as well for macOS and Windows (using mingw).

I think it should be possible, with some tweaks. Has anyone tried either of these?

Bug by read_ctic

I found a bug by calling the read_ctic function.
After trying out multiple times, I found out that reading 1, 2 and 4 bytes does work but not 3 (gives ERROR_FATAL).
(For my particular case I am sending a 3 byte long information for rgb colors).

Here is the code I'm using:

typedef struct sColor
{
  uint8_t r;
  uint8_t g;
  uint8_t b;
} sColor_t;

//Some more code...

char cBuffer[5];
iError = read_ctic(localnode(),3,cBuffer,3);
if(ERROR_FATAL != iError)
{
   sChoosedColor.r = (uint8_t)cBuffer[0];
   sChoosedColor.g = (uint8_t)cBuffer[1];
   sChoosedColor.b = (uint8_t)cBuffer[2];
   printf("sChoosedColor = r:%d g:%d b:%d\n",sChoosedColor.r,sChoosedColor.g,sChoosedColor.b);
}
else
{
   printf("Fatal error by Color reading\n");
}

Race condition when btferret starts for the first time

During the boot sequence of my embedded device on which I run btferret, I need to run a Broadcom script to load the Bluetooth firmware. In my app, I wait for hci0 to come up:

socket(31, SOCK_RAW | SOCK_CLOEXEC | SOCK_NONBLOCK, BTPROTO_HCI);
while (failure) {
	ioctl(dd, HCIGETDEVINFO, (void*) &di);
	check di info
}
init_blue();
le_server(le_callback, 0);

Then, the device advertises correctly and I can see the advertisement on a phone or a PC. btferret outputs "Listening for LE clients to connect (x=stop server)". No problem so far.

But if I connect from that phone or PC, nothing is received by btferret. log doesn't show any "< HCI OGF=08 OCF=0A" when the connection is tried from the phone.

I need to insert a sleep between 1 and 5 seconds before calling init_blue and then btferret can successfully receive data from the adapter.

Obviously, If I start my app manually a "long time" after boot, everything works correctly including a device connection.

How could I debug this situation? Or more interestingly, what do I need to check to confirm it's not too early to start btferret during the boot sequence?

Handling of server disconnections

Sometimes the LE-server of my chessnut device disconnects (in case of weak connections).
Then I want to start a new connection, but my client thread gets stuck in function 'readhci()' and so no further actions are possible.
(Anyway, every 10 seconds I see a message '... not connected' from btlib.c).
This is the output of btlib.c:

...
 4999  6234 board_cb received 38 byte
chessnut has disconnected
chessnut not connected as LE server
chessnut not connected as LE server
...

How is it possible to react to this disconnections?

Characteristics aren't updated correctly

To start I would like to thank you for developping this library, because a tested a lot of different libraries and they were either badly documented or not functionnal on my raspberry and yours was the first I found that worked fine the first time I used it.

For my testing procedures I'm using the nRF Connect Application on my iPhone XS and the bluetooth server is running on a Raspberry Pi B3 (if it can help for the debugging).

I tried multiple things and found out that updating the devices.txt file between two runs wasn't working as it kept finding the characteristics I've set the first time on the nRF Connect application.

Here are screenshots of the application logs:
image
t

And the here is my devices.txt file:
devices.txt

Here you can see that on nRF Connect there isn't the new "Send" Characteristic I added:
T

HCI socket ERROR

Hi,

I'm currently doing a project on BLE mesh networks, and your interface seems perfect for this.
However I keep getting the following errors:

Initialising...
Bluez down failed
Bind failed
HCI socket ERROR - no Bluetooth?

What would the problem be and how can I fix it?

Manufacturer code

In the code, I see:

unsigned char leadvert[40] = { 36,0,0,0,0x01,0x08,0x20,0x20,0x0F,0x08,0xFF,0x34,0x12,
0x00,0x00,0xC0,0xDE,0x99,0x05,0x08,0x61,0x62,0x63,0x64,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 };

btmon says:

< HCI Command: LE Set Advertising Data (0x08|0x0008) plen 32    [hci0] 6.798348
        Length: 17
        Company: not assigned (50087)
          Data: 0000c0de99

What is the relation between 0xC0,0xDE,0x99 and 50087? Android sees 50087.

Huge delay for several continuous packets

Hi petzval,
I have been using this library for the past week and it is great! The documentation is so clear. But I am running into a problem. I'm communicating between two Raspberry pis, one acting as a LE node server, that listens and receives packets, and the other as a node client, that sends packets to the node server continuously, every 500ms, until the loop is exited through a keyboard press. I'm using the function write_node() at the client to send the data. This data is just a 3 byte array of chars. But after a while, after the first 300 messages, the transfer lags a lot. By a few seconds. This is a huge delay, considering I am sending values to control the speed of a motor. How to I reduce this huge delay?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.