Showing posts with label dbus. Show all posts
Showing posts with label dbus. Show all posts

Tuesday, July 11, 2017

Dbus Tutorial GObject Introspection instead of python dbus

Dbus Tutorial GObject Introspection instead of python dbus


Introduction
Introspection
Network Manager
Create a Service
GObject Introspection


In previous posts, I have looked at using the python-dbus to communicate with other processes, essentially using it the same way we use the dbus-send command.

There is another way to create DBus messages. Its a bit more complicated than python-dbus, and it depends upon Gnome, but its also more robust and perhaps better maintained.

Using Gobject Introspection replacement for python-dbus is described several places, but the best example is here. Python-dbus as a separate bindings project has also suffered with complaints of "lightly maintained," and an awkward method of exposing properties that has been unfixed for years.


These examples only work for clients.  Gnome Bug #656330 shows that services cannot yet use PyGI.




Heres an example notification using Pygi instead of Python-DBus. Its based on this blog post by Martin Pitt, but expanded a bit to show all the variables I can figure out....


1) Header and load gi

#!/usr/bin/env python3

import gi.repository
from gi.repository import Gio, GLib


2) Connect to the DBus Session Bus
Documentation: http://developer.gnome.org/gio/2.29/GDBusConnection.html

session_bus = Gio.BusType.SESSION
cancellable = None
connection = Gio.bus_get_sync(session_bus, cancellable)


3) Create (but dont send) the DBus message header
Documentation: http://developer.gnome.org/gio/2.29/GDBusProxy.html

proxy_property = 0
interface_properties_array = None
destination = org.freedesktop.Notifications
path = /org/freedesktop/Notifications
interface = destination
notify = Gio.DBusProxy.new_sync(
connection,
proxy_property,
interface_properties_array,
destination,
path,
interface,
cancellable)


4) Create (but dont send) the DBus message data
The order is determined by arg order of the Notification system
Documentation: http://developer.gnome.org/notification-spec/#protocol

application_name = test
title = Hello World!
body_text = Subtext
id_num_to_replace = 0
actions_list = []
hints_dict = {}
display_milliseconds = 5000
icon = gtk-ok # Can use full path, too /usr/share/icons/Humanity/actions/
args = GLib.Variant((susssasa{sv}i), (
application_name,
id_num_to_replace,
icon,
title,
body_text,
actions_list,
hints_dict,
display_milliseconds))


5) Send the DBus message header and data to the notification service
Documentation: http://developer.gnome.org/gio/2.29/GDBusProxy.html

method = Notify
timeout = -1
result = notify.call_sync(method, args, proxy_property, timeout, cancellable)


6) (Optional) Convert the result value from a Uint32 to a python integer

id = result.unpack()[0]
print(id)

Play with it a bit, and you will quickly see how the pieces work together.



Here is a different, original example DBus client using introspection and this askubuntu question. You can see this is a modified and simplified version of the above example:

#!/usr/bin/env python3
import gi.repository
from gi.repository import Gio, GLib

# Create the DBus message
destination = org.freedesktop.NetworkManager
path = /org/freedesktop/NetworkManager
interface = org.freedesktop.DBus.Introspectable
method = Introspect
args = None
answer_fmt = GLib.VariantType.new ((v))
proxy_prpty = Gio.DBusCallFlags.NONE
timeout = -1
cancellable = None

# Connect to DBus, send the DBus message, and receive the reply
bus = Gio.bus_get_sync(Gio.BusType.SYSTEM, None)
reply = bus.call_sync(destination, path, interface,
method, args, answer_fmt,
proxy_prpty, timeout, cancellable)

# Convert the result value to a formatted python element
print(reply.unpack()[0])




Here is a final DBus client example, getting the properties of the current Network Manager connection

#!/usr/bin/env python3
import gi.repository
from gi.repository import Gio, GLib

# Create the DBus message
destination = org.freedesktop.NetworkManager
path = /org/freedesktop/NetworkManager/ActiveConnection/19
interface = org.freedesktop.DBus.Properties
method = GetAll
args = GLib.Variant((ss),
(org.freedesktop.NetworkManager.Connection.Active, None))
answer_fmt = GLib.VariantType.new ((v))
proxy_prpty = Gio.DBusCallFlags.NONE
timeout = -1
cancellable = None

