예제 #1
0
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)
예제 #2
0
 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)
예제 #3
0
        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)
예제 #4
0
	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)
예제 #5
0
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'))
예제 #6
0
파일: udisksqt.py 프로젝트: Grumbel/dirtool
def main():
    signal.signal(signal.SIGINT, signal.SIG_DFL)
    app = QCoreApplication([])
    bus = QDBusConnection.systemBus()

    udisk_manager = UDiskManager(bus)
    udisk_manager.print_info()
    app.exec()
예제 #7
0
def main():
    signal.signal(signal.SIGINT, signal.SIG_DFL)
    app = QCoreApplication([])
    bus = QDBusConnection.systemBus()

    udisk_manager = UDiskManager(bus)
    udisk_manager.print_info()
    app.exec()
예제 #8
0
	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,
		)
예제 #9
0
 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')
예제 #10
0
	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_}')
			)
예제 #11
0
	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)
예제 #12
0
 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)
예제 #13
0
    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())
예제 #14
0
	def emitError(self, message: str) -> None:
		error = QDBusMessage.createError('failed', message)
		QDBusConnection.systemBus().send(error)
예제 #15
0
	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.
예제 #16
0
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,
예제 #17
0
    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)
예제 #18
0
	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)
예제 #19
0
	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)
예제 #20
0
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.
예제 #21
0
	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()
예제 #22
0
	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)