(Apache 2.2 + MySQL 5.1 + PHP 5.2 + PERL 5.10 +PEAR + SQLite + ProFTPD + phpMyAdmin + Webalizer + phpSQLiteAdmin + XAMPP Control Panel)
http://www.ubuntuforums.org/223410
http://www.apachefriends.org/f/viewtopic.php?t=21531#108517
The commands in this HOWTO must be entered in the terminal:
Applications -> Accessories -> Terminal
Download XAMPP to your desktop and extract the files:
http://apachefriends.org/xampp-linux
cd ~/Desktop
wget http://www.apachefriends.org/download.php?xampp-linux-1.7.1.tar.gz
sudo tar xvfz xampp-linux*.tar.gz -C /opt
Create a XAMPP start menu entry:
cd ~/.local/share/applications
gedit xampp-control-panel.desktop
Paste the following into the open file:
[Desktop Entry]
Comment=Start/Stop XAMPP
Name=XAMPP Control Panel
Exec=gksudo "python /opt/lampp/share/xampp-control-panel/xampp-control-panel.py"
Icon[en_CA]=/usr/share/icons/Tango/scalable/devices/network-wired.svg
Encoding=UTF-8
Terminal=false
Name[en_CA]=XAMPP Control Panel
Comment[en_CA]=Start/Stop XAMPP
Type=Application
Icon=/usr/share/icons/Tango/scalable/devices/network-wired.svg
[Desktop Entry]
Comment=Start/Stop XAMPP
Name=XAMPP Control Panel
Exec=gksudo /opt/lampp/share/xampp-control-panel/xampp-control-panel
Icon[en_CA]=/opt/lampp/htdocs/xampp/img/logo-small.gif
Encoding=UTF-8
Terminal=false
Name[en_CA]=XAMPP Control Panel
Comment[en_CA]=Start/Stop XAMPP
Type=Application
Icon=/opt/lampp/htdocs/xampp/img/logo-small.gif
Save and close the file.
Publish:
XAMPP uses /opt/lampp/htdocs as the root web directory, but you can publish pages in your home directory this way.
cd ~
mkdir public_html
sudo ln -s ~/public_html /opt/lampp/htdocs/$USER
Now any files and folders you place in ~/public_html will be
published to your personal webserver.
Start XAMPP via the terminal:
cd /opt/lampp
sudo ./lampp start
Stop XAMPP (if necessary):
cd /opt/lampp
sudo ./lampp stop
Via the XAMPP Control Panel:
Applications -> Other -> XAMPP Control Panel
If Apache2 or MySQL is already running, then XAMPP will not start. You must stop these applications, if you want to use XAMPP:
sudo /etc/init.d/apache2 stop
sudo /etc/init.d/mysql stop
PHP5 is the default, but you can switch between PHP4 and PHP5, if you like:
cd /opt/lampp
sudo ./lampp php4
sudo ./lampp php5
Open your new webpages at:
http://localhost/username/
Security:
http://apachefriends.org/xampp-linux/381
1. The MySQL root user has a blank password.
2. MySQL is accessible via your local network.
3. ProFTPD has user “nobody” with password “lampp”.
4. PhpMyAdmin is accessible via the local network.
5. Examples are accessible via the local network.
6. MySQL and Apache running under the same user “nobody”.
To configure some of the security features of xampp:
cd /opt/lampp
sudo ./lampp security
Tuesday, September 8, 2009
Google Wave!!!! - The Wave of the Future!!!!
Delighted to hear another new makings of Google!!!! Email+IM+Wiki+RealTimeCollaboration+Documents+Workflows+ServerSideBots+GoogleMagic+OpenStandards = Google Wave
This is the "Wave" of the Future ;)
Check this out!!!!
This is the "Wave" of the Future ;)
Check this out!!!!
Ride the D-Bus, Control your Linux desktop from the shell
What is the D-Bus?
From the D-Bus documentation: "D-Bus is an inter-process communication mechanism—a medium for local communication between processes running on the same host. (Inter-host connects may be added in the future, but that is not what D-Bus is meant for). D-Bus is meant to be fast and lightweight, and is designed for use as a unified middleware layer underneath the main free desktop environments"
So for the non technically inclined (why are you reading this anyway) ;) basically a simple way to think of D-Bus, is that it's a way for processes on an operating system to communicate with each other. That's probably a simple and non accurate enough wording, but it should help grasp the concept. Many utilities nowadays are implementing D-Bus connectivity. It is especially interesting (well for me anyway) to script some GUI elements like for example my KDE-4 desktop from the command line. This would help automate some tasks and is cool anyways. Let's see how to begin talking on the D-Bus
In order to communicate with running applications on the D-Bus, we need a front end CLI application, or we could use a language binding (say python bindings). However, we will choose a CLI application. It is possible to use "dbus-launch", or the "qdbus" command part of Qt4. I will be using qdbus since it demonstrates the point and is faster to use. So, let's launch qdbus, and list the running communications buses.
# qdbus
:1.1
org.kde.klauncher
:1.10
org.freedesktop.ScreenSaver
org.kde.krunner
org.kde.screensaver
:1.12
org.kde.plasma
:1.1249
... List continues
So basically, qdbus now contacts the running session D-Bus and lists available buses. The buses are named in a reverse DNS style names as you can see. Some buses do not have names, but rather numbers, as far as I can see those represent specific sessions of some applications. Now we need to pick an interesting bus to talk on. I will run the following command to list only freedesktop dbuses, as I believe those should work whether you're running Gnome or KDE. So, it should help any reader follow along
#qdbus | grep freedesktop
org.freedesktop.ScreenSaver
org.freedesktop.Notifications
org.freedesktop.PowerManagement
org.freedesktop.DBus
so, let's pick the ScreenSaver bus. In order to list the available objects on any specific bus, we call it like so:
#qdbus org.freedesktop.ScreenSaver
/
/App
/Interface
/KBookmarkManager
/KBookmarkManager/konqueror
/KDebug
/MainApplication
/ManagerIface_contact
/ScreenSaver
I mostly find only one "useful" object, in this case "/ScreenSaver". Let's contact that object, and list its avialable "methods". The methods of an object for those who have not done any object oriented coding before, is basically the list of actions or "things" this object can "do". So listing the methods:
# qdbus org.freedesktop.ScreenSaver /ScreenSaver
signal void org.freedesktop.ScreenSaver.ActiveChanged(bool)
method bool org.freedesktop.ScreenSaver.GetActive()
method uint org.freedesktop.ScreenSaver.GetActiveTime()
method uint org.freedesktop.ScreenSaver.GetSessionIdleTime()
method uint org.freedesktop.ScreenSaver.Inhibit(QString application_name, QString reason_for_inhibit)
method void org.freedesktop.ScreenSaver.Lock()
method bool org.freedesktop.ScreenSaver.SetActive(bool e)
method void org.freedesktop.ScreenSaver.SimulateUserActivity()
method uint org.freedesktop.ScreenSaver.Throttle(QString application_name, QString reason_for_inhibit)
method void org.freedesktop.ScreenSaver.UnInhibit(uint cookie)
method void org.freedesktop.ScreenSaver.UnThrottle(uint cookie)
method void org.kde.screensaver.configure()
method void org.kde.screensaver.saverLockReady()
method QDBusVariant org.freedesktop.DBus.Properties.Get(QString interface_name, QString property_name)
method void org.freedesktop.DBus.Properties.Set(QString interface_name, QString property_name, QDBusVariant value)
method QString org.freedesktop.DBus.Introspectable.Introspect()
Hmm, interesting stuff. Can you see the following method:
org.freedesktop.ScreenSaver.GetSessionIdleTime
Obviously it gives you the session idle time, i.e. how long has the interactive user not touched his keyboard or mouse. This piece of information is interesting if you want your shell script to only do certain things when the user is not interactively using his machine. Without D-Bus, getting this kind of information would be almost impossible, or too tricky. Now how do we call this method you ask? easy! just append it to the command line:
#qdbus org.freedesktop.ScreenSaver /ScreenSaver org.freedesktop.ScreenSaver.GetSessionIdleTime
0
So, the output from this command is a "0". Meaning the session idle time is zero! Everytime you execute this command, you get the same answer. Starting to guess why ? :) Basically, as you hit "enter" to run this command, you reset the session idle time back to zero! So, what do we do to test the functionality, try this:
# sleep 5 ; qdbus org.freedesktop.ScreenSaver /ScreenSaver org.freedesktop.ScreenSaver.GetSessionIdleTime
4
So, that previous combo command sleeps for 5 seconds .. then executes the D-Bus query without touching any further keyboard keys, so this time we get an answer of "4" seconds. Don't know where that extra second slipped though :)
Ok, as a second example let's focus on the following method:
method bool org.freedesktop.ScreenSaver.SetActive(bool e)
This method sets the screen saver active, i.e. it launches the screen saver from your shell command or script. Let's test it out:
# qdbus org.freedesktop.ScreenSaver /ScreenSaver org.freedesktop.ScreenSaver.SetActive
Error: org.freedesktop.DBus.Error.UnknownMethod
No such method 'SetActive' in interface 'org.freedesktop.ScreenSaver' at object path '/ScreenSaver' (signature '')
Oops, this time we got an error. Why? Basically the error is telling us that it cannot find that method we're calling with that "signature". A method signature usually means the arguments you pass to it and the return type. This simply means we're not calling the method the way it's meant to be called. The sharp shooters are going to instantly know this is because we missed the (bool e) at the end of the method. This means the method call is expecting a boolean (true/false) argument. So, let's call the screensaver method correctly this time:
# qdbus org.freedesktop.ScreenSaver /ScreenSaver org.freedesktop.ScreenSaver.SetActive True
true
Cool! We're now launching the screensaver from the command line. Let's see what else we can do:
# qdbus org.freedesktop.ScreenSaver /ScreenSaver org.freedesktop.ScreenSaver.Lock
Yep, that locks the screen on demand, cool! I'm hungry for more. Let's see. Let's call that inhibit method. This will basically inhibit the screensaver from kicking in, even if your computer is idle. Why would that be useful ? Say you're watching a You-tube longish video, and AFAIK, Flash doesn't yet communicate that to the system, and thus the screensaver will kick in to interrupt the video playback. So, let's do it:
# qdbus org.freedesktop.ScreenSaver /ScreenSaver org.freedesktop.ScreenSaver.Inhibit "$$" "Testing D-Bus Interface"
5822
Let's explain those arguments we passed, the first one should be the application name, in my case, the special shell variable $$ is the PID for the currently executing shell. The second string is the "reason for inhibit"! The method call returns a cookie, i.e. a magic number that identifies my request. This is useful when you want to turn off the inhibit, i.e. return the system to its normal state. You would need to pass back that magic cookie. This is used by the system to identify the different inhibit requests. So finally let's uninhibit our screensaver using that cookie number
# qdbus org.freedesktop.ScreenSaver /ScreenSaver org.freedesktop.ScreenSaver.UnInhibit 5822
Cool! Are you starting to see the possibilities just yet? Hope you had fun on this D-Bus tour
From the D-Bus documentation: "D-Bus is an inter-process communication mechanism—a medium for local communication between processes running on the same host. (Inter-host connects may be added in the future, but that is not what D-Bus is meant for). D-Bus is meant to be fast and lightweight, and is designed for use as a unified middleware layer underneath the main free desktop environments"
So for the non technically inclined (why are you reading this anyway) ;) basically a simple way to think of D-Bus, is that it's a way for processes on an operating system to communicate with each other. That's probably a simple and non accurate enough wording, but it should help grasp the concept. Many utilities nowadays are implementing D-Bus connectivity. It is especially interesting (well for me anyway) to script some GUI elements like for example my KDE-4 desktop from the command line. This would help automate some tasks and is cool anyways. Let's see how to begin talking on the D-Bus
In order to communicate with running applications on the D-Bus, we need a front end CLI application, or we could use a language binding (say python bindings). However, we will choose a CLI application. It is possible to use "dbus-launch", or the "qdbus" command part of Qt4. I will be using qdbus since it demonstrates the point and is faster to use. So, let's launch qdbus, and list the running communications buses.
# qdbus
:1.1
org.kde.klauncher
:1.10
org.freedesktop.ScreenSaver
org.kde.krunner
org.kde.screensaver
:1.12
org.kde.plasma
:1.1249
... List continues
So basically, qdbus now contacts the running session D-Bus and lists available buses. The buses are named in a reverse DNS style names as you can see. Some buses do not have names, but rather numbers, as far as I can see those represent specific sessions of some applications. Now we need to pick an interesting bus to talk on. I will run the following command to list only freedesktop dbuses, as I believe those should work whether you're running Gnome or KDE. So, it should help any reader follow along
#qdbus | grep freedesktop
org.freedesktop.ScreenSaver
org.freedesktop.Notifications
org.freedesktop.PowerManagement
org.freedesktop.DBus
so, let's pick the ScreenSaver bus. In order to list the available objects on any specific bus, we call it like so:
#qdbus org.freedesktop.ScreenSaver
/
/App
/Interface
/KBookmarkManager
/KBookmarkManager/konqueror
/KDebug
/MainApplication
/ManagerIface_contact
/ScreenSaver
I mostly find only one "useful" object, in this case "/ScreenSaver". Let's contact that object, and list its avialable "methods". The methods of an object for those who have not done any object oriented coding before, is basically the list of actions or "things" this object can "do". So listing the methods:
# qdbus org.freedesktop.ScreenSaver /ScreenSaver
signal void org.freedesktop.ScreenSaver.ActiveChanged(bool)
method bool org.freedesktop.ScreenSaver.GetActive()
method uint org.freedesktop.ScreenSaver.GetActiveTime()
method uint org.freedesktop.ScreenSaver.GetSessionIdleTime()
method uint org.freedesktop.ScreenSaver.Inhibit(QString application_name, QString reason_for_inhibit)
method void org.freedesktop.ScreenSaver.Lock()
method bool org.freedesktop.ScreenSaver.SetActive(bool e)
method void org.freedesktop.ScreenSaver.SimulateUserActivity()
method uint org.freedesktop.ScreenSaver.Throttle(QString application_name, QString reason_for_inhibit)
method void org.freedesktop.ScreenSaver.UnInhibit(uint cookie)
method void org.freedesktop.ScreenSaver.UnThrottle(uint cookie)
method void org.kde.screensaver.configure()
method void org.kde.screensaver.saverLockReady()
method QDBusVariant org.freedesktop.DBus.Properties.Get(QString interface_name, QString property_name)
method void org.freedesktop.DBus.Properties.Set(QString interface_name, QString property_name, QDBusVariant value)
method QString org.freedesktop.DBus.Introspectable.Introspect()
Hmm, interesting stuff. Can you see the following method:
org.freedesktop.ScreenSaver.GetSessionIdleTime
Obviously it gives you the session idle time, i.e. how long has the interactive user not touched his keyboard or mouse. This piece of information is interesting if you want your shell script to only do certain things when the user is not interactively using his machine. Without D-Bus, getting this kind of information would be almost impossible, or too tricky. Now how do we call this method you ask? easy! just append it to the command line:
#qdbus org.freedesktop.ScreenSaver /ScreenSaver org.freedesktop.ScreenSaver.GetSessionIdleTime
0
So, the output from this command is a "0". Meaning the session idle time is zero! Everytime you execute this command, you get the same answer. Starting to guess why ? :) Basically, as you hit "enter" to run this command, you reset the session idle time back to zero! So, what do we do to test the functionality, try this:
# sleep 5 ; qdbus org.freedesktop.ScreenSaver /ScreenSaver org.freedesktop.ScreenSaver.GetSessionIdleTime
4
So, that previous combo command sleeps for 5 seconds .. then executes the D-Bus query without touching any further keyboard keys, so this time we get an answer of "4" seconds. Don't know where that extra second slipped though :)
Ok, as a second example let's focus on the following method:
method bool org.freedesktop.ScreenSaver.SetActive(bool e)
This method sets the screen saver active, i.e. it launches the screen saver from your shell command or script. Let's test it out:
# qdbus org.freedesktop.ScreenSaver /ScreenSaver org.freedesktop.ScreenSaver.SetActive
Error: org.freedesktop.DBus.Error.UnknownMethod
No such method 'SetActive' in interface 'org.freedesktop.ScreenSaver' at object path '/ScreenSaver' (signature '')
Oops, this time we got an error. Why? Basically the error is telling us that it cannot find that method we're calling with that "signature". A method signature usually means the arguments you pass to it and the return type. This simply means we're not calling the method the way it's meant to be called. The sharp shooters are going to instantly know this is because we missed the (bool e) at the end of the method. This means the method call is expecting a boolean (true/false) argument. So, let's call the screensaver method correctly this time:
# qdbus org.freedesktop.ScreenSaver /ScreenSaver org.freedesktop.ScreenSaver.SetActive True
true
Cool! We're now launching the screensaver from the command line. Let's see what else we can do:
# qdbus org.freedesktop.ScreenSaver /ScreenSaver org.freedesktop.ScreenSaver.Lock
Yep, that locks the screen on demand, cool! I'm hungry for more. Let's see. Let's call that inhibit method. This will basically inhibit the screensaver from kicking in, even if your computer is idle. Why would that be useful ? Say you're watching a You-tube longish video, and AFAIK, Flash doesn't yet communicate that to the system, and thus the screensaver will kick in to interrupt the video playback. So, let's do it:
# qdbus org.freedesktop.ScreenSaver /ScreenSaver org.freedesktop.ScreenSaver.Inhibit "$$" "Testing D-Bus Interface"
5822
Let's explain those arguments we passed, the first one should be the application name, in my case, the special shell variable $$ is the PID for the currently executing shell. The second string is the "reason for inhibit"! The method call returns a cookie, i.e. a magic number that identifies my request. This is useful when you want to turn off the inhibit, i.e. return the system to its normal state. You would need to pass back that magic cookie. This is used by the system to identify the different inhibit requests. So finally let's uninhibit our screensaver using that cookie number
# qdbus org.freedesktop.ScreenSaver /ScreenSaver org.freedesktop.ScreenSaver.UnInhibit 5822
Cool! Are you starting to see the possibilities just yet? Hope you had fun on this D-Bus tour
Detecting Network Connectivity Using D-Bus
Preface
The Intel® Mobile Internet Device (MID) platform provides a full internet experience in a pocket-sized form factor. Combining Moblin-based operating systems with the Intel® Atom™ processor, MIDs are able to run any application that has been built for the x86 architecture, including Adobe Flash 10* and Adobe AIR 1.5*. While the features of the devices that are and will be on the market vary depending on OEM and target market, there are several features that the devices share in common; small form factor, emphasis on internet connectivity rather than extensive storage, and alternate input methods.
Although there are ultra-mobile computing devices in the market that run Microsoft Windows XP* or Windows Vista* and that are built on the same hardware platform as those running a Moblin-based operating systems such as Midinux* or Ubuntu* Mobile Edition, this series of whitepapers focuses entirely on Moblin-based MIDs. For information on how to retrieve this information from Windows operating systems, please consult that platform’s documentation, or see the Intel® Mobile Platform SDK.
The functionality described in this paper is also provided via the Platform Awareness Service, a light-weight, D-Bus initiated platform information provider. However, because the final software stack for each device is influenced heavily by the OEM and Service Providers, this service may not be pre-installed on some Moblin-based devices. We have therefore written these whitepapers in order to simplify access to this information on platforms that do not have this service installed.
For further information on how to use D-Bus to retrieve information from the Platform Awareness Service, please refer to the Platform Awareness Service documentation.
Introduction
With the advances of computer networking within the last decade, devices can be connected via a myriad of technologies and protocols, wired and wireless. This connectivity has become so prevalent that many applications can’t function without it. Some application functions take advantage of network communications such as email, network gaming, web browser, etc. Some real-time applications, especialy networking games, require a large bandwidth and high network reliability. These applications must be aware of the network connectivity. Mobile computing devices such as a laptop or Mobile Internet Device (MID), frequently use wireless technology and thus network awareness becomes even more important. Instead of letting each application write its own connectivity awareness code, we propose a uniform way to convey the connectivity information to applications. Laptop/MID applications can then refer to our system to get information on network connectivity and make proper decisions at run time.
As part of a whole project, MID Platform Awareness, this paper shows how we can call connectivity awareness methods and get event notifications.
The system was developed on Moblin[4], a Linux* platform, and uses D-Bus communication[1] to transport information to users [1]. Applications which want to get connectivity information need to use D-Bus as well. In the following sections, we briefly describe D-Bus and how we implement network connectivity awareness service using D-Bus. We show examples of how an application can retrieve the network connectivity information; (1)whether or not the device is connecting to a network, (2)whether or not the device can reach a given website, (3)the latency of the network when the device does connect, (4)the data rate involved when the device reaches a website, (5)the media type of the current network, and (6)the link speed of the network.
Background on D-Bus
D-Bus is a fast, lightweight message system which allows applications to communicate one on one or to broadcast messages to subscribers, (inter-process communication). [2]. D-Bus can be used as low-level API or via a higher level binding, such as Qt, Python*, Java*, C#, or Perl. This paper shows an application written in C using Glib bindings. Glib is the base library of GNOME and provides an object-based, event-driven environment.
Two buses are defined in D-Bus: the system bus and the session bus. The system bus allows communication between an application and the operating system while the session bus is designed to allow communication between two applications.
In order to use D-Bus, we need to understand a few basics. First, an object is an endpoint on the bus that is created by an application in the context of that application’s connection to the bus. Objects have names, and these names are called object paths. We can find an object via its path. A proxy allows clients to reference objects on the bus. Once we find an object, we usually keep a proxy to that object so we can subsequently refer to that object without searching again.
An object can perform specific operations, referred to as methods. Thus, a client can send a request to an object and ask the object to invoke a method. The object then executes the method (if the method exists) and the result is sent back to the client. If a method requires input parameters, these parameters are passed with the request. The result can be one or more output parameters, which are sent back to the client in the reply message. At the D-Bus layer, this method invocation/message passing sequence occurs asynchronously; the glib wrapper for the D-Bus object proxy allows the methods to be called either synchronously or asynchronously.
An object can also emit an event, or signal. When a signal is generated by an object, it is broadcasted to any interested observers. Signals can also carry parameters. Methods and Signals are embedded members of an object that can be grouped into an interface. An object can declare one or many interfaces.
In order to generate dbus-glib binding code, we use a tool called dbus-binding-tool. We first create an XML file, referred to as an Introspection XML file, in which we describe the methods and signals. Defining the interface this way ensures that clients can discover and introspect our D-Bus service. An example of the introspection XML is shown below:
- collapse sourceview plaincopy to clipboardprint?
1.
2. 3. "-//freedesktop//DTD D-Bus Object Introspection 1.0//EN"
4. "http://standards.freedesktop.org/dbus/1.0/introspect.dtd">
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
"-//freedesktop//DTD D-Bus Object Introspection 1.0//EN"
"http://standards.freedesktop.org/dbus/1.0/introspect.dtd">
In this introspection XML file, an interface called org.moblin.Platform.Connection defines six methods:
IsConnected, IsReachable, GetLatency, GetDatRate, GetMediaType and GetLinkSpeed. The annotation XML tags tell dbus-binding-tool what the name of the implementing C function should be. For example, IsConnected is the name of the method that will be visible to users over D-Bus. Internally, we need to implement a C function called isConnected. Method parameters and return values are both specified using the arg XML tag. The direction attribute for a parameter is "in"; for return values, the direction attribute is "out". Note that parameters and return values both have name attributes.
The type attribute of the arg XML tag indicates the data type of the parameter or return value. For example, the value "b" in the IsConnected method return value indicates that the method returns a Boolean. The second method, IsReachable, takes a string parameter representing the target URI (Uniform Resource Identifier) and returns a Boolean value. The next two methods, GetLatency and GetDataRate, also take a string parameter representing the URI and return a double representing seconds and kilobytes per second, respectively. The output of GetMediaType is a string. Finally, the output of the last method, GetLinkSpeed, is a Double data type, representing the number of kilobits per second.
Two signals are defined in the introspection XML file. The signal "Connected" is generated when the system changes state from having no connection to having at least one connection. The "Disconnected" signal is generated when the when the system changes state from having at least one connection to having no connections.
Below are primary steps to implement a D-Bus service. For more details, look here.
* Run dbus-binding-tool for an introspection XML file to generate dbus-glib binding code
* Acquire the D-Bus GObject wrapper
* Implement the instance initialization
* Implement the methods
* Register the object on the D-Bus
To call the methods implemented on a remote object, a client needs to follow the following steps:
* Connect to the bus
* Create a proxy object
* Invoke the methods on the proxy object.
The connectivity awareness service below uses D-Bus as a communication channel to send information to clients regarding network connectivity. Clients can thus use D-Bus to get connectivity information by querying the methods provided by the connectivity service. Client applications can also listen for the signals that the connectivity awareness service generates. The methods and events mentioned in the introspection file are implemented by the connectivity awareness service.
Getting Network Connectivity Information
The connectivity awareness service provides the means to query the following connectivity information on the computer where the service is installed.
Detecting the network connection
A networked application obviously requires an established network connection. Before allocating resources for a network transaction, it is useful to know whether or not the system has an established network connection. Therefore, the network connectivity service provides a method called IsConnected, which returns a Boolean value confirming the status of the network. The network connectivity service checks the status of all network devices on the computer. If at least one network device has an established connection, the Boolean value TRUE is returned. If all network devices on the computer are not running, the Boolean value FALSE is returned. To query the connectivity, the application first must bind to D-Bus service as shown in the following example
- collapse sourceview plaincopy to clipboardprint?
1. #include
2. #include
3. #include
4. #include
5. #include
6. #include
7.
8. #define PLATFORM_SERVICE "org.moblin.Platform"
9. #define PLATFORM_PATH "/org/moblin/Platform"
10. #define PLATFORM_CONNECTION_IF "org.moblin.Platform.Connection"
11.
12. int main(int argc, char** argv)
13. {
14. DBusGConnection* conn;
15. GError *error;
16. DBusGProxy *platformProxy;
17.
18. g_type_init();
19. error = NULL;
20. conn = dbus_g_bus_get(DBUS_BUS_SESSION, &error);
21.
22. // Create the proxy Platform
23. platformProxy = dbus_g_proxy_new_for_name(conn,
24. PLATFORM_SERVICE, // target for the method call
25. PLATFORM_PATH, // object to call on
26. PLATFORM_CONNECTION_IF); // interface to call on
27.
28. gboolean result;
29.
30. if (!dbus_g_proxy_call(platformProxy, "IsConnected", &error,
31. G_TYPE_INVALID,
32. G_TYPE_BOOLEAN, &result,
33. G_TYPE_INVALID))
34. {
35. g_printerr("Failed to call remotely: %s\n",
36. error->message);
37. g_error_free(error);
38. }
39. else
40. printf ("Remote call successes with returned value: %s\n", result? "TRUE" : "FALSE");
41.
42. . . . . . . . . . . . . . . . . . . . . . .
43. . . . . . . . . . . . . . . . . . . . . . .
44. . . . . . . . . . . . . . . . . . . . . . .
45.
46. return 0;
47. }
#include
#include
#include
#include
#include
#include
#define PLATFORM_SERVICE "org.moblin.Platform"
#define PLATFORM_PATH "/org/moblin/Platform"
#define PLATFORM_CONNECTION_IF "org.moblin.Platform.Connection"
int main(int argc, char** argv)
{
DBusGConnection* conn;
GError *error;
DBusGProxy *platformProxy;
g_type_init();
error = NULL;
conn = dbus_g_bus_get(DBUS_BUS_SESSION, &error);
// Create the proxy Platform
platformProxy = dbus_g_proxy_new_for_name(conn,
PLATFORM_SERVICE, // target for the method call
PLATFORM_PATH, // object to call on
PLATFORM_CONNECTION_IF); // interface to call on
gboolean result;
if (!dbus_g_proxy_call(platformProxy, "IsConnected", &error,
G_TYPE_INVALID,
G_TYPE_BOOLEAN, &result,
G_TYPE_INVALID))
{
g_printerr("Failed to call remotely: %s\n",
error->message);
g_error_free(error);
}
else
printf ("Remote call successes with returned value: %s\n", result? "TRUE" : "FALSE");
. . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . .
return 0;
}
Note that the application invokes the method IsConnected implemented in the connectivity awareness service: no input is required, and the method returns TRUE if the computer is connected to a network.
The back-end implementation of this method basically computes the list of network adapters available, and confirms the connection status if there is at least one network adapter running. The function detecting whether or not a network adapter is running, is shown below
- collapse sourceview plaincopy to clipboardprint?
1. netdev_ret netdev_get_running(netdev_dev *dev, // in
2. netdev_running *running) // out
3. {
4. struct ifreq ifr;
5. if(_get_ifreq(dev->ifname, SIOCGIFFLAGS, &ifr) != NETDEV_SUCCESS)
6. {
7. running = RUNNING_UNKNOWN;
8. return NETDEV_ERROR;
9. }
10.
11. short flags = ifr.ifr_flags;
12. if(flags & IFF_RUNNING)
13. {
14. *running = RUNNING_RUN;
15. }
16. else
17. {
18. *running = RUNNING_STOP;
19. }
20.
21. return NETDEV_SUCCESS;
22. }
23.
netdev_ret netdev_get_running(netdev_dev *dev, // in
netdev_running *running) // out
{
struct ifreq ifr;
if(_get_ifreq(dev->ifname, SIOCGIFFLAGS, &ifr) != NETDEV_SUCCESS)
{
running = RUNNING_UNKNOWN;
return NETDEV_ERROR;
}
short flags = ifr.ifr_flags;
if(flags & IFF_RUNNING)
{
*running = RUNNING_RUN;
}
else
{
*running = RUNNING_STOP;
}
return NETDEV_SUCCESS;
}
Detecting HTTP reachability
The second method queries the reachability of a specified website. When getting this request, the connectivity service forms a HTTP GET message[5] and sends it to the specified address (web address) at port 80 (the typical port for HTTP protocol). The socket timeout is set to 3 seconds in this implementation: the service will wait for a HTTP response with status 200[5] before disconnecting the socket. This method, IsReachable, requires a string parameter as the target address (web address) and returns a Boolean value confirming whether or not the web address can be reachable within the socket timeout. The format of the valid entry takes the protocol (http in this case) follows it with the URI. Examples of valid inputs are shown below
"http://www.intel.com/", "http://www.google.com/", "http://www.yahoo.com/", etc ...
The third method, GetLatency, computes the time delay between sending a HTTP GET message and receiving the reply. This method takes an input parameter which is the URI of the website and returns a value of type double, representing the time in seconds. If the socket timeout expires, this method returns a null value.
The fourth method, GetDataRate, calculates the data rate when sending a HTTP GET message and receiving the reply. This method takes an input parameter which is the URI of the website and returns a value of type double representing kilobyte per second (kBps). If the socket timeout expires, this method returns a null value. Data rate is computed using the following formula:
(length of HTTP GET sent + length of HTTP reply) / latency
Code referring to these D-Bus methods is shown below.
- collapse sourceview plaincopy to clipboardprint?
1. int result1;
2.
3. if (!dbus_g_proxy_call(platformProxy, "IsReachable", &error,
4. G_TYPE_STRING, "http://www.intel.com/",
5. G_TYPE_INVALID,
6. G_TYPE_BOOLEAN, &result1,
7. G_TYPE_INVALID))
8. {
9. g_printerr("Failed to call remotely: %s\n",
10. error->message);
11. g_error_free(error);
12. }
13. else
14. printf ("Remote call successes with returned value: %s\n", result1? "TRUE" : "FALSE");
15.
16. gdouble result2;
17.
18. if (!dbus_g_proxy_call(platformProxy, "GetLatency", &error,
19. G_TYPE_STRING, "http://www.intel.com/",
20. G_TYPE_INVALID,
21. G_TYPE_DOUBLE, &result2,
22. G_TYPE_INVALID))
23. {
24. g_printerr("Failed to call remotely: %s\n",
25. error->message);
26. g_error_free(error);
27. }
28. else
29. printf ("Remote call successes with returned value: %6.3f seconds\n", result2);
30.
31.
32. if (!dbus_g_proxy_call(platformProxy, "GetDataRate", &error,
33. G_TYPE_STRING, "http://www.intel.com/",
34. G_TYPE_INVALID,
35. G_TYPE_DOUBLE, &result2,
36. G_TYPE_INVALID))
37. {
38. g_printerr("Failed to call remotely: %s\n",
39. error->message);
40. g_error_free(error);
41. }
42. else
43. printf ("Remote call successes with returned value: %8.2f KB/sec\n", result2);
int result1;
if (!dbus_g_proxy_call(platformProxy, "IsReachable", &error,
G_TYPE_STRING, "http://www.intel.com/",
G_TYPE_INVALID,
G_TYPE_BOOLEAN, &result1,
G_TYPE_INVALID))
{
g_printerr("Failed to call remotely: %s\n",
error->message);
g_error_free(error);
}
else
printf ("Remote call successes with returned value: %s\n", result1? "TRUE" : "FALSE");
gdouble result2;
if (!dbus_g_proxy_call(platformProxy, "GetLatency", &error,
G_TYPE_STRING, "http://www.intel.com/",
G_TYPE_INVALID,
G_TYPE_DOUBLE, &result2,
G_TYPE_INVALID))
{
g_printerr("Failed to call remotely: %s\n",
error->message);
g_error_free(error);
}
else
printf ("Remote call successes with returned value: %6.3f seconds\n", result2);
if (!dbus_g_proxy_call(platformProxy, "GetDataRate", &error,
G_TYPE_STRING, "http://www.intel.com/",
G_TYPE_INVALID,
G_TYPE_DOUBLE, &result2,
G_TYPE_INVALID))
{
g_printerr("Failed to call remotely: %s\n",
error->message);
g_error_free(error);
}
else
printf ("Remote call successes with returned value: %8.2f KB/sec\n", result2);
The back-end implementation of the above three methods shares a common function: this function parses the input URI and then searches for the URI reachability using HTTP protocol. The parsing function validates the URI and retrieves the target IP address. The reachability function forms a HTTP GET message and sends to the target IP address at port 80. The reachability is confirmed if a HTTP reply message is received within a timeout limit. Readers are encouraged to refer to the source code of the MID Platform Awareness project for the implementation. For illustration, only the reachability function is shown below
- collapse sourceview plaincopy to clipboardprint?
1. bool HTTPIsReachable(
2. unsigned int *pTime, // in msec
3. double *pRate, // in KB/sec
4. PURI_INFO pUri)
5. {
6. bool bRet = false;
7. unsigned long StartTime, StopTime;
8. int dwStatusCode;
9. int conn;
10. int Len = 0;
11.
12. if (pTime)
13. *pTime = 0;
14.
15. if ( pUri->Port == 0 )
16. pUri->Port = HTTPPORT;
17.
18. StartTime = getTime();
19. if (pUri->DestPath)
20. conn = (int)socketClient( pUri->pHostIP, pUri->Port, 0);
21.
22. if (conn < 0)
23. {
24. printf("conn<0\n");
25. goto GracefulExit;
26. }
27.
28. char req[1024];
29. sprintf( req, "GET /%s HTTP/1.0\r\nHost: %s\r\n", pUri->FileName, pUri->DestPath);
30. strcat( req, "User-Agent: hget/" LIBHTTP_VERSION "\r\n");
31. strcat( req, "Pragma: no-cache\r\n" );
32. strcat( req, "Accept: */*\r\n\r\n" );
33. dwStatusCode = HttpRequest(conn, &Len, req); // in Bytes
34. close(conn);
35.
36. StopTime = getTime();
37.
38. printf("return code %d\n", dwStatusCode);
39. if ( dwStatusCode == 200 || pUri->FileName == 0 )
40. {
41. bRet = true;
42. if (pTime)
43. {
44. unsigned int st;
45. st = StopTime - StartTime; // in msec
46. *pTime = st;
47. *pRate = (double)Len / (double)st; // in KB/sec
48. }
49. }
50.
51. GracefulExit:
52. return bRet;
53. }
54.
bool HTTPIsReachable(
unsigned int *pTime, // in msec
double *pRate, // in KB/sec
PURI_INFO pUri)
{
bool bRet = false;
unsigned long StartTime, StopTime;
int dwStatusCode;
int conn;
int Len = 0;
if (pTime)
*pTime = 0;
if ( pUri->Port == 0 )
pUri->Port = HTTPPORT;
StartTime = getTime();
if (pUri->DestPath)
conn = (int)socketClient( pUri->pHostIP, pUri->Port, 0);
if (conn < 0)
{
printf("conn<0\n");
goto GracefulExit;
}
char req[1024];
sprintf( req, "GET /%s HTTP/1.0\r\nHost: %s\r\n", pUri->FileName, pUri->DestPath);
strcat( req, "User-Agent: hget/" LIBHTTP_VERSION "\r\n");
strcat( req, "Pragma: no-cache\r\n" );
strcat( req, "Accept: */*\r\n\r\n" );
dwStatusCode = HttpRequest(conn, &Len, req); // in Bytes
close(conn);
StopTime = getTime();
printf("return code %d\n", dwStatusCode);
if ( dwStatusCode == 200 || pUri->FileName == 0 )
{
bRet = true;
if (pTime)
{
unsigned int st;
st = StopTime - StartTime; // in msec
*pTime = st;
*pRate = (double)Len / (double)st; // in KB/sec
}
}
GracefulExit:
return bRet;
}
Detecting the media and speed of the network connection
The last two methods, GetMediaType and GetLinkSpeed, return the network media type and the link speed of the network. In the current implementation, only Ethernet and WiFi are supported. The output of GetMediaType is a string (i.e., "802.03", "802.11g"… etc) and the output of GetLinkSpeed is a value of type double, representing the number of kbps (kilobits per second).
- collapse sourceview plaincopy to clipboardprint?
1. char *result3;
2.
3. if (!dbus_g_proxy_call(platformProxy, "GetMediaType", &error,
4. G_TYPE_INVALID,
5. G_TYPE_STRING, &result3,
6. G_TYPE_INVALID))
7. {
8. g_printerr("Failed to call remotely: %s\n",
9. error->message);
10. g_error_free(error);
11. }
12. else
13. printf ("Remote call successes with returned value: %s\n", result3);
14.
15. double result4;
16.
17. if (!dbus_g_proxy_call(platformProxy, "GetLinkSpeed", &error,
18. G_TYPE_INVALID,
19. G_TYPE_DOUBLE, &result4,
20. G_TYPE_INVALID))
21. {
22. g_printerr("Failed to call remotely: %s\n",
23. error->message);
24. g_error_free(error);
25. }
26. else
27. printf ("Remote call successes with returned value: %10.1f Kbps (kbit per sec)\n", result4);
28.
char *result3;
if (!dbus_g_proxy_call(platformProxy, "GetMediaType", &error,
G_TYPE_INVALID,
G_TYPE_STRING, &result3,
G_TYPE_INVALID))
{
g_printerr("Failed to call remotely: %s\n",
error->message);
g_error_free(error);
}
else
printf ("Remote call successes with returned value: %s\n", result3);
double result4;
if (!dbus_g_proxy_call(platformProxy, "GetLinkSpeed", &error,
G_TYPE_INVALID,
G_TYPE_DOUBLE, &result4,
G_TYPE_INVALID))
{
g_printerr("Failed to call remotely: %s\n",
error->message);
g_error_free(error);
}
else
printf ("Remote call successes with returned value: %10.1f Kbps (kbit per sec)\n", result4);
The back-end implementation of the method GetMediaType is shown below.
- collapse sourceview plaincopy to clipboardprint?
1. char* RetrieveMediaType(void)
2. {
3. netdev_dev netdev_list[MAX_DEVICE];
4. int numInterface = 0;
5.
6. if(netdev_get_devices(netdev_list, &numInterface) == NETDEV_SUCCESS)
7. {
8. int i;
9. netdev_dev *net_devPtr = netdev_list;
10.
11. for (i=0; i= Frequency802_11a1) &&
12. (freq <= Frequency802_11a2) &&
13. (rate <= MaxRate802_11a))
14. return ("802.11a");
15.
16. if ((freq >= Frequency802_11b1) &&
17. (freq <= Frequency802_11b2) &&
18. (rate <= MaxRate802_11b))
19. return ("802.11b");
20.
21. if ((freq >= Frequency802_11g1) &&
22. (freq <= Frequency802_11g2) &&
23. (rate <= MaxRate802_11g))
24. return ("802.11g");
25.
26. return ("Unknown");
27. break;
28. }
29.
30. default:
31. return ("Unknown");
32. break;
33. }
34.
35. }
36.
37. else
38. return ("Unknown");
39.
40. }
41. }
42. net_devPtr++;
43. }
44.
45. }
46.
47. return ("Unknown");
48. }
49.
char* RetrieveMediaType(void)
{
netdev_dev netdev_list[MAX_DEVICE];
int numInterface = 0;
if(netdev_get_devices(netdev_list, &numInterface) == NETDEV_SUCCESS)
{
int i;
netdev_dev *net_devPtr = netdev_list;
for (i=0; i= Frequency802_11a1) &&
(freq <= Frequency802_11a2) &&
(rate <= MaxRate802_11a))
return ("802.11a");
if ((freq >= Frequency802_11b1) &&
(freq <= Frequency802_11b2) &&
(rate <= MaxRate802_11b))
return ("802.11b");
if ((freq >= Frequency802_11g1) &&
(freq <= Frequency802_11g2) &&
(rate <= MaxRate802_11g))
return ("802.11g");
return ("Unknown");
break;
}
default:
return ("Unknown");
break;
}
}
else
return ("Unknown");
}
}
net_devPtr++;
}
}
return ("Unknown");
}
The back-end implementation of the method GetLinkSpeed is shown below.
- collapse sourceview plaincopy to clipboardprint?
1. double RetrieveLinkSpeed(void) // in bps
2. {
3. netdev_dev netdev_list[MAX_DEVICE];
4. int numInterface = 0;
5.
6. if(netdev_get_devices(netdev_list, &numInterface) == NETDEV_SUCCESS)
7. {
8. int i;
9. netdev_dev *net_devPtr = netdev_list;
10.
11. for (i=0; i
double RetrieveLinkSpeed(void) // in bps
{
netdev_dev netdev_list[MAX_DEVICE];
int numInterface = 0;
if(netdev_get_devices(netdev_list, &numInterface) == NETDEV_SUCCESS)
{
int i;
netdev_dev *net_devPtr = netdev_list;
for (i=0; i
Readers are encouraged to refer to the source code of the MID Platform Awareness project for more details.
Monitoring Network Connectivity Change
An application can query the network connectivity information by invoking the methods above. However, instead of constantly invoking the method to query the network connectivity status, sometimes it is more practical that an application just subscribe to network events, or signals. The application will be notified whenever the network connectivity changes status. Two network events are defined: Connected and Disconnected. The Connected event is emitted by the network connectivity service when the network suddenly becomes available. Similarly, the Disconnected event is emitted by the network connectivity service when the network suddenly becomes unavailable. The following code shows how to use D-Bus signals for monitoring network connectivity.
- collapse sourceview plaincopy to clipboardprint?
1. DBusMessage* msg;
2. DBusConnection* conn;
3. DBusError err;
4.
5. printf("Listening for signals\n");
6.
7. // initialise the errors
8. dbus_error_init(&err);
9.
10. // connect to the bus and check for errors
11. conn = dbus_bus_get(DBUS_BUS_SESSION, &err);
12. if (dbus_error_is_set(&err))
13. {
14. fprintf(stderr, "Connection Error (%s)\n", err.message);
15. dbus_error_free(&err);
16. }
17.
18. if (NULL == conn)
19. exit(1);
20.
21. dbus_bus_add_match(conn, "type='signal',interface='org.moblin.Platform.Connection'", &err);
22. dbus_connection_flush(conn);
23.
24. if (dbus_error_is_set(&err))
25. {
26. fprintf(stderr, "Match Error (%s)\n", err.message);
27. exit(1);
28. }
29.
30. printf("Match rule sent\n");
31.
32. // loop listening for signals being emmitted
33. while (true)
34. {
35. // non blocking read of the next available message
36. dbus_connection_read_write(conn, 0);
37. msg = dbus_connection_pop_message(conn);
38.
39. // loop again if we haven't read a message
40. if (NULL == msg)
41. {
42. sleep(1);
43. continue;
44. }
45.
46. if (dbus_message_is_signal(msg, PLATFORM_CONNECTION_IF, CONN_CONNECTED_SIGNAL))
47. printf("Received signal %s\n", CONN_CONNECTED_SIGNAL);
48.
49. if (dbus_message_is_signal(msg, PLATFORM_CONNECTION_IF, CONN_DISCONNECTED_SIGNAL))
50. printf("Received signal %s\n", CONN_DISCONNECTED_SIGNAL);
51.
52. // free the message
53. dbus_message_unref(msg);
54. }
55.
56.
DBusMessage* msg;
DBusConnection* conn;
DBusError err;
printf("Listening for signals\n");
// initialise the errors
dbus_error_init(&err);
// connect to the bus and check for errors
conn = dbus_bus_get(DBUS_BUS_SESSION, &err);
if (dbus_error_is_set(&err))
{
fprintf(stderr, "Connection Error (%s)\n", err.message);
dbus_error_free(&err);
}
if (NULL == conn)
exit(1);
dbus_bus_add_match(conn, "type='signal',interface='org.moblin.Platform.Connection'", &err);
dbus_connection_flush(conn);
if (dbus_error_is_set(&err))
{
fprintf(stderr, "Match Error (%s)\n", err.message);
exit(1);
}
printf("Match rule sent\n");
// loop listening for signals being emmitted
while (true)
{
// non blocking read of the next available message
dbus_connection_read_write(conn, 0);
msg = dbus_connection_pop_message(conn);
// loop again if we haven't read a message
if (NULL == msg)
{
sleep(1);
continue;
}
if (dbus_message_is_signal(msg, PLATFORM_CONNECTION_IF, CONN_CONNECTED_SIGNAL))
printf("Received signal %s\n", CONN_CONNECTED_SIGNAL);
if (dbus_message_is_signal(msg, PLATFORM_CONNECTION_IF, CONN_DISCONNECTED_SIGNAL))
printf("Received signal %s\n", CONN_DISCONNECTED_SIGNAL);
// free the message
dbus_message_unref(msg);
}
Conclusion
D-Bus is a lightweight Remote Procedure Call (RPC) which is suitable for many applications running on a desktop. Because D-Bus is simple and relative small, yet powerful, we can adapt this technology for Mobile Internet Devices (MID). In this paper, we introduced a platform service for MID using D-Bus technology. We briefly described the six connectivity-related methods and two signals provided by the MIDPlatformSvc.
Although this implementation has been tested on the Moblin stack, this technology should also work on a Windows platform as well: therefore, with minimum change, this application should work on other form factors like UMPC, which run Windows* instead.
References
[1] D-Bus, http://www.freedesktop.org/wiki/Software/dbus
[2] D-Bus Tutorial, http://dbus.freedesktop.org/doc/dbus-tutorial.html
[3] http://www.moblin.org/toolkits/basicDevGuides/mobLinux/toolkits_DevGds_mobLinux_createDBUS.php
[4] Mobile and Internet Linux Project, http://moblin.org/
[5] RFC 1945 "Hypertext Transfer Protocol – HTTP/1.0"
The Intel® Mobile Internet Device (MID) platform provides a full internet experience in a pocket-sized form factor. Combining Moblin-based operating systems with the Intel® Atom™ processor, MIDs are able to run any application that has been built for the x86 architecture, including Adobe Flash 10* and Adobe AIR 1.5*. While the features of the devices that are and will be on the market vary depending on OEM and target market, there are several features that the devices share in common; small form factor, emphasis on internet connectivity rather than extensive storage, and alternate input methods.
Although there are ultra-mobile computing devices in the market that run Microsoft Windows XP* or Windows Vista* and that are built on the same hardware platform as those running a Moblin-based operating systems such as Midinux* or Ubuntu* Mobile Edition, this series of whitepapers focuses entirely on Moblin-based MIDs. For information on how to retrieve this information from Windows operating systems, please consult that platform’s documentation, or see the Intel® Mobile Platform SDK.
The functionality described in this paper is also provided via the Platform Awareness Service, a light-weight, D-Bus initiated platform information provider. However, because the final software stack for each device is influenced heavily by the OEM and Service Providers, this service may not be pre-installed on some Moblin-based devices. We have therefore written these whitepapers in order to simplify access to this information on platforms that do not have this service installed.
For further information on how to use D-Bus to retrieve information from the Platform Awareness Service, please refer to the Platform Awareness Service documentation.
Introduction
With the advances of computer networking within the last decade, devices can be connected via a myriad of technologies and protocols, wired and wireless. This connectivity has become so prevalent that many applications can’t function without it. Some application functions take advantage of network communications such as email, network gaming, web browser, etc. Some real-time applications, especialy networking games, require a large bandwidth and high network reliability. These applications must be aware of the network connectivity. Mobile computing devices such as a laptop or Mobile Internet Device (MID), frequently use wireless technology and thus network awareness becomes even more important. Instead of letting each application write its own connectivity awareness code, we propose a uniform way to convey the connectivity information to applications. Laptop/MID applications can then refer to our system to get information on network connectivity and make proper decisions at run time.
As part of a whole project, MID Platform Awareness, this paper shows how we can call connectivity awareness methods and get event notifications.
The system was developed on Moblin[4], a Linux* platform, and uses D-Bus communication[1] to transport information to users [1]. Applications which want to get connectivity information need to use D-Bus as well. In the following sections, we briefly describe D-Bus and how we implement network connectivity awareness service using D-Bus. We show examples of how an application can retrieve the network connectivity information; (1)whether or not the device is connecting to a network, (2)whether or not the device can reach a given website, (3)the latency of the network when the device does connect, (4)the data rate involved when the device reaches a website, (5)the media type of the current network, and (6)the link speed of the network.
Background on D-Bus
D-Bus is a fast, lightweight message system which allows applications to communicate one on one or to broadcast messages to subscribers, (inter-process communication). [2]. D-Bus can be used as low-level API or via a higher level binding, such as Qt, Python*, Java*, C#, or Perl. This paper shows an application written in C using Glib bindings. Glib is the base library of GNOME and provides an object-based, event-driven environment.
Two buses are defined in D-Bus: the system bus and the session bus. The system bus allows communication between an application and the operating system while the session bus is designed to allow communication between two applications.
In order to use D-Bus, we need to understand a few basics. First, an object is an endpoint on the bus that is created by an application in the context of that application’s connection to the bus. Objects have names, and these names are called object paths. We can find an object via its path. A proxy allows clients to reference objects on the bus. Once we find an object, we usually keep a proxy to that object so we can subsequently refer to that object without searching again.
An object can perform specific operations, referred to as methods. Thus, a client can send a request to an object and ask the object to invoke a method. The object then executes the method (if the method exists) and the result is sent back to the client. If a method requires input parameters, these parameters are passed with the request. The result can be one or more output parameters, which are sent back to the client in the reply message. At the D-Bus layer, this method invocation/message passing sequence occurs asynchronously; the glib wrapper for the D-Bus object proxy allows the methods to be called either synchronously or asynchronously.
An object can also emit an event, or signal. When a signal is generated by an object, it is broadcasted to any interested observers. Signals can also carry parameters. Methods and Signals are embedded members of an object that can be grouped into an interface. An object can declare one or many interfaces.
In order to generate dbus-glib binding code, we use a tool called dbus-binding-tool. We first create an XML file, referred to as an Introspection XML file, in which we describe the methods and signals. Defining the interface this way ensures that clients can discover and introspect our D-Bus service. An example of the introspection XML is shown below:
- collapse sourceview plaincopy to clipboardprint?
1.
2. 3. "-//freedesktop//DTD D-Bus Object Introspection 1.0//EN"
4. "http://standards.freedesktop.org/dbus/1.0/introspect.dtd">
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
"-//freedesktop//DTD D-Bus Object Introspection 1.0//EN"
"http://standards.freedesktop.org/dbus/1.0/introspect.dtd">
In this introspection XML file, an interface called org.moblin.Platform.Connection defines six methods:
IsConnected, IsReachable, GetLatency, GetDatRate, GetMediaType and GetLinkSpeed. The annotation XML tags tell dbus-binding-tool what the name of the implementing C function should be. For example, IsConnected is the name of the method that will be visible to users over D-Bus. Internally, we need to implement a C function called isConnected. Method parameters and return values are both specified using the arg XML tag. The direction attribute for a parameter is "in"; for return values, the direction attribute is "out". Note that parameters and return values both have name attributes.
The type attribute of the arg XML tag indicates the data type of the parameter or return value. For example, the value "b" in the IsConnected method return value indicates that the method returns a Boolean. The second method, IsReachable, takes a string parameter representing the target URI (Uniform Resource Identifier) and returns a Boolean value. The next two methods, GetLatency and GetDataRate, also take a string parameter representing the URI and return a double representing seconds and kilobytes per second, respectively. The output of GetMediaType is a string. Finally, the output of the last method, GetLinkSpeed, is a Double data type, representing the number of kilobits per second.
Two signals are defined in the introspection XML file. The signal "Connected" is generated when the system changes state from having no connection to having at least one connection. The "Disconnected" signal is generated when the when the system changes state from having at least one connection to having no connections.
Below are primary steps to implement a D-Bus service. For more details, look here.
* Run dbus-binding-tool for an introspection XML file to generate dbus-glib binding code
* Acquire the D-Bus GObject wrapper
* Implement the instance initialization
* Implement the methods
* Register the object on the D-Bus
To call the methods implemented on a remote object, a client needs to follow the following steps:
* Connect to the bus
* Create a proxy object
* Invoke the methods on the proxy object.
The connectivity awareness service below uses D-Bus as a communication channel to send information to clients regarding network connectivity. Clients can thus use D-Bus to get connectivity information by querying the methods provided by the connectivity service. Client applications can also listen for the signals that the connectivity awareness service generates. The methods and events mentioned in the introspection file are implemented by the connectivity awareness service.
Getting Network Connectivity Information
The connectivity awareness service provides the means to query the following connectivity information on the computer where the service is installed.
Detecting the network connection
A networked application obviously requires an established network connection. Before allocating resources for a network transaction, it is useful to know whether or not the system has an established network connection. Therefore, the network connectivity service provides a method called IsConnected, which returns a Boolean value confirming the status of the network. The network connectivity service checks the status of all network devices on the computer. If at least one network device has an established connection, the Boolean value TRUE is returned. If all network devices on the computer are not running, the Boolean value FALSE is returned. To query the connectivity, the application first must bind to D-Bus service as shown in the following example
- collapse sourceview plaincopy to clipboardprint?
1. #include
2. #include
3. #include
4. #include
5. #include
6. #include
7.
8. #define PLATFORM_SERVICE "org.moblin.Platform"
9. #define PLATFORM_PATH "/org/moblin/Platform"
10. #define PLATFORM_CONNECTION_IF "org.moblin.Platform.Connection"
11.
12. int main(int argc, char** argv)
13. {
14. DBusGConnection* conn;
15. GError *error;
16. DBusGProxy *platformProxy;
17.
18. g_type_init();
19. error = NULL;
20. conn = dbus_g_bus_get(DBUS_BUS_SESSION, &error);
21.
22. // Create the proxy Platform
23. platformProxy = dbus_g_proxy_new_for_name(conn,
24. PLATFORM_SERVICE, // target for the method call
25. PLATFORM_PATH, // object to call on
26. PLATFORM_CONNECTION_IF); // interface to call on
27.
28. gboolean result;
29.
30. if (!dbus_g_proxy_call(platformProxy, "IsConnected", &error,
31. G_TYPE_INVALID,
32. G_TYPE_BOOLEAN, &result,
33. G_TYPE_INVALID))
34. {
35. g_printerr("Failed to call remotely: %s\n",
36. error->message);
37. g_error_free(error);
38. }
39. else
40. printf ("Remote call successes with returned value: %s\n", result? "TRUE" : "FALSE");
41.
42. . . . . . . . . . . . . . . . . . . . . . .
43. . . . . . . . . . . . . . . . . . . . . . .
44. . . . . . . . . . . . . . . . . . . . . . .
45.
46. return 0;
47. }
#include
#include
#include
#include
#include
#include
#define PLATFORM_SERVICE "org.moblin.Platform"
#define PLATFORM_PATH "/org/moblin/Platform"
#define PLATFORM_CONNECTION_IF "org.moblin.Platform.Connection"
int main(int argc, char** argv)
{
DBusGConnection* conn;
GError *error;
DBusGProxy *platformProxy;
g_type_init();
error = NULL;
conn = dbus_g_bus_get(DBUS_BUS_SESSION, &error);
// Create the proxy Platform
platformProxy = dbus_g_proxy_new_for_name(conn,
PLATFORM_SERVICE, // target for the method call
PLATFORM_PATH, // object to call on
PLATFORM_CONNECTION_IF); // interface to call on
gboolean result;
if (!dbus_g_proxy_call(platformProxy, "IsConnected", &error,
G_TYPE_INVALID,
G_TYPE_BOOLEAN, &result,
G_TYPE_INVALID))
{
g_printerr("Failed to call remotely: %s\n",
error->message);
g_error_free(error);
}
else
printf ("Remote call successes with returned value: %s\n", result? "TRUE" : "FALSE");
. . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . .
return 0;
}
Note that the application invokes the method IsConnected implemented in the connectivity awareness service: no input is required, and the method returns TRUE if the computer is connected to a network.
The back-end implementation of this method basically computes the list of network adapters available, and confirms the connection status if there is at least one network adapter running. The function detecting whether or not a network adapter is running, is shown below
- collapse sourceview plaincopy to clipboardprint?
1. netdev_ret netdev_get_running(netdev_dev *dev, // in
2. netdev_running *running) // out
3. {
4. struct ifreq ifr;
5. if(_get_ifreq(dev->ifname, SIOCGIFFLAGS, &ifr) != NETDEV_SUCCESS)
6. {
7. running = RUNNING_UNKNOWN;
8. return NETDEV_ERROR;
9. }
10.
11. short flags = ifr.ifr_flags;
12. if(flags & IFF_RUNNING)
13. {
14. *running = RUNNING_RUN;
15. }
16. else
17. {
18. *running = RUNNING_STOP;
19. }
20.
21. return NETDEV_SUCCESS;
22. }
23.
netdev_ret netdev_get_running(netdev_dev *dev, // in
netdev_running *running) // out
{
struct ifreq ifr;
if(_get_ifreq(dev->ifname, SIOCGIFFLAGS, &ifr) != NETDEV_SUCCESS)
{
running = RUNNING_UNKNOWN;
return NETDEV_ERROR;
}
short flags = ifr.ifr_flags;
if(flags & IFF_RUNNING)
{
*running = RUNNING_RUN;
}
else
{
*running = RUNNING_STOP;
}
return NETDEV_SUCCESS;
}
Detecting HTTP reachability
The second method queries the reachability of a specified website. When getting this request, the connectivity service forms a HTTP GET message[5] and sends it to the specified address (web address) at port 80 (the typical port for HTTP protocol). The socket timeout is set to 3 seconds in this implementation: the service will wait for a HTTP response with status 200[5] before disconnecting the socket. This method, IsReachable, requires a string parameter as the target address (web address) and returns a Boolean value confirming whether or not the web address can be reachable within the socket timeout. The format of the valid entry takes the protocol (http in this case) follows it with the URI. Examples of valid inputs are shown below
"http://www.intel.com/", "http://www.google.com/", "http://www.yahoo.com/", etc ...
The third method, GetLatency, computes the time delay between sending a HTTP GET message and receiving the reply. This method takes an input parameter which is the URI of the website and returns a value of type double, representing the time in seconds. If the socket timeout expires, this method returns a null value.
The fourth method, GetDataRate, calculates the data rate when sending a HTTP GET message and receiving the reply. This method takes an input parameter which is the URI of the website and returns a value of type double representing kilobyte per second (kBps). If the socket timeout expires, this method returns a null value. Data rate is computed using the following formula:
(length of HTTP GET sent + length of HTTP reply) / latency
Code referring to these D-Bus methods is shown below.
- collapse sourceview plaincopy to clipboardprint?
1. int result1;
2.
3. if (!dbus_g_proxy_call(platformProxy, "IsReachable", &error,
4. G_TYPE_STRING, "http://www.intel.com/",
5. G_TYPE_INVALID,
6. G_TYPE_BOOLEAN, &result1,
7. G_TYPE_INVALID))
8. {
9. g_printerr("Failed to call remotely: %s\n",
10. error->message);
11. g_error_free(error);
12. }
13. else
14. printf ("Remote call successes with returned value: %s\n", result1? "TRUE" : "FALSE");
15.
16. gdouble result2;
17.
18. if (!dbus_g_proxy_call(platformProxy, "GetLatency", &error,
19. G_TYPE_STRING, "http://www.intel.com/",
20. G_TYPE_INVALID,
21. G_TYPE_DOUBLE, &result2,
22. G_TYPE_INVALID))
23. {
24. g_printerr("Failed to call remotely: %s\n",
25. error->message);
26. g_error_free(error);
27. }
28. else
29. printf ("Remote call successes with returned value: %6.3f seconds\n", result2);
30.
31.
32. if (!dbus_g_proxy_call(platformProxy, "GetDataRate", &error,
33. G_TYPE_STRING, "http://www.intel.com/",
34. G_TYPE_INVALID,
35. G_TYPE_DOUBLE, &result2,
36. G_TYPE_INVALID))
37. {
38. g_printerr("Failed to call remotely: %s\n",
39. error->message);
40. g_error_free(error);
41. }
42. else
43. printf ("Remote call successes with returned value: %8.2f KB/sec\n", result2);
int result1;
if (!dbus_g_proxy_call(platformProxy, "IsReachable", &error,
G_TYPE_STRING, "http://www.intel.com/",
G_TYPE_INVALID,
G_TYPE_BOOLEAN, &result1,
G_TYPE_INVALID))
{
g_printerr("Failed to call remotely: %s\n",
error->message);
g_error_free(error);
}
else
printf ("Remote call successes with returned value: %s\n", result1? "TRUE" : "FALSE");
gdouble result2;
if (!dbus_g_proxy_call(platformProxy, "GetLatency", &error,
G_TYPE_STRING, "http://www.intel.com/",
G_TYPE_INVALID,
G_TYPE_DOUBLE, &result2,
G_TYPE_INVALID))
{
g_printerr("Failed to call remotely: %s\n",
error->message);
g_error_free(error);
}
else
printf ("Remote call successes with returned value: %6.3f seconds\n", result2);
if (!dbus_g_proxy_call(platformProxy, "GetDataRate", &error,
G_TYPE_STRING, "http://www.intel.com/",
G_TYPE_INVALID,
G_TYPE_DOUBLE, &result2,
G_TYPE_INVALID))
{
g_printerr("Failed to call remotely: %s\n",
error->message);
g_error_free(error);
}
else
printf ("Remote call successes with returned value: %8.2f KB/sec\n", result2);
The back-end implementation of the above three methods shares a common function: this function parses the input URI and then searches for the URI reachability using HTTP protocol. The parsing function validates the URI and retrieves the target IP address. The reachability function forms a HTTP GET message and sends to the target IP address at port 80. The reachability is confirmed if a HTTP reply message is received within a timeout limit. Readers are encouraged to refer to the source code of the MID Platform Awareness project for the implementation. For illustration, only the reachability function is shown below
- collapse sourceview plaincopy to clipboardprint?
1. bool HTTPIsReachable(
2. unsigned int *pTime, // in msec
3. double *pRate, // in KB/sec
4. PURI_INFO pUri)
5. {
6. bool bRet = false;
7. unsigned long StartTime, StopTime;
8. int dwStatusCode;
9. int conn;
10. int Len = 0;
11.
12. if (pTime)
13. *pTime = 0;
14.
15. if ( pUri->Port == 0 )
16. pUri->Port = HTTPPORT;
17.
18. StartTime = getTime();
19. if (pUri->DestPath)
20. conn = (int)socketClient( pUri->pHostIP, pUri->Port, 0);
21.
22. if (conn < 0)
23. {
24. printf("conn<0\n");
25. goto GracefulExit;
26. }
27.
28. char req[1024];
29. sprintf( req, "GET /%s HTTP/1.0\r\nHost: %s\r\n", pUri->FileName, pUri->DestPath);
30. strcat( req, "User-Agent: hget/" LIBHTTP_VERSION "\r\n");
31. strcat( req, "Pragma: no-cache\r\n" );
32. strcat( req, "Accept: */*\r\n\r\n" );
33. dwStatusCode = HttpRequest(conn, &Len, req); // in Bytes
34. close(conn);
35.
36. StopTime = getTime();
37.
38. printf("return code %d\n", dwStatusCode);
39. if ( dwStatusCode == 200 || pUri->FileName == 0 )
40. {
41. bRet = true;
42. if (pTime)
43. {
44. unsigned int st;
45. st = StopTime - StartTime; // in msec
46. *pTime = st;
47. *pRate = (double)Len / (double)st; // in KB/sec
48. }
49. }
50.
51. GracefulExit:
52. return bRet;
53. }
54.
bool HTTPIsReachable(
unsigned int *pTime, // in msec
double *pRate, // in KB/sec
PURI_INFO pUri)
{
bool bRet = false;
unsigned long StartTime, StopTime;
int dwStatusCode;
int conn;
int Len = 0;
if (pTime)
*pTime = 0;
if ( pUri->Port == 0 )
pUri->Port = HTTPPORT;
StartTime = getTime();
if (pUri->DestPath)
conn = (int)socketClient( pUri->pHostIP, pUri->Port, 0);
if (conn < 0)
{
printf("conn<0\n");
goto GracefulExit;
}
char req[1024];
sprintf( req, "GET /%s HTTP/1.0\r\nHost: %s\r\n", pUri->FileName, pUri->DestPath);
strcat( req, "User-Agent: hget/" LIBHTTP_VERSION "\r\n");
strcat( req, "Pragma: no-cache\r\n" );
strcat( req, "Accept: */*\r\n\r\n" );
dwStatusCode = HttpRequest(conn, &Len, req); // in Bytes
close(conn);
StopTime = getTime();
printf("return code %d\n", dwStatusCode);
if ( dwStatusCode == 200 || pUri->FileName == 0 )
{
bRet = true;
if (pTime)
{
unsigned int st;
st = StopTime - StartTime; // in msec
*pTime = st;
*pRate = (double)Len / (double)st; // in KB/sec
}
}
GracefulExit:
return bRet;
}
Detecting the media and speed of the network connection
The last two methods, GetMediaType and GetLinkSpeed, return the network media type and the link speed of the network. In the current implementation, only Ethernet and WiFi are supported. The output of GetMediaType is a string (i.e., "802.03", "802.11g"… etc) and the output of GetLinkSpeed is a value of type double, representing the number of kbps (kilobits per second).
- collapse sourceview plaincopy to clipboardprint?
1. char *result3;
2.
3. if (!dbus_g_proxy_call(platformProxy, "GetMediaType", &error,
4. G_TYPE_INVALID,
5. G_TYPE_STRING, &result3,
6. G_TYPE_INVALID))
7. {
8. g_printerr("Failed to call remotely: %s\n",
9. error->message);
10. g_error_free(error);
11. }
12. else
13. printf ("Remote call successes with returned value: %s\n", result3);
14.
15. double result4;
16.
17. if (!dbus_g_proxy_call(platformProxy, "GetLinkSpeed", &error,
18. G_TYPE_INVALID,
19. G_TYPE_DOUBLE, &result4,
20. G_TYPE_INVALID))
21. {
22. g_printerr("Failed to call remotely: %s\n",
23. error->message);
24. g_error_free(error);
25. }
26. else
27. printf ("Remote call successes with returned value: %10.1f Kbps (kbit per sec)\n", result4);
28.
char *result3;
if (!dbus_g_proxy_call(platformProxy, "GetMediaType", &error,
G_TYPE_INVALID,
G_TYPE_STRING, &result3,
G_TYPE_INVALID))
{
g_printerr("Failed to call remotely: %s\n",
error->message);
g_error_free(error);
}
else
printf ("Remote call successes with returned value: %s\n", result3);
double result4;
if (!dbus_g_proxy_call(platformProxy, "GetLinkSpeed", &error,
G_TYPE_INVALID,
G_TYPE_DOUBLE, &result4,
G_TYPE_INVALID))
{
g_printerr("Failed to call remotely: %s\n",
error->message);
g_error_free(error);
}
else
printf ("Remote call successes with returned value: %10.1f Kbps (kbit per sec)\n", result4);
The back-end implementation of the method GetMediaType is shown below.
- collapse sourceview plaincopy to clipboardprint?
1. char* RetrieveMediaType(void)
2. {
3. netdev_dev netdev_list[MAX_DEVICE];
4. int numInterface = 0;
5.
6. if(netdev_get_devices(netdev_list, &numInterface) == NETDEV_SUCCESS)
7. {
8. int i;
9. netdev_dev *net_devPtr = netdev_list;
10.
11. for (i=0; i= Frequency802_11a1) &&
12. (freq <= Frequency802_11a2) &&
13. (rate <= MaxRate802_11a))
14. return ("802.11a");
15.
16. if ((freq >= Frequency802_11b1) &&
17. (freq <= Frequency802_11b2) &&
18. (rate <= MaxRate802_11b))
19. return ("802.11b");
20.
21. if ((freq >= Frequency802_11g1) &&
22. (freq <= Frequency802_11g2) &&
23. (rate <= MaxRate802_11g))
24. return ("802.11g");
25.
26. return ("Unknown");
27. break;
28. }
29.
30. default:
31. return ("Unknown");
32. break;
33. }
34.
35. }
36.
37. else
38. return ("Unknown");
39.
40. }
41. }
42. net_devPtr++;
43. }
44.
45. }
46.
47. return ("Unknown");
48. }
49.
char* RetrieveMediaType(void)
{
netdev_dev netdev_list[MAX_DEVICE];
int numInterface = 0;
if(netdev_get_devices(netdev_list, &numInterface) == NETDEV_SUCCESS)
{
int i;
netdev_dev *net_devPtr = netdev_list;
for (i=0; i= Frequency802_11a1) &&
(freq <= Frequency802_11a2) &&
(rate <= MaxRate802_11a))
return ("802.11a");
if ((freq >= Frequency802_11b1) &&
(freq <= Frequency802_11b2) &&
(rate <= MaxRate802_11b))
return ("802.11b");
if ((freq >= Frequency802_11g1) &&
(freq <= Frequency802_11g2) &&
(rate <= MaxRate802_11g))
return ("802.11g");
return ("Unknown");
break;
}
default:
return ("Unknown");
break;
}
}
else
return ("Unknown");
}
}
net_devPtr++;
}
}
return ("Unknown");
}
The back-end implementation of the method GetLinkSpeed is shown below.
- collapse sourceview plaincopy to clipboardprint?
1. double RetrieveLinkSpeed(void) // in bps
2. {
3. netdev_dev netdev_list[MAX_DEVICE];
4. int numInterface = 0;
5.
6. if(netdev_get_devices(netdev_list, &numInterface) == NETDEV_SUCCESS)
7. {
8. int i;
9. netdev_dev *net_devPtr = netdev_list;
10.
11. for (i=0; i
double RetrieveLinkSpeed(void) // in bps
{
netdev_dev netdev_list[MAX_DEVICE];
int numInterface = 0;
if(netdev_get_devices(netdev_list, &numInterface) == NETDEV_SUCCESS)
{
int i;
netdev_dev *net_devPtr = netdev_list;
for (i=0; i
Readers are encouraged to refer to the source code of the MID Platform Awareness project for more details.
Monitoring Network Connectivity Change
An application can query the network connectivity information by invoking the methods above. However, instead of constantly invoking the method to query the network connectivity status, sometimes it is more practical that an application just subscribe to network events, or signals. The application will be notified whenever the network connectivity changes status. Two network events are defined: Connected and Disconnected. The Connected event is emitted by the network connectivity service when the network suddenly becomes available. Similarly, the Disconnected event is emitted by the network connectivity service when the network suddenly becomes unavailable. The following code shows how to use D-Bus signals for monitoring network connectivity.
- collapse sourceview plaincopy to clipboardprint?
1. DBusMessage* msg;
2. DBusConnection* conn;
3. DBusError err;
4.
5. printf("Listening for signals\n");
6.
7. // initialise the errors
8. dbus_error_init(&err);
9.
10. // connect to the bus and check for errors
11. conn = dbus_bus_get(DBUS_BUS_SESSION, &err);
12. if (dbus_error_is_set(&err))
13. {
14. fprintf(stderr, "Connection Error (%s)\n", err.message);
15. dbus_error_free(&err);
16. }
17.
18. if (NULL == conn)
19. exit(1);
20.
21. dbus_bus_add_match(conn, "type='signal',interface='org.moblin.Platform.Connection'", &err);
22. dbus_connection_flush(conn);
23.
24. if (dbus_error_is_set(&err))
25. {
26. fprintf(stderr, "Match Error (%s)\n", err.message);
27. exit(1);
28. }
29.
30. printf("Match rule sent\n");
31.
32. // loop listening for signals being emmitted
33. while (true)
34. {
35. // non blocking read of the next available message
36. dbus_connection_read_write(conn, 0);
37. msg = dbus_connection_pop_message(conn);
38.
39. // loop again if we haven't read a message
40. if (NULL == msg)
41. {
42. sleep(1);
43. continue;
44. }
45.
46. if (dbus_message_is_signal(msg, PLATFORM_CONNECTION_IF, CONN_CONNECTED_SIGNAL))
47. printf("Received signal %s\n", CONN_CONNECTED_SIGNAL);
48.
49. if (dbus_message_is_signal(msg, PLATFORM_CONNECTION_IF, CONN_DISCONNECTED_SIGNAL))
50. printf("Received signal %s\n", CONN_DISCONNECTED_SIGNAL);
51.
52. // free the message
53. dbus_message_unref(msg);
54. }
55.
56.
DBusMessage* msg;
DBusConnection* conn;
DBusError err;
printf("Listening for signals\n");
// initialise the errors
dbus_error_init(&err);
// connect to the bus and check for errors
conn = dbus_bus_get(DBUS_BUS_SESSION, &err);
if (dbus_error_is_set(&err))
{
fprintf(stderr, "Connection Error (%s)\n", err.message);
dbus_error_free(&err);
}
if (NULL == conn)
exit(1);
dbus_bus_add_match(conn, "type='signal',interface='org.moblin.Platform.Connection'", &err);
dbus_connection_flush(conn);
if (dbus_error_is_set(&err))
{
fprintf(stderr, "Match Error (%s)\n", err.message);
exit(1);
}
printf("Match rule sent\n");
// loop listening for signals being emmitted
while (true)
{
// non blocking read of the next available message
dbus_connection_read_write(conn, 0);
msg = dbus_connection_pop_message(conn);
// loop again if we haven't read a message
if (NULL == msg)
{
sleep(1);
continue;
}
if (dbus_message_is_signal(msg, PLATFORM_CONNECTION_IF, CONN_CONNECTED_SIGNAL))
printf("Received signal %s\n", CONN_CONNECTED_SIGNAL);
if (dbus_message_is_signal(msg, PLATFORM_CONNECTION_IF, CONN_DISCONNECTED_SIGNAL))
printf("Received signal %s\n", CONN_DISCONNECTED_SIGNAL);
// free the message
dbus_message_unref(msg);
}
Conclusion
D-Bus is a lightweight Remote Procedure Call (RPC) which is suitable for many applications running on a desktop. Because D-Bus is simple and relative small, yet powerful, we can adapt this technology for Mobile Internet Devices (MID). In this paper, we introduced a platform service for MID using D-Bus technology. We briefly described the six connectivity-related methods and two signals provided by the MIDPlatformSvc.
Although this implementation has been tested on the Moblin stack, this technology should also work on a Windows platform as well: therefore, with minimum change, this application should work on other form factors like UMPC, which run Windows* instead.
References
[1] D-Bus, http://www.freedesktop.org/wiki/Software/dbus
[2] D-Bus Tutorial, http://dbus.freedesktop.org/doc/dbus-tutorial.html
[3] http://www.moblin.org/toolkits/basicDevGuides/mobLinux/toolkits_DevGds_mobLinux_createDBUS.php
[4] Mobile and Internet Linux Project, http://moblin.org/
[5] RFC 1945 "Hypertext Transfer Protocol – HTTP/1.0"
Convergence 09: Developing Power Aware Application using D-Bus
Introduction
Computer power consumption has become a passionate subject; hardware engineers trying to minimize the power consumed by devices, and software engineers trying to optimize their code to reduce the power consumed by their applications. Power is an even more important issue with Mobile Internet Devices (MIDs) since the small form factor limits the size of the battery. Applications running on MID's must therefore be very sensitive to power, and use power information to make smart decisions. For example, before beginning a lengthy transaction (such as downloading a video, or running an update), an application should check to see if the device is running on external power, and if not, determine whether or not there is sufficient power remaining to complete the transaction.
Background on D-Bus
D-Bus is a fast, lightweight message bus system which allows applications to communicate each other (Inter-process communication) [2]. It has a so-called D-Bus message bus (dbus deamon) which can accept messages from multiples applications and forward messages to them. D-Bus can be used as low-level API or higher level binding, such as Qt, Python*, Java*, C#, or Perl. This paper shows an application written in C using Glib bindings. Glib is the base library of GNOME, it provides an object system, object-based and event-driven programming.Two buses are defined in D-Bus: system bus and session bus. The system bus allows communication between an application and the operating system while the session bus is designed to serve the communication between two applications.
In order to use D-Bus, we need to explore some concepts about D-Bus. First, an object is an endpoint on the bus, an object is created by an application in the context that the application's connection to the bus (either system bus or session bus). Objects have names, and these names are called object paths. A proxy is an object on the bus that can be accessed through references. We can find an object by searching the bus name and the object living in that bus connection. Once we find it, we usually keep a proxy to that object so we can refer to that object again without searching again.
An object can perform some specific operations. Each operation is referred as method. Thus, a client can send a request to an object and ask the object to invoke a method. The object then executes the method (if the method exists) and the result is sent back to the client. If a method requires input parameters, these parameters have to be passed with the request. The result can be one or more output parameters, these parameters are sent back to the client in the reply message.
An object can also emit an event, or signal. When a signal is generated by an object, it will be broadcasted to any observers who are interested in that particular signal. Signals can carry parameters too. Methods and Signals are embedded members of an object. They can be grouped. An Interface of an object is just a group of its members. An object can declare one or many interfaces - its members are then classified in these interfaces.
Instead of forming a D-Bus method call message and sending to the remote object using Glib bindings, one can instantiate a proxy object representing the remote object and then just invoke the methods of that object.
In order to generate dbus-glib binding code, we can use a tool called dbus-binding-tool. We first create an XML file, referred as Introspection XML file, in which we describe the methods and signals. An example of the introspection XML is shown below:
- "1.0" encoding="UTF-8" ?>
-
- "-//freedesktop//DTD D-Bus Object Introspection 1.0//EN"
- "http://standards.freedesktop.org/dbus/1.0/introspect.dtd">
"/org/moblin/Platform" >-
"org.moblin.Platform.Power" > -
"org.freedesktop.DBus.GLib.CSymbol" value="org_moblin_platform_power"/> -
"IsUsingExternalPowerSource" > -
"org.freedesktop.DBus.GLib.CSymbol" value="isUsingExternalPowerSource" /> -
"b" name="usingExternalPowerSource" direction="out" /> -
-
"GetTimeRemaining" > -
"org.freedesktop.DBus.GLib.CSymbol" value="getTimeRemaining"/> -
"i" name="minutesRemaining" direction="out" /> -
-
"GetPercentRemaining" > -
"org.freedesktop.DBus.GLib.CSymbol" value="getPercentRemaining"/> -
"u" name="percentRemaining" direction="out" /> -
-
-
In this introspection XML file (named MIDPlatformSvcInterfaceDefinition.xml), an interface called org.moblin.Platform.Power defines three methods: IsUsingExternalPowerSource, GetTimeRemaining and GetPerCentRemaining. The output of the first method is a Boolean value. The output of the second method is an integer value representing the value in minutes, while the output of the third method is an unsigned integer value representing the percentage.
Below are primary steps to implement a service with methods to be exposed. More details are explained in [3].
- Run dbus-binding-tool for an introspection XML file to generate dbus-glib binding code
- Create a simple GObject for D-Bus
- Implement the instance initialization
- Implement the methods
- Register the object to the D-Bus
- Connect to the bus
- Create a proxy object
- Invoke the methods on the proxy object
Using D-Bus as a Communication Channel
We designed the power service application which uses D-Bus as a communication channel to send information on battery. Other applications which are interested in power awareness can use D-Bus to get power information by querying the methods that the power service provided. These applications can also listen for the events that the power service generated. Figure 1 illustrates the usage model:
Figure 1. Usage Model: A Client Registers to D-Bus to Get the Information Provided by the MISPlatformSvc
Gathering Battery Information
We will present the implementation of three methods that are part of a simple library that provides battery information. The first method queries the percent of battery power remaining (getPercentRemaining). This method returns the percent of power currently available in the battery.
The second method queries the time remaining until the MID runs out of battery power (getTimeRemaining). This method returns the remaining time in minutes.
The third method queries whether or not the MID is using an external power source (IsUsingExternalPowerSource). This method returns a Boolean: TRUE means the MID is currently using an external power source (e.g., AC), FALSE means that the MID is using its battery (DC).
The first method calculates the percent of battery power remaining in a MID. In Linux, the file /proc/acpi/ contains power-related information. In particular, the file /proc/acpi/battery/BAT1/state contains the current remaining capacity in the field "remaining capacity". The file /proc/acpi/battery/BAT1/info contains the maximum capacity information in the "last full capacity" field. From these entries, we can deduce the percent of power remaining as shown below:
- gboolean computePercentPowerRemaining(guint *result)
- {
- DIR *d;
- struct dirent *de;
- char *acpi_path = "/proc/acpi";
- char *device_type = "battery";
- char *stateFile = "state";
- char *infoFile = "info";
- FILE *file;
- char filename[PATH_LENGTH];
- char line[LINE_LENGTH];
- *result = 0;
- double power_left = 0.0;
- double power_full = 0.0;
- gboolean rc = FALSE;
-
- // First, check if the ACPI path exists
- if (chdir(acpi_path) <>
- {
- dbg("ACPI is not supported (\"%s\").\n", acpi_path);
- return rc;
- }
- else
- dbg("Path %s is found \n", acpi_path);
-
- // Check if battery directory exists
- if (chdir(device_type) <>
- {
- dbg("No support for device type: %s\n", device_type);
- return rc;
- }
- else
- dbg("Device %s is supported \n", device_type);
-
- // /proc/acpi/battery is found. Now search for available batteries
- d = opendir(".");
- if (!d) {
- dbg("Cannot open directory!\n");
- return rc;
- }
-
- while ((de = readdir(d))) {
- // Search for real directory ("BAT0", ...), not ".", ".."
- if (!strcmp(de->d_name, "."))
- continue;
-
- if (!strcmp(de->d_name, ".."))
- continue;
-
- dbg("device found: %s\n", de->d_name);
-
- // Open file "state".
- sprintf(filename, "%s/%s/%s/%s", acpi_path, device_type, de->d_name, stateFile);
- file = fopen(filename, "r");
- if (!file)
- {
- closedir(d);
- return rc;
- }
-
- memset(line, 0, LINE_LENGTH);
- while (fgets(line, LINE_LENGTH, file) != NULL) {
- if (strstr(line, "remaining capacity:") &&
- (strstr(line, "mWh") || strstr(line, "mAh")))
- {
- // Search the value
- char *c;
-
- c = strchr(line, ':');
- c++;
-
- power_left = strtoull(c, NULL, 10); // in mWh or mAh
-
- // Cannot perform conversion
- if ((0 == power_left) && (EINVAL == errno))
- {
- closedir(d);
- return rc;
- }
- break;
- }
- }
-
- fclose(file);
-
- // Open file "info".
- sprintf(filename, "%s/%s/%s/%s", acpi_path, device_type, de->d_name, infoFile);
- file = fopen(filename, "r");
- if (!file)
- {
- closedir(d);
- return rc;
- }
-
- memset(line, 0, LINE_LENGTH);
- while (fgets(line, LINE_LENGTH, file) != NULL) {
- if (strstr(line, "last full capacity:") &&
- (strstr(line, "mWh") || strstr(line, "mAh")))
- {
- // Search the value
- char *c;
-
- c = strchr(line, ':');
- c++;
-
- power_full = strtoull(c, NULL, 10); // in mWh or mAh
-
- // Cannot perform conversion
- if (0 == power_full)
- {
- closedir(d);
- return rc;
- }
-
- *result = (power_left/power_full)*100; // in %
- break;
- }
- }
-
- rc = TRUE;
- fclose(file);
-
- // Exit while loop
- break;
- }
- closedir(d);
-
- return rc;
- }
gboolean computePercentPowerRemaining(guint *result) { DIR *d; struct dirent *de; char *acpi_path = "/proc/acpi"; char *device_type = "battery"; char *stateFile = "state"; char *infoFile = "info"; FILE *file; char filename[PATH_LENGTH]; char line[LINE_LENGTH]; *result = 0; double power_left = 0.0; double power_full = 0.0; gboolean rc = FALSE; // First, check if the ACPI path exists if (chdir(acpi_path) < d =" opendir(" de =" readdir(d)))">d_name, ".")) continue; if (!strcmp(de->d_name, "..")) continue; dbg("device found: %s\n", de->d_name); // Open file "state". sprintf(filename, "%s/%s/%s/%s", acpi_path, device_type, de->d_name, stateFile); file = fopen(filename, "r"); if (!file) { closedir(d); return rc; } memset(line, 0, LINE_LENGTH); while (fgets(line, LINE_LENGTH, file) != NULL) { if (strstr(line, "remaining capacity:") && (strstr(line, "mWh") || strstr(line, "mAh"))) { // Search the value char *c; c = strchr(line, ':'); c++; power_left = strtoull(c, NULL, 10); // in mWh or mAh // Cannot perform conversion if ((0 == power_left) && (EINVAL == errno)) { closedir(d); return rc; } break; } } fclose(file); // Open file "info". sprintf(filename, "%s/%s/%s/%s", acpi_path, device_type, de->d_name, infoFile); file = fopen(filename, "r"); if (!file) { closedir(d); return rc; } memset(line, 0, LINE_LENGTH); while (fgets(line, LINE_LENGTH, file) != NULL) { if (strstr(line, "last full capacity:") && (strstr(line, "mWh") || strstr(line, "mAh"))) { // Search the value char *c; c = strchr(line, ':'); c++; power_full = strtoull(c, NULL, 10); // in mWh or mAh // Cannot perform conversion if (0 == power_full) { closedir(d); return rc; } *result = (power_left/power_full)*100; // in % break; } } rc = TRUE; fclose(file); // Exit while loop break; } closedir(d); return rc; }
The second method queries the time remaining until the MID is out battery power (getTimeRemaining). This method returns the remaining time in minutes. As mentioned above, the file /proc/acpi/battery/BAT1/state contains the current remaining capacity in the "remaining capacity" field. The "present rate" field in the same file contains the rate at which the battery capacity is changing. This field is significant only if the battery is discharging. From this information, we can deduce the remaining time in minutes as shown below:
- int computeTimeRemaining(void)
- {
- DIR *d;
- struct dirent *de;
-
- char *acpi_path = "/proc/acpi";
- char *device_type = "battery";
- char *stateFile = "state";
-
- FILE *file;
- char filename[PATH_LENGTH];
- char line[LINE_LENGTH];
- int result = -1;
- double power_left = 0.0;
- double power_full = 0.0;
- double dischargeRate = 0.0;
- int find = 0;
-
- // First, check if the ACPI path exists
- if (chdir(acpi_path) <>
- {
- dbg("ACPI is not supported (\"%s\").\n", acpi_path);
- return result;
- }
- else
- dbg("Path %s is found \n", acpi_path);
-
- // Check if battery directory exists
- if (chdir(device_type) <>
- {
- dbg("No support for device type: %s\n", device_type);
- return result;
- }
- else
- dbg("Device %s is supported \n", device_type);
-
- // /proc/acpi/battery is found. Now search for available batteries
- d = opendir(".");
- if (!d) {
- dbg("Cannot open directory!\n");
- return result;
- }
-
- while ((de = readdir(d))) {
- // Search for real directory ("BAT0", ...), not ".", ".."
- if (!strcmp(de->d_name, "."))
- continue;
-
- if (!strcmp(de->d_name, ".."))
- continue;
-
- dbg("device found: %s\n", de->d_name);
-
- // Open file "state".
- sprintf(filename, "%s/%s/%s/%s", acpi_path, device_type, de->d_name, stateFile);
- file = fopen(filename, "r");
- if (!file)
- {
- closedir(d);
- return result;
- }
-
- memset(line, 0, LINE_LENGTH);
-
- while (fgets(line, LINE_LENGTH, file) != NULL) {
- if (strstr(line, "charging state:") &&
- strstr(line, "discharging"))
- {
- find++;
- }
-
- if (strstr(line, "present rate:") &&
- (strstr(line, "mW") || strstr(line, "mA")))
- {
- // Search the value
- char *c;
-
- c = strchr(line, ':');
- c++;
-
- dischargeRate = strtoull(c, NULL, 10); // in mW or mA
-
- // Cannot perform conversion
- if ((0 == dischargeRate) && (EINVAL == errno))
- {
- closedir(d);
- return result;
- }
-
- find++;
- }
-
- if (strstr(line, "remaining capacity:") &&
- (strstr(line, "mWh") || strstr(line, "mAh")))
- {
- // Search the value
- char *c;
-
- c = strchr(line, ':');
- c++;
-
- power_left = strtoull(c, NULL, 10); // in mWh or mAh
-
- // Cannot perform conversion
- if ((0 == power_left) && (EINVAL == errno))
- {
- closedir(d);
- return result;
- }
-
- find++;
- }
-
-
- }
-
- fclose(file);
-
- // Exit while loop
- break;
- }
- closedir(d);
-
- if (find == 3)
- {
- result = 0;
-
- if (dischargeRate > 0)
- result = (power_left/dischargeRate)*60; // convert to minutes
- }
-
- return result;
- }
int computeTimeRemaining(void) { DIR *d; struct dirent *de; char *acpi_path = "/proc/acpi"; char *device_type = "battery"; char *stateFile = "state"; FILE *file; char filename[PATH_LENGTH]; char line[LINE_LENGTH]; int result = -1; double power_left = 0.0; double power_full = 0.0; double dischargeRate = 0.0; int find = 0; // First, check if the ACPI path exists if (chdir(acpi_path) < d =" opendir(" de =" readdir(d)))">d_name, ".")) continue; if (!strcmp(de->d_name, "..")) continue; dbg("device found: %s\n", de->d_name); // Open file "state". sprintf(filename, "%s/%s/%s/%s", acpi_path, device_type, de->d_name, stateFile); file = fopen(filename, "r"); if (!file) { closedir(d); return result; } memset(line, 0, LINE_LENGTH); while (fgets(line, LINE_LENGTH, file) != NULL) { if (strstr(line, "charging state:") && strstr(line, "discharging")) { find++; } if (strstr(line, "present rate:") && (strstr(line, "mW") || strstr(line, "mA"))) { // Search the value char *c; c = strchr(line, ':'); c++; dischargeRate = strtoull(c, NULL, 10); // in mW or mA // Cannot perform conversion if ((0 == dischargeRate) && (EINVAL == errno)) { closedir(d); return result; } find++; } if (strstr(line, "remaining capacity:") && (strstr(line, "mWh") || strstr(line, "mAh"))) { // Search the value char *c; c = strchr(line, ':'); c++; power_left = strtoull(c, NULL, 10); // in mWh or mAh // Cannot perform conversion if ((0 == power_left) && (EINVAL == errno)) { closedir(d); return result; } find++; } } fclose(file); // Exit while loop break; } closedir(d); if (find == 3) { result = 0; if (dischargeRate > 0) result = (power_left/dischargeRate)*60; // convert to minutes } return result; }
The third method queries whether or not the MID is using an external power source. The information in the file /proc/acpi/ac_adaptor/ACAD/state shows the status of the battery. Below shows the implementation.
- int computePowerSource()
- {
- DIR *d;
- struct dirent *de;
- char *acadaptor_path = "/proc/acpi/ac_adapter";
- char *stateFile = "state";
- FILE *file;
- int result = -1;
- char filename[PATH_LENGTH];
-
- // First, check if the ac_adaptor path exists
- if (chdir(acadaptor_path) <>
- {
- return result;
- }
-
- // /proc/acpi/ac_adaptor is found. Now search for available entry
- d = opendir(".");
- if (!d) {
- return result;
- }
-
- while ((de = readdir(d))) {
- char line[LINE_LENGTH];
- // Search for real directory (not ".", ".."
- if (!strcmp(de->d_name, "."))
- continue;
-
- if (!strcmp(de->d_name, ".."))
- continue;
-
- sprintf(filename, "%s/%s/%s", acadaptor_path, de->d_name, stateFile);
- file = fopen(filename, "r");
- if (!file)
- {
- closedir(d);
- return result;
- }
-
- memset(line, 0, LINE_LENGTH);
- while (fgets(line, LINE_LENGTH, file) != NULL) {
- if (strstr(line, "state:") && strstr(line, "off-line"))
- result = 0; // AC (battery)
- else if (strstr(line, "state:") && strstr(line, "on-line"))
- result = 1; // DC
- }
-
- fclose(file);
- }
-
- closedir(d);
-
- return result;
- }
int computePowerSource() { DIR *d; struct dirent *de; char *acadaptor_path = "/proc/acpi/ac_adapter"; char *stateFile = "state"; FILE *file; int result = -1; char filename[PATH_LENGTH]; // First, check if the ac_adaptor path exists if (chdir(acadaptor_path) < d =" opendir(" de =" readdir(d)))">d_name, ".")) continue; if (!strcmp(de->d_name, "..")) continue; sprintf(filename, "%s/%s/%s", acadaptor_path, de->d_name, stateFile); file = fopen(filename, "r"); if (!file) { closedir(d); return result; } memset(line, 0, LINE_LENGTH); while (fgets(line, LINE_LENGTH, file) != NULL) { if (strstr(line, "state:") && strstr(line, "off-line")) result = 0; // AC (battery) else if (strstr(line, "state:") && strstr(line, "on-line")) result = 1; // DC } fclose(file); } closedir(d); return result; }
Putting Things Together
First, the introspection XML in previous section clearly defined the three methods for battery. We can now generate a D-Bus binding header file using the D-Bus binding tool.
- % dbus-binding-tool --mode=glib-server -–prefix=MIDPlatformSvc --output=MIDPlatformSvc-dbus-glue.h MIDPlatformSvcInterfaceDefinition.xml
% dbus-binding-tool --mode=glib-server -–prefix=MIDPlatformSvc --output=MIDPlatformSvc-dbus-glue.h MIDPlatformSvcInterfaceDefinition.xml
Then, we create a platform service object by following standard steps in [3]. We don't show it here since it is straightforward. In the final step, we just glue the three methods above to the implementation.
Each interface method has three parameters: the called object, the return value, and the error. Inside the interface method we glue the return value to its implementation.
- gboolean getPercentRemaining(MIDPlatformSvc *obj, guint *percentRemaining, GError **error)
- {
- gboolean rc = FALSE;
-
- rc = computePercentPowerRemaining(percentRemaining);
-
- if (rc)
- return TRUE;
- else
- {
- g_set_error(error,
- G_FILE_ERROR,
- G_FILE_ERROR_NOENT,
- "Failed to open file /proc/acpi/battery");
- return FALSE;
- }
- }
-
- gboolean getTimeRemaining(MIDPlatformSvc *obj, gint *timeRemaining, GError **error)
- {
- *timeRemaining = computeTimeRemaining();
-
- if (*timeRemaining > 0)
- {
- return TRUE;
- }
- else if (*timeRemaining == 0)
- {
- g_set_error(error,
- G_FILE_ERROR,
- G_FILE_ERROR_NOENT,
- "Cannot determine since information is missing!");
- return FALSE;
- }
- else
- {
- g_set_error(error,
- G_FILE_ERROR,
- G_FILE_ERROR_NOENT,
- "Failed to open file or directory");
- return FALSE;
- }
- }
-
- gboolean isUsingExternalPowerSource(MIDPlatformSvc *obj, gboolean *onExternalSource, GError **error)
- {
- int t = computePowerSource();
-
- if (t == 0)
- {
- *onExternalSource = FALSE;
- return TRUE;
- }
- else if (t == 1)
- {
- *onExternalSource = TRUE;
- return TRUE;
- }
- else
- {
- g_set_error(error,
- G_FILE_ERROR,
- G_FILE_ERROR_NOENT,
- "Failed to open file or directory");
-
- return FALSE;
- }
- }
gboolean getPercentRemaining(MIDPlatformSvc *obj, guint *percentRemaining, GError **error) { gboolean rc = FALSE; rc = computePercentPowerRemaining(percentRemaining); if (rc) return TRUE; else { g_set_error(error, G_FILE_ERROR, G_FILE_ERROR_NOENT, "Failed to open file /proc/acpi/battery"); return FALSE; } } gboolean getTimeRemaining(MIDPlatformSvc *obj, gint *timeRemaining, GError **error) { *timeRemaining = computeTimeRemaining(); if (*timeRemaining > 0) { return TRUE; } else if (*timeRemaining == 0) { g_set_error(error, G_FILE_ERROR, G_FILE_ERROR_NOENT, "Cannot determine since information is missing!"); return FALSE; } else { g_set_error(error, G_FILE_ERROR, G_FILE_ERROR_NOENT, "Failed to open file or directory"); return FALSE; } } gboolean isUsingExternalPowerSource(MIDPlatformSvc *obj, gboolean *onExternalSource, GError **error) { int t = computePowerSource(); if (t == 0) { *onExternalSource = FALSE; return TRUE; } else if (t == 1) { *onExternalSource = TRUE; return TRUE; } else { g_set_error(error, G_FILE_ERROR, G_FILE_ERROR_NOENT, "Failed to open file or directory"); return FALSE; } }
A Test Client
To test the interface power, we write a simple test client using D-Bus as well. The test client invokes the remote methods of object MIDPlatformSvc in order to retrieve battery information on the MID.
- #define PLATFORM_SERVICE "org.moblin.Platform"
- #define PLATFORM_PATH "/org/moblin/Platform"
- #define PLATFORM_POWER_IF "org.moblin.Platform.Power"
- #define POWER_SRC_CHANGED_SIGNAL "PowerSourceChanged"
-
- void queryMethod(char* param)
- {
- DBusGConnection* conn;
- GError *error;
- DBusGProxy *platformProxy;
- DBusError err;
-
- printf("Calling remote method: %s\n", param);
-
- g_type_init();
- error = NULL;
- conn = dbus_g_bus_get(DBUS_BUS_SESSION, &error);
-
- // Create the proxy Platform
- platformProxy = dbus_g_proxy_new_for_name(conn,
- PLATFORM_SERVICE, // target for the method call
- PLATFORM_PATH, // object to call on
- PLATFORM_POWER_IF); // interface to call on
-
- // Now call the metjod "IsUsingExternalPowerSource"
- if (param == "GetPercentRemaining")
- {
- uint result;
-
- if (!dbus_g_proxy_call(platformProxy, param, &error,
- G_TYPE_INVALID,
- G_TYPE_UINT, &result,
- G_TYPE_INVALID))
- {
- g_printerr("Failed to call remotely: %s\n",
- error->message);
- g_error_free(error);
- }
- else
- printf ("Remote call successes with returned value: %d%\n", result);
- }
- else if (param == "GetTimeRemaining")
- {
- int result;
-
- if (!dbus_g_proxy_call(platformProxy, param, &error,
- G_TYPE_INVALID,
- G_TYPE_INT, &result,
- G_TYPE_INVALID))
- {
- g_printerr("Failed to call remotely: %s\n",
- error->message);
- g_error_free(error);
- }
- else
- {
- printf ("Remote call successes with returned value: %d minutes\n",result);
- }
- }
- else if (param == "IsUsingExternalPowerSource")
- {
- gboolean result;
-
- if (!dbus_g_proxy_call(platformProxy, param, &error,
- G_TYPE_INVALID,
- G_TYPE_BOOLEAN, &result,
- G_TYPE_INVALID))
- {
- g_printerr("Failed to call remotely: %s\n",
- error->message);
- g_error_free(error);
- }
- else
- printf ("Remote call successes with returned value: %s\n", result? "TRUE" : "FALSE");
- }
-
- }
-
- int main(int argc, char** argv)
- {
- char* methodName[3] = {"GetPercentRemaining",
- "GetTimeRemaining",
- "IsUsingExternalPowerSource"};
-
- int i;
-
- for (i = 0; i <= 2; i++)
- queryMethod(methodName[i]);
-
- return 0;
- }
#define PLATFORM_SERVICE "org.moblin.Platform" #define PLATFORM_PATH "/org/moblin/Platform" #define PLATFORM_POWER_IF "org.moblin.Platform.Power" #define POWER_SRC_CHANGED_SIGNAL "PowerSourceChanged" void queryMethod(char* param) { DBusGConnection* conn; GError *error; DBusGProxy *platformProxy; DBusError err; printf("Calling remote method: %s\n", param); g_type_init(); error = NULL; conn = dbus_g_bus_get(DBUS_BUS_SESSION, &error); // Create the proxy Platform platformProxy = dbus_g_proxy_new_for_name(conn, PLATFORM_SERVICE, // target for the method call PLATFORM_PATH, // object to call on PLATFORM_POWER_IF); // interface to call on // Now call the metjod "IsUsingExternalPowerSource" if (param == "GetPercentRemaining") { uint result; if (!dbus_g_proxy_call(platformProxy, param, &error, G_TYPE_INVALID, G_TYPE_UINT, &result, G_TYPE_INVALID)) { g_printerr("Failed to call remotely: %s\n", error->message); g_error_free(error); } else printf ("Remote call successes with returned value: %d%\n", result); } else if (param == "GetTimeRemaining") { int result; if (!dbus_g_proxy_call(platformProxy, param, &error, G_TYPE_INVALID, G_TYPE_INT, &result, G_TYPE_INVALID)) { g_printerr("Failed to call remotely: %s\n", error->message); g_error_free(error); } else { printf ("Remote call successes with returned value: %d minutes\n",result); } } else if (param == "IsUsingExternalPowerSource") { gboolean result; if (!dbus_g_proxy_call(platformProxy, param, &error, G_TYPE_INVALID, G_TYPE_BOOLEAN, &result, G_TYPE_INVALID)) { g_printerr("Failed to call remotely: %s\n", error->message); g_error_free(error); } else printf ("Remote call successes with returned value: %s\n", result? "TRUE" : "FALSE"); } } int main(int argc, char** argv) { char* methodName[3] = {"GetPercentRemaining", "GetTimeRemaining", "IsUsingExternalPowerSource"}; int i; for (i = 0; i <= 2; i++) queryMethod(methodName[i]); return 0; }
Below is the result when running the test client.
Calling remote method: IsUsingExternalPowerSource
% ./clientTester
Calling remote method: GetPercentRemaining
Remote call successes with returned value: 96%
Calling remote method: GetTimeRemaining
Remote call successes with returned value: 235 minutes
Calling remote method: IsUsingExternalPowerSource
Remote call successes with returned value: FALSE
Conclusion
Because the MID form factor limits the size of the battery, applications that run on the platform must be aware of power state information in order to make smart decisions. Knowing how much power is remaining, how much time is remaining, and whether or not the system is running on external power can help software make wise use of the MID's resources. D-Bus is a lightweight Remote Procedure Call (RPC) which is suitable for many applications running on desktop. Because D-Bus is simple and relative small, yet powerful, we can adapt this technology for Mobile Internet Device (MID). In this paper, we introduced a platform service for MID using D-Bus technology. We showed how to implement three power-related methods provided by the MIDPlatformSvc. A sample test client is also shown to illustrate how we can use D-Bus to invoke these methods. As D-Bus not only supports methods, it can also support signals; we can also extend this application to include signals. In the feature, this platform service can be extended to include other interfaces such as network, location, CPU utilization...
References
[1] D-Bus, http://www.freedesktop.org/wiki/Software/dbus
[2] D-Bus Tutorial, http://dbus.freedesktop.org/doc/dbus-tutorial.html
[3] http://www.moblin.org/toolkits/basicDevGuides/mobLinux/toolkits_DevGds_mobLinux_createDBUS.php
[4] Mobile and Internet Linux Project, http://moblin.org/
Subscribe to:
Posts (Atom)