使用 dbus-cpp 列出 WPA 请求者网络属性
Posted
技术标签:
【中文标题】使用 dbus-cpp 列出 WPA 请求者网络属性【英文标题】:List WPA supplicant network properties using dbus-cpp 【发布时间】:2017-10-15 15:55:06 【问题描述】:当尝试列出网络属性 - https://w1.fi/wpa_supplicant/devel/dbus.html#dbus_network 使用 dbus-cpp 时,我收到了一些关于缺少 operator==
for 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/,但它们仅提供有限的帮助。 表示Properties属性的代码如下:
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
【问题讨论】:
+1 提示使用 apt-cache rdepends libdbus-cpp5。我一直在考虑使用这个 d-bus 绑定,但似乎支持很少。我想使用 Introspectable 接口,但那家伙甚至没有开箱即用地编译。 FWIW,我在 Ubuntu 14.04 上工作并尝试过:apt-cache rdepends libdbus-cpp2,它提供了几个服务。我现在正在研究其中的一些来源(例如 libubuntu-location-service-dev)。 【参考方案1】:更新:
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。所以:
asv :std::map<std::string, core::dbus::types::Variant>
av : 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 并且由于缺少 ==operator 实现而无法编译。 (我猜它需要转换特定的 ValueType)
dbus_object->get_all_properties() 调用不需要特定 ValueType 的 org.freedesktop.DBus.Properties.GetAll,因此它可以工作。
当然,这只是获取属性的一种解决方法,因为设置属性值与获取属性值绑定到相同的 shared_pointer。
【讨论】:
【参考方案2】:正如 fi.w1.wpa_supplicant1.Network.Properties.Properties 的文档所说:
[...] 所有值都是字符串类型,例如,频率是“2437”,而不是 2437。
所以尝试如下定义 DBusDict:
using DBusDict = std::map<std::string, std::string>;
【讨论】:
这显然是错误的。文档明确指出属性签名是“Properties - asv - (read/write)”。变体的内部无关紧要。我的意思是,它可以编译,但它会在运行时抛出org.freedesktop.DBus.Error.UnknownMethod: Method "Get" with signature "ss" on interface "org.freedesktop.DBus.Properties" doesn't exist
。以上是关于使用 dbus-cpp 列出 WPA 请求者网络属性的主要内容,如果未能解决你的问题,请参考以下文章
i.MX6ULL应用移植 | 移植wpa_supplicant到Linux开发板(2.7版本)
i.MX6ULL应用移植 | 移植wpa_supplicant到Linux开发板(2.7版本)
ini 使用带有此.conf文件的wpa_supplicant连接到WPA2企业网络。我用这个连接到我大学的无线网络。