dbus: implement StartPairing/StopPairing on the manager
Triggers a StartDiscovery()/StopDiscovery() on the bluetooth adapters, but with a fixed timeout of 30s.
This commit is contained in:
parent
3871fc1d58
commit
43b1c4057c
27
tuhi.py
27
tuhi.py
|
@ -138,14 +138,31 @@ class Tuhi(GObject.Object):
|
|||
GObject.Object.__init__(self)
|
||||
self.server = TuhiDBusServer()
|
||||
self.server.connect('bus-name-acquired', self._on_tuhi_bus_name_acquired)
|
||||
self.server.connect('pairing-start-requested', self._on_start_pairing_requested)
|
||||
self.server.connect('pairing-stop-requested', self._on_stop_pairing_requested)
|
||||
self.bluez = BlueZDeviceManager()
|
||||
self.bluez.connect('device-added', self._on_bluez_device_added)
|
||||
self.bluez.connect('discovery-started', self._on_bluez_discovery_started)
|
||||
self.bluez.connect('discovery-stopped', self._on_bluez_discovery_stopped)
|
||||
|
||||
self.devices = {}
|
||||
|
||||
self._pairing_stop_handler = None
|
||||
|
||||
def _on_tuhi_bus_name_acquired(self, dbus_server):
|
||||
self.bluez.connect_to_bluez()
|
||||
|
||||
def _on_start_pairing_requested(self, dbus_server, stop_handler):
|
||||
self._pairing_stop_handler = stop_handler
|
||||
self.bluez.start_discovery(timeout=30)
|
||||
|
||||
def _on_stop_pairing_requested(self, dbus_server):
|
||||
# If you request to stop, you get a successful stop and we ignore
|
||||
# anything the server does underneath
|
||||
self._pairing_stop_handler(0)
|
||||
self._pairing_stop_handler = None
|
||||
self.bluez.stop_discovery()
|
||||
|
||||
def _on_bluez_device_added(self, manager, bluez_device):
|
||||
if bluez_device.vendor_id != WACOM_COMPANY_ID:
|
||||
return
|
||||
|
@ -154,6 +171,16 @@ class Tuhi(GObject.Object):
|
|||
d = TuhiDevice(bluez_device, tuhi_dbus_device)
|
||||
self.devices[bluez_device.address] = d
|
||||
|
||||
def _on_bluez_discovery_started(self, manager):
|
||||
# Something else may turn discovery mode on, we don't care about
|
||||
# it then
|
||||
if not self._pairing_stop_handler:
|
||||
return
|
||||
|
||||
def _on_bluez_discovery_stopped(self, manager):
|
||||
if self._pairing_stop_handler is not None:
|
||||
self._pairing_stop_handler(0)
|
||||
|
||||
|
||||
def main(args):
|
||||
desc = "Daemon to extract the pen stroke data from Wacom SmartPad devices"
|
||||
|
|
54
tuhi/ble.py
54
tuhi/ble.py
|
@ -11,7 +11,7 @@
|
|||
# GNU General Public License for more details.
|
||||
|
||||
import logging
|
||||
from gi.repository import GObject, Gio
|
||||
from gi.repository import GObject, Gio, GLib
|
||||
|
||||
logger = logging.getLogger('tuhi.ble')
|
||||
|
||||
|
@ -256,6 +256,10 @@ class BlueZDeviceManager(GObject.Object):
|
|||
__gsignals__ = {
|
||||
"device-added":
|
||||
(GObject.SIGNAL_RUN_FIRST, None, (GObject.TYPE_PYOBJECT,)),
|
||||
"discovery-started":
|
||||
(GObject.SIGNAL_RUN_FIRST, None, ()),
|
||||
"discovery-stopped":
|
||||
(GObject.SIGNAL_RUN_FIRST, None, ()),
|
||||
}
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
|
@ -285,6 +289,54 @@ class BlueZDeviceManager(GObject.Object):
|
|||
for obj in self._om.get_objects():
|
||||
self._process_object(obj)
|
||||
|
||||
def _discovery_timeout_expired(self):
|
||||
self.stop_discovery()
|
||||
return False
|
||||
|
||||
def start_discovery(self, timeout=0):
|
||||
"""
|
||||
Start discovery mode, terminating after the specified timeout (in
|
||||
seconds). If timeout is 0, no timeout is imposed and the discovery
|
||||
mode stays on.
|
||||
|
||||
This emits the discovery-started signal
|
||||
"""
|
||||
self.emit("discovery-started")
|
||||
for obj in self._om.get_objects():
|
||||
i = obj.get_interface(ORG_BLUEZ_ADAPTER1)
|
||||
if i is None:
|
||||
continue
|
||||
|
||||
objpath = obj.get_object_path()
|
||||
i.StartDiscovery()
|
||||
logger.debug('{}: Discovery started (timeout {})'.format(objpath, timeout))
|
||||
|
||||
if timeout > 0:
|
||||
GObject.timeout_add_seconds(timeout, self._discovery_timeout_expired)
|
||||
|
||||
# FIXME: Any errors up to here should trigger discovery-stopped
|
||||
# signal with the status code
|
||||
|
||||
def stop_discovery(self):
|
||||
"""
|
||||
Stop an ongoing discovery mode. Any errors are logged but ignored.
|
||||
|
||||
This emits the discovery-stopped signal
|
||||
"""
|
||||
for obj in self._om.get_objects():
|
||||
i = obj.get_interface(ORG_BLUEZ_ADAPTER1)
|
||||
if i is None:
|
||||
continue
|
||||
|
||||
objpath = obj.get_object_path()
|
||||
try:
|
||||
i.StopDiscovery()
|
||||
logger.debug('{}: Discovery stopped'.format(objpath))
|
||||
except GLib.Error as e:
|
||||
logger.debug('{}: Failed to stop discovery ({})'.format(objpath, e))
|
||||
|
||||
self.emit("discovery-stopped")
|
||||
|
||||
def _on_om_object_added(self, om, obj):
|
||||
"""Callback for ObjectManager's object-added"""
|
||||
objpath = obj.get_object_path()
|
||||
|
|
|
@ -23,6 +23,19 @@ INTROSPECTION_XML = """
|
|||
<property type='ao' name='Devices' access='read'>
|
||||
<annotation name='org.freedesktop.DBus.Property.EmitsChangedSignal' value='true'/>
|
||||
</property>
|
||||
|
||||
<method name='StartPairing'>
|
||||
<annotation name='org.freedesktop.DBus.Method.NoReply' value='true'/>
|
||||
</method>
|
||||
|
||||
<method name='StopPairing'>
|
||||
<annotation name='org.freedesktop.DBus.Method.NoReply' value='true'/>
|
||||
</method>
|
||||
|
||||
<signal name='PairingStopped'>
|
||||
<arg name='status' type='i' />
|
||||
</signal>
|
||||
|
||||
</interface>
|
||||
|
||||
<interface name='org.freedesktop.tuhi1.Device'>
|
||||
|
@ -131,6 +144,15 @@ class TuhiDBusServer(GObject.Object):
|
|||
__gsignals__ = {
|
||||
"bus-name-acquired":
|
||||
(GObject.SIGNAL_RUN_FIRST, None, ()),
|
||||
|
||||
# Signal arguments:
|
||||
# pairing_stop_handler(status)
|
||||
# to be called when the pairing process has terminated, with
|
||||
# an integer status code (0 == success, negative errno)
|
||||
"pairing-start-requested":
|
||||
(GObject.SIGNAL_RUN_FIRST, None, (GObject.TYPE_PYOBJECT,)),
|
||||
"pairing-stop-requested":
|
||||
(GObject.SIGNAL_RUN_FIRST, None, ()),
|
||||
}
|
||||
|
||||
def __init__(self):
|
||||
|
@ -142,6 +164,7 @@ class TuhiDBusServer(GObject.Object):
|
|||
self._bus_aquired,
|
||||
self._bus_name_aquired,
|
||||
self._bus_name_lost)
|
||||
self._is_pairing = False
|
||||
|
||||
def _bus_aquired(self, connection, name):
|
||||
introspection = Gio.DBusNodeInfo.new_for_xml(INTROSPECTION_XML)
|
||||
|
@ -161,8 +184,16 @@ class TuhiDBusServer(GObject.Object):
|
|||
def _bus_name_lost(self, connection, name):
|
||||
pass
|
||||
|
||||
def _method_cb(self):
|
||||
pass
|
||||
def _method_cb(self, connection, sender, objpath, interface, methodname, args, invocation):
|
||||
if interface != INTF_MANAGER:
|
||||
return None
|
||||
|
||||
if methodname == 'StartPairing':
|
||||
self._start_pairing()
|
||||
invocation.return_value()
|
||||
elif methodname == 'StopPairing':
|
||||
self._stop_pairing()
|
||||
invocation.return_value()
|
||||
|
||||
def _property_read_cb(self, connection, sender, objpath, interface, propname):
|
||||
if interface != INTF_MANAGER:
|
||||
|
@ -176,6 +207,30 @@ class TuhiDBusServer(GObject.Object):
|
|||
def _property_write_cb(self):
|
||||
pass
|
||||
|
||||
def _start_pairing(self):
|
||||
if self._is_pairing:
|
||||
return
|
||||
|
||||
self._is_pairing = True
|
||||
self.emit("pairing-start-requested", self._on_pairing_stop)
|
||||
|
||||
def _stop_pairing(self):
|
||||
if not self._is_pairing:
|
||||
return
|
||||
|
||||
self._is_pairing = False
|
||||
self.emit("pairing-stop-requested")
|
||||
|
||||
def _on_pairing_stop(self, status):
|
||||
"""
|
||||
Called by whoever handles the pairing-start-requested signal
|
||||
"""
|
||||
logger.debug("Pairing has stopped")
|
||||
status = GLib.Variant.new_int32(status)
|
||||
status = GLib.Variant.new_tuple(status)
|
||||
self._connection.emit_signal(None, BASE_PATH, INTF_MANAGER,
|
||||
"PairingStopped", status)
|
||||
|
||||
def cleanup(self):
|
||||
Gio.bus_unown_name(self._dbus)
|
||||
|
||||
|
|
Loading…
Reference in New Issue