使用 dbus-cpp 列出 WPA 请求方网络属性
List WPA supplicant network properties using dbus-cpp
尝试列出网络属性时 - https://w1.fi/wpa_supplicant/devel/dbus.html#dbus_network 使用 dbus-cpp 时,我收到许多关于缺少operator==
的错误core::dbus::types::Variant
/usr/include/core/dbus/impl/object.h:185:17: required from ‘std::shared_ptr<core::dbus::Property<PropertyDescription> > core::dbus::Object::get_property() [with PropertyDescription = fi::w1::wpa_supplicant1::Network::Properties::Propertiez]’ /home/martin/ClionProjects/ang-wifi-controller/src/wpasupplicantclient.cpp:149:118: required from here /usr/include/c++/6/bits/stl_pair.h:364:51: error: no match for ‘operator==’ (operand types are ‘const core::dbus::types::Variant’ and ‘const core::dbus::types::Variant’)
{ return __x.first == __y.first && __x.second == __y.second; }
我的代码基于 dbus-cpp 示例和 http://quaintous.com/2015/08/30/cpp11-dbus/,但它们只提供有限的帮助。 表示属性属性的代码如下所示:
namespace fi {
namespace w1 {
struct wpa_supplicant1 {
struct Network {
struct Properties {
struct Propertiez {
inline static std::string name() { return "Properties"; };
typedef Network Interface;
typedef std::map<std::string, core::dbus::types::Variant> ValueType;
static const bool readable = true;
static const bool writable = true;
};
};
};
.cpp的冒犯线是networkProxy->get_property<fi::w1::wpa_supplicant1::Network::Properties::Propertiez>();
我发现这个问题已经在 https://answers.launchpad.net/ubuntu/+source/dbus-cpp/+question/593271 上提出过,但没有人提供任何建议。浏览apt-cache rdepends libdbus-cpp5
列出的软件包代码也没有产生任何结果。 我尝试弄乱ValueType
但这一切都导致了运行时错误,因为预期的结果可能真的是地图。老实说,对我来说,这似乎是库中的一个错误,但由于这必须是一个明显的用例,我试图找到我在使用库时的错误。那我做错了什么呢?
编辑:由于我没有得到任何回应,所以我包括最少的样本。
#include <core/dbus/bus.h>
#include <core/dbus/object.h>
#include <core/dbus/property.h>
#include <core/dbus/service.h>
#include <core/dbus/result.h>
#include <core/dbus/asio/executor.h>
#include <core/dbus/interfaces/properties.h>
#include <core/dbus/types/stl/string.h>
#include <core/dbus/types/stl/tuple.h>
#include <core/dbus/types/stl/vector.h>
#include <core/dbus/types/struct.h>
#include <core/dbus/types/variant.h>
using namespace std::chrono_literals;
using DBusDict = std::map<std::string, core::dbus::types::Variant>;
namespace fi {
namespace w1 {
struct wpa_supplicant1
{
struct GetInterface {
typedef wpa_supplicant1 Interface;
static const std::string &name()
{
static const std::string s("GetInterface");
return s;
}
inline static const std::chrono::milliseconds default_timeout() { return 1s; }
};
struct Iface
{
struct AddNetwork {
typedef Iface Interface;
static const std::string &name()
{
static const std::string s("AddNetwork");
return s;
}
inline static const std::chrono::milliseconds default_timeout() { return 1s; }
};
struct Properties
{
struct Networks
{
inline static std::string name()
{ return "Networks"; };
typedef Iface Interface;
typedef std::vector<core::dbus::types::ObjectPath> ValueType;
static const bool readable = true;
static const bool writable = false;
};
};
};
struct Network
{
struct Properties
{
struct Propertiez
{
inline static std::string name()
{ return "Properties"; };
typedef Network Interface;
typedef DBusDict ValueType;
static const bool readable = true;
static const bool writable = true;
};
};
};
};
};
};
namespace core {
namespace dbus {
namespace traits {
template <> struct Service<fi::w1::wpa_supplicant1> {
inline static const std::string &interface_name()
{
static const std::string s("fi.w1.wpa_supplicant1");
return s;
}
};
template <> struct Service<fi::w1::wpa_supplicant1::Iface> {
inline static const std::string &interface_name()
{
static const std::string s("fi.w1.wpa_supplicant1.Interface");
return s;
}
};
template <> struct Service<fi::w1::wpa_supplicant1::Network> {
inline static const std::string &interface_name()
{
static const std::string s("fi.w1.wpa_supplicant1.Network");
return s;
}
};
}
}
}
int main()
{
//bus
auto systemBus = std::make_shared<core::dbus::Bus>(core::dbus::WellKnownBus::system);
systemBus->install_executor(core::dbus::asio::make_executor(systemBus));
auto busThread = std::thread(std::bind(&core::dbus::Bus::run, systemBus));
//service
auto wpaService = core::dbus::Service::use_service<fi::w1::wpa_supplicant1>(systemBus);
auto wpaObjectPath = core::dbus::types::ObjectPath("/fi/w1/wpa_supplicant1");
auto wpaRootProxy = wpaService->object_for_path(wpaObjectPath);
//iface
auto ifacePath = wpaRootProxy->transact_method<fi::w1::wpa_supplicant1::GetInterface,
core::dbus::types::ObjectPath,
std::string>("wlan0"); //change this to your own wireless interface
auto wpaIfaceProxy = wpaService->object_for_path(ifacePath.value());
auto networkPaths = wpaIfaceProxy->get_property<fi::w1::wpa_supplicant1::Iface::Properties::Networks>();
//network
std::string ssid("network");
std::string password("password");
DBusDict args = {
{"ssid", core::dbus::types::Variant::encode(ssid)},
{"psk", core::dbus::types::Variant::encode(password)},
};
auto networkPath = wpaIfaceProxy->transact_method<fi::w1::wpa_supplicant1::Iface::AddNetwork,
core::dbus::types::ObjectPath,
DBusDict>(args);
auto networkProxy = wpaService->object_for_path(networkPath.value());
//get properties - uncomment line below to get compiler errors
//auto netProps = networkProxy->get_property<fi::w1::wpa_supplicant1::Network::Properties::Propertiez>();
while (true) {
continue;
}
}
编译使用:g++ $(pkg-config --cflags dbus-1 dbus-cpp) ./main.cpp $(pkg-config --libs dbus-1 dbus-cpp) -lpthread
更新:
dbus-cpp 有一个用于 org.freedesktop.DBus.Properties.Get 方法的实现。
获取:
auto resultVariant = dbus_object->invoke_method_synchronously
/*Method*/ <dbus::interfaces::Properties::Get,
/*Output Type*/ dbus::types::Variant,
/*Input Types*/ std::string, std::string>
("fi.w1.wpa_supplicant1.Network","Properties").value();
auto props = resultVariant.as<std::map<std::string, dbus::types::Variant>>();
可悲的是,Set方法虽然也实现了,但似乎不适用于任何带有嵌套变体的 ArgumentType。所以:
- a{sv} :
std::map<std::string, core::dbus::types::Variant>
- a{v} :
std::vector<core::dbus::types::Variant>
在 Set 方法调用实际上会导致程序崩溃。(没有测试更多)
旧帖子:
我今天遇到了同样的错误,并找到了至少获取属性值的解决方法。
而不是使用
auto prop = dbus_object->get_property<fi::w1::wpa_supplicant1::Network::Properties::Propertiez>();
尝试
//returns std::map<std::string, core::dbus::types::Variant>>
auto props = dbus_object->get_all_properties<fi::w1::wpa_supplicant1::Network>();
auto prop = props["Properties"];
auto prop_value = prop.as<std::map<std::string, core::dbus::types::Variant>>();
据我了解该错误,dbus-cpp 利用了org.freedesktop.DBus.Properties 接口,用于读取属性。
因此,dbus_object->get_property() 尝试调用 org.freedesktop.DBus.Properties.Get 并由于缺少 ==运算符实现而无法编译。(我猜它是转换特定 ValueType 所需的东西)
dbus_object->get_all_properties() 调用不需要特定 ValueType 的 org.freedesktop.DBus.Properties.GetAll,因此它可以工作。
当然,这只是获取属性的一种解决方法,因为设置属性值与获取属性值绑定到相同的shared_pointer。
作为fi.w1.wpa_supplicant1的文档。网络属性属性 说:
[...]所有值都是字符串类型,例如,频率是"2437",而不是 2437。
因此,尝试按如下方式定义 DBusDict:
using DBusDict = std::map<std::string, std::string>;
- 我的神经网络不起作用 [XOR 问题]
- 如何导出包含具有"std::unique_ptr"值的"std::map"属性的
- C++概念:如何使用'concept'检查模板化结构的属性?
- GetShortPathName在网络驱动器上使用中文文件夹时失败
- 子目录是否继承属性,例如add_definitions,include_directories和父Cmakelist.t
- 通过指向指针数组的指针访问子类的属性
- MSVC是否支持C++11样式的属性而不是__declspec
- 通过网络、跨平台传递std::变体是否安全
- 如何在MNIST上提高网络运行的准确性
- QML:修改在不同QML文件(而非main.QML)中定义的子对象的属性
- 类的C++属性似乎已重新初始化
- Qt Quick-如何仅从c++代码与qml属性交互
- Active Directory:从网络服务帐户下运行的Windows服务调用ADsOpenObject时失败
- 用概念检查属性的类型
- C++如何将同一类的实例作为属性
- OpenCV 4.1.2 - 从网络摄像头获取帧并将其拆分
- 使用OpenCV和覆盆子上的多个网络摄像头拍摄延时摄影,出现多个V4L错误
- 按多个属性排序
- 使用 dbus-cpp 列出 WPA 请求方网络属性
- 用于修改网络接口属性的 Win32 API