Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Is there a callback on connect and disconnect? #29

Closed
mmueller-kaffeeschluerfercom opened this issue Aug 14, 2019 · 5 comments
Closed

Comments

@mmueller-kaffeeschluerfercom

I need to take some actions in my program when a device connects or disconnects to GGK. Is there a lambda / callback / whatever, to be notified when a device connects or disconnects?

@nettlep
Copy link
Owner

nettlep commented Aug 14, 2019

The concept of a "connection" (i.e., a stateful connection) doesn't exist here.

@nettlep nettlep closed this as completed Aug 14, 2019
@mmueller-kaffeeschluerfercom
Copy link
Author

Well now I'm a little confused.

The only way for me to read and write a characteristic is to CONNECT the client to the server.

Please correct me if I'm wrong, but to my understanding, in BLE communication, in the "discovery phase", the server (here the rPi with gobbledegook) is advertising with its advertising interval. The client (in this case, android) responds to an advertising packet with a CONNECT_REQ packet ("connecting phase"). Then the server responds with a CONNECT_RSP packet and the connection is established ("connected phase"). And during the whole connection, the devices exchange packets called "connection events". I'm not sure if the rPi is still advertising during an established connection. Some BLE servers (e.g. Nordic nRf 52 series) don't and allow only a single connection at once. They can restart advertising when the connection is closed. But I read that the BLE spec allows multiple connections.

So I don't understand why there should be no concept of a "connection" here.

Is bluez not reporting new connections? Or is it on purpose that gobbledegook abstracts the connection handling?

I'm asking because in my application, I should know which device is connecting to the server. And besides that, I would like to show on a display on the rPi when a BLE client has connected.

Can you please clarify? I'm sure I'm missing something. Thank you!

@nettlep
Copy link
Owner

nettlep commented Aug 15, 2019

Ah, I see. In that case, here's some clarification and a potential solution for you...

The concept of a connection doesn't exist for GATT services under BlueZ. BlueZ handles the connection details and only calls upon our GATT services when needed. Characteristics and other data can even be cached by BlueZ, so there's no way to filter responses based on the client that requested the information.

However, if you just want to know about client connections as they come and go, this information is available. You can see it if you enable Debug logs (enabled in the standalone server with the -d parameter.) Scan the log output for DeviceConnected event and DeviceDisconnected event. This will show you the information available (you won't see device names, but you'll see their addresses.)

Since GGK only uses these events to track the number of active connections, it doesn't store this data. If you want access to it, you'll need to make some modifications to maintain a list of active connections and expose the data.

This should not be difficult to do since each connection is already represented as a DeviceConnectedEvent structure (see HciAdapter.h.) These structs are only created for the purpose of logging their information, then destroyed. All you would need to do is store each DeviceConnectedEvent (perhaps in a list) when connections arrive and remove them on disconnect.

So have a look in HciAdapter.cpp and hunt for this bit of code (around line 335):

// Command status event
case Mgmt::EDeviceConnectedEvent:
{
	DeviceConnectedEvent event(responsePacket);
	activeConnections += 1;
	Logger::debug(SSTR << "  > Connection count incremented to " << activeConnections);
	break;
}
// Command status event
case Mgmt::EDeviceDisconnectedEvent:
{
	DeviceDisconnectedEvent event(responsePacket);
	if (activeConnections > 0)
	{
		activeConnections -= 1;
		Logger::debug(SSTR << "  > Connection count decremented to " << activeConnections);
	}
	else
	{
		Logger::debug(SSTR << "  > Connection count already at zero, ignoring non-connected disconnect event");
	}
	break;
}

Simply add the event to your list in the first case and then remove the appropriate entry from your list in the second case. You should be able to match them based on the address member.

For reference, you can search the mgmt API for Device Connected Event and Device Disconnected Event to see the specs for those events.

I can imagine you would prefer the name of the connecting device (instead of the address) but I don't know if that is available. As you can see in the mgmt api, only an address is provided with those events. I did a cursory scan of the mgmt api for other ways to obtain the name of a connected device, but didn't see one.

If you decide to go forward with any part of this, a pull request would be welcomed.

@ukBaz
Copy link

ukBaz commented Aug 16, 2019

As well as using the mgmt api, Bluez also provides a DBus API for both the Adapter and Device interfaces.

Within the Device interface, a PropertiesChanged signal indicates changes to the connection status.

To see when a new device has been added you can use the standard DBus signal for interfacesAdded

@mmueller-kaffeeschluerfercom
Copy link
Author

Great, thanks a lot for the clarification! The DeviceConnectedEvent is exactly what I was looking for. I don't need the name of the device connecting. Two other questions, if dare:

  • Is it possible to limit the number of active connections to 1? As a potential solution, I imagine I could stop advertising in the EDeviceConnectedEvent event and restart advertising in EDeviceDisconnectedEvent. Or is there a better way?
  • Is it possible to force terminate an active connection from within GGK?

Background: A connected device has to write a certain value to a characteristic within 1 s (an insecure way to authenticate itself), and if it doesn't, the connection is closed by GGK?

Thank you very much!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants