Dear Dan, I do understand these fundamental concepts. Thank for your useful tutorial anyway.
I think my problem is I do not understand object as well as interface hierarchy exposed by NetworkManager DBus service. According to API spec here (http://projects.gnome.org/NetworkManager/developers/spec-07.html#org.freede sktop.NetworkManager) and (http://live.gnome.org/NetworkManager/SystemSetting). I understand it as below: 1. Service DBus named org.freedesktop.NetworkManagerSystemSetting and org.freedesktop.NetworkManagerUserSetting is one which I need to connect to inorder to get connection configuration. 2. Get org.freedesktop.NetworkManagerSettings interface of service proxy 3. Invoke ListConnection() on returned interface. It seems that your API spec isn't very clear so newcomers, like me, get confused when doing with this. Please instruct me how to get used particularly this service. Or please make your spec more clearly. Thank for your time & consideration. Toan Nguyen -----Original Message----- From: Dan Williams [mailto:d...@redhat.com] Sent: Wednesday, April 28, 2010 11:52 AM To: Nguyen Canh Toan Cc: jkli...@redhat.com; networkmanager-list@gnome.org Subject: RE: Confusing about DBus API speciDan Williams [d...@redhat.com]fication On Thu, 2010-04-29 at 06:08 -0700, Nguyen Canh Toan wrote: > Dear Jirka, > > It's weird. After adjusting my script, it's still error: D-Bus is simply an IPC mechanism, but it layers a few concepts on top of pure message-passing, as explained below. It did take me some time to understand how the D-Bus object model really works, so don't worry about it you don't completely understand how it all works yet. 1) 'service': a program that responds to requests from clients. Each service is identified by a "bus name" which clients use to find the service and send requests to it. The bus name usually looks like "org.foobar.Baz". A program can claim more than one bus name; NM claims org.freedesktop.NetworkManager and org.freedesktop.NetworkManagerSystemSettings, each is a unique serivce which provides different functionality to clients. 2) 'object': a method of organizing distinct entities, much like programming languages have objects. Each object is uniquely identified by an "object path" (basically a pointer) that looks like "/org/foobar/Baz/235235". Each request sent to the service must be directed to a specific object. Many services have a base object with a well-known path that you use to bootstrap your communication with the service. 3) 'interface': each request belongs to an interface, which is simply a way of logically separating different functionality. The same way that object-oriented languages like Java or C++ or GLib define an "interface"; a specific API that different objects can implement, but the caller doesn't need to know what type the object is, just the interface. Interface names often look like D-Bus service names, but have no relation to them. 4) 'method call': a request for an operation or information that a client sends to the service; method calls are defined by an Interface and are sent to objects. Say you have a binary called "mcdonaldsd" that provides a D-Bus service called "org.fastfood.McDonalds". Clients that want to talk to this service use "org.fastfood.McDonalds" to direct requests to mcdonaldsd. mcdonaldsd provides a base object called "/org/fastfood/McDonalds". This object implements the "org.fastfood.McDonalds" interface, which defines the method calls: - GetItems(void) -> ao - Order(ao) -> b GetItems returns an array of object-paths representing all the things on the menu that you can order. So if you call it you'll get something like this returned: [ '/org/fastfood/McDonalds/Item/0', '/org/fastfood/McDonalds/Item/1' ] Each of these returned object paths is a pointer to an object; mcdonaldsd probably even implements these as objects internally using Java or C++ or GObject or whatever. These objects are probably completely different (one may be a burger, one may be a drink) but they all implement a common interface "org.fastfood.McDonalds.Item". The org.fastfood.McDonalds.Item interface has the following method calls: - GetName - GetType (either TYPE_BURGER, TYPE_DRINK, or TYPE_FRIES) - GetPrice - Consume So even if you don't know what /org/fastfood/McDonalds/Item/0 is, you still can get a lot of information about it, enough to decide whether you want to order it or not. Assume that item "0" is a "BigMac" and item "1" is "Coke". These are clearly different objects, but each still has a name, a calorie count, a price, and can be consumed. Next, since each item is different (even though they all implement the common org.fastfood.McDonalds.Item interface) each item type will implement other interfaces that define functionality specific to that type of item. So item "0" (BigMac) implements the org.fastfood.McDonalds.Item.Burger interface which has the following methods: - Unwrap - AddMustard - RemovePickle (nobody likes those stupid limp pickles anyway) And item "1" (Coke) implements the org.fastfood.McDonalds.Item.Drink interface which has the following methods: - PutLidOn - InsertStraw - RemoveStraw Remember, since both objects *also* implement the base org.fastfood.McDonalds.Item interface, you can use the Consume() method to consume both items. But clearly, you don't want to include the InsertStraw() method on the generic org.fastfood.McDonalds.Item interface, because all items implement that interface, and it would be pretty funny if you tried to call InsertStraw() on the BigMac object. People would stare. So interfaces are about logically separating method calls that have specific functionality, and thus any object that wants that functionality can implement that interface, instead of having every object type duplicate all the calls of that interface. So, with pseudocode: # Get local proxy for the remove mcdonaldsd service bus = get_service("org.fastfood.McDonalds") mcds = bus.get_object("org.fastfood.McDonalds", "/org/fastfood/McDonalds") burger_path = None drink_path = None # Lets read all the menu items menu_items = mcds.GetItems() for object_path in menu_items: item = bus.get_object("org.fastfood.McDonalds.Item", object_path) print "Item: %s price %s" % (item.GetName(), item.GetPrice()) # Now let's figure out what we want to order; we'll order # the first burger we find and the first drink we find, but # only one of each. We just had breakfast so we're not that # hungry. item_type = item.GetType() if item_type == TYPE_BURGER and burger is None: burger_path = object_path elif item_type == TYPE_DRINK and drink is None: drink_path = object_path # We've found a burger and drink on the menu, lets order them if burger_path and drink_path: break food = mcds.Order([burger_path, drink_path]) if food.len() == 0: print "Oops, not enough money or something. Need to get a job." sys.exit(1) # Yay, we got our order. Now we take off the damn pickle burger = bus.get_object("org.fastfood.McDonalds.Item.Burger", burger_path) burger.RemovePickle() # And we're taking this to go, so we need a lid and straw for the drink drink = bus.get_object("org.fastfood.McDonalds.Item.Drink", drink_path) drink.InsertStraw() try: drink.PutLidOn() catch Exception, e: print "Oops, straw already inserted!" # We're distracted by the smell of the burger and put the # straw in before we put the lid on. Oops. Take the straw # out, put the lid on, and then re-insert the straw drink.RemoveStraw() drink.PutLidOn() drink.InsertStraw() # All ready. Now we can walk out and consume the burger and drink; # note that even though burger_proxy and drink_proxy were created # with D-Bus interfaces specific to their food type, we don't really # need to create another interface just to call the generic Consume() # method which both the burger and drink implement. Just give the # method call the generic interface. burger.Consume(dbus_interface="org.fastfood.McDonalds.Item") drink.Consume(dbus_interface="org.fastfood.McDonalds.Item") _______________________________________________ networkmanager-list mailing list networkmanager-list@gnome.org http://mail.gnome.org/mailman/listinfo/networkmanager-list