dbus实例讲解(三):数据类型和dteeth

来源:互联网 发布:文怡的服装淘宝店网址 编辑:程序博客网 时间:2024/06/08 09:45

我想在freerunner(一个开源linux手机)上查看fso(openmoko的诸多软件版本之一)的dbus信息。但fso的python没有gtk模块,跑不了d-feet。 在上一讲我介绍了d-feet的基本思路:用“org.freedesktop.DBus.ListNames”枚举消息总线上的连接,用“org.freedesktop.DBus.Introspectable.Introspect” 从"/"开始遍历连接的对象树。上一讲我们手工查看了两个连接,那么我们能不能写一个程序自动遍历连接的对象树, 输出指定连接的所有对象的所有接口的所有方法和信号?

当然可以,为此我写了一个叫dteeth的python脚本。不过在介绍这个脚本前,让我们先看看dbus的数据类型。

1、dbus的数据类型

dbus用xml描述接口,例如:

<?xml version="1.0" encoding="UTF-8" ?><node name="/org/freesmartphone/GSM/Device">  <interface name="org.freesmartphone.GSM.SMS">    <method name="SendMessage">       <arg name="number" type="s"/>       <arg name="contents" type="s"/>       <arg name="featuremap" type="a{sv}"/>       <arg type="i" direction="out"/>    </method>    <signal name="IncomingMessage">       <arg name="address" type="s"/>       <arg name="contents" type="s"/>       <arg name="features" type="a{sv}"/>    </signal>  </interface></node>

其实前两讲已经看过很多例子了。node就是接口中的对象,node可以包含node,构成对象树。 dbus的接口描述文件统一采用utf-8编码。 我相信读者很容易理解这个接口描述文件。我只想解释一下描述参数数据类型的type域。 dbus的数据类型是由"s"或"a{sv}"这样的类型签名(Type Signatures)定义的。 类型签名中可以使用以下标记:

aARRAY 数组bBOOLEAN 布尔值dDOUBLE IEEE 754双精度浮点数gSIGNATURE 类型签名iINT32 32位有符号整数nINT16 16位有符号整数oOBJECT_PATH 对象路径qUINT16 16位无符号整数sSTRING 零结尾的UTF-8字符串tUINT64 64位无符号整数uUINT32 32位无符号整数vVARIANT 可以放任意数据类型的容器,数据中包含类型信息。例如glib中的GValue。xINT64 64位有符号整数yBYTE 8位无符号整数()定义结构时使用。例如"(i(ii))"{}定义键-值对时使用。例如"a{us}"

a表示数组,数组元素的类型由a后面的标记决定。例如:

  • "as"是字符串数组。
  • 数组"a(i(ii))"的元素是一个结构。用括号将成员的类型括起来就表示结构了,结构可以嵌套。
  • 数组"a{sv}"的元素是一个键-值对。"{sv}"表示键类型是字符串,值类型是VARIANT。

在以后的例子中,我们会亲手实现上面这个xml描述的接口,包括服务器和客户程序。 到时候,读者会对dbus的数据类型有更直观的认识。

2、dteeth

2.1、运行dteeth

可以从这里下载dteeth的源代码。其中包含两个python脚本:dteeth.py和_introspect_parser.py。 dteeth.py是我写的。_introspect_parser.py是个开源模块,可以分析Introspect返回的xml数据。

dteeth用法如下:

$ ./dteeth.py -hUsage: dteeth [--system] <name of a connection on the bus >

默认连接session总线,除非你加上--system。可以一次指定同一消息总线的多个连接。先在PC上试一试:

$ ./dteeth.py org.fmddlmyy.Testorg.fmddlmyy.Test    /TestObj        org.fmddlmyy.Test.Basic            methods                Add( in i arg0 , in i arg1 , out i ret )        org.freedesktop.DBus.Introspectable            methods                Introspect( out s data )        org.freedesktop.DBus.Properties            methods                Set( in s interface , in s propname , in v value )                GetAll( in s interface , out a{sv} props )                Get( in s interface , in s propname , out v value )

我也在fso版本的freerunner手机上运行了一下,得到了org.freesmartphone.ogsmd的所有对象的所有的接口的所有方法和信号:

org.freesmartphone.ogsmd    /org/freedesktop/Gypsy        org.freedesktop.Gypsy.Time            signals                TimeChanged( i time )            methods                GetTime( out i )        org.freedesktop.DBus.Introspectable            methods                Introspect( out s )        org.freedesktop.Gypsy.Device            signals                FixStatusChanged( i fixstatus )                ConnectionStatusChanged( b constatus )            methods                GetConnectionStatus( out b )                Stop( )                Start( )                GetFixStatus( out i )        org.freedesktop.Gypsy.Course            signals                CourseChanged( i fields , i tstamp , d speed , d heading , d climb )            methods                GetCourse( out i , out i , out d , out d , out d )        org.freedesktop.Gypsy.Position            signals                PositionChanged( i fields , i tstamp , d lat , d lon , d alt )            methods                GetPosition( out i , out i , out d , out d , out d )        org.freedesktop.Gypsy.Accuracy            signals                AccuracyChanged( i fields , d pdop , d hdop , d vdop )            methods                GetAccuracy( out i , out d , out d , out d )        org.freesmartphone.Resource            methods                Enable( )                Disable( )                Suspend( )                Resume( )        org.freedesktop.Gypsy.Satellite            signals                SatellitesChanged( a(ubuuu) satellites )            methods                GetSatellites( out a(ubuuu) )        org.freesmartphone.GPS.UBX            signals                DebugPacket( s clid , i length , aa{sv} data )            methods                SendDebugPacket( in s clid , in i length , in aa{sv} data )                GetDebugFilter( in s clid , out b )                SetDebugFilter( in s clid , in b state )        org.freedesktop.Gypsy.Server            methods                Create( in s device , out o )                Shutdown( in o path )    /org/freesmartphone/Device/Audio        org.freedesktop.DBus.Introspectable            methods                Introspect( out s )        org.freesmartphone.Device.Audio            signals                SoundStatus( s name , s status , a{sv} properties )                Scenario( s scenario , s reason )            methods                SetScenario( in s name )                GetInfo( out s )                GetAvailableScenarios( out as )                PushScenario( in s name )                GetScenario( out s )                PullScenario( out s )                StopSound( in s name )                StopAllSounds( )                PlaySound( in s name )                StoreScenario( in s name )    /org/freesmartphone/Device/Display/pcf50633_bl        org.freedesktop.DBus.Introspectable            methods                Introspect( out s )        org.freesmartphone.Device.Display            methods                SetBrightness( in i brightness )                GetName( out s )                SetBacklightPower( in b power )                GetBrightness( out i )                GetBacklightPower( out b )    /org/freesmartphone/Device/IdleNotifier/0        org.freedesktop.DBus.Introspectable            methods                Introspect( out s )        org.freesmartphone.Device.IdleNotifier            signals                State( s state )            methods                SetState( in s state )                GetState( out s )                SetTimeout( in s state , in i timeout )                GetTimeouts( out a{si} )    /org/freesmartphone/Device/Info        org.freedesktop.DBus.Introspectable            methods                Introspect( out s )        org.freesmartphone.Device.Info            methods                GetCpuInfo( out a{sv} )    /org/freesmartphone/Device/Input        org.freesmartphone.Device.Input            signals                Event( s name , s action , i seconds )        org.freedesktop.DBus.Introspectable            methods                Introspect( out s )    /org/freesmartphone/Device/LED/gta02_aux_red        org.freedesktop.DBus.Introspectable            methods                Introspect( out s )        org.freesmartphone.Device.LED            methods                SetBrightness( in i brightness )                GetName( out s )                SetBlinking( in i delay_on , in i delay_off )    /org/freesmartphone/Device/LED/gta02_power_blue        org.freedesktop.DBus.Introspectable            methods                Introspect( out s )        org.freesmartphone.Device.LED            methods                SetBrightness( in i brightness )                GetName( out s )                SetBlinking( in i delay_on , in i delay_off )    /org/freesmartphone/Device/LED/gta02_power_orange        org.freedesktop.DBus.Introspectable            methods                Introspect( out s )        org.freesmartphone.Device.LED            methods                SetBrightness( in i brightness )                GetName( out s )                SetBlinking( in i delay_on , in i delay_off )    /org/freesmartphone/Device/LED/neo1973_vibrator        org.freedesktop.DBus.Introspectable            methods                Introspect( out s )        org.freesmartphone.Device.LED            methods                SetBrightness( in i brightness )                GetName( out s )                SetBlinking( in i delay_on , in i delay_off )    /org/freesmartphone/Device/PowerControl/Bluetooth        org.freesmartphone.Device.PowerControl            signals                Power( s device , b power )            methods                Reset( )                GetName( out s )                SetPower( in b power )                GetPower( out b )        org.freedesktop.DBus.Introspectable            methods                Introspect( out s )        org.freesmartphone.Resource            methods                Resume( )                Enable( )                Disable( )                Suspend( )    /org/freesmartphone/Device/PowerControl/UsbHost        org.freesmartphone.Device.PowerControl            signals                Power( s device , b power )            methods                Reset( )                GetName( out s )                SetPower( in b power )                GetPower( out b )        org.freedesktop.DBus.Introspectable            methods                Introspect( out s )    /org/freesmartphone/Device/PowerControl/WiFi        org.freesmartphone.Device.PowerControl            signals                Power( s device , b power )            methods                Reset( )                GetName( out s )                SetPower( in b power )                GetPower( out b )        org.freedesktop.DBus.Introspectable            methods                Introspect( out s )        org.freesmartphone.Resource            methods                Resume( )                Enable( )                Disable( )                Suspend( )    /org/freesmartphone/Device/PowerSupply/apm        org.freedesktop.DBus.Introspectable            methods                Introspect( out s )        org.freesmartphone.Device.PowerSupply            methods                GetName( out s )                GetEnergyPercentage( out i )                GetOnBattery( out b )                GetInfo( out a{sv} )    /org/freesmartphone/Device/PowerSupply/bat        org.freedesktop.DBus.Introspectable            methods                Introspect( out s )        org.freesmartphone.Device.PowerSupply            signals                PowerStatus( s status )                Capacity( i percent )            methods                GetEnergyPercentage( out i )                GetInfo( out a{sv} )                IsPresent( out b )                GetName( out s )                GetCapacity( out i )                GetPowerStatus( out s )    /org/freesmartphone/Device/RealTimeClock/rtc0        org.freedesktop.DBus.Introspectable            methods                Introspect( out s )        org.freesmartphone.Device.RealTimeClock            methods                GetWakeupReason( out s )                SetCurrentTime( in s t )                Suspend( )                GetWakeupTime( out s )                GetName( out s )                GetCurrentTime( out s )                SetWakeupTime( in s t )    /org/freesmartphone/Events        org.freedesktop.DBus.Introspectable            methods                Introspect( out s )        org.freesmartphone.Events            methods                AddRule( in s rule_str )                TriggerTest( in s name , in b value )    /org/freesmartphone/Framework        org.freedesktop.DBus.Introspectable            methods                Introspect( out s )        org.freesmartphone.Framework            methods                GetDebugLevel( in s logger , out s )                GetDebugDestination( out s , out s )                ListDebugLoggers( out as )                ListObjectsInSubsystem( in s subsystem , out as )                SetDebugDestination( in s category , in s destination )                SetDebugLevel( in s logger , in s levelname )                ListObjectsByInterface( in s interface , out ao )                ListSubsystems( out as )    /org/freesmartphone/GSM/Device        org.freesmartphone.GSM.Call            signals                CallStatus( i index , s status , a{sv} properties )            methods                Activate( in i index )                Emergency( in s number )                SendDtmf( in s tones )                ReleaseHeld( )                HoldActive( )                ReleaseAll( )                Initiate( in s number , in s type_ , out i )                ListCalls( out a(isa{sv}) )                Transfer( in s number )                Release( in i index )                ActivateConference( in i index )        org.freesmartphone.GSM.Debug            methods                DebugInjectString( in s channel , in s string )                DebugCommand( in s command , out as )                DebugEcho( in s echo , out s )                DebugListChannels( out as )        org.freedesktop.DBus.Introspectable            methods                Introspect( out s )        org.freesmartphone.GSM.Device            methods                CancelCommand( )                GetInfo( out a{sv} )                GetAntennaPower( out b )                SetSimBuffersSms( in b sim_buffers_sms )                GetFeatures( out a{sv} )                SetAntennaPower( in b power )                GetSimBuffersSms( out b )        org.freesmartphone.GSM.SMS            signals                IncomingMessage( s address , s text , a{sv} features )            methods                SendMessage( in s number , in s contents , in a{sv} featuremap , out i )        org.freesmartphone.GSM.SIM            signals                ReadyStatus( b status )                MemoryFull( )                AuthStatus( s status )                IncomingStoredMessage( i index )            methods                RetrievePhonebook( in s category , out a(iss) )                SendAuthCode( in s code )                ChangeAuthCode( in s old_pin , in s new_pin )                SendGenericSimCommand( in s command , out s )                ListPhonebooks( out as )                SetServiceCenterNumber( in s number )                GetHomeZones( out a(siii) )                RetrieveEntry( in s category , in i index , out s , out s )                DeleteMessage( in i index )                SendRestrictedSimCommand( in i command , in i fileid , in i p1 , in i p2 , in i p3 , in s data , out i , out i , out s )                GetMessagebookInfo( out a{sv} )                GetSimReady( out b )                GetPhonebookInfo( in s category , out a{sv} )                GetSimInfo( out a{sv} )                SendStoredMessage( in i index , out i )                SetAuthCodeRequired( in b required , in s pin )                GetAuthStatus( out s )                StoreMessage( in s number , in s contents , in a{sv} featuremap , out i )                GetAuthCodeRequired( out b )                RetrieveMessage( in i index , out s , out s , out s , out a{sv} )                StoreEntry( in s category , in i index , in s name , in s number )                Unlock( in s puk , in s new_pin )                GetServiceCenterNumber( out s )                RetrieveMessagebook( in s category , out a(isssa{sv}) )                DeleteEntry( in s category , in i index )        org.freesmartphone.GSM.Network            signals                Status( a{sv} status )                SignalStrength( i strength )                IncomingUssd( s mode , s message )            methods                EnableCallForwarding( in s reason , in s class_ , in s number , in i timeout )                ListProviders( out a(isss) )                GetCallForwarding( in s reason , out a{sv} )                Unregister( )                SetCallingIdentification( in s status )                Register( )                SendUssdRequest( in s request )                DisableCallForwarding( in s reason , in s class_ )                GetSignalStrength( out i )                GetCallingIdentification( out s )                RegisterWithProvider( in i operator_code )                GetNetworkCountryCode( out s )                GetStatus( out a{sv} )        org.freesmartphone.Resource            methods                Enable( )                Disable( )                Suspend( )                Resume( )        org.freesmartphone.GSM.CB            signals                IncomingCellBroadcast( i channel , s data )            methods                GetCellBroadcastSubscriptions( out s )                SetCellBroadcastSubscriptions( in s channels )        org.freesmartphone.GSM.PDP            signals                ContextStatus( i index , s status , a{sv} properties )            methods                SetCurrentGprsClass( in s class_ )                ActivateContext( in s apn , in s user , in s password )                DeactivateContext( )                ListAvailableGprsClasses( out as )                GetContextStatus( out s )                GetCurrentGprsClass( out s )    /org/freesmartphone/GSM/Server        org.freedesktop.DBus.Introspectable            methods                Introspect( out s )        org.freesmartphone.GSM.HZ            signals                HomeZoneStatus( s zone )            methods                GetHomeZoneStatus( out s )                GetKnownHomeZones( out as )    /org/freesmartphone/PIM/Contacts        org.freedesktop.DBus.Introspectable            methods                Introspect( out s )        org.freesmartphone.PIM.Contacts            methods                Query( in a{sv} query , out s )                Add( in a{sv} contact_data , out s )                GetSingleContactSingleField( in a{sv} query , in s field_name , out s )        org.freesmartphone.PIM.Contact            methods                GetContent( out a{sv} )                GetMultipleFields( in s field_list , out a{sv} )    /org/freesmartphone/PIM/Contacts/Queries        org.freedesktop.DBus.Introspectable            methods                Introspect( out s )        org.freesmartphone.PIM.ContactQuery            methods                GetContactPath( out s )                Skip( in i num_entries )                Dispose( )                GetResult( out a{sv} )                GetResultCount( out i )                Rewind( )                GetMultipleResults( in i num_entries , out aa{sv} )    /org/freesmartphone/PIM/Messages        org.freedesktop.DBus.Introspectable            methods                Introspect( out s )        org.freesmartphone.PIM.Messages            signals                NewMessage( s message_URI )            methods                GetSingleMessageSingleField( in a{sv} query , in s field_name , out s )                Query( in a{sv} query , out s )                Add( in a{sv} message_data , out s )                GetFolderURIFromName( in s folder_name , out s )                GetFolderNames( out as )        org.freesmartphone.PIM.Message            methods                GetContent( out a{sv} )                MoveToFolder( in s new_folder_name )                GetMultipleFields( in s field_list , out a{sv} )    /org/freesmartphone/PIM/Messages/Folders        org.freedesktop.DBus.Introspectable            methods                Introspect( out s )        org.freesmartphone.PIM.Messages            signals                NewMessage( s message_URI )            methods                GetSingleMessageSingleField( in a{sv} query , in s field_name , out s )                Query( in a{sv} query , out s )                Add( in a{sv} message_data , out s )                GetFolderURIFromName( in s folder_name , out s )                GetFolderNames( out as )        org.freesmartphone.PIM.Message            methods                GetContent( out a{sv} )                MoveToFolder( in s new_folder_name )                GetMultipleFields( in s field_list , out a{sv} )    /org/freesmartphone/PIM/Messages/Folders/0        org.freesmartphone.PIM.MessageFolder            signals                MessageMoved( s message_uri , s new_folder_name )            methods                GetMessageCount( out i )                GetMessageURIs( in i first_message_id , in i message_count , out as )        org.freedesktop.DBus.Introspectable            methods                Introspect( out s )    /org/freesmartphone/PIM/Messages/Folders/1        org.freesmartphone.PIM.MessageFolder            signals                MessageMoved( s message_uri , s new_folder_name )            methods                GetMessageCount( out i )                GetMessageURIs( in i first_message_id , in i message_count , out as )        org.freedesktop.DBus.Introspectable            methods                Introspect( out s )    /org/freesmartphone/PIM/Messages/Queries        org.freedesktop.DBus.Introspectable            methods                Introspect( out s )        org.freesmartphone.PIM.MessageQuery            methods                Skip( in i num_entries )                Dispose( )                GetResult( out a{sv} )                GetResultCount( out i )                Rewind( )                GetMultipleResults( in i num_entries , out a{ia{sv}} )                GetMessageURI( out s )    /org/freesmartphone/PIM/Sources        org.freesmartphone.PIM.Sources            methods                GetEntryCount( out i )                InitAllEntries( )        org.freedesktop.DBus.Introspectable            methods                Introspect( out s )        org.freesmartphone.PIM.Source            methods                GetSupportedPIMDomains( out as )                GetName( out s )                GetStatus( out s )    /org/freesmartphone/Phone        org.freedesktop.DBus.Introspectable            methods                Introspect( out s )        org.freesmartphone.Phone            signals                Incoming( o call )            methods                InitProtocols( out as )                CreateCall( in s number , in s protocol , in b force , out o )    /org/freesmartphone/Preferences        org.freesmartphone.Preferences            methods                GetProfiles( out as )                GetService( in s name , out o )                GetServices( out as )                SetProfile( in s profile )                GetProfile( out s )        org.freedesktop.DBus.Introspectable            methods                Introspect( out s )    /org/freesmartphone/Preferences/rules        org.freedesktop.DBus.Introspectable            methods                Introspect( out s )        org.freesmartphone.Preferences.Service            signals                Notify( s key , v value )            methods                GetType( in s key , out s )                SetValue( in s key , in v value )                GetKeys( out as )                IsProfilable( in s key , out b )                GetValue( in s key , out v )    /org/freesmartphone/Time        org.freedesktop.DBus.Introspectable            methods                Introspect( out s )        org.freesmartphone.Time            signals                Minute( i year , i mon , i day , i hour , i min , i sec , i wday , i yday , i isdst )            methods                GetLocalTime( in i seconds , out i , out i , out i , out i , out i , out i , out i , out i , out i )    /org/freesmartphone/Time/Alarm        org.freedesktop.DBus.Introspectable            methods                Introspect( out s )        org.freesmartphone.Time.Alarm            methods                ClearAlarm( in s busname )                SetAlarm( in s busname , in i timestamp )    /org/freesmartphone/Usage        org.freesmartphone.Usage            signals                ResourceAvailable( s resourcename , b state )                ResourceChanged( s resourcename , b state , a{sv} attributes )            methods                ReleaseResource( in s resourcename )                Suspend( )                GetResourceState( in s resourcename , out b )                SetResourcePolicy( in s resourcename , in s policy )                GetResourcePolicy( in s resourcename , out s )                GetResourceUsers( in s resourcename , out as )                ListResources( out as )                RegisterResource( in s resourcename , in o path )                RequestResource( in s resourcename )        org.freedesktop.DBus.Introspectable            methods                Introspect( out s )

2.2、源代码

下面是dteeth的源代码:

$ cat -n dteeth.py     1  #!/usr/bin/env python     2  # -*- coding: utf-8 -*-     3     4  import dbus     5  import _introspect_parser     6  import getopt, sys     7     8  MARGIN_WIDTH = 4     9  ONE_MARGIN = ' ' * MARGIN_WIDTH    10    11  # signal是个元组,它有一个元素,是一个列表。列表的元素是signal的参数    12  # 列表的每个元素都是字典。它有两个元素,键值分别是'type'和'name'    13  def show_signal(name, signal, margin):    14      print margin+name+'(',    15      args = signal[0]    16      for i, arg in enumerate(args):    17          if i > 0:    18              print ',',    19          if arg['name']:    20              print '%s %s' % (arg['type'], arg['name']),    21          else:    22              print '%s' % arg['type'],    23      print  ')'    24    25  # method是个元组,它有两个元素,都是列表。前一个列表的元素是输入参数,后一个列表的元素是输出参数    26  def show_method(name, method, margin):    27      print margin+name+'(',    28  # 输入参数    29      args = method[0]    30      in_num = len(args)    31      out_num = len(method[1])    32      for i, arg in enumerate(args):    33          if i > 0:    34              print ',',    35          if arg['name']:    36              print 'in %s %s' % (arg['type'], arg['name']),    37          else:    38              print 'in %s' % arg['type'],    39  # 输出参数    40      if (in_num > 0) and (out_num > 0) :    41          print ',',    42      args = method[1]    43      for i, arg in enumerate(args):    44          if i > 0:    45              print ',',    46          if arg['name']:    47              print 'out %s %s' % (arg['type'], arg['name']),    48          else:    49              print 'out %s' % arg['type'],    50      print  ')'    51    52  def show_property(name, property, margin):    53      print margin+name    54      print margin,    55      print property    56    57  # interfaces是个字典,它有三个元素,键值分别是'signals'、'methods'和'properties'    58  def show_iface(name, iface, margin):    59      print margin + name    60      margin += ONE_MARGIN    61      signals=iface['signals']    62      l = len(signals)    63      if l > 0:    64          print margin+'signals'    65          for node in signals:    66              show_signal(node, signals[node], margin+ONE_MARGIN)    67    68      methods=iface['methods']    69      l = len(methods)    70      if l > 0:    71          print margin+'methods'    72          for node in methods:    73              show_method(node, methods[node], margin+ONE_MARGIN)    74    75      properties=iface['properties']    76      l = len(properties)    77      if l > 0:    78          print margin+'properties'    79          for node in properties:    80              show_property(node, properties[node], margin+ONE_MARGIN)    81    82  def show_obj(bus, name, obj_name, margin):    83      obj=bus.get_object(name, obj_name)    84      iface=dbus.Interface(obj, 'org.freedesktop.DBus.Introspectable')    85      xml=iface.Introspect();    86      data = _introspect_parser.process_introspection_data(xml)    87    88      # data是个字典,它有两个元素,键值分别是'child_nodes'和'interfaces'    89      if len(data['interfaces']) > 0:    90          print margin + obj_name    91    92      for node in data['interfaces']:    93          iface=data['interfaces'][node]    94          show_iface(node, iface, margin+ONE_MARGIN)    95    96      for node in data['child_nodes']:    97          if obj_name == '/':    98              show_obj(bus, name, '/' + node, margin)    99          else:   100              show_obj(bus, name, obj_name + '/' + node, margin)   101   102  def show_connection(bus, name, margin):   103      print margin + name   104      show_obj(bus, name, '/', margin+ONE_MARGIN)   105   106  def usage():   107      print "Usage: dteeth [--system] "   108   109  def main():   110      try:   111          opts, args = getopt.getopt(sys.argv[1:], "h", ["help", "system"])   112      except getopt.GetoptError, err:   113          # print help information and exit:   114          print str(err) # will print something like "option -a not recognized"   115          usage()   116          sys.exit(2)   117   118      if len(args) == 0:   119          usage()   120          sys.exit(2)   121   122      use_system = False   123      for o, a in opts:   124          if o in ("-h", "--help"):   125              usage()   126              sys.exit()   127          if o == "--system":   128              use_system = True   129          else:   130              assert False, "unhandled option"   131   132      if use_system:   133          bus=dbus.SystemBus()   134      else:   135          bus=dbus.SessionBus()   136   137      for arg in args:   138          show_connection(bus, arg, "")   139   140  if __name__ == "__main__":   141      main()