# Connect to DBus, send the DBus message, and receive the reply
bus = Gio.bus_get_sync(Gio.BusType.SYSTEM, None)
reply = bus.call_sync(destination, path, interface,
method, args, answer_fmt,
proxy_prpty, timeout, cancellable)

# Convert the result value to a useful python object and print
[print(item[0], item[1]) for item in result.unpack()[0].items()]

As you can see from this example, dbus communication is actually pretty easy using GLib: Assign the nine variables, turn the crank, and unpack the result.
Read more »

Thursday, July 6, 2017

Dbus Tutorial Create a service

Dbus Tutorial Create a service


Introduction
Introspection
Network Manager 
Create a Service
GObject Introspection



A dbus service is usable by other applications. It listens for input from another process, and responds with output.

When you create a service, you need to make a couple decisions about when you want to start your service, and when you want to terminate it...

Start: Startup, login, first-use, on-demand?
End: Each time? logout? Shutdown?
In other words, is this a single-use service, or a forever-running daemon?

Happily, the actual code differences are trivial. Dbus itself can launch a service thats not running yet. (Indeed, a lot of startup and login depends on that!)



Example Dbus Service in Python3

Heres an example of  a self-contained daemon written in Python 3 (source). Its introspectable and executable from dbus-send or d-feet. When called, it simply returns a "Hello, World!" string.

It can be started by either dbus or another process (like Upstart or a script). Since it runs in an endless loop awaiting input, it will run until logout. It can also be manually terminated by uncommenting the Gtk.main_quit() command.

#!/usr/bin/env/python3
# This file is /home/me/test-dbus.py
# Remember to make it executable if you want dbus to launch it
# It works with both Python2 and Python3

from gi.repository import Gtk
import dbus
import dbus.service
from dbus.mainloop.glib import DBusGMainLoop

class MyDBUSService(dbus.service.Object):
def __init__(self):
bus_name = dbus.service.BusName(org.me.test, bus=dbus.SessionBus())
dbus.service.Object.__init__(self, bus_name, /org/me/test)

@dbus.service.method(org.me.test)
def hello(self):
#Gtk.main_quit() # Terminate after running. Daemons dont use this.
return "Hello,World!"

DBusGMainLoop(set_as_default=True)
myservice = MyDBUSService()
Gtk.main()



Daemon that runs all the time

Just run the script at startup (or login). Or send a dbus-send message to the service, and dbus will start it. It will be terminated as part of shutdown (or logout). While its running, its introspectable and visible from d-feet.


Dbus-initiated start

Add a .service file. This file simply tells dbus how to start the service.

Heres an example service file:

# Service file: /usr/share/dbus-1/services/test.service
[D-BUS Service]
Name=org.me.test
Exec="/home/me/test-dbus.py"

Dbus should automatically pick up the new service without need for any restart. Lets test if dbus discovered the service:

$ dbus-send --session --print-reply 
--dest="org.freedesktop.DBus"
/org/freedesktop/DBus
org.freedesktop.DBus.ListActivatableNames
| grep test
string "org.me.test"

The new service does not show up in d-feet until after it is run the first time, since before there is nothing to probe or introspect. But it does exist, and is findable and usable by other dbus-aware applications.

Lets try the new service:

$ dbus-send --session --print-reply 
--dest="org.me.test" /org/me/test org.me.test.hello

method return sender=:1.239 -> dest=:1.236 reply_serial=2
string "Hello,World!"

$ dbus-send --session --print-reply
--dest="org.me.test" /org/me/test org.me.test.Frank

Error org.freedesktop.DBus.Error.UnknownMethod: Traceback (most recent call last):
File "/usr/lib/python3/dist-packages/dbus/service.py", line 654, in _message_cb
(candidate_method, parent_method) = _method_lookup(self, method_name, interface_name)
File "/usr/lib/python3/dist-packages/dbus/service.py", line 246, in _method_lookup
raise UnknownMethodException(%s is not a valid method of interface %s % (method_name, dbus_interface))
dbus.exceptions.UnknownMethodException: org.freedesktop.DBus.Error.UnknownMethod: Unknown method: Frank is not a valid method of interface org.me.test

