Is there a method using the dbus API that one can use to determine if =
there is an active BLE connection or not? I have an ARM Linux board =
setup as a BLE peripheral, and I want another process to behave =
differently based on whether it can determine there is an active =
connection at the moment or not. I could set a timestamp based on when I =
see WriteValue or other ble dbus activity and then timeout on that, but =
I was hoping for something more direct.=
Hi Travis,
On Mon, Sep 12, 2016 at 8:49 PM, Travis Griggs <[email protected]> wro=
te:
>
>> On Sep 12, 2016, at 8:52 AM, Travis Griggs <[email protected]> wrot=
e:
>>
>> It seems to me though, that maybe I=E2=80=99m going about this wrong. I =
don=E2=80=99t care about the device identity, or which devices are connecte=
d or not. What I really care about is if any device is connected to my app.=
And maybe I have this (kind of indirectly). My characteristic will get a S=
tartNotify/StopNotify event on connect/disconnect edges. I can just use tho=
se to keep track of when I=E2=80=99m active or not.
>
> So I implemented this, and now notice that while I get the StartNotify ev=
ents, I don=E2=80=99t seem to get the StopNotify events.
>
> In one case, I just shut down my iOS app (which had successfully triggere=
d the StartNotify), while the device eventually showed up as disconnected, =
it never propagated a stop notify.
>
> In the next case, I used the LightBlueLE app which allows one to explicit=
ly start listen and stop listen. Explicit stop listen commands on either di=
dn=E2=80=99t show anything.
>
> Running btmon during a start listen/stop listen cycle produced the follow=
ing output:
>
> # btmon
> Bluetooth monitor ver 5.41
> =3D New Index: 5C:F3:70:68:C1:F9 (Primary,USB,hci0) [hci0] =
0.149811
>> ACL Data RX: Handle 64 flags 0x02 dlen 9 [hci0] 2.6=
81703
> ATT: Write Request (0x12) len 4
> Handle: 0x000d
> Data: 0100
> < ACL Data TX: Handle 64 flags 0x00 dlen 5 [hci0] 2.=
693201
> ATT: Write Response (0x13) len 0
>> HCI Event: Number of Completed Packets (0x13) plen 5 [hci0] 3.0=
36696
> Num handles: 1
> Handle: 64
> Count: 1
>> ACL Data RX: Handle 64 flags 0x02 dlen 9 [hci0] 11.8=
62591
> ATT: Write Request (0x12) len 4
> Handle: 0x000d
> Data: 0000
> < ACL Data TX: Handle 64 flags 0x00 dlen 5 [hci0] 11.=
864894
> ATT: Write Response (0x13) len 0
>> HCI Event: Number of Completed Packets (0x13) plen 5 [hci0] 12.1=
61577
> Num handles: 1
> Handle: 64
> Count: 1
>
>
> (also, having btmon running when connected caused btmon to buffer overflo=
w and die)--
We did have some fixes recently to btmon, please check with upstream
version. Regarding StopNotify we are currently using refcount to track
when to disable the notifications so I suspect this is not working
properly. Also we are not stopping the notification when there is no
peer connected, so there is a couple of things to fix.
--=20
Luiz Augusto von Dentz
Hello Travis,
On 12 September 2016 at 16:52, Travis Griggs <[email protected]> wrote=
:
>
>> On Sep 7, 2016, at 3:19 PM, Barry Byford <[email protected]> wrote:
>>
>> Hi Travis,
>>
>> On 7 September 2016 at 22:14, Travis Griggs <[email protected]> wro=
te:
>> <snip>
>>> What is the difference between and adapter and device in the lingo here=
?
>> As you correctly identify the adapter is the bluetooth dongle on your Li=
nux SBC
>> The device is the remote Bluetooth device that you are connecting to.
>
> Aha! Lightbulb moment there for me. Thank you so much!
Excellent news! Glad it helped
>>> <reboot linux device>
>>> # ./connected
>>> (no output)
>>> <ble connect from iphone>
>>> # ./connected
>>> /org/bluez/hci0/dev_49_7C_73_51_21_1E Connected: 1
>>> <terminate iOS app, should disconnect>
>>> # ./connected
>>> /org/bluez/hci0/dev_49_7C_73_51_21_1E Connected: 0
>>> <wait a minute or so>
>>> # ./connected
>>> /org/bluez/hci0/dev_49_7C_73_51_21_1E Connected: 0
>>> <reconnect iOs app>
>>> ./connected
>>> /org/bluez/hci0/dev_49_7C_73_51_21_1E Connected: 0
>>> /org/bluez/hci0/dev_41_7B_77_4F_E4_AA Connected: 1
>>> <disconnect>
>>
>> If looks like your iOS app is creating a different device address each
>> time it is started. I see this on a few of the Android apps that I use
>> that emulate things like heart rate monitors or battery services.
>>
>>
>>> Is there a way to register something more event based so I could be not=
ified when it changes?
>>
>> Yes there is. You can connect to the 'PropertiesChanged' signal on the
>> 'org.bluez.Device1' interface.
>> I've done a piece of code that demonstrates this. I've used an Android
>> app to test it. To get around the issue of it having a different
>> address each time I switch the app on, I've left the app running and
>> then in a separate window on my SBC I use Bluetoothctl to do the
>> connect/disconnect commands.
>>
>> Hopefully the email tool will not mangle the formatting of this code too=
much:
>>
>> #!/usr/bin/env python3
>> import dbus
>> import dbus.mainloop.glib
>> from gi.repository import GLib
>>
>> dbus.mainloop.glib.DBusGMainLoop(set_as_default=3DTrue)
>> mainloop =3D GLib.MainLoop()
>>
>>
>> def get_iface_prop(iface, prop):
>> response =3D {}
>> bus =3D dbus.SystemBus()
>> mng =3D dbus.Interface(bus.get_object('org.bluez', '/'),
>> 'org.freedesktop.DBus.ObjectManager')
>> for path, ifaces in mng.GetManagedObjects().items():
>> if iface in ifaces:
>> response[path] =3D ifaces[iface][prop]
>> return response
>>
>> class Device:
>> def __init__(self, device_path):
>> self.bus =3D dbus.SystemBus()
>> self.device_path =3D device_path
>> self.device_obj =3D self.bus.get_object('org.bluez', device_path)
>> device_props =3D dbus.Interface(self.device_obj, dbus.PROPERTIES_=
IFACE)
>> device_props.connect_to_signal('PropertiesChanged',
>> self.on_prop_changed)
>>
>> def on_prop_changed(self, iface, changed_props, invalidated_props):
>> if 'org.bluez.Device1' in iface:
>> if 'Connected' in changed_props:
>> print('{0} is now {1}'.format(self.device_path,
>> changed_props['Connected']))
>>
>>
>> if __name__ =3D=3D '__main__':
>> for k, v in get_iface_prop('org.bluez.Device1', 'Connected').items():
>> print('{0} is {1}'.format(k, v))
>> Device(k)
>>
>> mainloop.run()
>>
>> My test output looked like this:
>>
>> ./connected_devices.py
>> /org/bluez/hci0/dev_E8_A9_41_CE_31_5A is 0
>> /org/bluez/hci0/dev_5E_4B_97_7B_22_C3 is 1
>> /org/bluez/hci0/dev_B0_B4_48_BE_5D_83 is 0
>> /org/bluez/hci0/dev_F7_17_E4_09_C0_C6 is 0
>> /org/bluez/hci0/dev_8C_2D_AA_44_0E_3A is 0
>> /org/bluez/hci0/dev_5E_4B_97_7B_22_C3 is now 0
>> /org/bluez/hci0/dev_5E_4B_97_7B_22_C3 is now 1
>> /org/bluez/hci0/dev_5E_4B_97_7B_22_C3 is now 0
>>
>> This was all done using BlueZ 5.40 with the experimental flag switched
>> on. I hope that helps move things forward for you.
>
> Your code worked.
Also good news!
> But it seems that it only has a one a time pass to determine which remote=
devices to register the property change. So for a given snapshot of curren=
t devices, it can notify their state changes. But it won=E2=80=99t notice i=
f a new object path shows up.
True the code I gave as an example did not update if a device was
added after initial invocation.
You will need to look at the 'InterfacesAdded' signal to see when a
device gets added.
An example of how to do that would be:
bus.add_signal_receiver(interfaces_added,
dbus_interface=3D'org.freedesktop.DBus.ObjectMa=
nager',
signal_name=3D'InterfacesAdded')
The interfaces_added function could then use the Device class we
created previously to connect to the PropertiesChanged signal on that
device to listen if it was connected or not.
>
> It seems to me though, that maybe I=E2=80=99m going about this wrong. I d=
on=E2=80=99t care about the device identity, or which devices are connected=
or not. What I really care about is if any device is connected to my app. =
And maybe I have this (kind of indirectly). My characteristic will get a St=
artNotify/StopNotify event on connect/disconnect edges. I can just use thos=
e to keep track of when I=E2=80=99m active or not.
Not sure the StopNotify is a reliable way to detect that there has
been a disconnect.
The full code that I used to test what I had written above was:
#!/usr/bin/env python3
import dbus
import dbus.mainloop.glib
from gi.repository import GLib
dbus.mainloop.glib.DBusGMainLoop(set_as_default=3DTrue)
mainloop =3D GLib.MainLoop()
def interfaces_added(path, interfaces):
if 'org.bluez.Device1' in interfaces:
print('Device added at {}'.format(path))
Device(path)
def get_iface_prop(iface, prop):
response =3D {}
bus =3D dbus.SystemBus()
mng =3D dbus.Interface(bus.get_object('org.bluez', '/'),
'org.freedesktop.DBus.ObjectManager')
bus.add_signal_receiver(interfaces_added,
dbus_interface=3D'org.freedesktop.DBus.ObjectMa=
nager',
signal_name=3D'InterfacesAdded')
for path, ifaces in mng.GetManagedObjects().items():
if iface in ifaces:
response[path] =3D ifaces[iface][prop]
return response
class Device:
def __init__(self, device_path):
self.bus =3D dbus.SystemBus()
self.device_path =3D device_path
self.device_obj =3D self.bus.get_object('org.bluez', device_path)
device_props =3D dbus.Interface(self.device_obj, dbus.PROPERTIES_IF=
ACE)
device_props.connect_to_signal('PropertiesChanged',
self.on_prop_changed)
def on_prop_changed(self, iface, changed_props, invalidated_props):
if 'org.bluez.Device1' in iface:
if 'Connected' in changed_props:
print('{0} is now {1}'.format(self.device_path,
changed_props['Connected']))
if __name__ =3D=3D '__main__':
for k, v in get_iface_prop('org.bluez.Device1', 'Connected').items():
print('{0} is {1}'.format(k, v))
Device(k)
mainloop.run()
I removed all the devices before I started running the script so no
devices were reported at invocation. Again, I had a separate window
doing the scanning and connecting which resulted in the following
output:
$ ./connect_devices.py
Device added at /org/bluez/hci0/dev_48_C0_7B_35_98_A5
/org/bluez/hci0/dev_48_C0_7B_35_98_A5 is now 1
/org/bluez/hci0/dev_48_C0_7B_35_98_A5 is now 0
Device added at /org/bluez/hci0/dev_60_06_57_DD_4C_2F
Device added at /org/bluez/hci0/dev_54_1F_46_F1_AA_32
/org/bluez/hci0/dev_54_1F_46_F1_AA_32 is now 1
/org/bluez/hci0/dev_54_1F_46_F1_AA_32 is now 0
> On Sep 12, 2016, at 8:52 AM, Travis Griggs <[email protected]> =
wrote:
>=20
> It seems to me though, that maybe I=E2=80=99m going about this wrong. =
I don=E2=80=99t care about the device identity, or which devices are =
connected or not. What I really care about is if any device is connected =
to my app. And maybe I have this (kind of indirectly). My characteristic =
will get a StartNotify/StopNotify event on connect/disconnect edges. I =
can just use those to keep track of when I=E2=80=99m active or not.
So I implemented this, and now notice that while I get the StartNotify =
events, I don=E2=80=99t seem to get the StopNotify events.
In one case, I just shut down my iOS app (which had successfully =
triggered the StartNotify), while the device eventually showed up as =
disconnected, it never propagated a stop notify.
In the next case, I used the LightBlueLE app which allows one to =
explicitly start listen and stop listen. Explicit stop listen commands =
on either didn=E2=80=99t show anything.
Running btmon during a start listen/stop listen cycle produced the =
following output:
# btmon
Bluetooth monitor ver 5.41
=3D New Index: 5C:F3:70:68:C1:F9 (Primary,USB,hci0) [hci0] =
0.149811
> ACL Data RX: Handle 64 flags 0x02 dlen 9 [hci0] =
2.681703
ATT: Write Request (0x12) len 4
Handle: 0x000d
Data: 0100
< ACL Data TX: Handle 64 flags 0x00 dlen 5 [hci0] =
2.693201
ATT: Write Response (0x13) len 0
> HCI Event: Number of Completed Packets (0x13) plen 5 [hci0] =
3.036696
Num handles: 1
Handle: 64
Count: 1
> ACL Data RX: Handle 64 flags 0x02 dlen 9 [hci0] =
11.862591
ATT: Write Request (0x12) len 4
Handle: 0x000d
Data: 0000
< ACL Data TX: Handle 64 flags 0x00 dlen 5 [hci0] =
11.864894
ATT: Write Response (0x13) len 0
> HCI Event: Number of Completed Packets (0x13) plen 5 [hci0] =
12.161577
Num handles: 1
Handle: 64
Count: 1
(also, having btmon running when connected caused btmon to buffer =
overflow and die)=
> On Sep 7, 2016, at 3:19 PM, Barry Byford <[email protected]> wrote:
>=20
> Hi Travis,
>=20
> On 7 September 2016 at 22:14, Travis Griggs <[email protected]> =
wrote:
> <snip>
>> What is the difference between and adapter and device in the lingo =
here?
> As you correctly identify the adapter is the bluetooth dongle on your =
Linux SBC
> The device is the remote Bluetooth device that you are connecting to.
Aha! Lightbulb moment there for me. Thank you so much!
>=20
>> <reboot linux device>
>> # ./connected
>> (no output)
>> <ble connect from iphone>
>> # ./connected
>> /org/bluez/hci0/dev_49_7C_73_51_21_1E Connected: 1
>> <terminate iOS app, should disconnect>
>> # ./connected
>> /org/bluez/hci0/dev_49_7C_73_51_21_1E Connected: 0
>> <wait a minute or so>
>> # ./connected
>> /org/bluez/hci0/dev_49_7C_73_51_21_1E Connected: 0
>> <reconnect iOs app>
>> ./connected
>> /org/bluez/hci0/dev_49_7C_73_51_21_1E Connected: 0
>> /org/bluez/hci0/dev_41_7B_77_4F_E4_AA Connected: 1
>> <disconnect>
>=20
> If looks like your iOS app is creating a different device address each
> time it is started. I see this on a few of the Android apps that I use
> that emulate things like heart rate monitors or battery services.
>=20
>=20
>> Is there a way to register something more event based so I could be =
notified when it changes?
>=20
> Yes there is. You can connect to the 'PropertiesChanged' signal on the
> 'org.bluez.Device1' interface.
> I've done a piece of code that demonstrates this. I've used an Android
> app to test it. To get around the issue of it having a different
> address each time I switch the app on, I've left the app running and
> then in a separate window on my SBC I use Bluetoothctl to do the
> connect/disconnect commands.
>=20
> Hopefully the email tool will not mangle the formatting of this code =
too much:
>=20
> #!/usr/bin/env python3
> import dbus
> import dbus.mainloop.glib
> from gi.repository import GLib
>=20
> dbus.mainloop.glib.DBusGMainLoop(set_as_default=3DTrue)
> mainloop =3D GLib.MainLoop()
>=20
>=20
> def get_iface_prop(iface, prop):
> response =3D {}
> bus =3D dbus.SystemBus()
> mng =3D dbus.Interface(bus.get_object('org.bluez', '/'),
> 'org.freedesktop.DBus.ObjectManager')
> for path, ifaces in mng.GetManagedObjects().items():
> if iface in ifaces:
> response[path] =3D ifaces[iface][prop]
> return response
>=20
> class Device:
> def __init__(self, device_path):
> self.bus =3D dbus.SystemBus()
> self.device_path =3D device_path
> self.device_obj =3D self.bus.get_object('org.bluez', =
device_path)
> device_props =3D dbus.Interface(self.device_obj, =
dbus.PROPERTIES_IFACE)
> device_props.connect_to_signal('PropertiesChanged',
> self.on_prop_changed)
>=20
> def on_prop_changed(self, iface, changed_props, invalidated_props):
> if 'org.bluez.Device1' in iface:
> if 'Connected' in changed_props:
> print('{0} is now {1}'.format(self.device_path,
> changed_props['Connected']))
>=20
>=20
> if __name__ =3D=3D '__main__':
> for k, v in get_iface_prop('org.bluez.Device1', =
'Connected').items():
> print('{0} is {1}'.format(k, v))
> Device(k)
>=20
> mainloop.run()
>=20
> My test output looked like this:
>=20
> ./connected_devices.py
> /org/bluez/hci0/dev_E8_A9_41_CE_31_5A is 0
> /org/bluez/hci0/dev_5E_4B_97_7B_22_C3 is 1
> /org/bluez/hci0/dev_B0_B4_48_BE_5D_83 is 0
> /org/bluez/hci0/dev_F7_17_E4_09_C0_C6 is 0
> /org/bluez/hci0/dev_8C_2D_AA_44_0E_3A is 0
> /org/bluez/hci0/dev_5E_4B_97_7B_22_C3 is now 0
> /org/bluez/hci0/dev_5E_4B_97_7B_22_C3 is now 1
> /org/bluez/hci0/dev_5E_4B_97_7B_22_C3 is now 0
>=20
> This was all done using BlueZ 5.40 with the experimental flag switched
> on. I hope that helps move things forward for you.
Your code worked. But it seems that it only has a one a time pass to =
determine which remote devices to register the property change. So for a =
given snapshot of current devices, it can notify their state changes. =
But it won=E2=80=99t notice if a new object path shows up.
It seems to me though, that maybe I=E2=80=99m going about this wrong. I =
don=E2=80=99t care about the device identity, or which devices are =
connected or not. What I really care about is if any device is connected =
to my app. And maybe I have this (kind of indirectly). My characteristic =
will get a StartNotify/StopNotify event on connect/disconnect edges. I =
can just use those to keep track of when I=E2=80=99m active or not.=20
Hi Travis,
On 7 September 2016 at 22:14, Travis Griggs <[email protected]> wrote:
<snip>
> What is the difference between and adapter and device in the lingo here?
As you correctly identify the adapter is the bluetooth dongle on your Linux SBC
The device is the remote Bluetooth device that you are connecting to.
> <reboot linux device>
> # ./connected
> (no output)
> <ble connect from iphone>
> # ./connected
> /org/bluez/hci0/dev_49_7C_73_51_21_1E Connected: 1
> <terminate iOS app, should disconnect>
> # ./connected
> /org/bluez/hci0/dev_49_7C_73_51_21_1E Connected: 0
> <wait a minute or so>
> # ./connected
> /org/bluez/hci0/dev_49_7C_73_51_21_1E Connected: 0
> <reconnect iOs app>
> ./connected
> /org/bluez/hci0/dev_49_7C_73_51_21_1E Connected: 0
> /org/bluez/hci0/dev_41_7B_77_4F_E4_AA Connected: 1
> <disconnect>
If looks like your iOS app is creating a different device address each
time it is started. I see this on a few of the Android apps that I use
that emulate things like heart rate monitors or battery services.
> Is there a way to register something more event based so I could be notified when it changes?
Yes there is. You can connect to the 'PropertiesChanged' signal on the
'org.bluez.Device1' interface.
I've done a piece of code that demonstrates this. I've used an Android
app to test it. To get around the issue of it having a different
address each time I switch the app on, I've left the app running and
then in a separate window on my SBC I use Bluetoothctl to do the
connect/disconnect commands.
Hopefully the email tool will not mangle the formatting of this code too much:
#!/usr/bin/env python3
import dbus
import dbus.mainloop.glib
from gi.repository import GLib
dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
mainloop = GLib.MainLoop()
def get_iface_prop(iface, prop):
response = {}
bus = dbus.SystemBus()
mng = dbus.Interface(bus.get_object('org.bluez', '/'),
'org.freedesktop.DBus.ObjectManager')
for path, ifaces in mng.GetManagedObjects().items():
if iface in ifaces:
response[path] = ifaces[iface][prop]
return response
class Device:
def __init__(self, device_path):
self.bus = dbus.SystemBus()
self.device_path = device_path
self.device_obj = self.bus.get_object('org.bluez', device_path)
device_props = dbus.Interface(self.device_obj, dbus.PROPERTIES_IFACE)
device_props.connect_to_signal('PropertiesChanged',
self.on_prop_changed)
def on_prop_changed(self, iface, changed_props, invalidated_props):
if 'org.bluez.Device1' in iface:
if 'Connected' in changed_props:
print('{0} is now {1}'.format(self.device_path,
changed_props['Connected']))
if __name__ == '__main__':
for k, v in get_iface_prop('org.bluez.Device1', 'Connected').items():
print('{0} is {1}'.format(k, v))
Device(k)
mainloop.run()
My test output looked like this:
./connected_devices.py
/org/bluez/hci0/dev_E8_A9_41_CE_31_5A is 0
/org/bluez/hci0/dev_5E_4B_97_7B_22_C3 is 1
/org/bluez/hci0/dev_B0_B4_48_BE_5D_83 is 0
/org/bluez/hci0/dev_F7_17_E4_09_C0_C6 is 0
/org/bluez/hci0/dev_8C_2D_AA_44_0E_3A is 0
/org/bluez/hci0/dev_5E_4B_97_7B_22_C3 is now 0
/org/bluez/hci0/dev_5E_4B_97_7B_22_C3 is now 1
/org/bluez/hci0/dev_5E_4B_97_7B_22_C3 is now 0
This was all done using BlueZ 5.40 with the experimental flag switched
on. I hope that helps move things forward for you.
Cheers,
Barry
Hi Travis,
On 7 September 2016 at 08:37, Tobias Svehagen <[email protected]> wrote:
> The property is not on the Adapter1 interface but it is found on the
> Device1 interface. Also note that you have to check for every object
> under /org/bluez/hci0 if that one is connected. I don't think there is
> a way to see if an adapter is connected or not. Here is an example of
> getting the Connected property of all the devices.
>
> #!/usr/bin/env python3
>
> import dbus
> import os
> import sys
>
> def get_managed_objects():
> bus = dbus.SystemBus()
> manager = dbus.Interface(bus.get_object("org.bluez", "/"),
>
> "org.freedesktop.DBus.ObjectManager")
> return manager.GetManagedObjects()
>
> def main():
> bus = dbus.SystemBus()
>
> objects = get_managed_objects()
> for path, ifaces in iter(objects.items()):
> dev = ifaces.get("org.bluez.Device1")
> if dev is None:
> continue
>
> props = dbus.Interface(bus.get_object("org.bluez", path),
> "org.freedesktop.DBus.Properties")
>
> print(path, "Connected:", props.Get("org.bluez.Device1", "Connected"))
>
> if __name__ == '__main__':
> main()
>
> /Tobias
> --
> To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in
> the body of a message to [email protected]
> More majordomo info at http://vger.kernel.org/majordomo-info.html
I know Tobias has answered this but I thought you might be interested
in seeing a couple of code alternatives:
#!/usr/bin/env python3
import dbus
def get_iface_prop(iface, prop):
response = {}
bus = dbus.SystemBus()
mng = dbus.Interface(bus.get_object('org.bluez', '/'),
'org.freedesktop.DBus.ObjectManager')
for path, ifaces in mng.GetManagedObjects().items():
if iface in ifaces:
response[path] = ifaces[iface][prop]
return response
if __name__ == '__main__':
for k, v in get_iface_prop('org.bluez.Device1', 'Connected').items():
print('{0} is {1}'.format(k, v))
Gives an output something like:
$ ./connected_devices.py
/org/bluez/hci0/dev_F7_17_E4_09_C0_C6 is 1
/org/bluez/hci0/dev_E8_A9_41_CE_31_5A is 0
/org/bluez/hci0/dev_B0_B4_48_BE_5D_83 is 0
/org/bluez/hci0/dev_8C_2D_AA_44_0E_3A is 0
Hope that helps.
Cheers,
Barry
> On Sep 7, 2016, at 12:37 AM, Tobias Svehagen =
<[email protected]> wrote:
>=20
> The property is not on the Adapter1 interface but it is found on the
> Device1 interface. Also note that you have to check for every object
> under /org/bluez/hci0 if that one is connected. I don't think there is
> a way to see if an adapter is connected or not. Here is an example of
> getting the Connected property of all the devices.
<snip>
Thank you very much, your code example worked nicely. Now I have =
additional questions of course. :)
What is the difference between and adapter and device in the lingo here? =
I=E2=80=99m using a usb bluetooth dongle. Can I assume that that is an =
adapter? That if I had two dongles, I would have 2 adapters?
But what then does the =E2=80=9Cdevice=E2=80=9D represent? And why would =
I have more than one of them? Or is it just that they are arbitrarily =
named? The values shown don=E2=80=99t seem to correspond to the addr =
numbers I see when I run hciconfig.
Running the code you graciously shared, I saw some interesting results.
<reboot linux device>
# ./connected
(no output)
<ble connect from iphone>
# ./connected=20
/org/bluez/hci0/dev_49_7C_73_51_21_1E Connected: 1
<terminate iOS app, should disconnect>
# ./connected=20
/org/bluez/hci0/dev_49_7C_73_51_21_1E Connected: 0
<wait a minute or so>
# ./connected=20
/org/bluez/hci0/dev_49_7C_73_51_21_1E Connected: 0
<reconnect iOs app>
./connected=20
/org/bluez/hci0/dev_49_7C_73_51_21_1E Connected: 0
/org/bluez/hci0/dev_41_7B_77_4F_E4_AA Connected: 1
<disconnect>
./connected=20
/org/bluez/hci0/dev_49_7C_73_51_21_1E Connected: 0
/org/bluez/hci0/dev_41_7B_77_4F_E4_AA Connected: 0
<reconnect>
./connected=20
/org/bluez/hci0/dev_49_7C_73_51_21_1E Connected: 0
/org/bluez/hci0/dev_41_7B_77_4F_E4_AA Connected: 1
<reboot linux device>
# ./connected
(no output)
<ble connect from iphone>
./connected
/org/bluez/hci0/dev_41_7B_77_4F_E4_AA Connected: 1
<disconnect, pretty soon after connection, 5s maybe>
./connected
/org/bluez/hci0/dev_41_7B_77_4F_E4_AA Connected: 1
<wait 30s or so>
./connected
/org/bluez/hci0/dev_41_7B_77_4F_E4_AA Connected: 1
<after a minute or so>
./connected
(no response)
If I continued, I think I=E2=80=99d say more variations on the theme. =
The basic patterns I see are that a disconnected/reconnect cycle behaves =
in a couple of different ways
1) the device shows up immediately as not connected, and stays listed as =
not connected, on reconnect is reused and again shows as connected
2) the device shows up immediately as not connected, stays listed as not =
connected, on reconnect a NEW device shows up
3) no device is listed any more (connected or not connected), on =
reconnect the same device again shows up as connected
4) no device is listed any more (connected or not connected), on =
reconnect a NEW device shows up
I would love to understand this.
Running the sample you shared takes 1200-800 ms on my paltry ARM board. =
I don=E2=80=99t know if that is all python/dbus setup or, or query time. =
That=E2=80=99s a long time. Is there a way to register something more =
event based so I could be notified when it changes? Seems like a catch =
22 since I don=E2=80=99t know what the device name will be before hand.
The property is not on the Adapter1 interface but it is found on the
Device1 interface. Also note that you have to check for every object
under /org/bluez/hci0 if that one is connected. I don't think there is
a way to see if an adapter is connected or not. Here is an example of
getting the Connected property of all the devices.
#!/usr/bin/env python3
import dbus
import os
import sys
def get_managed_objects():
bus = dbus.SystemBus()
manager = dbus.Interface(bus.get_object("org.bluez", "/"),
"org.freedesktop.DBus.ObjectManager")
return manager.GetManagedObjects()
def main():
bus = dbus.SystemBus()
objects = get_managed_objects()
for path, ifaces in iter(objects.items()):
dev = ifaces.get("org.bluez.Device1")
if dev is None:
continue
props = dbus.Interface(bus.get_object("org.bluez", path),
"org.freedesktop.DBus.Properties")
print(path, "Connected:", props.Get("org.bluez.Device1", "Connected"))
if __name__ == '__main__':
main()
/Tobias
> On Sep 6, 2016, at 1:53 PM, Tobias Svehagen =
<[email protected]> wrote:
>=20
> Travis,
>=20
> There is a Connected property on the org.bluez.Device1 interface (see
> =
http://git.kernel.org/cgit/bluetooth/bluez.git/tree/doc/device-api.txt).
> This will tell you if that specific device is connected or not. Would
> this solve your problem?
I think it would. If I could figure out how to read it. My python/dbus =
skills are very much monkey-see-monkey-do at this point. I was excited, =
because I already have a snippet that sets the =E2=80=98Alias=E2=80=99 =
of the same interface, so I thought I could just modify a little:
#!/usr/bin/env python3
import dbus
import dbus.mainloop.glib
import gi.repository.GLib as glib
import os
import sys
Adapter =3D '/org/bluez/hci0'
def main():
dbus.mainloop.glib.DBusGMainLoop(set_as_default=3DTrue)
bus =3D dbus.SystemBus()
adapterProperties =3D dbus.Interface(bus.get_object('org.bluez', =
Adapter), 'org.freedesktop.DBus.Properties')
value =3D adapterProperties.Get('org.bluez.Adapter1', 'Connected')
print('connected', value)
mainloop =3D glib.MainLoop()
try:
mainloop.run()
except KeyboardInterrupt:
mainloop.quit()
if __name__ =3D=3D '__main__':
main()
Unfortunately, that doesn=E2=80=99t work. I got the following error:
root@nelson:/Pilot# ./connected=20
Traceback (most recent call last):
File "./connected", line 28, in <module>
main()
File "./connected", line 17, in main
value =3D adapterProperties.Get('org.bluez.Adapter1', 'Connected')
File "/usr/lib/python3/dist-packages/dbus/proxies.py", line 70, in =
__call__
return self._proxy_method(*args, **keywords)
File "/usr/lib/python3/dist-packages/dbus/proxies.py", line 145, in =
__call__
**keywords)
File "/usr/lib/python3/dist-packages/dbus/connection.py", line 651, in =
call_blocking
message, timeout)
dbus.exceptions.DBusException: org.freedesktop.DBus.Error.InvalidArgs: =
No such property =E2=80=98Connected'
My original code had a .Set() call, but maybe I was naive in assuming =
that a .Get() would be the converse? Do I even need to do the runloop =
thing in this case?=
Travis,
There is a Connected property on the org.bluez.Device1 interface (see
http://git.kernel.org/cgit/bluetooth/bluez.git/tree/doc/device-api.txt).
This will tell you if that specific device is connected or not. Would
this solve your problem?
Regards,
Tobias