dteeth是我写的第一个超过10行的python脚本。对于熟悉python的读者,dteeth应该是很简单的。 不过我还是简单解释一下dteeth的主要逻辑。

2.3、dteeth的主要逻辑

main函数分析命令行,对命令行上指定的每个连接调用show_connection函数。 show_connection在打印连接名后调用show_obj函数。show_obj从根对象"/"开始遍历连接的对象树。

show_obj对输入对象调用Introspect方法,返回的xml数据交由_introspect_parser处理。 _introspect_parser会从xml数据中分出inerface和node。 show_obj对inerface调用show_iface显示。 show_obj对node会递归调用show_obj,实现对象树的遍历。

2.3、_introspect_parser的输出格式

_introspect_parser.process_introspection_data函数分析Introspect方法返回的xml数据。 为了了解_introspect_parser的输出格式,我们可以写个小脚本:

$ cat ti.py#!/usr/bin/env pythonimport dbusimport _introspect_parserbus=dbus.SessionBus()obj=bus.get_object('org.freesmartphone.ogsmd', '/org/freesmartphone/GSM/Device')iface=dbus.Interface(obj, 'org.freedesktop.DBus.Introspectable')xml=iface.Introspect();data = _introspect_parser.process_introspection_data(xml)print data

可以用这个脚本直接打印process_introspection_data返回的数据。下面是整理后的输出:

{'interfaces': {u'org.freedesktop.DBus.Introspectable': {'signals': {}, 'methods': {u'Introspect': ([], [{'type': u's', 'name': u'data'}])}, 'properties': {}}, u'org.freedesktop.DBus.Properties': {'signals': {}, 'methods': {u'Set': ([{'type': u's', 'name': u'interface'}, {'type': u's', 'name': u'propname'}, {'type': u'v', 'name': u'value'}], []), u'GetAll': ([{'type': u's', 'name': u'interface'}], [{'type': u'a{sv}', 'name': u'props'}]), u'Get': ([{'type': u's', 'name': u'interface'}, {'type': u's', 'name': u'propname'}], [{'type': u'v', 'name': u'value'}])}, 'properties': {}}, u'org.freesmartphone.GSM.SMS': {'signals': {u'IncomingMessage': ([{'type': u's', 'name': None}, {'type': u's', 'name': None}, {'type': u'a{sv}', 'name': None}],)},'methods': {u'SendMessage': ([{'type': u's', 'name': u'number'}, {'type': u's', 'name': u'contents'}, {'type': u'a{sv}', 'name': u'featuremap'}], [{'type': u'i', 'name': u'arg3'}])},'properties': {}}}, 'child_nodes': []}

所有字符串前面都有前缀u,表示这些字符串都是Unicode编码。在python中,字典用{},元组用(),列表用[]。从括号我们就能看出数据格式。