It worked! Dbus launches the script, waits for the service to come up, then asks the service for the appropriate method.Upon execution of the method, the waiting loop terminates, and the script finishes and shuts down.

As a test, you can see that hello is indeed a valid method and returns a valid response, while the invalid method Frank causes a not-found error.


Dbus-initiated stop

Dbus doesnt stop scripts or processes. But a script can stop itself.

In order to wait for input, python-dbus uses a Gtk.main() loop. In this case, simply uncomment the line Gtk.main_quit(). When the method is called,the main() loop gets terminated, and the script continues to the next loop or end.

If you use on-demand starting and stopping, be aware that the service will exist, but will be visible in d-feet or introspectable only for the few seconds its actually running.



Obsolete: Before python included introspection, you needed to include an interface definition. But you dont need this anymore - introspection seems to have replaced it. Avoid confusion - some old tutorials out there still include it.

<?xml version="1.0" encoding="UTF-8"?>
<!-- /usr/share/dbus-1/interfaces/org.me.test.xml -->
<node name="/org/me/test">
<interface name="org.me.test">
<annotation name="org.freedesktop.DBus.GLib.CSymbol" value="server"/>
<method name="EchoString">
<arg type="s" name="original" direction="in" />
<arg type="s" name="echo" direction="out" />
</method>
<!-- Add more methods/signals if you want -->
</interface>
</node>




Read more »

Monday, July 3, 2017

Dbus Tutorial Introspection Figuring Out The Rules

Dbus Tutorial Introspection Figuring Out The Rules


Introduction
Introspection
Network Manager 
Create a Service
Gobject Introspection


Last time, we discussed what to use dbus for and the basics of structuring a dbus command. We went over how to structure the grammar of a command so it makes sense (mapping the destination, path, method, and message elements), and we went over the syntax (stringing together those elements in a coherent way).

This lesson is about figuring out what methods are available and how to use them.


Introspection

dbus is introspectable. That means you can ask dbus what commands are available.

Heres an introspection example. You can see that the return is XML wrapped inside a string (you dont need to read it all):

$ dbus-send --system --print-reply --dest=org.freedesktop.NetworkManager /org/freedesktop/NetworkManager org.freedesktop.DBus.Introspectable.Introspect
method return sender=:1.4 -&gt; dest=:1.441 reply_serial=2
string "
<node>
<interface name="org.freedesktop.DBus.Introspectable">
<method name="Introspect">
<arg direction="out" name="data" type="s">
</arg></method>
<interface name="org.freedesktop.DBus.Properties">
<method name="Get">
<arg direction="in" name="interface" type="s">
<arg direction="in" name="propname" type="s">
<arg direction="out" name="value" type="v">
</arg></arg></arg></method>
<method name="Set">
<arg direction="in" name="interface" type="s">
<arg direction="in" name="propname" type="s">
<arg direction="in" name="value" type="v">
</arg></arg></arg></method>
<method name="GetAll">
<arg direction="in" name="interface" type="s">
<arg direction="out" name="props" type="a{sv}">
</arg></arg></method>
</interface>
<interface name="org.freedesktop.NetworkManager">
<method name="state">
<arg direction="out" name="state" type="u">
</arg></method>
<method name="SetLogging">
<arg direction="in" name="level" type="s">
<arg direction="in" name="domains" type="s">
</arg></arg></method>
<method name="GetPermissions">
<arg direction="out" name="permissions" type="a{ss}">
</arg></method>
<method name="Enable">
<arg direction="in" name="enable" type="b">
</arg></method>
<method name="Sleep">
<arg direction="in" name="sleep" type="b">
</arg></method>
<method name="DeactivateConnection">
<arg direction="in" name="active_connection" type="o">
</arg></method>
<method name="AddAndActivateConnection">
<arg direction="in" name="connection" type="a{sa{sv}}">
<arg direction="in" name="device" type="o">
<arg direction="in" name="specific_object" type="o">
<arg direction="out" name="path" type="o">
<arg direction="out" name="active_connection" type="o">
</arg></arg></arg></arg></arg></method>
<method name="ActivateConnection">
<arg direction="in" name="connection" type="o">
<arg direction="in" name="device" type="o">
<arg direction="in" name="specific_object" type="o">
<arg direction="out" name="active_connection" type="o">
</arg></arg></arg></arg></method>
<method name="GetDeviceByIpIface">
<arg direction="in" name="iface" type="s">
<arg direction="out" name="device" type="o">
</arg></arg><<method>
<method name="GetDevices">
<arg direction="out" name="devices" type="ao">
</arg></method>
<signal name="DeviceRemoved">
<arg type="o">
</arg> </signal>
<signal name="DeviceAdded">
<arg type="o">
</arg> </signal>
<signal name="PropertiesChanged">
<arg type="a{sv}">
</arg> </signal>
<signal name="StateChanged">
<arg type="u">
</arg> </signal>
<signal name="CheckPermissions">
</signal>
<property access="read" name="State" type="u">
<property access="read" name="Version" type="s">
<property access="read" name="ActiveConnections" type="ao">
<property access="read" name="WimaxHardwareEnabled" type="b">
<property access="readwrite" name="WimaxEnabled" type="b">
<property access="read" name="WwanHardwareEnabled" type="b">
<property access="readwrite" name="WwanEnabled" type="b">
<property access="read" name="WirelessHardwareEnabled" type="b">
<property access="readwrite" name="WirelessEnabled" type="b">
<property access="read" name="NetworkingEnabled" type="b">
</property> </property> </property> </property> </property> </property> </property> </property> </property> </property>
<node name="AccessPoint">
<node name="ActiveConnection">
<node name="AgentManager">
<node name="DHCP4Config">
<node name="Devices">
<node name="IP4Config">
<node name="Settings">
</node>
" </node> </node> </node> </node> </node> </node>

 
Lets see if we can translate this into something more human readable.

