ble: make object manager return sorted object list
The object list returned by object managers get_objects() function is not sorted. Though, we rely on objects being sorted by their object path. Replace the object managers get_objects() function with a variant fixing that. Additionally, our variant makes it possible to filter the returned object list by object path and interface. Examples: - get_objects(): / /org/bluez /org/bluez/hci0 /org/bluez/hci0/dev_00_00_00_00_00_00 /org/bluez/hci0/dev_00_00_00_00_00_00/service0000 /org/bluez/hci0/dev_00_00_00_00_00_00/service0000/char0000 /org/bluez/hci0/dev_00_00_00_00_00_00/service1111 /org/bluez/hci0/dev_00_00_00_00_00_00/service1111/char1111 /org/bluez/hci0/dev_FF_FF_FF_FF_FF_FF /org/bluez/hci0/dev_FF_FF_FF_FF_FF_FF/serviceffff /org/bluez/hci0/dev_FF_FF_FF_FF_FF_FF/serviceffff/charffff - get_objects(interface='org.bluez.Adapter1'): /org/bluez/hci0 - get_objects(interface='org.bluez.GattCharacteristic1' base_path='/org/bluez/hci0/dev_00_00_00_00_00_00'): /org/bluez/hci0/dev_00_00_00_00_00_00/service0000/char0000 /org/bluez/hci0/dev_00_00_00_00_00_00/service1111/char1111 Signed-off-by: Daniel Martin <consume.noise@gmail.com>
This commit is contained in:
parent
1016fb29d0
commit
e7f8cc2bc2
70
tuhi/ble.py
70
tuhi/ble.py
|
@ -11,6 +11,7 @@
|
|||
# GNU General Public License for more details.
|
||||
|
||||
import logging
|
||||
from functools import partial
|
||||
from gi.repository import GObject, Gio, GLib
|
||||
|
||||
logger = logging.getLogger('tuhi.ble')
|
||||
|
@ -284,6 +285,54 @@ class BlueZDevice(GObject.Object):
|
|||
return f'Device {self.name}:{self.objpath}'
|
||||
|
||||
|
||||
class BlueZObjectManager:
|
||||
'''
|
||||
Namespace to encapsulate our modification to the object manager.
|
||||
'''
|
||||
@classmethod
|
||||
def instance(cls):
|
||||
proxy = Gio.DBusObjectManagerClient.new_for_bus_sync(
|
||||
Gio.BusType.SYSTEM,
|
||||
Gio.DBusObjectManagerClientFlags.NONE,
|
||||
'org.bluez',
|
||||
'/',
|
||||
None,
|
||||
None,
|
||||
None)
|
||||
|
||||
# Replace the object managers get_objects() with our pimped one.
|
||||
proxy.get_objects_unsorted = proxy.get_objects
|
||||
proxy.get_objects = partial(cls.get_objects, proxy)
|
||||
|
||||
return proxy
|
||||
|
||||
def get_objects(self, interface=None, base_path=None):
|
||||
'''
|
||||
Get objects sorted by their object path.
|
||||
|
||||
Optional arguments can be used to filter the returned object list.
|
||||
|
||||
:param interface: filter objects by interface, default is None
|
||||
:param base_path: filter objects by object path, default is None
|
||||
(the objects path has to start with `base_path`)
|
||||
'''
|
||||
def base_path_filter(obj):
|
||||
return obj.get_object_path().startswith(base_path)
|
||||
|
||||
def interface_filter(obj):
|
||||
return obj.get_interface(interface) is not None
|
||||
|
||||
objs = self.get_objects_unsorted()
|
||||
|
||||
if base_path is not None:
|
||||
objs = filter(base_path_filter, objs)
|
||||
|
||||
if interface is not None:
|
||||
objs = filter(interface_filter, objs)
|
||||
|
||||
return sorted(objs, key=lambda obj: obj.get_object_path())
|
||||
|
||||
|
||||
class BlueZDeviceManager(GObject.Object):
|
||||
'''
|
||||
Manager object that connects to org.bluez's root object and handles the
|
||||
|
@ -311,20 +360,10 @@ class BlueZDeviceManager(GObject.Object):
|
|||
resolved as they come in. The device-added signal is emitted for
|
||||
each device.
|
||||
'''
|
||||
self._om = Gio.DBusObjectManagerClient.new_for_bus_sync(
|
||||
Gio.BusType.SYSTEM,
|
||||
Gio.DBusObjectManagerClientFlags.NONE,
|
||||
'org.bluez',
|
||||
'/',
|
||||
None,
|
||||
None,
|
||||
None)
|
||||
self._om = BlueZObjectManager.instance()
|
||||
self._om.connect('object-added', self._on_om_object_added)
|
||||
self._om.connect('object-removed', self._on_om_object_removed)
|
||||
|
||||
# We rely on nested object paths, so let's sort the objects by
|
||||
# object path length and process them in order, this way we're
|
||||
# guaranteed that the objects we need already exist.
|
||||
for obj in self._om.get_objects():
|
||||
self._process_object(obj)
|
||||
|
||||
|
@ -346,10 +385,8 @@ class BlueZDeviceManager(GObject.Object):
|
|||
|
||||
self._discovery = True
|
||||
|
||||
for obj in self._om.get_objects():
|
||||
for obj in self._om.get_objects(interface=ORG_BLUEZ_ADAPTER1):
|
||||
i = obj.get_interface(ORG_BLUEZ_ADAPTER1)
|
||||
if i is None:
|
||||
continue
|
||||
|
||||
# remove the duplicate data filter so we get notifications as they come in
|
||||
i.SetDiscoveryFilter('(a{sv})', {'DuplicateData': GLib.Variant.new_boolean(False)})
|
||||
|
@ -381,11 +418,8 @@ class BlueZDeviceManager(GObject.Object):
|
|||
|
||||
self._discovery = False
|
||||
|
||||
for obj in self._om.get_objects():
|
||||
for obj in self._om.get_objects(interface=ORG_BLUEZ_ADAPTER1):
|
||||
i = obj.get_interface(ORG_BLUEZ_ADAPTER1)
|
||||
if i is None:
|
||||
continue
|
||||
|
||||
objpath = obj.get_object_path()
|
||||
try:
|
||||
i.StopDiscovery()
|
||||
|
|
Loading…
Reference in New Issue