我们看到process_introspection_data返回返回一个字典。这个字典有两个映射。一个映射的键值是"interfaces",另一个映射的键值是"child_nodes"。

  • 映射"child_nodes"的值是一个列表,列出所有子节点的名称。

  • 映射"interfaces"的值还是一个字典。这个字典的每个映射的键值是一个接口名称。每个映射的值类型还是字典, 这个字典有3个映射,映射的键值分别是'signals'、'methods'和'properties',映射的值类型都是字典。

    • 'signals'对应字典的每个键值是一个信号名称。每个映射的值类型是元组。这个元组只有一个元素,类型是列表, 即信号的参数列表。

      • 参数列表的元素类型是字典。这个字典有2个映射,映射的键值分别是'type'和'name'。'type'是参数类型,'name'是参数名称。 映射的值类型都是字符串。

    • 'methods'对应字典的每个键值是一个方法名称。每个映射的值类型是元组。这个元组有两个元素,类型是列表, 分别是方法的输入参数列表和输出参数列表。参数列表的元素类型和信号的参数列表相同。

    • 我看到'properties'映射都是空的,就没有研究。

3、python基础

简单介绍一下与dteeth有关的python语法。

3.1、代码块和缩进

python用缩进来区分语句所属的代码块,从类定义、函数到for、if的代码块都是用缩进来去区分的。 没有缩进的代码块是脚本的主体代码。 一个脚本文件也被称作一个模块。 不管模块被直接运行还是被其它模块导入,主体代码都会在载入时被执行。 例如dteeth的主体代码只有两句:

   140  if __name__ == "__main__":   141      main()