For example,

<node>
<interface name="org.freedesktop.DBus.Introspectable">
<method name="Introspect">
<arg direction="out" name="data" type="s">
</arg&gt;&lt;/method> 
 ... 
</node>

is the method we used for introspection (remember?).

See the org.freedesktop.DBus.Introspectable.Introspect?  The arg direction "out" means the the response, and type "d" means data string).


How to use introspection to create a dbus query or command

Heres a slightly more complex example of an introspection response:

 <interface name="org.freedesktop.DBus.Properties">
...
<method name="GetAll">
<arg direction="in" name="interface" type="s">
<arg direction="out" name="props" type="a{sv}">
</arg> </arg> </method>
 ...
 <interface name="org.freedesktop.NetworkManager"> 

This generic method, org.freedesktop.DBus.Properties.GetAll, returns a complete dump of all of some other interfaces properties.

Lets go back to grammar (destination, path, method, message) and say that again:

I want to see a dump of Network managers top-level properties.
"Hey Network Manager, please give me a printout of all of Network Managers top-level properties."

Destination: "Hey, Network Manager": org.freedesktop.NetworkManager

Path:  "Network Managers": org/freedesktop/NetworkManager

Method: "Give me a printout of properties": org.freedesktop.DBus.Properties.GetAll

Message: "top-level": org.freedesktop.NetworkManager

You probably noticed that this example has some duplication. When working with dbus, get used to it.


Now lets put it into the right syntax:

dbus-send [ --system| --session] --print-reply --dest=DEST PATH METHOD [MESSAGE]


$ dbus-send --system --print-reply 
--dest=org.freedesktop.NetworkManager
org/freedesktop/NetworkManager
org.freedesktop.DBus.Properties.GetAll
string:"org.freedesktop.NetworkManager"


Lets do one more slightly different example:

<interface name="org.freedesktop.NetworkManager">
...
<method name="ActivateConnection">
<arg direction="in" name="connection" type="o">
<arg direction="in" name="device" type="o">
<arg direction="in" name="specific_object" type="o">
<arg direction="out" name="active_connection" type="o">
</arg> </arg> </arg> </arg> </method>

</node>
" </node> </node> </node> </node> </node> </node>

This method, ActivateConnection, makes a known connection into the active network connection. For example, when switching from one access point to another. There are three extra pieces of information needed, and network manager returns one piece of information in the response.

