User Tools

Site Tools


Sidebar

Network and communication

k24:k24.9:k24.9.0:k24.9.0.3:start

24.9.0.3 D-Bus signature

In Gambas, a method - declared as a function - can return exactly one value. A D-Bus signal or a D-Bus method, on the other hand, can return several values. Using the signature of a signal or method, you can easily see how many values are returned with a received signal or with a method call via its arguments - stored in a variant array - and which data type the individual D-Bus values have.

The classes DBusVariant and DBusValues (gb.dbus) allow you to define D-Bus values for a given D-Bus signature. The description of both classes DBusVariant and DBusValues can be found in chapter 24.9.8.0. Both classes have only the Value property and one constant each. There you will also learn that you must use the class DBusVariant for a signature such as“(ia{sv}av)” and the class DBusValues for a signature such as “u(ia{sv}av)”.

Note:
At http://gambaswiki.org/wiki/doc/dbus#t10 you will find a table summarizing how Gambas data types are converted to D-Bus data types and vice versa.

Determination: A D-Bus signature is defined as a string constant.

24.9.0.3.1 Example 1

To evaluate the return value of a D-Bus method or an intercepted D-Bus signal, you need its signatures to map the D-Bus data with its D-Bus data types to Gambas data and its data types.

In example 1, a special “MountAdded” signal is analyzed that is sent by the d-bus-enabled application with the D-Bus name org.gtk.vfs.UDisks2VolumeMonitor and with the object path /org/gtk/Private/RemoteVolumeMonitor - among many other signals - when a USB stick is inserted, for example. You can use the console program dbus-send for introspection:

$ dbus-send --session --print-reply --dest=org.gtk.vfs.UDisks2VolumeMonitor \
 /org/gtk/Private/RemoteVolumeMonitor \
 org.freedesktop.DBus.Introspectable.Introspect > volumemonitor.introspection.xml

Here is an excerpt from the XML file volumemonitor.introspection.xml:

<signal name="MountAdded">
  <arg type="s" name="dbus_name"/>
  <arg type="s" name="id"/>
  <arg type="(ssssssbsassa{sv})" name="mount"/>
</signal>

You need the specified signatures to map the D-Bus data with its D-Bus data types to Gambas data and its data types. According to the conversion table above, you can see that the first two arguments have the native data type “s”, which Gambas also knows. Therefore, you do not have to convert anything here. The third argument with the signature “ssssssbsassa{sv}”, which can be characterized as a complex data type, looks completely different:

String String String String String String Boolean String String-Array String Collection(String:Variant)

These are the individual Gambas data types that can be specified for the third argument according to the above table, whereby the third argument is a variant array in type - recognizable by the enclosing parentheses in the signature. The parentheses are also noted as Struct of (…) in the D-Bus notation. Array of[datatype] identifies an array of elements of the specified data type. The D-Bus notation Dict of {…} for example stands for a{ss} or a{sv} and requires conversion to the Gambas data type collection.

Struct of (
s				6x String
b				1x Boolean
s				1x String
Array of [string]  	       1x String-Array
s				1x String
Dict of {String,Variant}	1x Collection (Key-Typ=String, Value-Typ=Variant)
)

If you intercept the signal using the class DBusObserver with the message type'DBus.Signal' and the event hDbusObserver_Message(), then this declaration of suitable variables and the following value assignments (Variable ⇒ Argument value) are useful:

Public Sub hDBusObserver_Message()
 
  Dim bTF as Boolean
  Dim k as Integer = 1
  Dim sA1, sA2 As String
  Dim sA31, sA32, sA33, sA34, sA35, sA36, sA37, sA38 As String
  Dim vElement As Variant
  Dim cCollection As Collection
  Dim aArray As String[]
  Dim aSignalArguments As Variant[]
 
  aSignalArguments = hDBusObserver.Message.Arguments ' Speichern aller Signal-Argumente in aSignalArguments
 
  sA1  =  aSignalArguments[0]
  sA2  =  aSignalArguments[1]
  sA31 =  aSignalArguments[2][0]
  sA32 =  aSignalArguments[2][1]
  sA33 =  aSignalArguments[2][2]
  sA34 =  aSignalArguments[2][3]
  sA35 =  aSignalArguments[2][4]
  sA36 =  aSignalArguments[2][5]
  bTF  =  aSignalArguments[2][6]
  sA37 =  aSignalArguments[2][7]
 
  aArray = New String[]
  aArray = aSignalArguments[2][8]
  If aArray.Count > 0 Then
     For Each vElement In Array
       Print "Element " & Str(k) & "  =   " & vElement
       Inc k
     Next
  Else
     Print "Attention: The string array is empty!" & gb.NewLine
  Endif
 
  sA38 =  aSignalArguments[2][9]
 