__xxx__这样的标志符通常是python的系统变量。如果模块被导入,__name__的值是模块的名字。 如果模块被直接执行,__name__的值是"__main__"。 我们通常在模块被直接执行时,调用主函数或模块的测试函数。

3.2、脚本文件格式

python脚本的起始行通常是:/p>

     1  #!/usr/bin/env python

env是一个可以修改环境变量并执行程序的工具,它可以自动在系统路径中搜索要执行的程序。 python脚本文件必须以0A为换行符,默认仅支持ASCII字符。 如果要写中文注释(显然是不提倡的),可以在起始行后用以下语句将文件指定为utf-8编码:

     2  # -*- coding: utf-8 -*-

这时,文件必须被保存为没有BOM的utf-8编码文件。

3.3、列表、元组和字典

列表类似于C的数组,列表元素用[]包括。元组是不可变的列表,元组元素用()包括。元组的元素个数和类型在创建后就不能改变了。 元组中基本类型的值是不能改变的,但如果元组的一个元素是列表,我们可以改变列表内容, 即我们可以改变元组中可变元素的内容。例如:

>>> a=(1,2,['abc'])>>> a[2]='def'Traceback (most recent call last):  File "", line 1, in TypeError: 'tuple' object does not support item assignment>>> a[2][0]='def'>>> a(1, 2, ['def'])

字典是键-值对的集合,字典元素用{}包括。

4、结束语

本文介绍了一个叫作dteeth的python脚本。 这个脚本逻辑很简单,读者可以根据需要修改或扩充。 讲了这么多dbus,我们还没有接触C代码。下一讲,我们讨论dbus的C实例。

来源:http://www.fmddlmyy.cn/text54.html

原创粉丝点击