def observe(name: str, callback: Callable[[Any], None]) -> None: """Observe changes in a state value. Args: name: ID of the state variable. "exposure", "focusPeakingColor", etc. callback: Function called when the state updates and upon subscription. Called with one parameter, the new value. Called when registered and when the value updates. Note: Some frequently updated values (> 10/sec) are only available via polling due to flooding concerns. They can not be observed, as they're assumed to *always* be changed. See the API docs for more details. Rationale: It is convenient and less error-prone if we only have one callback that handles the initialization and update of values. The API provides separate initialization and update methods, so we'll store the initialization and use it to perform the initial call to the observe() callback. In addition, this means we only have to query the initial state once, retrieving a blob of all the data available, rather than retrieving each key one syscall at a time as we instantiate each Qt control. """ callback(_camState[name]) QDBusConnection.systemBus().connect('com.krontech.chronos.control.mock', '/', '', name, callback)
def test3(): self._state["recordingExposureNs"] = int(8.5e8) signal = QDBusMessage.createSignal( '/', 'com.krontech.chronos.control.mock', 'recordingExposureNs') signal << self._state["recordingExposureNs"] QDBusConnection.systemBus().send(signal)
def __init__(self): super(Wrapper, self).__init__() return # DDR 2018-06-22: The following function never returns, so everything is broken. QDBusConnection.systemBus().connect( 'com.krontech.chronos.control.mock', '/', '', key, self.updateKey)
def __init__(self): """ NetworkInterfaces is a list of the plugged-in network connections. ```python [{ "path": b"/org/freedesktop/NetworkManager/Devices/1" "name": "Ethernet", "address": "192.168.100.166" or "2001:0db8:85a3::8a2e:0370:7334" }, { ... }] ``` You can `networkInterfaces.observe(callback)` to get updates. """ super().__init__() self._connections = [] #observers collection self._callbacks = [] self.networkManager = QDBusInterface( f"org.freedesktop.NetworkManager", #Service f"/org/freedesktop/NetworkManager", #Path f"org.freedesktop.NetworkManager", #Interface QDBusConnection.systemBus(), ) self.networkManager.setTimeout(10) #Set to 1000 after startup period. #Retry. This doesn't connect the first time, no matter what the time limit is. I don't know why, probably something in the start-on-demand logic. if not self.networkManager.isValid(): self.networkManager = QDBusInterface( f"org.freedesktop.NetworkManager", #Service f"/org/freedesktop/NetworkManager", #Path f"org.freedesktop.NetworkManager", #Interface QDBusConnection.systemBus(), ) self.networkManager.setTimeout(10) if not self.networkManager.isValid(): log.critical(f"Error: Can not connect to NetworkManager at {self.networkManager.service()}. ({self.networkManager.lastError().name()}: {self.networkManager.lastError().message()}) Try running `apt install network-manager`?") raise Exception("D-Bus Setup Error") self.networkManager.setTimeout(1000) #The .connect call freezes if we don't do this, or if we do this twice. #This bug was fixed by Qt 5.11. QDBusConnection.systemBus().registerObject( f"/org/freedesktop/NetworkManager", self, ) self._acquireInterfacesCall = QDBusPendingCallWatcher( self.networkManager.asyncCall('GetDevices') ) self._acquireInterfacesCall.finished.connect(self._acquireInterfaceData)
def unmount_usb_device(block_device: str): """ Attempts to unmount a USB device via org.freedesktop.UDisks2.Filesystem D-Bus interface as described at http://storaged.org/doc/udisks2-api/latest/gdbus-org.freedesktop.UDisks2.Filesystem.html#gdbus-method-org-freedesktop-UDisks2-Filesystem.Unmount. :param block_device: a partition name to unmount, for example /dev/sdb1 """ if block_device is None: raise TypeError("'block_device' cannot be of type 'NoneType'") elif block_device == '': raise ValueError("'block_device' cannot be empty") path = block_device.replace('/dev', '/org/freedesktop/UDisks2/block_devices') file_system_interface = QDBusInterface( 'org.freedesktop.UDisks2', path, 'org.freedesktop.UDisks2.Filesystem', QDBusConnection.systemBus()) if not file_system_interface.isValid(): raise RuntimeError(_translate('DriveUtils', 'Invalid D-Bus interface')) reply = file_system_interface.call('Unmount', {}) if reply.type() == QDBusMessage.ErrorMessage: raise RuntimeError(reply.errorMessage()) elif reply.type() != QDBusMessage.ReplyMessage: raise RuntimeError( _translate('DriveUtils', 'Unexpected reply from Udisks'))
def main(): signal.signal(signal.SIGINT, signal.SIG_DFL) app = QCoreApplication([]) bus = QDBusConnection.systemBus() udisk_manager = UDiskManager(bus) udisk_manager.print_info() app.exec()
def __init__(self): super(APIValues, self).__init__() #The .connect call freezes if we don't do this, or if we do this twice. QDBusConnection.systemBus().registerObject( f"/ca/krontech/chronos/{'control_mock_hack' if USE_MOCK else 'control_hack'}", self, ) self._callbacks = {value: [] for value in _camState} self._callbacks['all'] = [] #meta, watch everything QDBusConnection.systemBus().connect( f"ca.krontech.chronos.{'control_mock' if USE_MOCK else 'control'}", f"/ca/krontech/chronos/{'control_mock' if USE_MOCK else 'control'}", f"", 'notify', self.__newKeyValue, )
def __init__(self): super(DbusTest, self).__init__() bus = QDBusConnection.systemBus() bus.registerObject('/', self) bus.connect( 'org.freedesktop.DBus', '/org/freedesktop/DBus', 'org.freedesktop.DBus', 'NameAcquired', self.testMessage ) print('Connected')
def __init__(self): super().__init__() self._signalObservers = { 'sof': [], #Use lists here to preserve order of callbacks. 'eof': [], 'segment': [], } #The .connect call freezes if we don't do this, or if we do this twice. QDBusConnection.systemBus().registerObject( f"/ca/krontech/chronos/{'video_mock_hack' if USE_MOCK else 'video_hack'}", self, ) for signal_ in self._signalObservers: QDBusConnection.systemBus().connect( f"ca.krontech.chronos.{'video_mock' if USE_MOCK else 'video'}", f"/ca/krontech/chronos/{'video_mock' if USE_MOCK else 'video'}", f"", signal_, getattr(self, f'_{type(self).__name__}__{signal_}') )
def __init__(self, service, path, interface="", bus=QDBusConnection.systemBus()): if not QDBusConnection.systemBus().isConnected(): log.error("Can not connect to D-Bus. Is D-Bus itself running?") raise Exception("D-Bus Setup Error") self.name = type(self).__name__ self.iface = QDBusInterface(service, path, interface, bus) # For Asynchronous call handling. self.enqueuedCalls = [] self.callInProgress = False self.activeCall = None log.info("Connected to D-Bus %s API at %s", self.name, self.iface.path()) # Check for errors. if not self.iface.isValid(): # Otherwise, an error occured. log.error("Can not connect to %s D-Bus API at %s. (%s: %s)", self.name, self.iface.service(), self.iface.lastError().name(), self.iface.lastError().message()) else: self.iface.setTimeout(API_TIMEOUT_MS)
def __init__(self, args, output=OUTPUT, keyboards=KEYBOARDS, pointers=POINTERS, touchscreens=TOUCHSCREENS): super().__init__(args) self._settings = None self._laptop = None self._input_devices = None # Logging logging.basicConfig(filename=LOG_FILE, level=LOG_LEVEL) # access to env (for making external calls) self.env = os.environ.copy() # Output display to rotate self.output = output # weed out any input devices that aren't actually available self.keyboards = self.verify_input_devices(keyboards) self.pointers = self.verify_input_devices(pointers) self.touchscreens = self.verify_input_devices(touchscreens) self.accel_base_dir = None self.incl_base_dir = None # After suspending, we might be resetting the USB device, so we allow a # small number of consecutive failures self._read_fails = 0 self._read_fails_max = 100 self.keyboard_pid = None self._forced = False self._mode_forced = False self._orientation = 'normal' self._poll_interval = POLL_INTERVAL self._accel = [0, 0] self._incl = [0, 0, 0] interface = "se.ewpettersson.yoga" path = "/se/ewpettersson/yoga" method = "tabletmode" self.bus = QDBusConnection.systemBus() # signal is sent by dbus-send so empty service self.bus.connect('', path, interface, method, 'b', self.check_mode) self._tray = QSystemTrayIcon(QIcon.fromTheme("input-tablet"), self) self._tray.show() self._tray.activated.connect(self.systray_clicked) self.make_menu() # Don't quit when settings window is closed self.setQuitOnLastWindowClosed(False) # Run event loop every POLL_INTERVAL seconds self._timer = self.startTimer(self._poll_interval * 1000)
def __ensureDBusSetup(cls): if cls.__connection: return if _has_qt and QCoreApplication.instance(): if os.environ.get("CHARON_USE_SESSION_BUS", 1) == 1: cls.__connection = QDBusConnection.sessionBus() else: cls.__connection = QDBusConnection.systemBus() cls.__signal_forwarder = DBusSignalForwarder(cls.__connection) cls.__use_qt = True return if os.environ.get("CHARON_USE_SESSION_BUS", 0) == 1: cls.__connection = dbus.Bus.get_session() else: GLib.MainLoop().run() cls.__connection = dbus.SystemBus( private=True, mainloop=dbus.mainloop.glib.DBusGMainLoop())
def emitError(self, message: str) -> None: error = QDBusMessage.createError('failed', message) QDBusConnection.systemBus().send(error)
Usage: import api_mock as api print(api.video('thing')) Any comment or call in this file should be considered a proposal, at best, or a bug. """ import sys from PyQt5.QtCore import pyqtSlot, QObject from PyQt5.QtDBus import QDBusConnection#, QDBusMessage, QDBusError # Set up d-bus interface. Connect to mock system buses. Check everything's working. if not QDBusConnection.systemBus().isConnected(): print("Error: Can not connect to D-Bus. Is D-Bus itself running?", file=sys.stderr) sys.exit(-1) ################################## # Callbacks for Set Values # ################################## #Pending callbacks is used by state callbacks to queue long-running or multi #arg tasks such as changeRecordingResolution. This is so a call to set which #contains x/y/w/h of a new camera resolution only actually resets the camera #video pipeline once. Each function which appears in the list is called only #once, after all values have been set.
The service provider component can be extracted if interaction with the HTTP api is desired. While there is a more complete C-based mock, in chronos-cli, it is exceptionally hard to add new calls to. """ import sys import random from debugger import dbg, brk dbg, brk from PyQt5.QtCore import pyqtSlot, QObject, QTimer from PyQt5.QtDBus import QDBusConnection, QDBusInterface, QDBusReply, QDBusMessage from typing import Callable, Any # Set up d-bus interface. Connect to mock system buses. Check everything's working. if not QDBusConnection.systemBus().isConnected(): print("Error: Can not connect to D-Bus. Is D-Bus itself running?", file=sys.stderr) sys.exit(-1) ############################################## # Set up mock dbus interface provider. # ############################################## class ControlMock(QObject): _state = { "recording": { #Hack around video pipeline reconstruction being very slow. "hres": 200, "vres": 300, "hoffset": 800,
def __init__(self, argv: List[str]): parser = argparse.ArgumentParser( description= '"Toast" Linux distros or other ISO files on USB drives.') parser.add_argument('json', nargs='?', type=str, help="Path to JSON file with available distros") parser.add_argument( '-k', '--kiosk', action='store_true', help="Enable kiosk mode (ignore any attempt to close)") parser.set_defaults(kiosk=False) args = parser.parse_args(argv[1:]) self.kiosk = args.kiosk self.threads = dict() self.parameters = dict() filename = args.json if filename is None: # noinspection PyArgumentList filename = QFileDialog.getOpenFileName(None, "Select JSON data file", '', 'JSON file (*.json)') filename = filename[0] # Pressing "cancel" in the file dialog if filename == '': print("Select a file") exit(1) json_distros = None distros = [] logos = dict() try: with open(filename) as file: json_distros = json.loads(file.read()) except FileNotFoundError: print(f"Cannot open {filename} for reading") exit(1) except JSONDecodeError as e: print( f"JSON decode error in {filename} on line {e.lineno}, col {e.colno}: {e.msg}" ) exit(1) for json_distro in json_distros: if json_distro['logo'] in logos: rendered_logo = logos[json_distro['logo']] else: icon = QIcon(json_distro['logo']) size = self.height_for_width(icon, 100) rendered_logo = icon.pixmap(size) logos[json_distro['logo']] = rendered_logo distro = Distro(json_distro['name'], json_distro['file'], json_distro['logo'], rendered_logo, json_distro['description']) distros.append(distro) # noinspection PyArgumentList super().__init__() self.progress_signal.connect(self.toaster_signaled) self.status_bar = self.statusBar() # noinspection PyArgumentList self.progress_area = QVBoxLayout() self.distro_widget = DistroList(distros) self.drives_list = DriveList() self.window() # noinspection PyArgumentList dbus = QDBusConnection.systemBus() dbus.connect('org.freedesktop.UDisks2', '/org/freedesktop/UDisks2', 'org.freedesktop.DBus.ObjectManager', 'InterfacesAdded', self.handle_dbus_add) dbus.connect('org.freedesktop.UDisks2', '/org/freedesktop/UDisks2', 'org.freedesktop.DBus.ObjectManager', 'InterfacesRemoved', self.handle_dbus_remove)
def emitControlSignal(self, name: str, value=None) -> None: """Emit an update signal, usually for indicating a value has changed.""" signal = QDBusMessage.createSignal('/ca/krontech/chronos/control_mock', 'ca.krontech.chronos.control_mock', 'notify') signal << { name: getattr(state, name) if value is None else value } QDBusConnection.systemBus().send(signal)
def __init__(self): """ Get _partitions, a list of things you can save video to. { "name": "Testdisk", "device": "mmcblk0p1", "uuid": "a14d610d-b524-4af2-9a1a-fa3dd1184258", "path": bytes("/dev/sda", 'utf8'), "size": 1294839100, #bytes, 64-bit positive integer "readOnly": False, "interface": "usb", #"usb" or "sd" } """ super().__init__() self._partitions = [] #observers collection self._callbacks = [] self.uDisks2ObjectManager = QDBusInterface( f"org.freedesktop.UDisks2", #Service f"/org/freedesktop/UDisks2", #Path f"org.freedesktop.DBus.ObjectManager", #Interface QDBusConnection.systemBus(), ) self.uDisks2ObjectManager.setTimeout(10) #Set to 1000 after startup period. #Retry. This doesn't connect the first time, no matter what the time limit is. I don't know why, probably something in the start-on-demand logic. if not self.uDisks2ObjectManager.isValid(): self.uDisks2ObjectManager = QDBusInterface( f"org.freedesktop.UDisks2", #Service f"/org/freedesktop/UDisks2", #Path f"org.freedesktop.DBus.ObjectManager", #Interface QDBusConnection.systemBus(), ) self.uDisks2ObjectManager.setTimeout(10) if not self.uDisks2ObjectManager.isValid(): log.critical(f"Error: Can not connect to udisks2 at {self.uDisks2ObjectManager.service()}. ({self.uDisks2ObjectManager.lastError().name()}: {self.uDisks2ObjectManager.lastError().message()}) Try running `apt install udisks2`?") raise Exception("D-Bus Setup Error") self.uDisks2ObjectManager.setTimeout(1000) #The .connect call freezes if we don't do this, or if we do this twice. #This bug was fixed by Qt 5.11. QDBusConnection.systemBus().registerObject( f"/org/freedesktop/UDisks2", self, ) QDBusConnection.systemBus().connect( f"org.freedesktop.UDisks2", #Service f"/org/freedesktop/UDisks2", #Path f"org.freedesktop.DBus.ObjectManager", #Interface 'InterfacesAdded', #Signal self.__interfacesAddedEvent, ) QDBusConnection.systemBus().connect( f"org.freedesktop.UDisks2", #Service f"/org/freedesktop/UDisks2", #Path f"org.freedesktop.DBus.ObjectManager", #Interface 'InterfacesRemoved', #Signal self.__interfacesRemovedEvent, ) for name, data in QDBusReply(self.uDisks2ObjectManager.call('GetManagedObjects')).value().items(): self.__interfacesAdded(name, data)
from PyQt5.QtCore import pyqtSlot, QObject from PyQt5.QtDBus import QDBusConnection, QDBusInterface, QDBusReply, QDBusPendingCallWatcher, QDBusPendingReply from debugger import *; dbg from animate import delay import logging; log = logging.getLogger('Chronos.api') #Mock out the old API; use production for this one so we can switch over piecemeal. USE_MOCK = False #os.environ.get('USE_CHRONOS_API_MOCK') in ('always', 'web') API_INTERCALL_DELAY = 0 API_SLOW_WARN_MS = 100 API_TIMEOUT_MS = 5000 # Set up d-bus interface. Connect to mock system buses. Check everything's working. if not QDBusConnection.systemBus().isConnected(): print("Error: Can not connect to D-Bus. Is D-Bus itself running?", file=sys.stderr) raise Exception("D-Bus Setup Error") cameraControlAPI = QDBusInterface( f"ca.krontech.chronos.{'control_mock' if USE_MOCK else 'control'}", #Service f"/ca/krontech/chronos/{'control_mock' if USE_MOCK else 'control'}", #Path f"", #Interface QDBusConnection.systemBus() ) cameraVideoAPI = QDBusInterface( f"ca.krontech.chronos.{'video_mock' if USE_MOCK else 'video'}", #Service f"/ca/krontech/chronos/{'video_mock' if USE_MOCK else 'video'}", #Path f"", #Interface QDBusConnection.systemBus() ) cameraControlAPI.setTimeout(API_TIMEOUT_MS) #Default is -1, which means 25000ms. 25 seconds is too long to go without some sort of feedback, and the only real long-running operation we have - saving - can take upwards of 5 minutes. Instead of setting the timeout to half an hour, we use events which are emitted as the task progresses. One frame (at 15fps) should be plenty of time for the API to respond, and also quick enough that we'll notice any slowness.
def _acquireInterfaceData(self, reply): """Continuation of __init__. [DDR 2019-11-05] Note: In Qt 5.7, we can't just go self._networkInterfaces['Device'].property(), like we could with self._networkInterfaces['Device'].call(), because .property() doesn't seem to work. afaik, it _should_ work, and the example in https://stackoverflow.com/questions/20042995/error-getting-dbus-interface-property-with-qdbusinterface which is directly relevant to our situation shows it working. Yet, I cannot figure out how to port it to Python. So we do it manually with the `'* property interface'`s. Note: https://doc.qt.io/archives/qt-5.7/qnetworkinterface.html is a thing. Shame it doesn't have notification events. Command-line based examples: docs: https://developer.gnome.org/NetworkManager/0.9/spec.html org.freedesktop.NetworkManager.Device.Wired has ipv4/6 properties gdbus introspect --system --dest org.freedesktop.NetworkManager.Device.Wired --object-path /org/freedesktop/NetworkManager/Device/Wired - Get network interfaces: > gdbus introspect --system --dest org.freedesktop.NetworkManager --object-path /org/freedesktop/NetworkManager - Has ActivateConnection method in org.freedesktop.NetworkManager - Has GetDevices method in org.freedesktop.NetworkManager > gdbus call --system --dest org.freedesktop.NetworkManager --object-path /org/freedesktop/NetworkManager --method org.freedesktop.NetworkManager.GetDevices - ([objectpath '/org/freedesktop/NetworkManager/Devices/0', '/org/freedesktop/NetworkManager/Devices/1', '/org/freedesktop/NetworkManager/Devices/2', '/org/freedesktop/NetworkManager/Devices/3'],) > gdbus introspect --system --dest org.freedesktop.NetworkManager --object-path /org/freedesktop/NetworkManager/Devices/0 - This is apparently a network connection - in this case, loopback. - Links to IPv4/6 config. > gdbus introspect --system --dest org.freedesktop.NetworkManager --object-path /org/freedesktop/NetworkManager/Devices/1 - eth0 - is plugged in? - org.freedesktop.NetworkManager.Device.Wired property Carrier - [implements g interfaces] Filter org.freedesktop.NetworkManager.GetDevices to get the list of plugged-in interfaces. > gdbus introspect --system --dest org.freedesktop.NetworkManager --object-path /org/freedesktop/NetworkManager/DHCP4Config/0 - yields org.freedesktop.NetworkManager.DHCP4Config - from ip_address' Dhcp4Config property - [implements g n lan IPv4 or v6] in properties & PropertiesChanged signal. > gdbus introspect --system --dest org.freedesktop.NetworkManager --object-path /org/freedesktop/NetworkManager/IP6Config/2 - yields org.freedesktop.NetworkManager.IP6Config - from ip_address' Ip6Config property - [implements g n g n www IPv4 or v6] in Addresses (first item) & PropertiesChanged signal. - has Disconnect method - https://developer.gnome.org/NetworkManager/0.9/spec.html#org.freedesktop.NetworkManager.Device.Disconnect > gdbus introspect --system --dest org.freedesktop.NetworkManager --object-path /org/freedesktop/NetworkManager/Devices/2 - eth1 > gdbus introspect --system --dest org.freedesktop.NetworkManager --object-path /org/freedesktop/NetworkManager/Devices/3 - usb0 """ reply = QDBusPendingReply(reply) if reply.isError(): raise DBusException("%s: %s" % (reply.error().name(), reply.error().message())) reply = reply.value() self._networkInterfaces = [{ 'Device': QDBusInterface( #Provides node. f"org.freedesktop.NetworkManager", #Service devicePath, #Path f"org.freedesktop.NetworkManager.Device", #Interface QDBusConnection.systemBus(), ), 'Device.Wired': QDBusInterface( #Provides node. f"org.freedesktop.NetworkManager", #Service devicePath, #Path f"org.freedesktop.NetworkManager.Device.Wired", #Interface QDBusConnection.systemBus(), ), 'Device property interface': QDBusInterface( #Provides interface to get properties of previous node, because `.property()` is broken. "org.freedesktop.NetworkManager", #Service devicePath, #Path "org.freedesktop.DBus.Properties",#Interface QDBusConnection.systemBus() ), } for devicePath in reply ] for interfaces in self._networkInterfaces: for networkInterface in interfaces.values(): networkInterface.setTimeout(1000) if not networkInterface.isValid(): log.critical(f"Error: Can not connect to NetworkManager at {networkInterface.service()}. ({networkInterface.lastError().name()}: {networkInterface.lastError().message()}) Try running `apt install network-manager`?") raise Exception("D-Bus Setup Error") #Deadlock fix as above. QDBusConnection.systemBus().registerObject( interfaces['Device'].path(), self ) #Use above interface to look up the IP address interfaces. interfaces['Ip4Config'] = QDBusInterface( #Provides interface to get properties of previous node, because `.property()` is broken. "org.freedesktop.NetworkManager", #Service QDBusReply(interfaces['Device property interface'].call('Get', #Method 'org.freedesktop.NetworkManager.Device', 'Ip4Config' )).value(), #Interface, Property → Path "org.freedesktop.NetworkManager.IP4Config", #Interface QDBusConnection.systemBus() ) interfaces['Ip4Config property interface'] = QDBusInterface( #Provides interface to get properties of previous node, because `.property()` is broken. "org.freedesktop.NetworkManager", #Service interfaces['Ip4Config'].path(), #Path "org.freedesktop.DBus.Properties",#Interface QDBusConnection.systemBus() ) interfaces['Ip6Config'] = QDBusInterface( #Provides interface to get properties of previous node, because `.property()` is broken. "org.freedesktop.NetworkManager", #Service QDBusReply(interfaces['Device property interface'].call('Get', #Method 'org.freedesktop.NetworkManager.Device', 'Ip6Config' )).value(), #Interface, Property → Path "org.freedesktop.NetworkManager.IP6Config", #Interface QDBusConnection.systemBus() ) interfaces['Ip6Config property interface'] = QDBusInterface( #Provides interface to get properties of previous node, because `.property()` is broken. "org.freedesktop.NetworkManager", #Service interfaces['Ip6Config'].path(), #Path "org.freedesktop.DBus.Properties",#Interface QDBusConnection.systemBus() ) #Subscribe to network update signals, for ip address and carrier status. QDBusConnection.systemBus().connect( f"org.freedesktop.NetworkManager", #Service interfaces['Device'].path(), f"org.freedesktop.NetworkManager.Device", #Interface 'PropertiesChanged', #Signal self.__interfacePropertiesChangedEvent, ) QDBusConnection.systemBus().connect( f"org.freedesktop.NetworkManager", #Service interfaces['Device'].path(), f"org.freedesktop.NetworkManager.Device.Wired", #Interface 'PropertiesChanged', #Signal self.__interfacePropertiesChangedEvent, ) QDBusConnection.systemBus().connect( #untested, don't know how to change ip4 address f"org.freedesktop.NetworkManager", #Service QDBusReply(interfaces['Device property interface'].call('Get', 'org.freedesktop.NetworkManager.Device', 'Dhcp4Config' ) ).value(), #Interface, Property → Path f"org.freedesktop.NetworkManager.Dhcp4Config", #Interface 'PropertiesChanged', #Signal self.__interfacePropertiesChangedEvent, ) QDBusConnection.systemBus().connect( #untested, don't know how to change ip6 address f"org.freedesktop.NetworkManager", #Service QDBusReply(interfaces['Device property interface'].call('Get', 'org.freedesktop.NetworkManager.Device', 'Dhcp6Config' ) ).value(), #Interface, Property → Path f"org.freedesktop.NetworkManager.Dhcp6Config", #Interface 'PropertiesChanged', #Signal self.__interfacePropertiesChangedEvent, ) self.__rescan()
def emitSignal(self, signalName: str, *args) -> None: """Emit an arbitrary signal. (Use emitControlSignal for API values.)""" signal = QDBusMessage.createSignal('/ca/krontech/chronos/control_mock', 'ca.krontech.chronos.control_mock', signalName) for arg in args: signal << arg QDBusConnection.systemBus().send(signal)