tools: use the shared dbus client bindings for kete
Since most of the signals are propagated by the bindings we largely just need to hook up simple methods to log what is happening. One nasty hack: we import some of the bits into the kete namespace so tuhi-live continues to work. This can be fixed up in a follow-up commit. Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
This commit is contained in:
parent
07cefa3c26
commit
cd84de4f32
387
tools/kete.py
387
tools/kete.py
|
@ -20,7 +20,6 @@ import errno
|
||||||
import os
|
import os
|
||||||
import json
|
import json
|
||||||
import logging
|
import logging
|
||||||
import re
|
|
||||||
import readline
|
import readline
|
||||||
import struct
|
import struct
|
||||||
import threading
|
import threading
|
||||||
|
@ -31,12 +30,17 @@ from pathlib import Path
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from tuhi.svg import JsonSvg
|
from tuhi.svg import JsonSvg
|
||||||
|
import tuhi.dbusclient
|
||||||
except ModuleNotFoundError:
|
except ModuleNotFoundError:
|
||||||
# If PYTHONPATH isn't set up or we never installed Tuhi, the module
|
# If PYTHONPATH isn't set up or we never installed Tuhi, the module
|
||||||
# isn't available. And since we don't install kete, we can assume that
|
# isn't available. And since we don't install kete, we can assume that
|
||||||
# we're still in the git repo, so messing with the path is "fine".
|
# we're still in the git repo, so messing with the path is "fine".
|
||||||
sys.path.insert(0, os.path.dirname(os.path.realpath(__file__)) + '/..') # noqa
|
sys.path.insert(0, os.path.dirname(os.path.realpath(__file__)) + '/..') # noqa
|
||||||
from tuhi.svg import JsonSvg
|
from tuhi.svg import JsonSvg
|
||||||
|
import tuhi.dbusclient
|
||||||
|
|
||||||
|
# get those into our namespace for tuhi-live's beneft
|
||||||
|
from tuhi.dbusclient import TUHI_DBUS_NAME, ROOT_PATH, ORG_FREEDESKTOP_TUHI1_MANAGER
|
||||||
|
|
||||||
|
|
||||||
CONFIG_PATH = Path(xdg.BaseDirectory.xdg_data_home, 'tuhi-kete')
|
CONFIG_PATH = Path(xdg.BaseDirectory.xdg_data_home, 'tuhi-kete')
|
||||||
|
@ -98,13 +102,6 @@ logger = logging.getLogger('tuhi-kete')
|
||||||
logger.addHandler(logger_handler)
|
logger.addHandler(logger_handler)
|
||||||
logger.setLevel(logging.INFO)
|
logger.setLevel(logging.INFO)
|
||||||
|
|
||||||
TUHI_DBUS_NAME = 'org.freedesktop.tuhi1'
|
|
||||||
ORG_FREEDESKTOP_TUHI1_MANAGER = 'org.freedesktop.tuhi1.Manager'
|
|
||||||
ORG_FREEDESKTOP_TUHI1_DEVICE = 'org.freedesktop.tuhi1.Device'
|
|
||||||
ROOT_PATH = '/org/freedesktop/tuhi1'
|
|
||||||
|
|
||||||
ORG_BLUEZ_DEVICE1 = 'org.bluez.Device1'
|
|
||||||
|
|
||||||
# remove ':' from the completer delimiters of readline so we can match on
|
# remove ':' from the completer delimiters of readline so we can match on
|
||||||
# device addresses
|
# device addresses
|
||||||
completer_delims = readline.get_completer_delims()
|
completer_delims = readline.get_completer_delims()
|
||||||
|
@ -118,340 +115,52 @@ def b2hex(bs):
|
||||||
return ' '.join([''.join(s) for s in zip(hx[::2], hx[1::2])])
|
return ' '.join([''.join(s) for s in zip(hx[::2], hx[1::2])])
|
||||||
|
|
||||||
|
|
||||||
class DBusError(Exception):
|
class TuhiKeteManager(tuhi.dbusclient.TuhiDBusClientManager):
|
||||||
def __init__(self, message):
|
|
||||||
self.message = message
|
|
||||||
|
|
||||||
|
|
||||||
class _DBusObject(GObject.Object):
|
|
||||||
_connection = None
|
|
||||||
|
|
||||||
def __init__(self, name, interface, objpath):
|
|
||||||
GObject.GObject.__init__(self)
|
|
||||||
|
|
||||||
if _DBusObject._connection is None:
|
|
||||||
self._connect_to_session()
|
|
||||||
|
|
||||||
self.interface = interface
|
|
||||||
self.objpath = objpath
|
|
||||||
|
|
||||||
try:
|
|
||||||
self.proxy = Gio.DBusProxy.new_sync(self._connection,
|
|
||||||
Gio.DBusProxyFlags.NONE, None,
|
|
||||||
name, objpath, interface, None)
|
|
||||||
except GLib.Error as e:
|
|
||||||
if (e.domain == 'g-io-error-quark' and
|
|
||||||
e.code == Gio.IOErrorEnum.DBUS_ERROR):
|
|
||||||
raise DBusError(e.message)
|
|
||||||
else:
|
|
||||||
raise e
|
|
||||||
|
|
||||||
if self.proxy.get_name_owner() is None:
|
|
||||||
raise DBusError(f'No-one is handling {name}, is the daemon running?')
|
|
||||||
|
|
||||||
self.proxy.connect('g-properties-changed', self._on_properties_changed)
|
|
||||||
self.proxy.connect('g-signal', self._on_signal_received)
|
|
||||||
|
|
||||||
def _connect_to_session(self):
|
|
||||||
try:
|
|
||||||
_DBusObject._connection = Gio.bus_get_sync(Gio.BusType.SESSION, None)
|
|
||||||
except GLib.Error as e:
|
|
||||||
if (e.domain == 'g-io-error-quark' and
|
|
||||||
e.code == Gio.IOErrorEnum.DBUS_ERROR):
|
|
||||||
raise DBusError(e.message)
|
|
||||||
else:
|
|
||||||
raise e
|
|
||||||
|
|
||||||
def _on_properties_changed(self, proxy, changed_props, invalidated_props):
|
|
||||||
# Implement this in derived classes to respond to property changes
|
|
||||||
pass
|
|
||||||
|
|
||||||
def _on_signal_received(self, proxy, sender, signal, parameters):
|
|
||||||
# Implement this in derived classes to respond to signals
|
|
||||||
pass
|
|
||||||
|
|
||||||
def property(self, name):
|
|
||||||
p = self.proxy.get_cached_property(name)
|
|
||||||
if p is not None:
|
|
||||||
return p.unpack()
|
|
||||||
return p
|
|
||||||
|
|
||||||
def terminate(self):
|
|
||||||
del(self.proxy)
|
|
||||||
|
|
||||||
|
|
||||||
class _DBusSystemObject(_DBusObject):
|
|
||||||
'''
|
|
||||||
Same as the _DBusObject, but connects to the system bus instead
|
|
||||||
'''
|
|
||||||
def __init__(self, name, interface, objpath):
|
|
||||||
self._connect_to_system()
|
|
||||||
super().__init__(name, interface, objpath)
|
|
||||||
|
|
||||||
def _connect_to_system(self):
|
|
||||||
try:
|
|
||||||
self._connection = Gio.bus_get_sync(Gio.BusType.SYSTEM, None)
|
|
||||||
except GLib.Error as e:
|
|
||||||
if (e.domain == 'g-io-error-quark' and
|
|
||||||
e.code == Gio.IOErrorEnum.DBUS_ERROR):
|
|
||||||
raise DBusError(e.message)
|
|
||||||
else:
|
|
||||||
raise e
|
|
||||||
|
|
||||||
|
|
||||||
class BlueZDevice(_DBusSystemObject):
|
|
||||||
def __init__(self, objpath):
|
|
||||||
super().__init__('org.bluez', ORG_BLUEZ_DEVICE1, objpath)
|
|
||||||
self.proxy.connect('g-properties-changed', self._on_properties_changed)
|
|
||||||
|
|
||||||
@GObject.Property
|
|
||||||
def connected(self):
|
|
||||||
return self.proxy.get_cached_property('Connected').unpack()
|
|
||||||
|
|
||||||
def _on_properties_changed(self, obj, properties, invalidated_properties):
|
|
||||||
properties = properties.unpack()
|
|
||||||
|
|
||||||
if 'Connected' in properties:
|
|
||||||
self.notify('connected')
|
|
||||||
|
|
||||||
|
|
||||||
class TuhiKeteDevice(_DBusObject):
|
|
||||||
def __init__(self, manager, objpath):
|
|
||||||
_DBusObject.__init__(self, TUHI_DBUS_NAME,
|
|
||||||
ORG_FREEDESKTOP_TUHI1_DEVICE,
|
|
||||||
objpath)
|
|
||||||
self.manager = manager
|
|
||||||
self.is_registering = False
|
|
||||||
self.live = False
|
|
||||||
self._bluez_device = BlueZDevice(self.property('BlueZDevice'))
|
|
||||||
self._bluez_device.connect('notify::connected', self._on_connected)
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def is_device_address(cls, string):
|
|
||||||
if re.match(r'[0-9a-f]{2}(:[0-9a-f]{2}){5}$', string.lower()):
|
|
||||||
return string
|
|
||||||
raise argparse.ArgumentTypeError(f'"{string}" is not a valid device address')
|
|
||||||
|
|
||||||
@GObject.Property
|
|
||||||
def address(self):
|
|
||||||
return self._bluez_device.property('Address')
|
|
||||||
|
|
||||||
@GObject.Property
|
|
||||||
def name(self):
|
|
||||||
return self._bluez_device.property('Name')
|
|
||||||
|
|
||||||
@GObject.Property
|
|
||||||
def listening(self):
|
|
||||||
return self.property('Listening')
|
|
||||||
|
|
||||||
@GObject.Property
|
|
||||||
def drawings_available(self):
|
|
||||||
return self.property('DrawingsAvailable')
|
|
||||||
|
|
||||||
@GObject.Property
|
|
||||||
def battery_percent(self):
|
|
||||||
return self.property('BatteryPercent')
|
|
||||||
|
|
||||||
@GObject.Property
|
|
||||||
def battery_state(self):
|
|
||||||
return self.property('BatteryState')
|
|
||||||
|
|
||||||
@GObject.Property
|
|
||||||
def connected(self):
|
|
||||||
return self._bluez_device.connected
|
|
||||||
|
|
||||||
def _on_connected(self, bluez_device, pspec):
|
|
||||||
self.notify('connected')
|
|
||||||
|
|
||||||
def register(self):
|
|
||||||
logger.debug(f'{self}: Register')
|
|
||||||
# FIXME: Register() doesn't return anything useful yet, so we wait until
|
|
||||||
# the device is in the Manager's Devices property
|
|
||||||
self.s1 = self.manager.connect('notify::devices', self._on_mgr_devices_updated)
|
|
||||||
self.is_registering = True
|
|
||||||
self.proxy.Register()
|
|
||||||
|
|
||||||
def start_listening(self):
|
|
||||||
self.proxy.StartListening()
|
|
||||||
|
|
||||||
def stop_listening(self):
|
|
||||||
try:
|
|
||||||
self.proxy.StopListening()
|
|
||||||
except GLib.Error as e:
|
|
||||||
if (e.domain != 'g-dbus-error-quark' or
|
|
||||||
e.code != Gio.IOErrorEnum.EXISTS or
|
|
||||||
Gio.dbus_error_get_remote_error(e) != 'org.freedesktop.DBus.Error.ServiceUnknown'):
|
|
||||||
raise e
|
|
||||||
|
|
||||||
def start_live(self, fd):
|
|
||||||
fd_list = Gio.UnixFDList.new()
|
|
||||||
fd_list.append(fd)
|
|
||||||
|
|
||||||
res, fds = self.proxy.call_with_unix_fd_list_sync('org.freedesktop.tuhi1.Device.StartLive',
|
|
||||||
GLib.Variant('(h)', (fd,)),
|
|
||||||
Gio.DBusCallFlags.NO_AUTO_START,
|
|
||||||
-1,
|
|
||||||
fd_list,
|
|
||||||
None)
|
|
||||||
if res[0] == 0:
|
|
||||||
self.live = True
|
|
||||||
|
|
||||||
def stop_live(self):
|
|
||||||
self.proxy.StopLive()
|
|
||||||
self.live = False
|
|
||||||
|
|
||||||
def json(self, timestamp):
|
|
||||||
SUPPORTED_FILE_FORMAT = 1
|
|
||||||
return self.proxy.GetJSONData('(ut)', SUPPORTED_FILE_FORMAT, timestamp)
|
|
||||||
|
|
||||||
def _on_signal_received(self, proxy, sender, signal, parameters):
|
|
||||||
if signal == 'ButtonPressRequired':
|
|
||||||
logger.info(f'{self}: Press button on device now')
|
|
||||||
elif signal == 'ListeningStopped':
|
|
||||||
err = parameters[0]
|
|
||||||
if err == -errno.EACCES:
|
|
||||||
logger.error(f'{self}: wrong device, please re-register.')
|
|
||||||
elif err < 0:
|
|
||||||
logger.error(f'{self}: an error occured: {os.strerror(-err)}')
|
|
||||||
self.notify('listening')
|
|
||||||
elif signal == 'SyncState':
|
|
||||||
state = parameters[0]
|
|
||||||
if state:
|
|
||||||
logger.debug(f'{self}: Downloading from device')
|
|
||||||
else:
|
|
||||||
logger.debug(f'{self}: Download done')
|
|
||||||
|
|
||||||
def _on_properties_changed(self, proxy, changed_props, invalidated_props):
|
|
||||||
if changed_props is None:
|
|
||||||
return
|
|
||||||
|
|
||||||
changed_props = changed_props.unpack()
|
|
||||||
|
|
||||||
if 'DrawingsAvailable' in changed_props:
|
|
||||||
self.notify('drawings-available')
|
|
||||||
elif 'Listening' in changed_props:
|
|
||||||
self.notify('listening')
|
|
||||||
elif 'BatteryPercent' in changed_props:
|
|
||||||
self.notify('battery-percent')
|
|
||||||
elif 'BatteryState' in changed_props:
|
|
||||||
self.notify('battery-state')
|
|
||||||
|
|
||||||
def __repr__(self):
|
|
||||||
return f'{self.address} - {self.name}'
|
|
||||||
|
|
||||||
def _on_mgr_devices_updated(self, manager, pspec):
|
|
||||||
if not self.is_registering:
|
|
||||||
return
|
|
||||||
|
|
||||||
for d in manager.devices:
|
|
||||||
if d.address == self.address:
|
|
||||||
self.is_registering = False
|
|
||||||
self.manager.disconnect(self.s1)
|
|
||||||
del(self.s1)
|
|
||||||
logger.info(f'{self}: Registration successful')
|
|
||||||
|
|
||||||
def terminate(self):
|
|
||||||
try:
|
|
||||||
self.manager.disconnect(self.s1)
|
|
||||||
except AttributeError:
|
|
||||||
pass
|
|
||||||
self._bluez_device.terminate()
|
|
||||||
super(TuhiKeteDevice, self).terminate()
|
|
||||||
|
|
||||||
|
|
||||||
class TuhiKeteManager(_DBusObject):
|
|
||||||
__gsignals__ = {
|
|
||||||
'unregistered-device':
|
|
||||||
(GObject.SignalFlags.RUN_FIRST, None, (GObject.TYPE_PYOBJECT,)),
|
|
||||||
}
|
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
_DBusObject.__init__(self, TUHI_DBUS_NAME,
|
super().__init__()
|
||||||
ORG_FREEDESKTOP_TUHI1_MANAGER,
|
self.connect('unregistered_device', self._on_unregistered_device)
|
||||||
ROOT_PATH)
|
|
||||||
|
|
||||||
self._devices = {}
|
self.sigs = {}
|
||||||
self._unregistered_devices = {}
|
for d in self.devices:
|
||||||
|
self.sigs[d] = []
|
||||||
|
self._connect_device(d)
|
||||||
|
|
||||||
for objpath in self.property('Devices'):
|
def _disconnect_device_signals(self, device):
|
||||||
device = TuhiKeteDevice(self, objpath)
|
|
||||||
self._devices[device.address] = device
|
|
||||||
|
|
||||||
@GObject.Property
|
|
||||||
def devices(self):
|
|
||||||
return [v for k, v in self._devices.items()]
|
|
||||||
|
|
||||||
@GObject.Property
|
|
||||||
def unregistered_devices(self):
|
|
||||||
return [v for k, v in self._unregistered_devices.items()]
|
|
||||||
|
|
||||||
@GObject.Property
|
|
||||||
def searching(self):
|
|
||||||
return self.proxy.get_cached_property('Searching')
|
|
||||||
|
|
||||||
def start_search(self):
|
|
||||||
self._unregistered_devices = {}
|
|
||||||
self.proxy.StartSearch()
|
|
||||||
|
|
||||||
def stop_search(self):
|
|
||||||
try:
|
try:
|
||||||
self.proxy.StopSearch()
|
for s in self.sigs[device]:
|
||||||
except GLib.Error as e:
|
device.disconnect(s)
|
||||||
if (e.domain != 'g-dbus-error-quark' or
|
self.sigs[device] = []
|
||||||
e.code != Gio.IOErrorEnum.EXISTS or
|
except KeyError:
|
||||||
Gio.dbus_error_get_remote_error(e) != 'org.freedesktop.DBus.Error.ServiceUnknown'):
|
pass
|
||||||
raise e
|
|
||||||
self._unregistered_devices = {}
|
|
||||||
|
|
||||||
def terminate(self):
|
def _on_unregistered_device(self, manager, device):
|
||||||
for dev in self._devices.values():
|
self._disconnect_device_signals(device)
|
||||||
dev.terminate()
|
|
||||||
self._devices = {}
|
|
||||||
self._unregistered_devices = {}
|
|
||||||
super(TuhiKeteManager, self).terminate()
|
|
||||||
|
|
||||||
def _on_properties_changed(self, proxy, changed_props, invalidated_props):
|
def log_press_required(device):
|
||||||
if changed_props is None:
|
logger.info(f'{device}: Press button on device now')
|
||||||
return
|
device.connect('button-press-required', log_press_required)
|
||||||
|
|
||||||
changed_props = changed_props.unpack()
|
def log_registered(device):
|
||||||
|
logger.info(f'{device}: Registration successful')
|
||||||
|
device.connect('registered', log_registered)
|
||||||
|
device.connect('registered', self._connect_device)
|
||||||
|
|
||||||
if 'Devices' in changed_props:
|
def _connect_device(self, device):
|
||||||
objpaths = changed_props['Devices']
|
self._disconnect_device_signals(device)
|
||||||
for objpath in objpaths:
|
|
||||||
try:
|
|
||||||
d = self._unregistered_devices[objpath]
|
|
||||||
self._devices[d.address] = d
|
|
||||||
del self._unregistered_devices[objpath]
|
|
||||||
except KeyError:
|
|
||||||
# if we called Register() on an existing device it's not
|
|
||||||
# in unregistered devices
|
|
||||||
pass
|
|
||||||
self.notify('devices')
|
|
||||||
if 'Searching' in changed_props:
|
|
||||||
self.notify('searching')
|
|
||||||
|
|
||||||
def _handle_unregistered_device(self, objpath):
|
def log_sync_state(device, pspec):
|
||||||
for addr, dev in self._devices.items():
|
if device.sync_state:
|
||||||
if dev.objpath == objpath:
|
logger.debug(f'{device}: Communicating with device')
|
||||||
self.emit('unregistered-device', dev)
|
else:
|
||||||
return
|
logger.debug(f'{device}: Communication complete')
|
||||||
|
device.connect('notify::sync-state', log_sync_state)
|
||||||
|
|
||||||
device = TuhiKeteDevice(self, objpath)
|
def log_device_error(d, err):
|
||||||
self._unregistered_devices[objpath] = device
|
if err == -errno.EACCES:
|
||||||
|
logger.error(f'{device}: wrong device, please re-register.')
|
||||||
logger.debug(f'New unregistered device: {device}')
|
elif err < 0:
|
||||||
self.emit('unregistered-device', device)
|
logger.error(f'{device}: an error occured: {os.strerror(-err)}')
|
||||||
|
device.connect('device-error', log_device_error)
|
||||||
def _on_signal_received(self, proxy, sender, signal, parameters):
|
|
||||||
if signal == 'SearchStopped':
|
|
||||||
self.notify('searching')
|
|
||||||
elif signal == 'UnregisteredDevice':
|
|
||||||
objpath = parameters[0]
|
|
||||||
self._handle_unregistered_device(objpath)
|
|
||||||
|
|
||||||
def __getitem__(self, btaddr):
|
|
||||||
return self._devices[btaddr]
|
|
||||||
|
|
||||||
|
|
||||||
class Worker(GObject.Object):
|
class Worker(GObject.Object):
|
||||||
|
@ -743,7 +452,7 @@ class TuhiKeteShell(cmd.Cmd):
|
||||||
readline.set_history_length(100)
|
readline.set_history_length(100)
|
||||||
|
|
||||||
Gio.bus_watch_name(Gio.BusType.SESSION,
|
Gio.bus_watch_name(Gio.BusType.SESSION,
|
||||||
TUHI_DBUS_NAME,
|
tuhi.dbusclient.TUHI_DBUS_NAME,
|
||||||
Gio.BusNameWatcherFlags.NONE,
|
Gio.BusNameWatcherFlags.NONE,
|
||||||
self._on_name_appeared,
|
self._on_name_appeared,
|
||||||
self._on_name_vanished)
|
self._on_name_vanished)
|
||||||
|
@ -875,7 +584,7 @@ class TuhiKeteShell(cmd.Cmd):
|
||||||
add_help=False)
|
add_help=False)
|
||||||
parser.add_argument('-h', action='help', help=argparse.SUPPRESS)
|
parser.add_argument('-h', action='help', help=argparse.SUPPRESS)
|
||||||
parser.add_argument('address', metavar='12:34:56:AB:CD:EF',
|
parser.add_argument('address', metavar='12:34:56:AB:CD:EF',
|
||||||
type=TuhiKeteDevice.is_device_address,
|
type=tuhi.dbusclient.TuhiDBusClientDevice.is_device_address,
|
||||||
default=None,
|
default=None,
|
||||||
help='the address of the device to listen to')
|
help='the address of the device to listen to')
|
||||||
parser.add_argument('mode', choices=['on', 'off'], nargs='?',
|
parser.add_argument('mode', choices=['on', 'off'], nargs='?',
|
||||||
|
@ -986,7 +695,7 @@ class TuhiKeteShell(cmd.Cmd):
|
||||||
add_help=False)
|
add_help=False)
|
||||||
parser.add_argument('-h', action='help', help=argparse.SUPPRESS)
|
parser.add_argument('-h', action='help', help=argparse.SUPPRESS)
|
||||||
parser.add_argument('address', metavar='12:34:56:AB:CD:EF',
|
parser.add_argument('address', metavar='12:34:56:AB:CD:EF',
|
||||||
type=TuhiKeteDevice.is_device_address,
|
type=tuhi.dbusclient.TuhiDBusClientDevice.is_device_address,
|
||||||
default=None,
|
default=None,
|
||||||
help='the address of the device to fetch drawing from')
|
help='the address of the device to fetch drawing from')
|
||||||
parser.add_argument('index', metavar='{<index>|all}',
|
parser.add_argument('index', metavar='{<index>|all}',
|
||||||
|
@ -1083,7 +792,7 @@ class TuhiKeteShell(cmd.Cmd):
|
||||||
add_help=False)
|
add_help=False)
|
||||||
parser.add_argument('-h', action='help', help=argparse.SUPPRESS)
|
parser.add_argument('-h', action='help', help=argparse.SUPPRESS)
|
||||||
parser.add_argument('address', metavar='12:34:56:AB:CD:EF',
|
parser.add_argument('address', metavar='12:34:56:AB:CD:EF',
|
||||||
type=TuhiKeteDevice.is_device_address,
|
type=tuhi.dbusclient.TuhiDBusClientDevice.is_device_address,
|
||||||
default=None,
|
default=None,
|
||||||
help='the address of the device to register')
|
help='the address of the device to register')
|
||||||
|
|
||||||
|
@ -1137,7 +846,7 @@ class TuhiKeteShell(cmd.Cmd):
|
||||||
add_help=False)
|
add_help=False)
|
||||||
parser.add_argument('-h', action='help', help=argparse.SUPPRESS)
|
parser.add_argument('-h', action='help', help=argparse.SUPPRESS)
|
||||||
parser.add_argument('address', metavar='12:34:56:AB:CD:EF',
|
parser.add_argument('address', metavar='12:34:56:AB:CD:EF',
|
||||||
type=TuhiKeteDevice.is_device_address,
|
type=tuhi.dbusclient.TuhiDBusClientDevice.is_device_address,
|
||||||
default=None, nargs='?',
|
default=None, nargs='?',
|
||||||
help='the address of the device to listen to')
|
help='the address of the device to listen to')
|
||||||
|
|
||||||
|
@ -1189,7 +898,7 @@ class TuhiKeteShell(cmd.Cmd):
|
||||||
add_help=False)
|
add_help=False)
|
||||||
parser.add_argument('-h', action='help', help=argparse.SUPPRESS)
|
parser.add_argument('-h', action='help', help=argparse.SUPPRESS)
|
||||||
parser.add_argument('address', metavar='12:34:56:AB:CD:EF',
|
parser.add_argument('address', metavar='12:34:56:AB:CD:EF',
|
||||||
type=TuhiKeteDevice.is_device_address,
|
type=tuhi.dbusclient.TuhiDBusClientDevice.is_device_address,
|
||||||
default=None, nargs='?',
|
default=None, nargs='?',
|
||||||
help='the address of the device to listen to')
|
help='the address of the device to listen to')
|
||||||
parser.add_argument('mode', choices=['on', 'off'], nargs='?',
|
parser.add_argument('mode', choices=['on', 'off'], nargs='?',
|
||||||
|
@ -1246,7 +955,7 @@ def main(args):
|
||||||
with TuhiKeteShell() as shell:
|
with TuhiKeteShell() as shell:
|
||||||
shell.run()
|
shell.run()
|
||||||
|
|
||||||
except DBusError as e:
|
except tuhi.dbusclient.DBusError as e:
|
||||||
logger.error(e.message)
|
logger.error(e.message)
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue