DBus 协议 C++实现 (demo)

D-Bus

简介

待补充。。。

标准接口

org.freedesktop.DBus.Peer
org.freedesktop.DBus.Peer.Ping() //方法
org.freedesktop.DBus.Peer.GetMachineId(out STRING machine_uuid)	//方法

org.freedesktop.DBus.Introspectable
org.freedesktop.DBus.Introspectable.Introspect(输出 STRING xml_data)//方法

org.freedesktop.DBus.Properties
org.freedesktop.DBus.Properties.Get(
						in STRING interface_name, 
						in STRING property_name,
						out VARIANT value
						);	//方法
org.freedesktop.DBus.Properties.Set(
    					in STRING interface_name, 
						in STRING property_name,
						in VARIANT value
						);	//方法
org.freedesktop.DBus.Properties.GetAll(
				in STRING interface_name,
                out ARRAY of DICT_ENTRY<STRING,VARIANT> props);		//方法
                
org.freedesktop.DBus.ObjectManager
org.freedesktop.DBus.ObjectManager.GetManagedObjects(
				out ARRAY of DICT_ENTRY<OBJPATH,ARRAY of 
				DICT_ENTRY<STRING,ARRAY of 
				DICT_ENTRY<STRING,VARIANT>>> 
				objpath_interfaces_and_properties
				);
org.freedesktop.DBus.ObjectManager.InterfacesAdded(
				OBJPATH object_path,
				ARRAY of DICT_ENTRY<STRING,ARRAY of 
				DICT_ENTRY<STRING,VARIANT>> i
				nterfaces_and_properties
				);
org.freedesktop.DBus.ObjectManager.InterfacesRemoved(
				OBJPATH object_path,
				ARRAY<STRING> interfaces
				);

D-Bus工具

dbus-send

dbus-send 发送消息
dbus-send [--system | --session] --type=TYPE --print-reply --dest=连接名 对象路径 接口名.方法名 参数类型:参数值 参数类型:参数值
e.g.
dbus-send --session --type=method_call --print-reply --dest=连接名 对象路径 接口名.方法名 参数类型:参数值 参数类型:参数值
dbus-send --session --type=method_call --print-reply --dest=org.freedesktop.DBus / org.freedesktop.DBus.Introspectable.Introspect

dbus-send支持的参数类型包括:string, int32, uint32, double, byte, boolean。
Tips:如果是会话总线(session),不能在root用户下执行dbus-send命令

dbus-monitor

dbus-monitor监视通道上流动的消息
dbus-monitor [--system | --session | --address ADDRESS] [--profile | --monitor] [watch expressions]
e.g.
dbus-monitor "type='signal', sender='org.gnome.TypingMonitor', interface='org.gnome.TypingMonitor'"
Tips:不能在root用户下执行此命令

dbus-daemon

