从 DBUS org.freedesktop.dbus 和 java 获取数据 - org.freedesktop.DBus$Error$UnknownMethod: 方法不存在

Posted

技术标签:

【中文标题】从 DBUS org.freedesktop.dbus 和 java 获取数据 - org.freedesktop.DBus$Error$UnknownMethod: 方法不存在【英文标题】:Get data from DBUS org.freedesktop.dbus and java - org.freedesktop.DBus$Error$UnknownMethod: Method doesn't exist 【发布时间】:2019-03-12 05:46:32 【问题描述】:

我尝试从 dbus 服务获取一些数据并在 Java 中使用它。

我可以使用以下命令在cli中获取信息:

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

结果是:

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

我试图在 Java 中获取这些数据的是:

经过几个小时的阅读,我创建了一个界面。

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();


这里我调用getConnection()和getRemoteObject()成功了。

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;

...

解决所有依赖项并编译代码是一项艰巨的任务。但最后我做到了。所以,javac 现在运行没有错误。

但是如果我尝试调用方法 GetValue(),我会得到以下异常:

[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)

是否需要实现这个方法GetValue?但是为什么例如我该怎么做?我只想获取此信息,而不是像服务器一样提供它。

【问题讨论】:

【参考方案1】:

为什么获取所有依赖项是一项艰巨的任务? dbus-java 库和依赖项都在 maven Central 中可用,因此一个合适的 maven 项目应该开箱即用。

回到主题:

你不必实现GetValue(),但你需要一个适合BusItem的java接口。

据我在 victronenergy (https://www.victronenergy.com/live/open_source:ccgx:d-bus) 的文档中看到的,您的界面不正确。

您提供了 SetDefault()/GetDefault() 方法,这些方法仅适用于 com.victronenergy.settings 对象,但您想检索 com.victronenergy.BusItem(不是 com.victronenergy.settings 包的一部分)。

这是一个错误。第二个错误是:你为 BusItem 类使用了错误的包名。

在您的情况下,DBus 将尝试使用连接的 BusAddress com.victronenergy.solarcharger.ttyUSB0 未提供的路径 javadbus.BusItem 解析对象。

BusItem 类必须在包com.victronenergy 中,否则您必须使用注解@DBusInterfaceName("com.victronenergy.BusItem")

注解将告诉 DBus 库忽略 java 包/类名并使用注解中提供的名称。

【讨论】:

【参考方案2】:

接口 BusItem 由来自 https://dbus.freedesktop.org/doc/dbus-java/dbus-java/dbus-javase10.html 的 CreateInterface-Script 和来自 Introspect() 的 XML 创建

但是你解决了我真正的问题。我现在使用注释 @DBusInterfaceName("com.victronenergy.BusItem")。没有例外,我从我的太阳能充电器获取数据。非常感谢!

【讨论】:

以上是关于从 DBUS org.freedesktop.dbus 和 java 获取数据 - org.freedesktop.DBus$Error$UnknownMethod: 方法不存在的主要内容,如果未能解决你的问题,请参考以下文章

从 shell dbus-send 在 C 中调用 dbus

如何从控制台创建 dbus 服务?

无法从 ubuntu 中的服务连接到会话 dbus

如何从 Python 将无符号值发送到 dBus

如何在python中将dbus.Array从at解码为十六进制或字符串

有没有办法从 dbus-monitor 输出中排除某些接口/地址?