Lets go back to grammar (destination, path, method, message) and say that again:

"Hey Network Manager, make Access Point Foo (using wireless device 0 and network password settings 67) the active connection."

Destination: "Hey, Network Manager": org.freedesktop.NetworkManager

Path:  "Network Manager": org/freedesktop/NetworkManager

Method: "Make...the active connection": org.freedesktop.NetworkManager.ActivateConnection

Message 1: "Access Point Foo": org/freedesktop/NetworkManager/AccessPoint/220

Message 2: "wireless device 0": org/freedesktop/NetworkManager/Device/0

Message 3: "network password info 67": org/freedesktop/NetworkManager/Settings/67

Now lets put it into the right syntax:

dbus-send [ --system| --session] --print-reply --dest=DEST PATH METHOD [MESSAGE]


$ dbus-send --system --print-reply 
--dest=org.freedesktop.NetworkManager
org/freedesktop/NetworkManager
org.freedesktop.NetworkManager/ActivateConnection
objpath:"org/freedesktop/NetworkManager/AccessPoint/220"
 objpath:"org/freedesktop/NetworkManager/Device/0" 
objpath:"org/freedesktop/NetworkManager/Settings/67"

Obviously, this example wont work for you unless you do the introspection to find valid Access Points, Devices, and Settings that work together. dbus will tell you a lot of it...if you ask...but its not a user-friendly graphical user interface. You need to ask the right questions and use your own logic.

Making introspection easier is where d-feet comes in.


d-feet makes introspection easy

d-feet is a python application (part of the d-feet package in Debian and Ubuntu) that does introspection for you while you write your program.


In this screenshot, you can see lots of the same introspection information that we retrieved before. Easier to read and understand, isnt it? See how the Interfaces and Methods are listed for each Object Path?

Without d-feet, use the following dbus-send command to find out whats available on the bus:

$ dbus-send --session --print-reply --dest="org.freedesktop.DBus" /org/freedesktop/DBus org.freedesktop.DBus.ListActivatableNames


Now you know how to find the information you need to use dbus properly.
Read more »

Sunday, June 11, 2017

Dbus Tutorial Fun with Network Manager

Dbus Tutorial Fun with Network Manager


Introduction
Introspection: figuring out the rules 
Fun with Network Manager
Create a service 
Gobject Introspection


Lets figure out how to use  dbus to get detailed information out of Network Manager (NM), and then to plug our own information back into NM.

Example #1: This script determines if a specific network is the active connection. This is handy for, say, mapping network printers or networked drives, or setting the time, or automating backups, or lots of other stuff.

#!/bin/sh
# What network am I on?

