Ejemplo n.º 1
0
    def iface(self):
        if hasattr(self, "_iface"):
            iface = self._iface
        else:
            iface_methods = []
            for method_name, (args_xform, returns_xform,
                              fn) in self.methods.items():
                iface_methods.append(
                    Method(
                        method_name,
                        arguments=args_xform.signature(),
                        returns=returns_xform.signature(),
                    ))

            iface_properties = []
            for prop_name, (xform, _, kwargs) in self.properties.items():
                iface_properties.append(
                    Property(prop_name, xform.signature(), **kwargs))

            iface_signals = []
            for signal_name, xform in self.signals.items():
                iface_signals.append(Signal(signal_name, xform.signature()))

            iface = DBusInterface(
                f"{self.service.namespace}.{self.iface_name}",
                *(iface_methods + iface_properties + iface_signals),
            )
            self._iface = iface
        return iface
Ejemplo n.º 2
0
class BlueZLEAdvertisement(DBusObject):
    """
    org.bluez.LEAdvertisement1 interface implementation
    """

    interface_name: str = "org.bluez.LEAdvertisement1"

    iface: DBusInterface = DBusInterface(
        interface_name, Method("Release"), Property("Type", "s"),
        Property("ServiceUUIDs", "as"), Property("ManufacturerData", "a{qay}"),
        Property("SolicitUUIDs", "as"), Property("ServiceData", "a{sv}"),
        Property("IncludeTxPower", "b"))

    dbusInterfaces: List[DBusInterface] = [iface]

    ad_type: DBusProperty = DBusProperty("Type")
    service_uuids: DBusProperty = DBusProperty("ServiceUUIDs")
    # manufacturer_data = DBusProperty("ManufacturerData")
    # solicit_uuids = DBusProperty("SolicitUUIDs")
    # service_data = DBusProperty("ServiceData")
    include_tx_power: DBusProperty = DBusProperty("IncludeTxPower")

    def __init__(
            self,
            advertising_type: Type,
            index: int,
            app: "BlueZGattApplication"  # noqa: F821
    ):
        """
        New Low Energy Advertisement

        Parameters
        ----------
        advertising_type : Type
            The type of advertisement
        index : int,
            The index of the advertisement
        app : BlueZGattApplication
            The Application that is responsible for this advertisement
        """
        self.ad_type: str = advertising_type.value
        self.path = app.base_path + "/advertisement" + str(index)

        self.service_uuids: List[str] = []
        self.manufacturer_data: Dict = {}
        self.solicit_uuids = ['']
        self.service_data = {'': 0}

        self.include_tx_power: bool = False

        self.data = None
        super(BlueZLEAdvertisement, self).__init__(self.path)

    @dbusMethod(interface_name, "Release")
    def Release(self):  # noqa: N802
        print("%s: Released!" % self.path)
Ejemplo n.º 3
0
class BlueZGattService(DBusObject):
    """
    org.bluez.GattService1 interface implementation
    """

    interface_name: str = defs.GATT_SERVICE_INTERFACE

    iface: DBusInterface = DBusInterface(
            interface_name,
            Property("UUID", "s"),
            Property("Primary", "b"),
            )

    dbusInterfaces: List[DBusInterface] = [iface]

    uuid: DBusProperty = DBusProperty("UUID")
    primary: DBusProperty = DBusProperty("Primary")

    def __init__(
            self,
            uuid: str,
            primary: bool,
            index: int,
            app: 'BlueZGattApplication',  # noqa: F821
            ):
        """
        Initialize the DBusObject

        Parameters
        ----------
        uuid : str
            A string representation of the unique identifier
        primary : bool
            Whether the service is the primary service for the application it
            belongs to
        index : int
            The index of the service amongst the other service of the
            application
        app : BlueZApp
            A BlueZApp object that owns this service
        """
        self.path: str = app.base_path + "/service" + str(index)
        self.bus: client = app.bus
        self.destination: str = app.destination
        self.uuid: str = uuid
        self.primary: bool = primary
        self.loop: asyncio.AbstractEventLoop = app.loop
        self.app: 'BlueZGattApplication' = app  # noqa: F821

        self.characteristics: List[BlueZGattCharacteristic] = []
        super(BlueZGattService, self).__init__(self.path)
Ejemplo n.º 4
0
class Network(BaseIface):
    """Interface implemented by objects representing configured networks"""

    INTERFACE_PATH = 'fi.w1.wpa_supplicant1.Network'

    iface = DBusInterface(
        INTERFACE_PATH,
        Signal('PropertiesChanged', 'a{sv}')
    )

    def __repr__(self):
        return str(self)

    def __str__(self):
        return "Network(Path: %s, Properties: %s)" % (self.get_path(),
                                                      self.get_properties())

    #
    # Properties
    #
    def get_properties(self):
        """Properties of the configured network

        Dictionary contains entries from "network" block of  wpa_supplicant.conf.
        All values are string type, e.g., frequency is "2437", not 2437.
        """

        network_properties = self.get('Properties')
        ssid = network_properties.get('ssid', '')
        if ssid:
            quote_chars = {'"', "'"}
            ssid = ssid[1:] if ssid[0] in quote_chars else ssid
            ssid = ssid[:-1] if ssid[-1] in quote_chars else ssid
        network_properties.update({
            'ssid': ssid
        })
        return network_properties

    def get_enabled(self):
        """Determines if the configured network is enabled or not"""

        return self.get('Enabled')
