错误 org.freedesktop.DBus.Error.UnknownMethod: 未知/无效的方法 ‘Notify’

huangapple go评论155阅读模式
英文:

Error org.freedesktop.DBus.Error.UnknownMethod: Unknown / invalid method 'Notify'

问题

我正在尝试使用godbus创建一个通知服务器,但是我无法正确地将我的服务器对象导出到dbus,dbus只能识别我的introspect xml。我正在按照https://specifications.freedesktop.org/notification-spec/notification-spec-latest.html进行实现。我还在我的服务器代码中使用了godbus存储库中的_example/server.go,你可以在下面提供的服务器代码中注意到这一点。
以下是服务器代码:

package main

import (
	"fmt"
	"os"

	"github.com/godbus/dbus/v5"
	"github.com/godbus/dbus/v5/introspect"
)

const xml = `
<node>
	<interface name="org.freedesktop.Notifications">
		<method name="Notify">
    		<arg direction="in" type="s"/>
    		<arg direction="in" type="u"/>
    		<arg direction="in" type="s"/>
    		<arg direction="in" type="s"/>
    		<arg direction="in" type="s"/>
    		<arg direction="in" type="as"/>
    		<arg direction="in" type="a{sv}"/>
    		<arg direction="in" type="i"/>
    		<arg direction="out" type="u"/>
		</method>

		<method name="GetCapabilities">
		    <arg direction="out" type="as"/>
		</method>

		<method name="GetServerInformation">
			<arg direction="out" type="s"/>
			<arg direction="out" type="s"/>
			<arg direction="out" type="s"/>
			<arg direction="out" type="s"/>
		</method>

		<method name="CloseNotification">
			<arg direction="in" type="u"/>
		</method>

		<signal name="NotificationClosed">
      		<arg type="u" name="id"/>
      		<arg type="u" name="reason"/>
    	</signal>
	</interface>` + introspect.IntrospectDataString + `</node> `

type NotificationServer struct {
}

func (s *NotificationServer) Notify(appName string, replacesID uint32, appIcon string, summary string, body string, actions []string, hints map[string]dbus.Variant, expireTimeout int32) (uint32, *dbus.Error) {
	fmt.Printf("New notification: %s\n", body)
	return 0, nil
}

func (s *NotificationServer) GetCapabilities() ([]string, *dbus.Error) {
	return []string{"action-icons", "actions", "body", "body-hyperlinks", "body-images", "body-markup", "icon-multi", "icon-static", "persistence", "sound"}, nil
}

func (s *NotificationServer) GetServerInformation() (string, string, string, string, *dbus.Error) {
	return "antarctica", "antarctica.com", "1.0", "1.2", nil
}

func (s *NotificationServer) CloseNotification(id uint32) *dbus.Error {
	s.NotificationClosed(id, 0)
	return nil
}
func (s *NotificationServer) NotificationClosed(id, reason uint32) {

}

func main() {
	conn, err := dbus.ConnectSessionBus()
	if err != nil {
		panic(err)
	}
	defer conn.Close()

	reply, err := conn.RequestName("com.antarctica.notification",
		dbus.NameFlagDoNotQueue)
	if err != nil {
		panic(err)
	}

	if reply != dbus.RequestNameReplyPrimaryOwner {
		fmt.Fprintln(os.Stderr, "name already taken")
		os.Exit(1)
	}
	server := NotificationServer{}
	err = conn.Export(server,"/org/freedesktop/Notifications","org.freedesktop.Notifications")
	if err != nil {
		panic(err)
	}
	conn.Export(introspect.Introspectable(xml), "/org/freedesktop/Notifications", "org.freedesktop.DBus.Introspectable")
	fmt.Println("Listening on com.antarctica.notification / /com/antarctica/notification ...")
	select {}
}

现在的问题是,尽管introspect xml对客户端是可访问的:

$ gdbus introspect --session --dest com.antarctica.notification --object-path /org/freedesktop/Notifications --xml
> 返回xml

但我无法使用我在服务器代码中编写的org.freedesktop.Notifications方法。例如,Notify是未知/无效的,对于每个方法都是如此:

$ dbus-send --session --print-reply=literal --dest=com.antarctica.notification /org/freedesktop/Notifications org.freedesktop.Notifications.Notify
> 错误 org.freedesktop.DBus.Error.UnknownMethod: Unknown / invalid method 'Notify'

此外,在qdbusviewer中,当我尝试执行任何方法时,它会显示“在接口org.freedesktop.Notifications的路径/org/freedesktop/Notifications上找不到方法x”。

我尝试过的方法:

  1. 检查dbus是否正在运行
  2. 检查我的服务器是否正在运行
  3. 我尝试重新启动dbus服务和我的计算机
  4. 我认为NotificationServer实例(server)根本没有被导出,但我不知道为什么
英文:

I am trying to make a notification server with godbus but i cant properly export my server object to dbus and dbus only recognizes my introspect xml. I am following https://specifications.freedesktop.org/notification-spec/notification-spec-latest.html to implement it. I have also used _example/server.go in godbus repo as you might notice in my server code provided below.
Here is the server code:

package main
import (
&quot;fmt&quot;
&quot;os&quot;
&quot;github.com/godbus/dbus/v5&quot;
&quot;github.com/godbus/dbus/v5/introspect&quot;
)
const xml = `
&lt;node&gt;
&lt;interface name=&quot;org.freedesktop.Notifications&quot;&gt;
&lt;method name=&quot;Notify&quot;&gt;
&lt;arg direction=&quot;in&quot; type=&quot;s&quot;/&gt;
&lt;arg direction=&quot;in&quot; type=&quot;u&quot;/&gt;
&lt;arg direction=&quot;in&quot; type=&quot;s&quot;/&gt;
&lt;arg direction=&quot;in&quot; type=&quot;s&quot;/&gt;
&lt;arg direction=&quot;in&quot; type=&quot;s&quot;/&gt;
&lt;arg direction=&quot;in&quot; type=&quot;as&quot;/&gt;
&lt;arg direction=&quot;in&quot; type=&quot;a{sv}&quot;/&gt;
&lt;arg direction=&quot;in&quot; type=&quot;i&quot;/&gt;
&lt;arg direction=&quot;out&quot; type=&quot;u&quot;/&gt;
&lt;/method&gt;
&lt;method name=&quot;GetCapabilities&quot;&gt;
&lt;arg direction=&quot;out&quot; type=&quot;as&quot;/&gt;
&lt;/method&gt;
&lt;method name=&quot;GetServerInformation&quot;&gt;
&lt;arg direction=&quot;out&quot; type=&quot;s&quot;/&gt;
&lt;arg direction=&quot;out&quot; type=&quot;s&quot;/&gt;
&lt;arg direction=&quot;out&quot; type=&quot;s&quot;/&gt;
&lt;arg direction=&quot;out&quot; type=&quot;s&quot;/&gt;
&lt;/method&gt;
&lt;method name=&quot;CloseNotification&quot;&gt;
&lt;arg direction=&quot;in&quot; type=&quot;u&quot;/&gt;
&lt;/method&gt;
&lt;signal name=&quot;NotificationClosed&quot;&gt;
&lt;arg type=&quot;u&quot; name=&quot;id&quot;/&gt;
&lt;arg type=&quot;u&quot; name=&quot;reason&quot;/&gt;
&lt;/signal&gt;
&lt;/interface&gt;` + introspect.IntrospectDataString + `&lt;/node&gt; `
type NotificationServer struct {
}
func (s *NotificationServer) Notify(appName string, replacesID uint32, appIcon string, summary string, body string, actions []string, hints map[string]dbus.Variant, expireTimeout int32) (uint32, *dbus.Error) {
fmt.Printf(&quot;New notification: %s\n&quot;, body)
return 0, nil
}
func (s *NotificationServer) GetCapabilities() ([]string, *dbus.Error) {
return []string{&quot;action-icons&quot;, &quot;actions&quot;, &quot;body&quot;, &quot;body-hyperlinks&quot;, &quot;body-images&quot;, &quot;body-markup&quot;, &quot;icon-multi&quot;, &quot;icon-static&quot;, &quot;persistence&quot;, &quot;sound&quot;}, nil
}
func (s *NotificationServer) GetServerInformation() (string, string, string, string, *dbus.Error) {
return &quot;antarctica&quot;, &quot;antarctica.com&quot;, &quot;1.0&quot;, &quot;1.2&quot;, nil
}
func (s *NotificationServer) CloseNotification(id uint32) *dbus.Error {
s.NotificationClosed(id, 0)
return nil
}
func (s *NotificationServer) NotificationClosed(id, reason uint32) {
}
func main() {
conn, err := dbus.ConnectSessionBus()
if err != nil {
panic(err)
}
defer conn.Close()
reply, err := conn.RequestName(&quot;com.antarctica.notification&quot;,
dbus.NameFlagDoNotQueue)
if err != nil {
panic(err)
}
if reply != dbus.RequestNameReplyPrimaryOwner {
fmt.Fprintln(os.Stderr, &quot;name already taken&quot;)
os.Exit(1)
}
server := NotificationServer{}
err = conn.Export(server,&quot;/org/freedesktop/Notifications&quot;,&quot;org.freedesktop.Notifications&quot;)
if err != nil {
panic(err)
}
conn.Export(introspect.Introspectable(xml), &quot;/org/freedesktop/Notifications&quot;, &quot;org.freedesktop.DBus.Introspectable&quot;)
fmt.Println(&quot;Listening on com.antarctica.notification / /com/antarctica/notification ...&quot;)
select {}
}

Now the problem is that eventho the introspect xml is accessible to client:

$ gdbus introspect --session --dest com.antarctica.notification --object-path /org/freedesktop/Notifications --xml
&gt; returns xml