' Collection -> KeyType = String, DataType = Variant
  cCollection = New Collection
  cCollection = aSignalArguments[2][10]
  If cCollection.Count > 0 Then
     For Each vElement In cCollection
       Print "Element " & Str(k) & "  :   " & cCollection.Key & " = " & vElement & gb.NewLine
       Inc k
     Next
  Else
     Print "Attention: The collection is empty!"
  Endif
 
End

24.9.0.3.2 Example 2

This example shows you a D-Bus data server and a D-Bus client. The server provides a service where a value with a complex data type is returned with a method call (GetT(…)) with a (string) argument.

Figure 24.9.0.3.1: The service is used …

The second example is deliberately constructed for demonstration purposes so that the signature of the return value of the method GetT(…) uses many data types.

 String         s0    ' Sensor Number/Type: 70358 KNX T-B-UP
 Integer 1      i1    ' Day     15
 Integer 2      i2    ' Month   12
 Integer 3      i3    ' Year    2017

 Variant-Array  av
 Array[0]       i4    ' Hour    15
 Array[1]       i5    ' Minute  24
 Array[2]       i6    ' Second  37
 Array[3]       s1    ' Time zone "LocalTime"

 Collection     a{sv} ' Key.Type=String, Value-Type=Variant
 c["T"]         f1    ' Temperature -1.4
 c["L"]         s2    ' Label       °
 c["S"]         s3    ' Scale       C

 Boolean        b0    ' TempLog     True/False

With these defaults for the return value of the method GetT(…) the following signature results after a conversion of the Gambas data types into D-Bus data types, which is described in a separate file - here RValue.class - as a string constant:

' Gambas class file
 
Export
Inherits DBusValues
 
Public Const Signature As String = "siiiava{sv}b"
 
Eine Introspection für das exportierte Objekt liefert diese Übersicht:
 
  <interface name="org.gambas.dbusserver3.msservice">
    <method name="GetT">
      <arg name="arg1" type="s"/>
      <arg name="value1" type="s" direction="out"/>
      <arg name="value2" type="i" direction="out"/>
      <arg name="value3" type="i" direction="out"/>
      <arg name="value4" type="i" direction="out"/>
      <arg name="value5" type="av" direction="out"/>
      <arg name="value6" type="a{sv}" direction="out"/>
      <arg name="value7" type="b" direction="out"/>
    </method>
  </interface>

In a further step, you must define the method GetT(…) in another class file (MSService.class) after the signature has been declared. The data type of the function value is of type RValue:

' Gambas class file
 
Inherits DBusObject
Create Static
 
' Signal definition ...
 
'' Definition of a method. The method has exactly one argument.
Public Function GetT(ShortScale As String) As RValue
 
  Dim hItem As RValue
  Dim s0, s1, s2, s3 As String
  Dim i1, i2, i3, i4, i5, i6 As Integer
  Dim f1 As Float
  Dim aTime As Variant[]
  Dim cTemperature As Collection
  Dim bTempLog As Boolean
 
  s0 = "Sensor 34 : 70358 KNX T-B-UP"
 
  i1 = Day(Now())
  i2 = Month(Now())
  i3 = Year(Now())
 
  i4 = Hour(Now())
  i5 = Minute(Now())
  i6 = Second(Now())
  s1 = ("LocalTime")
  aTime = [i4, i5, i6, s1]
 
' The temperature value is read out in real operation from an RS232-AD converter
' A random value for the current temperature is generated here
  f1 = Round(Rnd(-3, 2), -4)
 
  Select Case ShortScale
    Case "C"
      s2 = "°"
      s3 = "C"
    Case "K"
      f1 = f1 + 273.15
      s2 = ""
      s3 = "K"
    Case "F"
      f1 = (9 / 5) * f1 + 32
      s2 = "°"
      s3 = "F"
    Default
      s2 = "°"
      s3 = "C"
  End Select
 
  cTemperature = New Collection
  cTemperature.Add(f1, "Temperature") ' Temperature
  cTemperature.Add(s2, "Label")       ' Label
  cTemperature.Add(s3, "Scale")       ' Temperature scale
 
  bTempLog = True
 
  hItem = New RValue
' hItem.Value with complex data type:
  hItem.Value = [s0, i1, i2, i3, aTime, cTemperature, bTempLog]
 
  Return hItem
 
End

In the download area you will find the projects for the D-Bus-Server3 and the D-Bus-Client3, so that you can trace the interaction of D-Bus signature and data conversion yourself.

The client not only reads the complex return value with the signature “siiiava{sv}b”, but also evaluates a signal that the server sends when it is switched on or off. An introspection of the server service has also been implemented for the client.

Download

This website uses cookies. By using the website, you agree with storing the cookies on your computer. More information in the privacy policy.
k24/k24.9/k24.9.0/k24.9.0.3/start.txt · Last modified: 02.07.2018 (external edit)

Page Tools