Search code examples
javainterfacedbus

Get data from DBUS org.freedesktop.dbus and java - org.freedesktop.DBus$Error$UnknownMethod: Method doesn't exist


I try to get some data from a dbus service and work with it in Java.

I can get the information in cli with the following command:

dbus-send --print-reply --system --dest=com.victronenergy.solarcharger.ttyUSB0 /Dc/0/Voltage com.victronenergy.BusItem.GetValue

The result is:

method return time=1538903662.321580 sender=:1.14 -> destination=:1.806 serial=335692 reply_serial=2
variant       double 13.43

What I tried to get this data in Java, is:

After hours of reading, I created an Interface.

package javadbus;

import java.util.Map;
import org.freedesktop.dbus.DBusInterface;
import org.freedesktop.dbus.DBusSignal;
import org.freedesktop.dbus.Variant;
import org.freedesktop.dbus.exceptions.DBusException;
public interface BusItem extends DBusInterface
{
   public static class PropertiesChanged extends DBusSignal
   {
      public final Map<String,Variant> changes;
      public PropertiesChanged(String path, Map<String,Variant> changes) throws DBusException
      {
         super(path, changes);
         this.changes = changes;
      }
   }

  public String GetDescription(String language, int length);
  public Variant GetValue();
  public String GetText();
  public int SetValue(Variant value);
  public Variant GetMin();
  public Variant GetMax();
  public int SetDefault();
  public Variant GetDefault();

}

Here I call getConnection() and getRemoteObject() successfully.

package javadbus;
import org.freedesktop.dbus.DBusConnection;
import org.freedesktop.dbus.exceptions.DBusException;
import org.freedesktop.dbus.Variant;

public class VictronEnergyDBusSolarCharger {

private String port;
private DBusConnection conn;

public VictronEnergyDBusSolarCharger(String port) {
    this.port = port;
    try {
        this.conn = DBusConnection.getConnection(DBusConnection.SYSTEM);
    } catch (DBusException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}

private String getData(String item) {
    BusItem bi;
    String data = null;
    Variant vData = null;
    try {
        bi = (BusItem)conn.getRemoteObject("com.victronenergy.solarcharger." + this.port, item, BusItem.class);
        vData = bi.GetValue();
        //data = bi.GetText();
    } catch (DBusException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    return data;
}
...
}

It was a big task to resolve all dependecies and get the code compiled. But finaly I did it. So, javac now runs without errors.

But if I try to call the Method GetValue(), I get the following Exception:

[Sender] INFO org.freedesktop.dbus.MessageWriter - <= MethodCall(0,1) { Path=>/org/freedesktop/DBus, Interface=>org.freedesktop.DBus, Member=>Hello, Destination=>org.freedesktop.DBus } { }
[Sender] INFO org.freedesktop.dbus.MessageWriter - <= MethodCall(0,3) { Path=>/Dc/0/Voltage, Interface=>javadbus.BusItem, Member=>GetValue, Destination=>com.victronenergy.solarcharger.ttyUSB0 } { }
Exception in thread "main" org.freedesktop.DBus$Error$UnknownMethod: Method "GetValue" with signature "" on interface "javadbus.BusItem" doesn't exist
        at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
        at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
        at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
        at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
        at org.freedesktop.dbus.Error.getException(Error.java:141)
        at org.freedesktop.dbus.Error.throwException(Error.java:171)
        at org.freedesktop.dbus.RemoteInvocationHandler.executeRemoteMethod(RemoteInvocationHandler.java:158)
        at org.freedesktop.dbus.RemoteInvocationHandler.invoke(RemoteInvocationHandler.java:222)
        at com.sun.proxy.$Proxy1.GetValue(Unknown Source)
        at javadbus.VictronEnergyDBusSolarCharger.getData(VictronEnergyDBusSolarCharger.java:28)
        at javadbus.VictronEnergyDBusSolarCharger.getDcV(VictronEnergyDBusSolarCharger.java:38)
        at javadbus.MainClass.main(MainClass.java:7)

Is it necessary to make a implementation of this Method GetValue? But why e.g. how should I do this? I only want to get this Information and not provide it like a Server.


Solution

  • Why was it a big task to get all dependencies? dbus-java library and dependencies are all available at maven central, so a proper maven project should just work out-of-the-box.

    Back to topic:

    You don't have to implement GetValue(), but you need a suitable java interface for BusItem.

    As far as I can see in the documentation of victronenergy (https://www.victronenergy.com/live/open_source:ccgx:d-bus) , your interface is not correct.

    You provide SetDefault()/GetDefault() methods, which are only available on com.victronenergy.settings Objects, but you want to retrieve a com.victronenergy.BusItem (no part of the com.victronenergy.settings package).

    This is one error. The second error is: you use the wrong package name for your BusItem class.

    In your case DBus will try to resolve an object with the path javadbus.BusItem which is not provided by the connected BusAddress com.victronenergy.solarcharger.ttyUSB0.

    The BusItem class has to be in package com.victronenergy or you have to use the annotation @DBusInterfaceName("com.victronenergy.BusItem").

    The annotation will tell the DBus library to ignore the java package/class name and use the one provided in the annotation.