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 method, on the other hand, can return multiple values. Via the signature of a signal or a method, you can easily see how many values are returned with a received signal or with a method call via their 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 to a given D-Bus signature. You can read the description of the two classes DBusVariant and DBusValues in chapter 24.9.8.0. Both classes have only the property Value 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:
See http://gambaswiki.org/wiki/doc/dbus#t10 for a table summarising how Gambas data types are converted to D-Bus data types and vice versa.

Definition: 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 their 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 signal “MountAdded” is analysed, which 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, for example, a USB stick is plugged in. You can use the console programme 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 situation is completely different for the third argument with the signature “ssssssbsassa{sv}”, which can be characterised as a complex data type:

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 table above, where the third argument is a variant array by type - recognisable by the enclosing round brackets in the signature. The round brackets are also noted in the D-Bus notation as Struct of (…). Array of [datatype] indicates an array with elements of the specified data type. For example, the D-Bus notation Dict of {…} 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 via the class DBusObserver with the message type 'DBus.Signal' and the event hDbusObserver_Message(), then this declaration of suitable variables and the subsequent value assignments (variable ⇒ argument value) are suitable:

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

For this example, you will be introduced to a D-Bus data server and a D-Bus client. The server provides a service where a method call (GetT(…)) with a (string) argument returns a value with a complex data type.


Figure 24.9.0.3.1: The service is used …

For demonstration purposes, the second example is deliberately constructed so that the signature of the return value of the GetT(…) method 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 specifications 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, after declaring the signature, you must define the method GetT(…) in another class file (MSService.class). 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 understand 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. For the client, an introspection of the server service was also implemented.

Download

The website uses a temporary session cookie. This technically necessary cookie is deleted when the browser is closed. You can find information on cookies in our privacy policy.
k24/k24.9/k24.9.0/k24.9.0.3/start.txt · Last modified: 16.08.2022 (external edit)

Page Tools