启动dbus-daemon的命令:(非root用户下
DBUS_VERBOSE=1 dbus-daemon --session --print-address

dbus-daemon是有地址的,环境变量DBUS_SESSION_BUS_ADDRESS用于表示当前登录用户的session的dbus-daemon进程的地址,可以使用echo $DBUS_SESSION_BUS_ADDRESS查看。
用自己启动的dbus-daemon转发消息:

  1. 启动一个dbus-daemon,输出如下:
xxxx@840-G7-PC:~$ DBUS_VERBOSE=1 dbus-daemon --session --print-address
unix:abstract=/tmp/dbus-dgsyNdddpv,guid=7d7666e25b903df290de42516569509f

  1. 用以下命令运行客户端、服务端程序
xxxx@840-G7-PC:~$ DBUS_SESSION_BUS_ADDRESS=unix:abstract=/tmp/dbus-dgsyNdddpv,guid=7d7666e25b903df290de42516569509f ./test_dbus_client
xxxx@840-G7-PC:~$ DBUS_SESSION_BUS_ADDRESS=unix:abstract=/tmp/dbus-dgsyNdddpv,guid=7d7666e25b903df290de42516569509f ./test_dbus_server

service

dbus中指的service是/usr/share/dbus-1/services 下的服务;
个人私自指定的服务也要放在此处。

D-Bus demo [1]

server端

#include <dbus/dbus.h>
#include <unistd.h>
#include <iostream>

void listen_signal(){
	DBusMessage * msg;
	DBusMessageIter arg;
	DBusConnection * connection;
	DBusError err;
	
	//init dbus error
	::dbus_error_init(&err);
	//建立dbus连接 (session)
	connection = ::dbus_bus_get(DBUS_BUS_SESSION, &err);
	//给 连接名(Bus name) 分配一个方便记忆的名字:test.singal.dest,这个步骤不是必须的,但推荐这样处理
	::dbus_bus_request_name(connection, "test.singal.dest", 
				DBUS_NAME_FLAG_REPLACE_EXISTING, &err);
	//通知D-Bus daemon,希望监听接口(test.signal.Type)的信号
	::dbus_bus_add_match(connection,"type='signal', interface='test.signal.Type'",&err);
	//实际需要发送东西给daemon来通知希望监听的内容,所以需要flush
    ::dbus_connection_flush(connection);
    /*在循环中监听,每隔开1秒,就去自己的连接中获取这个信号。
    这里给出的是连接中获取任何消息的方式,所以获取后去检查一下这个消息是否我们期望的信号,并获取内容。
    我们也可以通过这个方式来获取method call消息。*/
    while(1){
        ::dbus_connection_read_write(connection,0);
        msg = ::dbus_connection_pop_message (connection);
        if(msg == NULL){
            sleep(1);
            continue;
        }
        if(dbus_message_is_signal(msg,"test.signal.Type","Test")){
            if(!dbus_message_iter_init(msg,&arg))
                fprintf(stderr,"MessageHas no Param");
            else if(dbus_message_iter_get_arg_type(&arg)!= DBUS_TYPE_STRING)
                fprintf(stderr,"Param isnot string");
            else
                dbus_message_iter_get_basic(&arg,&sigvalue);
            printf("Recetive Singal Value : %s\n",sigvalue);
        }
        dbus_message_unref(msg);
    }//End of while
}

连接名 - Bus Name
唯一连接名 - unique connection name

当连接建立以后,D-Bus 服务会分配一个不可改变的连接名,称为唯一连接名(unique connection name),唯一连接名即使在进程结束后也不会再被其他进程所使用。唯一连接名以冒号开头,如“:34-907”。但唯一连接名总是临时分配,无法确定,也难以记忆,因此应用可以要求有另外一个名字公共名(well-known name)来对应唯一连接名。

client端

#include <dbus/dbus-glib.h>
#include <dbus/dbus.h>
#include <unistd.h>
#include <iostream>

int send_a_signal(const char *sigvalue){
	DBusError err;
    DBusConnection * connection;
    DBusMessage * msg;
    DBusMessageIter arg;
    dbus_uint32_t  serial = 0;
	//init dbus error
    dbus_error_init(&err);
    //建立dbus连接 (session)
	connection = ::dbus_bus_get(DBUS_BUS_SESSION, &err);
	/* 给 连接名 分配一个well-known的名字,这个步骤不是必须的,
	可以用if 0来注释着一段代码,我们可以用这个名字来检查是否已经
	开启了这个应用的另外的进程。*/
	#if 1
	    ::dbus_bus_request_name(connection, "test.singal.source", DBUS_NAME_FLAG_REPLACE_EXISTING, &err);
	    if(::dbus_error_is_set(&err)){
	        fprintf(stderr,"Name Err :%s\n",err.message);
	        ::dbus_error_free(&err);
	    }
	    if(ret !=DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER)
	        return -1;
	#endif
	//发送一个信号, 给出这个信号的路径(即可以指向对象)、接口、信号名,创建一个Message
	msg = ::dbus_message_new_signal("/test/signal/Object", "test.signal.Type", "Test");
	if(msg == NULL){
        fprintf(stderr,"MessageNULL\n");
        return -1;
    }
    //给这个信号(Messge)具体的内容
    ::dbus_message_iter_init_append(msg, &arg);
    bool ret = ::dbus_message_iter_append_basic(&arg, DBUS_TYPE_STRING, &sigvalue);
    if(!ret){
        fprintf(stderr,"Out OfMemory!\n");
        return -1;
    }
    printf("Signal Send: %s\n",sigvalue);
    //将信号从连接中发送
    bool res = ::dbus_connection_send(connection, msg, &serial);
    if(!res){
        fprintf(stderr,"Out of Memory!\n");
        return -1;
    }
    ::dbus_connection_flush(connection);
    printf("--------Success Signal Send----------\n");

    //释放相关的分配的内存。
    ::dbus_message_unref(msg);
    return 0;
}
  • 10
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
DBus(Desktop Bus)是一个进程间通信的机制,它可以让不同进程之间进行通信和交互。而DT7是大疆公司的一种飞控遥控器,它支持DBus协议来和其他系统进行通信。 如果你想在C++程序中调用DT7的DBus协议,你需要先安装DBus的开发库和DT7的DBus协议接口库。然后,你可以使用DBus的API来连接DT7的DBus协议接口,并调用DT7提供的方法来实现你的需求。 以下是一个简单的示例代码,演示如何使用DBus API来连接DT7的DBus协议接口,并调用DT7提供的方法: ```c++ #include <dbus/dbus.h> int main(int argc, char** argv) { // 初始化DBus连接 DBusError error; dbus_error_init(&error); DBusConnection* conn = dbus_bus_get(DBUS_BUS_SYSTEM, &error); if (dbus_error_is_set(&error)) { printf("DBus connection error: %s\n", error.message); dbus_error_free(&error); return 1; } // 连接DT7的DBus协议接口 const char* interface_name = "com.dji.dt7"; const char* object_path = "/com/dji/dt7"; const char* method_name = "get_battery_level"; DBusMessage* msg = dbus_message_new_method_call(interface_name, object_path, interface_name, method_name); DBusMessage* reply = dbus_connection_send_with_reply_and_block(conn, msg, -1, &error); if (dbus_error_is_set(&error)) { printf("DBus method call error: %s\n", error.message); dbus_error_free(&error); return 1; } // 解析DT7返回的数据 dbus_uint32_t battery_level = 0; dbus_message_get_args(reply, &error, DBUS_TYPE_UINT32, &battery_level, DBUS_TYPE_INVALID); if (dbus_error_is_set(&error)) { printf("DBus message error: %s\n", error.message); dbus_error_free(&error); return 1; } // 输出DT7返回的数据 printf("Battery level: %u\n", battery_level); // 释放DBus连接和消息 dbus_message_unref(msg); dbus_message_unref(reply); dbus_connection_unref(conn); return 0; } ``` 这个示例代码连接了DT7的DBus协议接口,调用了`get_battery_level`方法,并输出了DT7返回的电池电量。你可以根据自己的需求修改这个示例代码来调用DT7的其他DBus方法。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值