I cant use org.freedesktop.Notifications methods that i wrote in my server code. for example Notify is Unknown/Invalid and this is the same for each method:

$ dbus-send --session --print-reply=literal --dest=com.antarctica.notification /org/freedesktop/Notifications org.freedesktop.Notifications.Notify
&gt; Error org.freedesktop.DBus.Error.UnknownMethod: Unknown / invalid method &#39;Notify&#39;

Also in qdbusviewer when I try to execute any method it says "Unable to find method x on path /org/freedesktop/Notifications in interface org.freedesktop.Notifications"

What I have tried:

  1. checked if dbus is running
  2. checked if my server is running
  3. I tried restarting dbus service and my computer as well
  4. I think NotificationServer instance (server) isnt being exported at all but i have no idea why

答案1

得分: 1

这个代码是可以工作的。你犯了两个错误:

  1. com.antarctica.notification
  2. func (s *NotificationServer)

你需要将名称请求为'org.freedesktop.Notifications',并且在函数中不能使用指针。

  1. org.freedesktop.Notifications
  2. func (s NotificationServer)
  3. (你也不需要introspection)
package main

import (
	"fmt"
	"os"

	"github.com/godbus/dbus/v5"
)

type notificationServer struct{}

func (s notificationServer) Notify(appName string, replacesID uint32, appIcon string, summary string, body string, actions []string, hints map[string]dbus.Variant, expireTimeout int32) (uint32, *dbus.Error) {
	fmt.Printf("新通知:%s\n", body)
	return 0, nil
}

func (s notificationServer) GetCapabilities() ([]string, *dbus.Error) {
	return []string{"action-icons", "actions", "body", "body-hyperlinks", "body-images", "body-markup", "icon-multi", "icon-static", "persistence", "sound"}, nil
}

func (s notificationServer) GetServerInformation() (string, string, string, string, *dbus.Error) {
	return "antarctica", "antarctica.com", "1.0", "1.2", nil
}

func main() {
	conn, err := dbus.ConnectSessionBus()
	if err != nil {
		panic(err)
	}
	defer conn.Close()

	f := notificationServer{}
	conn.Export(f, "/org/freedesktop/Notifications", "org.freedesktop.Notifications")

	reply, err := conn.RequestName("org.freedesktop.Notifications", dbus.NameFlagDoNotQueue)
	if err != nil {
		panic(err)
	}
	if reply != dbus.RequestNameReplyPrimaryOwner {
		fmt.Fprintln(os.Stderr, "名称已被占用")
		os.Exit(1)
	}
	fmt.Println("监听中...")
	select {}
}
英文:

This works. You made two mistakes:

  1. com.antarctica.notification
  2. func (s *NotificationServer)

You have to request 'org.freedesktop.Notifications' as name and you can not use a pointer in the func.

  1. org.freedesktop.Notifications
  2. func (s NotificationServer)
  3. (you don't need introspection either)
package main
import (
&quot;fmt&quot;
&quot;os&quot;
&quot;github.com/godbus/dbus/v5&quot;
)
type notificationServer struct{}
func (s notificationServer) Notify(appName string, replacesID uint32, appIcon string, summary string, body string, actions []string, hints map[string]dbus.Variant, expireTimeout int32) (uint32, *dbus.Error) {
fmt.Printf(&quot;New notification: %s\n&quot;, body)
return 0, nil
}
func (s notificationServer) GetCapabilities() ([]string, *dbus.Error) {
return []string{&quot;action-icons&quot;, &quot;actions&quot;, &quot;body&quot;, &quot;body-hyperlinks&quot;, &quot;body-images&quot;, &quot;body-markup&quot;, &quot;icon-multi&quot;, &quot;icon-static&quot;, &quot;persistence&quot;, &quot;sound&quot;}, nil
}
func (s notificationServer) GetServerInformation() (string, string, string, string, *dbus.Error) {
return &quot;antarctica&quot;, &quot;antarctica.com&quot;, &quot;1.0&quot;, &quot;1.2&quot;, nil
}
func main() {
conn, err := dbus.ConnectSessionBus()
if err != nil {
panic(err)
}
defer conn.Close()
f := notificationServer{}
conn.Export(f, &quot;/org/freedesktop/Notifications&quot;, &quot;org.freedesktop.Notifications&quot;)
reply, err := conn.RequestName(&quot;org.freedesktop.Notifications&quot;, dbus.NameFlagDoNotQueue)
if err != nil {
panic(err)
}
if reply != dbus.RequestNameReplyPrimaryOwner {
fmt.Fprintln(os.Stderr, &quot;name already taken&quot;)
os.Exit(1)
}
fmt.Println(&quot;Listening...&quot;)
select {}
}

huangapple
  • 本文由 发表于 2023年5月28日 16:47:55
  • 转载请务必保留本文链接:https://go.coder-hub.com/76350665.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定