Перечислите свойства сети соискателя WPA, используя 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/, но они предлагают только ограниченную помощь.
Код, представляющий свойство 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

2

Решение

Обновить:

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

К сожалению, Задавать Метод, хотя и реализован, похоже, не работает с любыми типами ArgumentType с вложенными в них вариантами. Так:

  • a {sv}: std::map<std::string, core::dbus::types::Variant>
  • {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 () вызывает org.freedesktop.DBus.Properties.GetAll, который не требует определенного ValueType, поэтому он работает.


Конечно, это всего лишь обходной путь к получению свойств, поскольку установка значения свойства привязана к тому же shared_pointer, что и при получении.

2

Другие решения

В документации для fi.w1.wpa_supplicant1.Network.Properties.Properties говорится:

[…] Все значения имеют строковый тип, например, частота 2437, а не 2437.

Поэтому попробуйте определить DBusDict следующим образом:

using DBusDict = std::map<std::string, std::string>;
0

По вопросам рекламы [email protected]