# Get the Active Connection path
# Result should be like: /org/freedesktop/NetworkManager/ActiveConnection/187
active_connection_path=$( dbus-send --system --print-reply
--dest=org.freedesktop.NetworkManager
/org/freedesktop/NetworkManager
org.freedesktop.DBus.Properties.Get
string:"org.freedesktop.NetworkManager"
string:"ActiveConnections"
| grep ActiveConnection/ | cut -d" -f2 )

# Get the Access Point path
# Result should be like: /org/freedesktop/NetworkManager/AccessPoint/194
access_point_path=$( dbus-send --system --print-reply
--dest=org.freedesktop.NetworkManager
"$active_connection_path"
org.freedesktop.DBus.Properties.Get
string:"org.freedesktop.NetworkManager.Connection.Active"
string:"SpecificObject"
| grep variant | cut -d" -f2 )

# Get the Access Point ESSID
# Result should be something like "NETGEAR"
essid=$( dbus-send --system --print-reply
--dest=org.freedesktop.NetworkManager
"$access_point_path"
org.freedesktop.DBus.Properties.Get
string:"org.freedesktop.NetworkManager.AccessPoint"
string:"Ssid"
| grep variant | cut -d" -f2 )



# If we are on the HOME network
if [ "$essid"=="MyHomeNet" ]; then
# Do network-specific changes here

elif [ "$essid"=="WorkCorporateNet" ]
# Do network-specific changes here

else
# Do changes for unrecognized network or no network at all here

fi
exit 0


Example #2: Disable networking

$ dbus-send --system --print-reply 
--dest=org.freedesktop.NetworkManager
/org/freedesktop/NetworkManager
org.freedesktop.DBus.Properties.Set
string:"org.freedesktop.NetworkManager"
string:"NetworkingEnabled"
variant:boolean:false


Example #3: Enable networking. Its exactly the same as the previous example, except for the last line.

$ dbus-send --system --print-reply 
--dest=org.freedesktop.NetworkManager
/org/freedesktop/NetworkManager
org.freedesktop.DBus.Properties.Set
string:"org.freedesktop.NetworkManager"
string:"NetworkingEnabled"
variant:boolean:true


Example #4: Check networking status

$ dbus-send --system --print-reply 
--dest=org.freedesktop.NetworkManager
/org/freedesktop/NetworkManager
org.freedesktop.DBus.Properties.Get
string:"org.freedesktop.NetworkManager"
string:"NetworkingEnabled"

method return sender=:1.4 -> dest=:1.325 reply_serial=2
variant boolean true


Example #5: Disable Wireless

$ dbus-send --system --print-reply 
--dest=org.freedesktop.NetworkManager
/org/freedesktop/NetworkManager
org.freedesktop.DBus.Properties.Set
string:"org.freedesktop.NetworkManager"
string:"WirelessEnabled"
variant:boolean:false


Example #6: Enable Wireless

$ dbus-send --system --print-reply 
--dest=org.freedesktop.NetworkManager
/org/freedesktop/NetworkManager
org.freedesktop.DBus.Properties.Set
string:"org.freedesktop.NetworkManager"
string:"WirelessEnabled"
variant:boolean:true


Example #7: Check Wireless Status

$ dbus-send --system --print-reply 
--dest=org.freedesktop.NetworkManager
/org/freedesktop/NetworkManager
org.freedesktop.DBus.Properties.Get
string:"org.freedesktop.NetworkManager"
string:"WirelessEnabled"

method return sender=:1.4 -> dest=:1.326 reply_serial=2
variant boolean true


Example #8:



Example #9: List all active network connections

$ dbus-send --system --print-reply 
--dest=org.freedesktop.NetworkManager
/org/freedesktop/NetworkManager
org.freedesktop.DBus.Properties.Get
string:"org.freedesktop.NetworkManager"
string:"ActiveConnections"

method return sender=:1.4 -> dest=:1.328 reply_serial=2
variant array [
object path "/org/freedesktop/NetworkManager/ActiveConnection/18"
]


Example #10: Which interface is the active connection using?

$ dbus-send --system --print-reply 
--dest=org.freedesktop.NetworkManager
/org/freedesktop/NetworkManager/ActiveConnection/18
org.freedesktop.DBus.Properties.Get
string:"org.freedesktop.NetworkManager.Connection.Active"
string:"Devices"

method return sender=:1.4 -> dest=:1.331 reply_serial=2
variant array [
object path "/org/freedesktop/NetworkManager/Devices/0"

$ dbus-send --system --print-reply
--dest=org.freedesktop.NetworkManager
/org/freedesktop/NetworkManager/Devices/0
org.freedesktop.DBus.Properties.Get
string:"org.freedesktop.NetworkManager.Device"
string:"Interface"

method return sender=:1.4 -> dest=:1.332 reply_serial=2
variant string "wlan0"


Example #11: Get the current wireless access point

$ dbus-send --system --print-reply 
--dest=org.freedesktop.NetworkManager
/org/freedesktop/NetworkManager/ActiveConnection/18
org.freedesktop.DBus.Properties.Get
string:"org.freedesktop.NetworkManager.Connection.Active"
string:"SpecificObject"

method return sender=:1.4 -> dest=:1.334 reply_serial=2
variant object path "/org/freedesktop/NetworkManager/AccessPoint/209"


Example #12: Get the list of all visible wireless access points

$ dbus-send --system --print-reply 
--dest=org.freedesktop.NetworkManager
/org/freedesktop/NetworkManager/Devices/0
org.freedesktop.NetworkManager.Device.Wireless.GetAccessPoints

method return sender=:1.4 -> dest=:1.333 reply_serial=2
array [
object path "/org/freedesktop/NetworkManager/AccessPoint/209"
object path "/org/freedesktop/NetworkManager/AccessPoint/208"
object path "/org/freedesktop/NetworkManager/AccessPoint/207"
object path "/org/freedesktop/NetworkManager/AccessPoint/206"
]


Example #13: Read the SSID of the active wireless access point

$ dbus-send --system --print-reply 
--dest=org.freedesktop.NetworkManager
/org/freedesktop/NetworkManager/AccessPoint/209
org.freedesktop.DBus.Properties.Get
string:"org.freedesktop.NetworkManager.AccessPoint"
string:"Ssid"

method return sender=:1.4 -> dest=:1.335 reply_serial=2
variant array of bytes "NETGEAR"


Example #14: Read the signal strength of the active wireless point

$ dbus-send --system --print-reply 
--dest=org.freedesktop.NetworkManager
/org/freedesktop/NetworkManager/AccessPoint/209
org.freedesktop.DBus.Properties.Get
string:"org.freedesktop.NetworkManager.AccessPoint"
string:"Strength"

method return sender=:1.4 -> dest=:1.340 reply_serial=2
variant byte 54
# 54 in byte (hexadecimal) = 84 in decimal. Strength = 84%


Example #15: Read the stored NM connection that is currently active

$ dbus-send --system --print-reply 
--dest=org.freedesktop.NetworkManager
/org/freedesktop/NetworkManager/ActiveConnection/18
org.freedesktop.DBus.Properties.Get
string:"org.freedesktop.NetworkManager.Connection.Active"
string:"Connection"

method return sender=:1.4 -> dest=:1.379 reply_serial=2
variant object path "/org/freedesktop/NetworkManager/Settings/10"


Example #16: Disconnect from the current network connection (auto-reconnect)

$ dbus-send --system --print-reply 
--dest=org.freedesktop.NetworkManager
/org/freedesktop/NetworkManager
org.freedesktop.NetworkManager.DeactivateConnection
objpath:"/org/freedesktop/NetworkManager/ActiveConnection/18"

method return sender=:1.4 -> dest=:1.370 reply_serial=2


Example #17: Disconnect from the current network connection and stay disconnected

$ dbus-send --system --print-reply 
--dest=org.freedesktop.NetworkManager
/org/freedesktop/NetworkManager/Devices/0
org.freedesktop.NetworkManager.Device.Disconnect

method return sender=:1.4 -> dest=:1.354 reply_serial=2


Example #18: Connect to a specific wireless network

$ dbus-send --system --print-reply 
--dest=org.freedesktop.NetworkManager
org/freedesktop/NetworkManager
org.freedesktop.NetworkManager.ActivateConnection
objpath:"/org/freedesktop/NetworkManager/Settings/10"
objpath:"/org/freedesktop/NetworkManager/Devices/0"
objpath:"/org/freedesktop/NetworkManager/AccessPoint/209"

method return sender=:1.4 -> dest=:1.382 reply_serial=2
object path "/org/freedesktop/NetworkManager/ActiveConnection/20"


Example #19: Dump all information about an access point

$ dbus-send --system --print-reply 
--dest=org.freedesktop.NetworkManager
/org/freedesktop/NetworkManager/Settings/10
org.freedesktop.NetworkManager.Settings.Connection.GetSettings

method return sender=:1.4 -> dest=:1.386 reply_serial=2
array [## EDITED - its really long]


Read more »

Thursday, May 18, 2017

Dbus Tutorial Intro and Resources

Dbus Tutorial Intro and Resources


Introduction
Introspection
Network Manager 
Create a Service 
Gobject Introspection



Introduction to dbus

dbus (Desktop Bus) is a system, used mostly in Linux, that various applications and daemons and the operating system use to communicate with each other.

You can also use dbus to send text command, instead of a mouse click, that control applications and settings and windows and actions and much more.

For example, you can use dbus to pull information from Network Manager, like the name of a wireless access point. You can send commands to it, like to enable networking or to connect to a specific access point. Many of these actions you can also do other ways, for example through shell commands.

Learning dbus is learning a whole new dimension of how to control your system. And its much like learning a new language.


Resources

We will use the d-feet application (sudo apt-get install d-feet) to search for dbus resources on our system. We will use the dbus-send shell command to interact with dbus.

Thats it. One helper application and one command. The rest is up to you.


dbus Grammar

Heres a sample dbus command. All it does is tell Network Manager to enable networking, just like you right-clicked on the NM icon and ticked "Enable Networking". In english, we would say something a bit more like: "Hey Network Manager, (you) please turn on (entire) networking"

dbus commands have four important elements: Destination, path, method, and message.

$ dbus-send --system --print-reply # (Hey,)
--dest=org.freedesktop.NetworkManager # destination (Network Manager)
/org/freedesktop/NetworkManager # path (you)
org.freedesktop.DBus.Properties.Set # method (turn)
string:"org.freedesktop.NetworkManager" # message (networking)
string:"NetworkingEnabled" # message (entire)
variant:boolean:true # message (on)


dbus grammar is very simple, but that doesnt mean it is easy the first time you try it. The grammar is meant for machines.

Destination: Which process/program/application you are talking to.
Path: Which resource you are talking about.
Method: What you are telling the destination to do with the path.
Message: Specific information needed for the method to make sense.

For example: "Sally, please throw the red ball to Fred."

You are talking to Sally (in english Grammar, often but not always the subject).
Sally is the destination.

The red ball is the resource (in english grammar, usually the direct object).
The red ball is the path.

"Throw" is the action you want Sally to do with the ball (in english grammar, usually the verb)
Throw is the method.

"To Fred" is additional information that makes the throw successful.
To Fred is message that is needed by the method.


dbus Syntax

The grammar is the hardest part - restructuring your statement clearly in those four terms. After that, its easy.

The syntax of the actual command using dbus-send  is explained thoroughly in man dbus-send, though some of the teminology differs a bit.

dbus-send [--system | --session] [--dest=NAME] [--print-reply]
[--type=TYPE] <destination object="" path=""> <message name=""> [contents ...]

system vs. session simply refers to which bus. There are usually two running, one at user (session) level, and one at admin/sudo/root (system) level.

"type" simply means if its a signal or a method call. Signals are usually one-way, little response is generated. A method call usually creates a response, even if just an acknowledgement.

"print reply" prints the response from dbus, if any.


A more simple (and slightly rearranged) syntax that we use is:

dbus-send [ --system| --session] --print-reply --dest=DEST PATH METHOD [MESSAGE]

$ dbus-send --system --print-reply # Root-level, since its hardware
--dest=org.freedesktop.NetworkManager # destination (dest)
/org/freedesktop/NetworkManager # path (path)
org.freedesktop.DBus.Properties.Set # message name (method)
string:"org.freedesktop.NetworkManager" # message (contents)
string:"NetworkingEnabled" # message (contents)
variant:boolean:true # message (contents)

This multi-line command connected with backslashes () is just for readability, especially in scripts. When I really type them in, they look like this:

$ dbus-send --system --print-reply --dest=org.freedesktop.NetworkManager /org/freedesktop/NetworkManager org.freedesktop.DBus.Properties.Set string:"org.freedesktop.NetworkManager" string:"NetworkingEnabled" variant:boolean:true



Using Shell Variables

Simple grammar and syntax means that its easy to use shell variables to improve readbility and reduce typos, especially in scripts.

dest="org.freedesktop.NetworkManager"
path="/org/freedesktop/NetworkManager"
method="org.freedesktop.DBus.Properties.Set"

# Enable Networking
dbus-send --system --print-reply --dest="$dest" "$path" "$method"
string:"$dest" string:"NetworkingEnabled" variant:boolean:true

And, of course, you can nest entire commands within variables:

dest="org.freedesktop.NetworkManager"
path="/org/freedesktop/NetworkManager"
method="org.freedesktop.DBus.Properties.Set"

network_command="dbus-send --system --print-reply --dest=$dest $path $method"
enable_network="string:$dest string:"NetworkingEnabled" variant:boolean:true"

# Enable Networking
$network_command $enable_network

Next, lets ligure out how to find all those weird dbus properties using introspection.
Read more »