Ejemplo n.º 5
0
to run on every PC but serves as a reference.
"""

from twisted.internet import reactor, defer
from txdbus import client, error
from txdbus.interface import DBusInterface, Method, Signal
import time

dbus_name = 'fi.w1.wpa_supplicant1'
root_iface_str = 'fi.w1.wpa_supplicant1'
root_iface_obj_path = "/" + root_iface_str.replace('.', '/')

interface_iface_str = root_iface_str + ".Interface"
interface_iface = DBusInterface(
    interface_iface_str, Signal('ScanDone', 'b'),
    Method('Scan', arguments='a{sv}'),
    Method('AddNetwork', arguments='a{sv}', returns='o'),
    Method('RemoveNetwork', arguments='o'),
    Method('SelectNetwork', arguments='o'))


@defer.inlineCallbacks
def set_mode_example():
    cli = yield client.connect(reactor, busAddress='system')

    root_obj = yield cli.getRemoteObject(dbus_name, root_iface_obj_path)
    print "Root Object: %s" % root_obj

    wlan0_obj_path = yield root_obj.callRemote('GetInterface', 'wlan1')
    print "WLAN0 Object Path: %s" % wlan0_obj_path

    wlan0_obj = yield cli.getRemoteObject(dbus_name, wlan0_obj_path,
Ejemplo n.º 6
0
__all__ = [
    'BUS_NAME', 'OBJECT_PATH', 'si446x_dbus_interface', 'Si446xDbus',
    'reactor_loop'
]

BUS_NAME = 'org.tagnet.si446x'
OBJECT_PATH = '/org/tagnet/si446x/0/0'  # object name includes device id/port numbers

si446x_dbus_interface = DBusInterface(
    BUS_NAME,
    Method('cca', returns='u'),
    Method('clear_status', returns='s'),
    Method('control', arguments='s', returns='s'),
    Method('dump_radio', arguments='s', returns='s'),
    Method('dump_trace', arguments='sissu', returns='a(dyssay)'),
    Method('send', arguments='ayu', returns='s'),
    Method('spi_send', arguments='ays', returns='s'),
    Method('spi_send_recv', arguments='ayuss', returns='ay'),
    Method('status', returns='s'),
    Signal('new_status', 's'),
    Signal('receive', 'ayu'),
    Signal('send_cmp', 's'),
)


class Si446xDbus(objects.DBusObject):
    """
    provides the interface for accessing the SI446x Radio Chip Driver
    """
    dbusInterfaces = [si446x_dbus_interface]
Ejemplo n.º 7
0
class BlueZGattService(DBusObject):
    """
    org.bluez.GattService1 interface implementation
    """

    interface_name: str = defs.GATT_SERVICE_INTERFACE

    iface: DBusInterface = DBusInterface(
        interface_name,
        Property("UUID", "s"),
        Property("Primary", "b"),
    )

    dbusInterfaces: List[DBusInterface] = [iface]

    uuid: DBusProperty = DBusProperty("UUID")
    primary: DBusProperty = DBusProperty("Primary")

    def __init__(
        self,
        uuid: str,
        primary: bool,
        index: int,
        app: "BlueZGattApplication",  # noqa: F821
    ):
        """
        Initialize the DBusObject

        Parameters
        ----------
        uuid : str
            A string representation of the unique identifier
        primary : bool
            Whether the service is the primary service for the application it
            belongs to
        index : int
            The index of the service amongst the other service of the
            application
        app : BlueZApp
            A BlueZApp object that owns this service
        """
        hex_index: str = hex(index)[2:].rjust(4, "0")
        self.path: str = app.base_path + "/service" + hex_index
        self.bus: client = app.bus
        self.destination: str = app.destination
        self.uuid: str = uuid
        self.primary: bool = primary
        self.loop: asyncio.AbstractEventLoop = app.loop
        self.app: "BlueZGattApplication" = app  # noqa: F821

        self.characteristics: List[BlueZGattCharacteristic] = []
        super(BlueZGattService, self).__init__(self.path)

    async def add_characteristic(
        self, uuid: str, flags: List[Flags], value: Any
    ) -> BlueZGattCharacteristic:
        """
        Adds a BlueZGattCharacteristic to the service.

        Parameters
        ----------
        uuid : str
            The string representation of the UUID for the characteristic
        flags : List[Flags],
            A list of flags to apply to the characteristic
        value : Any
            The characteristic's value
        """
        index: int = len(self.characteristics) + 1
        characteristic: BlueZGattCharacteristic = BlueZGattCharacteristic(
            uuid, flags, index, self
        )
        characteristic.value = value
        self.characteristics.append(characteristic)
        await self.app._register_object(characteristic)
        return characteristic

    async def get_obj(self) -> Dict:
        """
        Obtain the underlying dictionary within the BlueZ API that describes
        the service

        Returns
        -------
        Dict
            The dictionary that describes the service
        """
        dbus_obj: RemoteDBusObject = await self.app.bus.getRemoteObject(
            self.app.destination, self.path
        ).asFuture(self.app.loop)
        dict_obj: Dict = await dbus_obj.callRemote(
            "GetAll",
            defs.GATT_SERVICE_INTERFACE,
            interface=defs.PROPERTIES_INTERFACE,
        ).asFuture(self.app.loop)
        return dict_obj
Ejemplo n.º 8
0
class BSS(BaseIface):
    """Interface implemented by objects representing a scanned BSSs (scan results)"""

    INTERFACE_PATH = 'fi.w1.wpa_supplicant1.BSS'

    iface = DBusInterface(
        INTERFACE_PATH,
        Signal('PropertiesChanged', 'a{sv}')
    )

    def __repr__(self):
        return str(self)

    def __str__(self):
        return "BSS(Path: %s, SSID: %s, BSSID: %s, Signal: %sdBm)" % (self.get_path(),
                                                                      self.get_ssid(),
                                                                      self.get_bssid(),
                                                                      self.get_signal_dbm())

    def to_dict(self):
        """Dict representation of a BSS object"""

        elements = (
            ('ssid', self.get_ssid),
            ('rsn', self.get_rsn),
            ('channel', self.get_channel),
            ('privacy', self.get_privacy),
            ('wpa', self.get_wpa),
            ('signal_dbm', self.get_signal_dbm),
            ('signal_quality', self.get_signal_quality),
            ('network_type', self.get_network_type),
            ('privacy', self.get_privacy),
        )
        out = {}
        for k, v in elements:
            try:
                out[k] = v()
            except:
                logger.exception('Error while fetching BSS information')
        return out

    #
    # Properties
    #
    def get_channel(self):
        """Wi-Fi channel number (1-14)"""
        freq = self.get_frequency()

        if freq == 2484:  # Handle channel 14
            return 14
        elif freq >= 2412 and freq <= 2472:
            return 1 + (freq - 2412) / 5
        elif freq >= 5180 and freq <= 5905:
            return 36 + (freq - 5180) / 5
        else:
            logger.warn('Unexpected frequency %s', freq)
            raise WpaSupplicantException('Unexpected frequency in WiFi connection.')

    def get_ssid(self):
        """SSID of the BSS in ASCII"""

        return "".join(chr(i) for i in self.get('SSID'))

    def get_bssid(self):
        """BSSID of the BSS as hex bytes delimited by a colon"""

        return ":".join(["{:02X}".format(i) for i in self.get('BSSID')])

    def get_frequency(self):
        """Frequency of the BSS in MHz"""

        return self.get('Frequency')

    def get_wpa(self):
        """WPA information of the BSS, empty dictionary indicates no WPA support

        Dictionaries are::

            {
                "KeyMgmt": <Possible array elements: "wpa-psk", "wpa-eap", "wpa-none">,
                "Pairwise": <Possible array elements: "ccmp", "tkip">,
                "Group": <Possible values are: "ccmp", "tkip", "wep104", "wep40">,
                "MgmtGroup": <Possible values are: "aes128cmac">
            }
        """

        return self.get('WPA')

    def get_rsn(self):
        """RSN/WPA2 information of the BSS, empty dictionary indicates no RSN support

        Dictionaries are::

            {
                "KeyMgmt": <Possible array elements: "wpa-psk", "wpa-eap", "wpa-ft-psk", "wpa-ft-eap", "wpa-psk-sha256", "wpa-eap-sha256">,
                "Pairwise": <Possible array elements: "ccmp", "tkip">,
                "Group": <Possible values are: "ccmp", "tkip", "wep104", "wep40">,
                "MgmtGroup": <Possible values are: "aes128cmac">,
            }
        """

        return self.get('RSN')

    def get_ies(self):
        """All IEs of the BSS as a chain of TLVs"""

        return self.get('IEs')

    def get_privacy(self):
        """Indicates if BSS supports privacy"""

        return self.get('Privacy')

    def get_mode(self):
        """Describes mode of the BSS

            Possible values are: "ad-hoc"
                                 "infrastructure"

        """

        return self.get('Mode')

    def get_rates(self):
        """Descending ordered array of rates supported by the BSS in bits per second"""

        return self.get('Rates')

    def get_signal_dbm(self):
        """Signal strength of the BSS in dBm"""

        return self.get('Signal')

    def get_signal_quality(self):
        """Signal strength of the BSS as a percentage (0-100)"""

        dbm = self.get_signal_dbm()
        if dbm <= -100:
            return 0
        elif dbm >= -50:
            return 100
        else:
            return 2 * (dbm + 100)

    def get_network_type(self):
        """Return the network type as a string

        Possible values are:
                'WPA'
                'WPA2'
                'WEP'
                'OPEN'
        """

        if self.get_privacy():
            rsn_key_mgmt = self.get_rsn().get('KeyMgmt')
            if rsn_key_mgmt:
                return 'WPA2'

            wpa_key_mgmt = self.get_wpa().get('KeyMgmt')
            if wpa_key_mgmt:
                return 'WPA'

            return 'WEP'
        else:
            return 'OPEN'
Ejemplo n.º 9
0
class Interface(BaseIface):
    """Interface implemented by objects related to network interface added to wpa_supplicant"""

    INTERFACE_PATH = 'fi.w1.wpa_supplicant1.Interface'

    iface = DBusInterface(
        INTERFACE_PATH,
        Method('Scan', arguments='a{sv}'),
        Method('AddNetwork', arguments='a{sv}', returns='o'),
        Method('RemoveNetwork', arguments='o'),
        Method('SelectNetwork', arguments='o'),
        Method('Disconnect'),
        Signal('ScanDone', 'b'),
        Signal('PropertiesChanged', 'a{sv}')
    )

    def __repr__(self):
        return str(self)

    def __str__(self):
        return "Interface(Path: %s, Name: %s, State: %s)" % (self.get_path(),
                                                             self.get_ifname(),
                                                             self.get_state())

    #
    # Methods
    #
    def scan(self, type='active', ssids=None, ies=None, channels=None, block=False):
        """Triggers a scan

        :returns: List of `BSS` objects if block=True else None
        :raises InvalidArgs: Invalid argument format
        :raises MethodTimeout: Scan has timed out (only if block=True)
        :raises UnknownError: An unknown error occurred
        """

        # TODO: Handle the other arguments
        scan_options = {
            'Type': type
        }

        # If blocking, register for the ScanDone signal and return BSSs
        if block:
            deferred_queue = self.register_signal_once('ScanDone')
            self._call_remote('Scan', scan_options)  # Trigger scan
            success = deferred_queue.get(timeout=10)
            if success:
                return [BSS(path, self._conn, self._reactor) for path in self.get_all_bss()]
            else:
                raise UnknownError('ScanDone signal received without success')
        else:
            self._call_remote('Scan', scan_options)  # Trigger scan

    def add_network(self, network_cfg):
        """Adds a new network to the interface

        :param network_cfg: Dictionary of config, see wpa_supplicant.conf for k/v pairs
        :returns: `Network` object that was registered w/ wpa_supplicant
        :raises InvalidArgs: Invalid argument format
        :raises UnknownError: An unknown error occurred
        """

        network_path = self._call_remote('AddNetwork', network_cfg)
        return Network(network_path, self._conn, self._reactor)

    def remove_network(self, network_path):
        """Removes a configured network from the interface

        :param network_path: D-Bus object path to the desired network
        :returns: None
        :raises NetworkUnknown: The specified `network_path` is invalid
        :raises InvalidArgs: Invalid argument format
        :raises UnknownError: An unknown error occurred
        """

        self._call_remote('RemoveNetwork', network_path)

    def select_network(self, network_path):
        """Attempt association with a configured network

        :param network_path: D-Bus object path to the desired network
        :returns: None
        :raises NetworkUnknown: The specified `network_path` has not been added
        :raises InvalidArgs: Invalid argument format
        """

        self._call_remote('SelectNetwork', network_path)

    def disconnect_network(self):
        """Disassociates the interface from current network

        :returns: None
        :raises NotConnected: The interface is not currently connected to a network
        """

        self._call_remote('Disconnect')

    #
    # Properties
    #
    def get_ifname(self):
        """Name of network interface controlled by the interface, e.g., wlan0"""

        return self.get('Ifname')

    def get_current_bss(self):
        """BSS object path which wpa_supplicant is associated with

                Returns "/" if is not associated at all
        """

        bss_path = self.get('CurrentBSS')
        if bss_path == '/' or bss_path is None:
            return None
        else:
            return BSS(bss_path, self._conn, self._reactor)

    def get_current_network(self):
        """The `Network` object which wpa_supplicant is associated with

                Returns `None` if is not associated at all
        """

        network_path = self.get('CurrentNetwork')
        if network_path == '/' or network_path is None:
            return None
        else:
            return Network(network_path, self._conn, self._reactor)

    def get_networks(self):
        """List of `Network` objects representing configured networks"""

        networks = list()
        paths = self.get('Networks')
        for network_path in paths:
            if network_path == '/':
                networks.append(None)
            else:
                networks.append(Network(network_path, self._conn, self._reactor))
        return networks

    def get_state(self):
        """A state of the interface.

            Possible values are: "disconnected"
                                 "inactive"
                                 "scanning"
                                 "authenticating"
                                 "associating"
                                 "associated"
                                 "4way_handshake"
                                 "group_handshake"
                                 "completed"
                                 "unknown"
        """

        return self.get('State')

    def get_scanning(self):
        """Determines if the interface is already scanning or not"""

        return self.get('Scanning')

    def get_scan_interval(self):
        """Time (in seconds) between scans for a suitable AP. Must be >= 0"""

        return self.get('ScanInterval')

    def get_fast_reauth(self):
        """Identical to fast_reauth entry in wpa_supplicant.conf"""

        return self.get('FastReauth')

    def get_all_bss(self):
        """List of D-Bus objects paths representing BSSs known to the interface"""

        return self.get('BSSs')

    def get_driver(self):
        """Name of driver used by the interface, e.g., nl80211"""

        return self.get('Driver')

    def get_country(self):
        """Identical to country entry in wpa_supplicant.conf"""

        return self.get('Country')

    def get_bridge_ifname(self):
        """Name of bridge network interface controlled by the interface, e.g., br0"""

        return self.get('BridgeIfname')

    def get_bss_expire_age(self):
        """Identical to bss_expiration_age entry in wpa_supplicant.conf file"""

        return self.get('BSSExpireAge')

    def get_bss_expire_count(self):
        """Identical to bss_expiration_scan_count entry in wpa_supplicant.conf file"""

        return self.get('BSSExpireCount')

    def get_ap_scan(self):
        """Identical to ap_scan entry in wpa_supplicant configuration file.

                Possible values are 0, 1 or 2.
        """

        return self.get('ApScan')

    def set_country(self, country_code):
        self.set('Country', country_code)
Ejemplo n.º 10
0
class WpaSupplicant(BaseIface):
    """Interface implemented by the main wpa_supplicant D-Bus object

            Registered in the bus as "fi.w1.wpa_supplicant1"
    """

    INTERFACE_PATH = 'fi.w1.wpa_supplicant1'

    iface = DBusInterface(
        INTERFACE_PATH,
        Method('CreateInterface', arguments='a{sv}', returns='o'),
        Method('GetInterface', arguments='s', returns='o'),
        Method('RemoveInterface', arguments='o'),
        Signal('InterfaceAdded', 'o,a{sv}'),
        Signal('InterfaceRemoved', 'o'),
        Signal('PropertiesChanged', 'a{sv}')
    )

    def __init__(self, *args, **kwargs):
        BaseIface.__init__(self, *args, **kwargs)
        self._interfaces_cache = dict()

    def __repr__(self):
        return str(self)

    def __str__(self):
        return "WpaSupplicant(Interfaces: %s)" % self.get_interfaces()

    #
    # Methods
    #
    def get_interface(self, interface_name):
        """Get D-Bus object related to an interface which wpa_supplicant already controls

        :returns: Interface object that implements the wpa_supplicant Interface API.
        :rtype: :class:`~Interface`
        :raises InterfaceUnknown: wpa_supplicant doesn't know anything about `interface_name`
        :raises UnknownError: An unknown error occurred
        """

        interface_path = self._call_remote_without_introspection('GetInterface',
                                                                 interface_name)
        interface = self._interfaces_cache.get(interface_path, None)
        if interface is not None:
            return interface
        else:
            interface = Interface(interface_path, self._conn, self._reactor)
            self._interfaces_cache[interface_path] = interface
            return interface

    def create_interface(self, interface_name, driver=None):
        """Registers a wireless interface in wpa_supplicant

        :returns: Interface object that implements the wpa_supplicant Interface API
        :raises InterfaceExists: The `interface_name` specified is already registered
        :raises UnknownError: An unknown error occurred
        """

        interface_path = self._call_remote_without_introspection('CreateInterface',
                                                                 {'Ifname': interface_name,
                                                                  'Driver': driver})
        return Interface(interface_path, self._conn, self._reactor)

    def remove_interface(self, interface_path):
        """Deregisters a wireless interface from wpa_supplicant

        :param interface_path: D-Bus object path to the interface to be removed
        :returns: None
        :raises InterfaceUnknown: wpa_supplicant doesn't know anything about `interface_name`
        :raises UnknownError: An unknown error occurred
        """

        self._call_remote_without_introspection('RemoveInterface', interface_path)

    #
    # Properties
    #
    def get_debug_level(self):
        """Global wpa_supplicant debugging level

        :returns:  Possible values: "msgdump" (verbose debugging)
                                    "debug" (debugging)
                                    "info" (informative)
                                    "warning" (warnings)
                                    "error" (errors)
        :rtype: str
        """

        return self.get('DebugLevel')

    def get_debug_timestamp(self):
        """ Determines if timestamps are shown in debug logs"""

        return self.get('DebugTimestamp')

    def get_debug_showkeys(self):
        """Determines if secrets are shown in debug logs"""

        return self.get('DebugShowKeys')

    def get_interfaces(self):
        """An array with paths to D-Bus objects representing controlled interfaces"""

        return self.get('Interfaces')

    def get_eap_methods(self):
        """An array with supported EAP methods names"""

        return self.get('EapMethods')
Ejemplo n.º 11
0
class Bus(objects.DBusObject):
    """
    DBus Bus implementation.

    @ivar stdIface: L{interface.DBusInterface} containing the standard bus interface
    @type stdIface: L{interface.DBusInterface}
    """
    stdIface = DBusInterface(
        'org.freedesktop.DBus',
        Method('Hello', arguments='', returns='s'),
        Method('GetId', arguments='', returns='s'),
        Method('RequestName', arguments='su', returns='u'),
        Method('ReleaseName', arguments='s', returns='u'),
        Method('ListQueuedOwners', arguments='s', returns='as'),
        Method('AddMatch', arguments='s', returns=''),
        Method('RemoveMatch', arguments='s', returns=''),
        Method('GetNameOwner', arguments='s', returns='s'),
        Method('GetConnectionUnixUser', arguments='s', returns='u'),

        #Not Implemented Methods
        Method('GetConnectionUnixProcessId', arguments='s', returns='u'),
        Method('ListActivatableNames', arguments='', returns='as'),
        Method('UpdateActivationEnvironment', arguments='a{ss}', returns=''),
        Method('StartServiceByName', arguments='su', returns='u'),
        Method('GetAdtAuditSessionData', arguments='s', returns='u'),
        Method('GetConnectionSELinuxSecurityContext',
               arguments='su',
               returns='ay'),
        Method('ReloadConfig'),
        Signal('NameAcquired', arguments='s'),
        Signal('NameLost', arguments='s'),
        Signal('NameOwnerChanged', arguments='sss'))

    dbusInterfaces = [stdIface]

    def __init__(self):
        objects.DBusObject.__init__(self, '/org/freedesktop/DBus')
        self.uuid = binascii.hexlify(os.urandom(16))
        self.clients = dict()  # maps unique_bus_id to client connection
        self.busNames = dict()  # maps name to list of queued connections
        self.router = router.MessageRouter()
        self.next_id = 1
        self.obj_handler = objects.DBusObjectHandler(self)

        self.obj_handler.exportObject(self)

    # returns the new unique bus name for the client connection
    def clientConnected(self, proto):
        """
        Called when a client connects to the bus. This method assigns the
        new connection a unique bus name.
        """
        proto.uniqueName = ':1.%d' % (self.next_id, )
        self.next_id += 1
        self.clients[proto.uniqueName] = proto

    def clientDisconnected(self, proto):
        """
        Called when a client disconnects from the bus
        """
        for rule_id in proto.matchRules:
            self.router.delMatch(rule_id)

        for busName in proto.busNames.iterkeys():
            self.dbus_ReleaseName(busName, proto.uniqueName)

        if proto.uniqueName:
            del self.clients[proto.uniqueName]

    def sendMessage(self, msg):
        """
        Sends the supplied message to the correct destination. The 
        @type msg: L{message.DBusMessage}
        @param msg: The 'destination' field of the message must be set for
                    method calls and returns
        """
        if msg._messageType in (1, 2):
            assert msg.destination, 'Failed to specify a message destination'

        if msg.destination is not None:
            if msg.destination[0] == ':':
                p = self.clients.get(msg.destination, None)
            else:
                p = self.busNames.get(msg.destination, None)
                if p:
                    p = p[0]

            #print 'SND: ', msg._messageType, ' to ',  p.uniqueName, 'serial', msg.serial,

            if p:
                p.sendMessage(msg)
            else:
                log.msg('Invalid bus name in msg.destination: ' +
                        msg.destination)
        else:
            self.router.routeMessage(msg)

    def messageReceived(self, p, msg):
        mt = msg._messageType

        #print 'MSG: ', mt, ' from ', p.uniqueName, ' to ', msg.destination

        try:
            if mt == 1:
                self.methodCallReceived(p, msg)
            elif mt == 2:
                self.methodReturnReceived(p, msg)
            elif mt == 3:
                self.errorReceived(p, msg)
            elif mt == 4:
                self.signalReceived(p, msg)

            if msg.destination and not msg.destination == 'org.freedesktop.DBus':
                self.sendMessage(msg)

            self.router.routeMessage(msg)
        except DError, e:
            sig = None
            body = None
            if e.errorMessage:
                sig = 's'
                body = [e.errorMessage]

            r = message.ErrorMessage(e.errorName,
                                     msg.serial,
                                     signature=sig,
                                     body=body)
            p.sendMessage(r)
Ejemplo n.º 12
0
Archivo: bus.py Proyecto: pliu6/txdbus
class Bus(objects.DBusObject):
    """
    DBus Bus implementation.

    @ivar stdIface: L{interface.DBusInterface} containing the standard bus interface
    @type stdIface: L{interface.DBusInterface}
    """
    stdIface = DBusInterface(
        'org.freedesktop.DBus',
        Method('Hello', arguments='', returns='s'),
        Method('GetId', arguments='', returns='s'),
        Method('RequestName', arguments='su', returns='u'),
        Method('ReleaseName', arguments='s', returns='u'),
        Method('ListQueuedOwners', arguments='s', returns='as'),
        Method('AddMatch', arguments='s', returns=''),
        Method('RemoveMatch', arguments='s', returns=''),
        Method('GetNameOwner', arguments='s', returns='s'),
        Method('GetConnectionUnixUser', arguments='s', returns='u'),

        #Not Implemented Methods
        Method('GetConnectionUnixProcessId', arguments='s', returns='u'),
        Method('ListActivatableNames', arguments='', returns='as'),
        Method('UpdateActivationEnvironment', arguments='a{ss}', returns=''),
        Method('StartServiceByName', arguments='su', returns='u'),
        Method('GetAdtAuditSessionData', arguments='s', returns='u'),
        Method('GetConnectionSELinuxSecurityContext',
               arguments='su',
               returns='ay'),
        Method('ReloadConfig'),
        Signal('NameAcquired', arguments='s'),
        Signal('NameLost', arguments='s'),
        Signal('NameOwnerChanged', arguments='sss'))

    dbusInterfaces = [stdIface]

    def __init__(self):
        objects.DBusObject.__init__(self, '/org/freedesktop/DBus')
        self.uuid = binascii.hexlify(os.urandom(16))
        self.clients = dict()  # maps unique_bus_id to client connection
        self.busNames = dict()  # maps name to list of queued connections
        self.router = router.MessageRouter()
        self.next_id = 1
        self.obj_handler = objects.DBusObjectHandler(self)

        self.obj_handler.exportObject(self)

    # returns the new unique bus name for the client connection
    def clientConnected(self, proto):
        """
        Called when a client connects to the bus. This method assigns the
        new connection a unique bus name.
        """
        proto.uniqueName = ':1.%d' % (self.next_id, )
        self.next_id += 1
        self.clients[proto.uniqueName] = proto

    def clientDisconnected(self, proto):
        """
        Called when a client disconnects from the bus
        """
        for rule_id in proto.matchRules:
            self.router.delMatch(rule_id)

        for busName in proto.busNames.iterkeys():
            self.dbus_ReleaseName(busName, proto.uniqueName)

        if proto.uniqueName:
            del self.clients[proto.uniqueName]

    def sendMessage(self, msg):
        """
        Sends the supplied message to the correct destination. The 
        @type msg: L{message.DBusMessage}
        @param msg: The 'destination' field of the message must be set for
                    method calls and returns
        """
        if msg._messageType in (1, 2):
            assert msg.destination, 'Failed to specify a message destination'

        if msg.destination is not None:
            if msg.destination[0] == ':':
                p = self.clients.get(msg.destination, None)
            else:
                p = self.busNames.get(msg.destination, None)
                if p:
                    p = p[0]

            #print 'SND: ', msg._messageType, ' to ',  p.uniqueName, 'serial', msg.serial,

            if p:
                p.sendMessage(msg)
            else:
                log.msg('Invalid bus name in msg.destination: ' +
                        msg.destination)
        else:
            self.router.routeMessage(msg)

    def messageReceived(self, p, msg):
        mt = msg._messageType

        #print 'MSG: ', mt, ' from ', p.uniqueName, ' to ', msg.destination

        try:
            if mt == 1:
                self.methodCallReceived(p, msg)
            elif mt == 2:
                self.methodReturnReceived(p, msg)
            elif mt == 3:
                self.errorReceived(p, msg)
            elif mt == 4:
                self.signalReceived(p, msg)

            if msg.destination and not msg.destination == 'org.freedesktop.DBus':
                self.sendMessage(msg)

            self.router.routeMessage(msg)
        except DError as e:
            sig = None
            body = None
            if e.errorMessage:
                sig = 's'
                body = [e.errorMessage]

            r = message.ErrorMessage(e.errorName,
                                     msg.serial,
                                     signature=sig,
                                     body=body)
            p.sendMessage(r)

    def methodCallReceived(self, p, msg):
        if msg.destination == 'org.freedesktop.DBus':
            self.obj_handler.handleMethodCallMessage(msg)

    def methodReturnReceived(self, p, msg):
        pass

    def errorReceived(self, p, msg):
        pass

    def signalReceived(self, p, msg):
        pass

    def sendSignal(self,
                   p,
                   member,
                   signature=None,
                   body=None,
                   path='/org/freedesktop/DBus',
                   interface='org.freedesktop.DBus'):
        """
        Sends a signal to a specific connection
        
        @type p: L{BusProtocol}
        @param p: L{BusProtocol} instance to send a signal to

        @type member: C{string}
        @param member: Name of the signal to send

        @type path: C{string}
        @param path: Path of the object emitting the signal. Defaults to
                     'org/freedesktop/DBus'
        
        @type interface: C{string}
        @param interface: If specified, this specifies the interface containing the
                          desired method. Defaults to 'org.freedesktop.DBus'

        @type body: None or C{list}
        @param body: If supplied, this is a list of signal arguments. The contents
                     of the list must match the signature.

        @type signature: None or C{string}
        @param signature: If specified, this specifies the DBus signature of the
                          body of the DBus Signal message. This string must
                          be a valid Signature string as defined by the DBus
                          specification. If the body argumnent is supplied ,\
                          this parameter must be provided.
        """
        if not isinstance(body, (list, tuple)):
            body = [body]

        s = message.SignalMessage(path, member, interface, p.uniqueName,
                                  signature, body)
        p.sendMessage(s)

    def broadcastSignal(self,
                        member,
                        signature=None,
                        body=None,
                        path='/org/freedesktop/DBus',
                        interface='org.freedesktop.DBus'):
        """
        Sends a signal to all connections with registered interest
        
        @type member: C{string}
        @param member: Name of the signal to send

        @type path: C{string}
        @param path: Path of the object emitting the signal. Defaults to
                     'org/freedesktop/DBus'
        
        @type interface: C{string}
        @param interface: If specified, this specifies the interface containing the
                          desired method. Defaults to 'org.freedesktop.DBus'

        @type body: None or C{list}
        @param body: If supplied, this is a list of signal arguments. The contents
                     of the list must match the signature.

        @type signature: None or C{string}
        @param signature: If specified, this specifies the DBus signature of the
                          body of the DBus Signal message. This string must
                          be a valid Signature string as defined by the DBus
                          specification. If the body argumnent is supplied ,\
                          this parameter must be provided.
        """
        if not isinstance(body, (list, tuple)):
            body = [body]

        s = message.SignalMessage(path, member, interface, None, signature,
                                  body)
        self.router.routeMessage(s)

    #----------------------------------------------------------------
    # DBus Object Interface
    #
    def dbus_Hello(self, dbusCaller=None):
        raise DError('org.freedesktop.DBus.Error.Failed',
                     'Already handled an Hello message')

    def dbus_GetId(self):
        return self.uuid

    def dbus_RequestName(self, name, flags, dbusCaller=None):
        caller = self.clients[dbusCaller]

        allow_replacement = bool(flags & 0x1)
        replace_existing = bool(flags & 0x2)
        do_not_queue = bool(flags & 0x4)

        if not name:
            raise DError('org.freedesktop.DBus.Error.InvalidArgs',
                         'Empty string is not a valid bus name')

        if name[0] == ':':
            raise DError(
                'org.freedesktop.DBus.Error.InvalidArgs',
                'Cannot acquire a service starting with \':\' such as "%s"' %
                (name, ))

        try:
            marshal.validateBusName(name)
        except error.MarshallingError as e:
            raise DError('org.freedesktop.DBus.Error.InvalidArgs', str(e))

        def signalAcq(old_owner_name):
            self.sendSignal(caller, 'NameAcquired', 's', name)
            self.broadcastSignal('NameOwnerChanged', 'sss',
                                 [name, old_owner_name, caller.uniqueName])

        if not name in self.busNames:
            self.busNames[name] = [
                caller,
            ]
            caller.busNames[name] = allow_replacement

            signalAcq('')

            return client.NAME_ACQUIRED
        else:
            queue = self.busNames[name]
            owner = queue[0]

            if owner is caller:
                # Update the replacement flag
                owner.busNames[name] = allow_replacement

                return client.NAME_ALREADY_OWNER
            else:
                if not replace_existing:
                    return client.NAME_IN_USE

                if owner.busNames[name]:
                    del queue[0]
                    queue.insert(0, caller)
                    del owner.busNames[name]
                    caller.busNames[name] = allow_replacement
                    self.sendSignal(owner, 'NameLost', 's', name)
                    signalAcq(owner.uniqueName)
                    return client.NAME_ACQUIRED
                else:
                    if do_not_queue:
                        return client.NAME_IN_USE

                    queue.append(caller)
                    caller.busNames[name] = allow_replacement

                    return client.NAME_IN_QUEUE

    def dbus_ReleaseName(self, name, dbusCaller=None):
        caller = self.clients[dbusCaller]

        queue = self.busNames.get(name, None)

        if queue is None:
            return client.NAME_NON_EXISTENT

        owner = queue[0]

        if not caller is owner:
            return client.NAME_NOT_OWNER

        del queue[0]

        if caller.isConnected:
            self.sendSignal(caller, 'NameLost', 's', name)

        if queue:
            self.sendSignal(queue[0], 'NameAcquired', 's', name)
        else:
            del self.busNames[name]

        return client.NAME_RELEASED

    def dbus_ListQueuedOwners(self, name):
        queue = self.busNames.get(name, None)
        if queue:
            return [p.uniqueName for p in queue]
        else:
            raise DError(
                'org.freedesktop.DBus.Error.NameHasNoOwner',
                'Could not get owners of name \'%s\': no such name' % (name, ))

    def dbus_AddMatch(self, rule, dbusCaller=None):
        caller = self.clients[dbusCaller]

        kwargs = dict(mtype=None,
                      sender=None,
                      interface=None,
                      member=None,
                      path=None,
                      path_namespace=None,
                      destination=None,
                      args=None,
                      arg_paths=None,
                      arg0namespace=None)

        for item in rule.split(','):
            k, v = item.split('=')

            value = v[1:-1]

            if k == 'type':
                k = 'mtype'

            if k in kwargs:
                kwargs[k] = value

            elif k.startswith('arg'):
                if k.endswith('path'):
                    if kwargs['arg_paths'] is None:
                        kwargs['arg_paths'] = list()
                    kwargs['arg_paths'].append((int(k[3:-4]), value))
                else:
                    if kwargs['args'] is None:
                        kwargs['args'] = list()
                    kwargs['args'].append((int(k[3:]), value))

        self.router.addMatch(caller.sendMessage, **kwargs)

    def dbus_GetNameOwner(self, busName):
        if busName.startswith(':'):
            conn = self.clients.get(busName, None)
        else:
            conn = self.busNames.get(busName, None)
            if conn:
                conn = conn[0]

        if conn is None:
            raise DError(
                "org.freedesktop.DBus.Error.NameHasNoOwner",
                "Could not get UID of name '%s': no such name" % (busName, ))

        return conn.uniqueName

    def dbus_GetConnectionUnixUser(self, busName):
        if busName.startswith(':'):
            conn = self.clients.get(busName, None)
        else:
            conn = self.busNames.get(busName, None)
            if conn:
                conn = conn[0]

        if conn is None:
            raise DError(
                "org.freedesktop.DBus.Error.NameHasNoOwner",
                "Could not get UID of name '%s': no such name" % (busName, ))

        try:
            import pwd
            return pwd.getpwnam(conn.username).pw_uid
        except:
            raise DError(
                'org.freedesktop.DBus.Error',
                "Unable to determine unix user for bus '%s'" % (busName, ))
Ejemplo n.º 13
0
class Rfm69DBusService(objects.DBusObject):
	
	class NotImplementedError(Exception):
		dbusErrorName = "org.agile-rfm69.NotImplemented"
	
	class IOError(Exception):
		dbusErrorName = "org.agile-rfm69.IOError"
	
	class ValueError(Exception):
		dbusErrorName = "org.agile-rfm69.ValueError"
	
	class TypeError(Exception):
		dbusErrorName = "org.agile-rfm69.TypeError"
	
	iface = DBusInterface("iot.agile.Protocol",
					Method("Connect"),
					Method("Connected", returns="b"),
					Method("Disconnect"),
					Method("Setup", arguments="a{sv}"),
					Method("Send", arguments="a{sv}"),
					Method("Receive", returns="a{sv}"),
					Method("Subscribe", arguments="a{sv}"),
					Method("StartDiscovery"),
					Method("StopDiscovery"),
					Property("Devices", "av", writeable=False),
					Property("Name", "s", writeable=False),
					Property("Driver", "s", writeable=False),
					Property("Data", "a{sv}", writeable=False),
					Property("Status", "n", writeable=False)
					)
	
	_devices = DBusProperty("Devices")
	_name = DBusProperty("Name")
	_driver = DBusProperty("Driver")
	_lastRecord = DBusProperty("Data")
	_status = DBusProperty("Status")
	
	dbusInterfaces = [iface]
	
	def __init__(self, objectPath):
		super(Rfm69DBusService, self).__init__(objectPath)
		
		self._lastRecord = {"STATUS": "TIMEOUT"}
		self._status = 0
		self._driver = "No driver"
		self._name = PROTOCOL_NAME
		self._devices = ["None"]
		
		self._logger = logging.getLogger()
		self._full_path = PROTOCOL_PATH
		self._connected = False
		self._setup = {
			"MODEM_CONFIG_TABLE": MODEM_CONFIG_TABLE,
			"MODEM_CONFIG": MODEM_CONFIG,
			"key": MODEM_KEY,
			"channel": CHANNEL
		}

	def _setModemConfig(self):
		# Set RFM69 registers as per config
		settings = MODEM_CONFIG_TABLE[self._setup["MODEM_CONFIG"]]
		addresses = [0x02, 0x03, 0x04, 0x05, 0x06, 0x19, 0x1a, 0x37]
		for value, address in zip(settings, addresses):
			self._rfm69.spi_write(address, value)
			
	def _setModemKey(self):
		self._logger.debug("enabling ecryption")
		self._rfm69.set_encryption(self._setup["key"])
		
	def _getConnected(self):
		return self._connected
	
	def _setConnected(self, status):
		if status:
			self._connected = True
		else:
			self._connected = False 
	
	def dbus_Connect(self):
		self._logger.debug(
			"%s@Connect: Connect INIT", self._full_path)
		if self._getConnected():
			self._logger.debug(
				"%s@Connect: Module is already connected", self._full_path)
			raise self.IOError("Module is already connected.")
		
		self._logger.debug(
			"%s@Connect: MODE=%s", self._full_path, self._setup["MODEM_CONFIG"])
		self._rfm69 = rfm69.RFM69(25, 24, 0, rfm69.RFM69Configuration(), True)
		self._rfm69.set_channel(self._setup["channel"])
		self._rfm69.set_address(1)
		
		self._logger.debug("Class initialized")
		self._logger.debug("Calibrating RSSI")
		# self._rfm69.calibrate_rssi_threshold()
		self._logger.debug("Checking temperature")
		self._logger.debug(self._rfm69.read_temperature())
		
		# Make sure settings are correct to talk to other radios
		self._setModemConfig()
		self._setModemKey()
		
		self._logger.debug("reading all registers")
		for result in self._rfm69.read_registers():
			self._logger.debug(result)
		
		# Won't get here if something went wrong reading temps etc.
		self._setConnected(True)
		self._logger.debug("%s@Connect: Connect OK", self._full_path)
		
	def dbus_Connected(self):
		return self._connected

	def dbus_Disconnect(self):
		self._logger.debug(
			"%s@Disconnect: Disconnect INIT", self._full_path)
		self._setConnected(False)
		self._rfm69.disconnect()
		self._logger.debug("%s@Disconnect: Disconnect OK", self._full_path) 

	def dbus_Setup(self, args):
		self._logger.debug("%s@Setup: Setup INIT", self._full_path)
		self._setup.clear()
		self._setup = {}
		
		modemConfigTable = args.pop("MODEM_CONFIG_TABLE", MODEM_CONFIG_TABLE)
		self._setup["MODEM_CONFIG_TABLE"] = modemConfigTable
		
		modemConfig = args.pop("MODEM_CONFIG", MODEM_CONFIG)
		self._setup["MODEM_CONFIG"] = modemConfig
			
		modemKey = args.pop("key", MODEM_KEY)
		self._setup["key"] = modemKey
		
		channel = args.pop("channel", CHANNEL)
		self._setup["channel"] = channel
		
		self._logger.debug(
			"%s@Setup: Parameters=%s", self._full_path, self._setup)
		self._logger.debug(
			"%s@Setup: Setup OK", self._full_path)

	def dbus_Send(self, args):
		self._logger.debug(
			"%s@Send: Send INIT", self._full_path)
		
		if not self._getConnected():
			self._logger.debug(
				"%s@Send: Module is not connected", self._full_path)
			raise self.IOError("Module is not connected.")
		
		sendData = args.pop("DATA", "")
		
		if not sendData:
			self._logger.debug(
				"%s@Send/Rfm69: No data provided", self._full_path)
			raise self.ValueError("You must provide the data.")
		
		if not type(sendData) is list:
			self._logger.debug(
				"%s@Send/Rfm69: Data in wrong format", self._full_path)
			raise self.TypeError("You must provide the data as a list of values.")
		
		# Turn it back into bytes again, since D-Bus turns it into a list
		sendData = struct.pack("B"*len(sendData), *sendData)
		self._rfm69.send_packet(sendData)
	
	def dbus_Receive(self):
		self._logger.debug("%s@Receive: Receive INIT", self._full_path)
		if not self._getConnected():
			self._logger.debug(
				"%s@Receive: Module is not connected", self._full_path)
			raise self.IOError("Module is not connected.")
		
		response = self._rfm69.wait_for_packet(timeout=60)
		if response:
			(data, rssi) = response
			self._logger.debug("%s@Receive: receiveDone()", self._full_path)
			self._lastRecord = {"DATA": data, "RSSI": rssi, "STATUS": "OK"}
		else:
			self._lastRecord = {"STATUS": "TIMEOUT"}
		
		return self._lastRecord
		
	def dbus_Subscribe(self, args):
		raise self.NotImplementedError("Function not supported.")
	
	def dbus_StartDiscovery(self):
		pass
	
	def dbus_StopDiscovery(self):
		pass
Ejemplo n.º 14
0
#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

# global list of tag devices that are currently within radio range
#
taglist = dict()

#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

TAGNET_BUS_NAME = 'org.tagnet.tagmaster'  # bus name for tagnet forwarder
TAGNET_OBJECT_PATH = '/org/tagnet/tagmaster'

tagmaster_dbus_interface = DBusInterface(
    TAGNET_BUS_NAME,
    Method('tag_list', arguments='s', returns='ay'),
    Signal('tag_found', 'ay'),  # report new tag
    Signal('tag_lost', 'ay'),  # report tag out of range
    Signal('tag_events', 'ay'),  # report new tag events
    Signal('tagnet_status', 'ay'),
)


class TagNetDbus(objects.DBusObject):
    """
    provides the interface for accessing the tagnet port
    """
    dbusInterfaces = [tagmaster_dbus_interface]

    def __init__(self, object_path):
        super(TagNetDbus, self).__init__(object_path)
        self.object_path = object_path
        self.obj_handler = objects.DBusObjectHandler(self)
Ejemplo n.º 15
0
class BlueZGattCharacteristic(DBusObject):
    """
    org.bluez.GattCharacteristic1 interface implementation
    """

    interface_name: str = defs.GATT_CHARACTERISTIC_INTERFACE

    iface: DBusInterface = DBusInterface(
        interface_name,
        Method("ReadValue", arguments="a{sv}", returns="ay"),
        Method("WriteValue", arguments="aya{sv}"),
        Method("StartNotify"),
        Method("StopNotify"),
        Property("UUID", "s"),
        Property("Service", "o"),
        Property("Value", "ay"),
        Property("Notifying", "b"),
        Property("Flags", "as"),
    )

    dbusInterfaces: List[DBusInterface] = [iface]

    uuid: DBusProperty = DBusProperty("UUID")
    service: DBusProperty = DBusProperty("Service")
    flags: DBusProperty = DBusProperty("Flags")
    value: DBusProperty = DBusProperty("Value")
    notifying: DBusProperty = DBusProperty("Notifying")

    def __init__(
            self,
            uuid: str,
            flags: List[Flags],
            index: int,
            service: "BlueZGattService",  # noqa: F821
    ):
        """
        Create a BlueZ Gatt Characteristic

        Parameters
        ----------
        uuid : str
            The unique identifier for the characteristic
        flags : List[Flags]
            A list of strings that represent the properties of the
            characteristic
        index : int
            The index number for this characteristic in the service
        service : BlueZService
            The Gatt Service that owns this characteristic
        """
        self.path: str = service.path + "/char" + f"{index:04d}"
        self.uuid: str = uuid
        self.flags: List[str] = [x.value for x in flags]
        self.service: str = service.path  # noqa: F821
        self._service: "BlueZGattService" = service  # noqa: F821

        self.value: bytes = b""
        self.notifying: bool = False
        self.descriptors: List["BlueZGattDescriptor"] = []  # noqa: F821

        super(BlueZGattCharacteristic, self).__init__(self.path)

    @dbusMethod(interface_name, "ReadValue")
    def ReadValue(self, options: Dict) -> bytearray:  # noqa: N802
        """
        Read the value of the characteristic.
        This is to be fully implemented at the application level

        Parameters
        ----------
        options : Dict
            A list of options

        Returns
        -------
        bytearray
            The bytearray that is the value of the characteristic
        """
        f = self._service.app.Read
        if f is None:
            raise NotImplementedError()
        return f(self)

    @dbusMethod(interface_name, "WriteValue")
    def WriteValue(self, value: bytearray, options: Dict):  # noqa: N802
        """
        Write a value to the characteristic
        This is to be fully implemented at the application level

        Parameters
        ----------
        value : bytearray
            The value to set
        options : Dict
            Some options for you to select from
        """
        f = self._service.app.Write
        if f is None:
            raise NotImplementedError()
        f(self, value)

    @dbusMethod(interface_name, "StartNotify")
    def StartNotify(self):  # noqa: N802
        """
        Begin a subscription to the characteristic
        """
        f = self._service.app.StartNotify
        if f is None:
            raise NotImplementedError()
        f(None)
        self._service.app.subscribed_characteristics.append(self.uuid)

    @dbusMethod(interface_name, "StopNotify")
    def StopNotify(self):  # noqa: N802
        """
        Stop a subscription to the characteristic
        """
        f = self._service.app.StopNotify
        if f is None:
            raise NotImplementedError()
        f(None)
        self._service.app.subscribed_characteristics.remove(self.uuid)

    async def get_obj(self) -> Dict:
        """
        Obtain the underlying dictionary within the BlueZ API that describes
        the characteristic

        Returns
        -------
        Dict
            The dictionary that describes the characteristic
        """
        dbus_obj: RemoteDBusObject = await self._service.app.bus.getRemoteObject(
            self._service.app.destination,
            self.path).asFuture(self._service.app.loop)
        dict_obj: Dict = await dbus_obj.callRemote(
            "GetAll",
            defs.GATT_CHARACTERISTIC_INTERFACE,
            interface=defs.PROPERTIES_INTERFACE,
        ).asFuture(self._service.app.loop)
        return dict_obj
Ejemplo n.º 16
0
from dockcomact               import DockcomFsmActionHandlers
from dockcomserial            import DockcomSerial
from dockcomdef               import *
import dockcomtrace

__all__ = ['BUS_NAME', 'OBJECT_PATH', 'dockcom_dbus_interface', 'DockcomDbus', 'reactor_loop']

BUS_NAME = 'org.tagnet.dockcom'
OBJECT_PATH = '/org/tagnet/dockcom/0/0'   # object name includes device id/port numbers

dockcom_dbus_interface = DBusInterface( BUS_NAME,
                            Method('clear_status', returns='s'),
                            Method('control', arguments='s', returns='s'),
                            Method('dump', arguments='s', returns='s'),
                            Method('dump_trace', arguments='s', returns='a(dyssay)'),
                            Method('send', arguments='ayu', returns='s'),
                            Method('status', returns='s'),
                            Signal('new_status', 's'),
                            Signal('receive', 'ayu'),
                            Signal('send_cmp', 's'),
                         )

class DockcomDbus(objects.DBusObject):
    """
    provides the interface for accessing the Dockcom Serial Chip Driver
    """
    dbusInterfaces = [dockcom_dbus_interface]
    
    def __init__(self, objectPath, trace=None):
        super(DockcomDbus,self).__init__(objectPath)
        self.uuid = binascii.hexlify(os.urandom(16))