User Tools

Site Tools


Sidebar

Network and communication

k24:k24.9:k24.9.8:k24.9.8.2:start

24.9.8.2 Projects - Create, export and use D-Bus object

This chapter introduces a gambas program that implements a D-Bus server that offers a service for d-bus-compatible programs that is provided by a D-Bus object exported to the Session D-Bus. The implemented service can be described in this way:

  • If the implemented method GetT(ShortScale As String) is called with a parameter of data type String from a d-bus-capable client, a return value with a complex data type is returned.
  • The complex data type described in the signature“(siiiava{sv})” - was chosen to cover a wide range of applications for your own projects.

The complex data type for the return value of the GetT(ShortScale As String) method has the signature“(siiiava{sv})”. This signature becomes understandable when you look at the (partial) data of the return value and its 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

Since the function value for GetT(ShortScale As String) is not a native data type, you have to convert the individual Gambas data types into D-Bus data types! Use the table at http://gambaswiki.org/wiki/doc/dbus#t10 to learn how to convert Gambas data types to D-Bus data types and vice versa.

Signatures have already been described in chapters 24.9.0.3 and 24.9.6.3.

24.9.8.2.1 Project Server

For a complex data type for the return value of the implemented method, the source code for the D-Bus server consists of at least 3 class files whose names you can freely define:

  • (A) In the file RValue.class the complex data type for the return value of the method GetT(…) is defined by its signature constant.
  • (B) The service is implemented in a D-Bus object described in a special class file MSService.class. The class uses the return value of the method GetT(…) from (A).
  • (C) In the start class FMain.class, the D-Bus object “/MSService” is exported from (B) to the Session D-Bus so that d-bus-compatible programs can use the service.

First you create a new class RValue.class to be exported (Export) and from the class DBusVariant (Inherits DBusVariant). Then define the required signature as a constant. The relevant source code of the class RValue.class in the first 6 lines is very short. All other lines are a description of the signature.

' Gambas class file
 
Export
Inherits DBusVariant
 
Public Const Signature As String = "(siiiava{sv})"
 
' Signature = "(siiiava{sv})"
'--------------------------------------------------------------
' 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
 
' The introspection shows the signature of the method and the type of the one argument
 
' 1. Case with the command 'dbus-send' in one console:
' dbus-send --session --print-reply --dest=org.gambas.dbusserver2 \
' /MSService org.freedesktop.DBus.Introspectable.Introspect \
' > tservice.introspection.xml
 
' 2. Case with code for introspection in DBusClient2:
' sXMLDocument = DBus[("session://" & "org.gambas.dbusserver2")]._Introspect("/MSService")
' Extract from the XML document:
'  ...
'   <interface name="org.gambas.dbusserver2.msservice">
'     <method name="GetT">
'       <arg name="arg1" type="s"/>
'       <arg name="value" type="(siiiava{sv})" direction="out"/>
'     </method>
'   </interface>
'  ...

Then declare a method GetT(…) in the file MSService.class whose function value is of type RValue. Proceed according to the following concept:

  1. First create a new object hItem of data type RValue (lines 14 and 59) in the GetT(ShortScale As String) As RValue function.
  2. Then assign the defined values (lines 21 to 30 and line 35) to all (partial) data that exist in the return value.
  3. Then assign the array[s0, i1, i2, i3, aTime, cTemperature] to the hItem.Value property, which follows the above signature “(siiiava{sv})”. First fill the variant array (lines 31) with the corresponding values and the collection with the planned value-key pairs (lines 55 to 57).
  4. Finally, return the object hItem with'Return hItem' as function value of GetT(…) (line 63).

The following source code in the MSService.class file implements the concept:

[1] ' Gambas class file
[2]
[3] Inherits DBusObject
[4] Create Static
[5]
[6] '' Definition of a signal:
[7] '' This signal has exactly 1 argument 'sFlag' of the data type string
[8] Event org_gambas_dbusserver2_MSService_OnOff(sFlag As String)
[9]
[10] '' Definition of a method:
[11] '' The method has exactly one argument.
[12] Public Function GetT(ShortScale As String) As RValue
[13]
[14]   Dim hItem As RValue
[15]   Dim s0, s1, s2, s3 As String
[16]   Dim i1, i2, i3, i4, i5, i6 As Integer
[17]   Dim f1 As Float
[18]   Dim aTime As Variant[]
[19]   Dim cTemperature As Collection
[20]
[21]   s0 = "Sensor 34 : 70358 KNX T-B-UP"
[22]
[23]   i1 = Day(Now())
[24]   i2 = Month(Now())
[25]   i3 = Year(Now())
[26]
[27]   i4 = Hour(Now())
[28]   i5 = Minute(Now())
[29]   i6 = Second(Now())
[30]   s1 = "LocalTime"
[31]   aTime = [i4, i5, i6, s1]
[32]
[33] ' The temperature value is read out in real operation from an RS232-AD converter
[34] ' A random value for the current temperature is generated here
[35]   f1 = Round(Rnd(-3, 2), -4)
[36]
[37]   Select Case ShortScale
[38]     Case "C"
[39]       s2 = "°"
[40]       s3 = "C"
[41]     Case "K"
[42]       f1 = f1 + 273.15
[43]       s2 = ""
[44]       s3 = "K"
[45]     Case "F"
[46]       f1 = (9 / 5) * f1 + 32
[47]       s2 = "°"
[48]       s3 = "F"
[49]     Default
[50]       s2 = "°"
[51]       s3 = "C"
[52]   End Select
[53]
[54]   cTemperature = New Collection
[55]   cTemperature.Add(f1, "Temperature") ' Temperature
[56]   cTemperature.Add(s2, "Label")       ' Label
[57]   cTemperature.Add(s3, "Scale")       ' Temperature scale
[58]
[59]   hItem = New RValue
[60] ' hItem.Value with complex data type:
[61]   hItem.Value = [s0, i1, i2, i3, aTime, cTemperature]
[62]
[63]   Return hItem
[64]
[65] End

Hint:

Line 8 declares a signal with an argument. This signal is sent when the server is shut down or restarted. The client intercepts this signal and reacts according to the read-out value (“on” or “off”) of the argument.

In the source code of FMain.class, the registration of the D-Bus object in line 15 and the transmission of a D-Bus signal in lines 22 and 41 are the central instructions after a new D-Bus object of type MSService has been created in line 8:

[1] ' Gambas class file
[2]
[3] Private hDBusObject As MSService
[4] Private hDBusSignal As DBusSignal
[5]
[6] Public Sub Form_Open()
[7]
[8]   hDBusObject = New MSService
[9]
[10]   FMain.Resizable = False
[11]   FMain.Caption = ("The data server is activated")
[12]   DBus.Unique = True
[13] ' For tests only: DBus.Debug = True
[14]
[15]   Try DBus.Session.Register(hDBusObject, "/MSService")
[16]   If Error Then
[17]      Message.Error("An instance of " & Application.Name & " already exists.")
[18]      FMain.Close()
[19]   Endif
[20]
[21]   hDBusSignal = New DBusSignal(DBus.Session, Null, True)
[22]   SendSignal("on")
[23]
[24] End
[25]
[26] Private Sub SendSignal(OnOff As String)
[27]
[28]   Dim sSignalName As String
[29]   Dim aArguments As New Variant[]
[30]
[31]   sSignalName = "org.gambas.dbusserver2.MSService.OnOff"
[32]   aArguments = [OnOff]
[33]
[34]   DBus.Raise(hDBusObject, sSignalName, aArguments)
[35]
[36] End
[37]
[38] Public Sub Form_Close()
[39]
[40]   SendSignal("off")
[41]
[42]   If hDBusSignal Then hDBusSignal.Enabled = False
[43]   If DBus.IsRegistered(hDBusObject) Then DBus.Session.Unregister(hDBusObject)
[44]
[45]   FMain.Close()
[46]
[47] End

24.9.8.2.2 Project Client

The complete source code for the client dbusclient2 is specified and then commented:

[1] ' Gambas class file
[2]
[3] Private $hDBusProxy As DBusProxy
[4] Private $hDBusSignal As DBusSignal
[5]
[6] Private $sDBusName As String
[7] Private $sDBusObjectPath As String
[8] Private $sReportLine As String
[9] Private $hDate As Date
[10] Private $bInspectable As Boolean
[11] Private k As Integer
[12] Private $iFirst As Integer
[13]
[14] Public Sub Form_Open()
[15]
[16]   Dim sMessage As String
[17]
[18]   DBus.Debug = True
[19]   FMain.Resizable = False
[20]   FMain.Caption = ("Remote data enquiry via D-Bus")
[21]   Application.MainWindow = FMain
[22]
[23]   cmbScale.Add("Celsius")
[24]   cmbScale.Add("Kelvin")
[25]   cmbScale.Add("Fahrenheit")
[26]   cmbScale.Index = 0
[27]
[28]   $sDBusName = "org.gambas.dbusserver2"
[29]   $sDBusObjectPath = "/MSService"
[30]
[31] If Not DBus.Session.Applications.Exist($sDBusName) Then
[32]      sMessage = ("There is no suitable data server on the session bus!")
[33]      sMessage &= "<center><font color='red'>"
[34]      sMessage &= ("The program is terminated.")
[35]      sMessage &= "</font></center>"
[36]      Message.Warning(sMessage)
[37]      FMain.Close()
[38]   Else
[39]     $hDBusProxy = DBus[$sDBusName][$sDBusObjectPath]
[40]     SetLEDColor(picStatus, "green")
[41]     $bInspectable = True
[42]     $hDBusSignal = New DBusSignal(DBus.Session, Null, True) As "ObservedSignal"
[43]   Endif
[44]
[45] End
[46]
[47] Public Sub ObservedSignal_Signal(Signal As String, Arguments As Variant[])
[48]
[49]   If Lower(Signal) = "onoff" And If Arguments[0] = "on" Then
[50]      If $iFirst = 0 Then Inc $iFirst
[51]      txaReport.Insert(gb.NewLine)
[52]      txaReport.Insert("   " & ("The data server is online!") & gb.NewLine)
[53]      txaReport.Pos = txaReport.Length
[54]      $bInspectable = True
[55]      SetLEDColor(picStatus, "green")
[56]      SendSound("on.wav")
[57]   Endif
[58]   If Lower(Signal) = "onoff" And If Arguments[0] = "off" Then
[59]      txaReport.Insert(gb.NewLine & gb.NewLine)
[60]      txaReport.Insert("   " & ("The data server is down!") & gb.NewLine)
[61]      txaReport.Pos = txaReport.Length
[62]      $bInspectable = False
[63]      SetLEDColor(picStatus, "red")
[64]      SendSound("off.wav")
[65]   Endif
[66]
[67] End
[68]
[69] Private Sub GetData()
[70]
[71] '  <interface name="org.gambas.dbusserver2.msservice">
[72] '    <method name="GetT">
[73] '      <arg name="arg1" type="s"/>
[74] '      <arg name="value" type="(iiiava{sv})" direction="out"/>
[75] '    </method>
[76] '  </interface>
[77]
[78]   Dim R As Variant[] ' Result
[79]
[80]   R = $hDBusProxy.GetT(Left(cmbScale.Text))
[81]
[82]   ' Print R[0]        ' Sensor Number/Type
[83]   ' Print R[1]        ' Day     15
[84]   ' Print R[2]        ' Month   12
[85]   ' Print R[3]        ' Year    2017
[86]   ' Print R[4][0]     ' Hour    15
[87]   ' Print R[4][1]     ' Minute  24
[88]   ' Print R[4][2]     ' Second   37
[89]   ' Print R[4][3]     ' Time zone "LocelTime"
[90]   ' Print R[5]["T"]   ' Temperature 22.4
[91]   ' Print R[5]["L"]   ' Label       °
[92]   ' Print R[5]["S"]   ' Scale       C
[93]
[94]   $hDate = Date(R[3], R[2], R[1], R[4][0], R[4][1], R[4][2])
[95]
[96]   txaReport.Insert(gb.NewLine)
[97]   If k = 0 Then
[98]      $sReportLine = "   " & R[0] & "   | " & R[4][3] & gb.NewLine & gb.NewLine
[99]      txaReport.Insert($sReportLine)
[100]      Inc k
[101]   Endif
[102]   $sReportLine = "   " & Format($hDate, "dd. mmmm yyyy  -  hh:nn:ss")
[103]   $sReportLine &= " Uhr"
[104]   $sReportLine &= "   |   " & ("Temperature") & " =  "
[105]   If cmbScale.Text = "Kelvin" Then
[106]      $sReportLine &= Format(R[5]["Temperature"], "0.#0") & " " & R[5]["Label"] & R[5]["Scale"]
[107]   Else
[108]      $sReportLine &= Format(R[5]["Temperature"], "+0.#0") & " " & R[5]["Label"] & R[5]["Scale"]
[109]   Endif
[110]   txaReport.Insert($sReportLine)
[111]   txaReport.Pos = txaReport.Length
[112]
[113] End
[114]
[115] Public Sub btnGetData_Click()
[116]   If DBus.Session.Applications.Exist($sDbusName) Then
[117]      SetLEDColor(picStatus, "green")
[118]      GetData()
[119]      $bInspectable = True
[120]   Else
[121]      SetLEDColor(picStatus, "red")
[122]   Endif
[123] End
[124]
[125] '' Sends a sound<br>
[126] '' Sound: Name of the sound file in the project folder 'sounds'.<br>
[127] '' Play back audio files on a PulseAudio sound server - the player is 'paplay'
[128] Public Sub SendSound(SoundFileName As String)
[129]   If System.Exist("paplay") Then
[130]      Shell "paplay " & Application.Path &/ "sounds" &/ SoundFileName
[131]   Endif
[132] End
[133]
[134] Private Sub SetLEDColor(picBox As PictureBox, sLEDColor As String)
[135]   picBox.Picture = Picture["LED/led_" & sLEDColor & ".svg"]
[136] End
[137]
[138] Public Sub btnIntrospektion_Click()
[139]   If $bInspectable = True Then FIntrospection.Show()
[140] End
[141]
[142] Public Sub Form_Close()
[143]   If $hDBusSignal Then $hDBusSignal.Enabled = False
[144]   FMain.Close()
[145] End

Comment:

  • Line 17 checks if the application with the D-Bus name org.gambas.dbusserver2 exists on the session bus. If this is the case, a proxy is created after the assignment in line 31 in line 39 and worked with this.
  • In the procedure GetData() in line 80, the method GetT(ShortScale As String) implemented in the D-Bus object “/MSService” is called with one of the three possible arguments and the return value with the complex data type is read into the variable R.
  • All (partial) data corresponding to the known signature“(siiiava{sv})” in lines 94 to 111 are extracted and displayed.

24.9.8.2.3 Use of server and client

Server

B1

Figure 24.9.8.2.1: Server GUI

The server is started, exports a D-Bus object to the Session D-Bus with the implemented service and waits for requests from d-bus-capable clients.

The presented client uses the offered service of the server:

B2

Figure 24.9.8.2.2: Client GUI

B3

Figure 24.9.8.2.3: Two temperature queries

You can use a combo box to define the argument for the method call so that the temperature values are retrieved in the temperature scale defined in this way. The conversion takes place on the server and is part of the service offered.

B4

Figure 24.9.8.2.4: The server is switched off

The permanent monitoring of the “OnOff” signal by the client informs you visually and acoustically at any time when the server is switched off or restarted successfully.

B5

Figure 24.9.8.2.5: The server is online again

Figure 24.9.8.2.6: The service will continue to be used…

At any time you can find out about the implemented method, its signature and the input parameter via an implemented introspection that is implemented by clicking the i button. You can also close the window with the ESC key.

Figure 24.9.8.2.7: Successful introspection of the “/MSService” object

The following figure shows the use of the d-feet program to use the server's service:

DFEET

Figure 24.9.8.2.8: Method call with the argument 'F'

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.8/k24.9.8.2/start.txt · Last modified: 02.07.2018 (external edit)

Page Tools