blob: 7a2d037d4191456e172417b9567ae5d48cb0b56c [file] [log] [blame]
#include <boost/asio.hpp>
#include <sdbusplus/asio/connection.hpp>
#include <sdbusplus/asio/object_server.hpp>
#include <sdbusplus/asio/property.hpp>
#include <sdbusplus/bus.hpp>
#include <sdbusplus/unpack_properties.hpp>
#include <iostream>
namespace xyz
{
namespace demo
{
const std::string path = "/xyz/demo";
const std::string name = "xyz.demo";
const std::string interface = "xyz.demo.interface";
} // namespace demo
} // namespace xyz
namespace name
{
const std::string greetings = "Greetings";
const std::string goodbyes = "Goodbyes";
const std::string value = "Value";
} // namespace name
class Application
{
public:
Application(boost::asio::io_context& ioc, sdbusplus::asio::connection& bus,
sdbusplus::asio::object_server& objServer) :
ioc_(ioc),
bus_(bus), objServer_(objServer)
{
demo_ = objServer_.add_interface(xyz::demo::path, xyz::demo::interface);
demo_->register_property_r(name::greetings, std::string(),
sdbusplus::vtable::property_::const_,
[this](const auto&) { return greetings_; });
demo_->register_property_rw(
name::goodbyes, std::string(),
sdbusplus::vtable::property_::emits_change,
[this](const auto& newPropertyValue, const auto&) {
goodbyes_ = newPropertyValue;
return 1;
},
[this](const auto&) { return goodbyes_; });
demo_->register_property_r(
name::value, uint32_t{42}, sdbusplus::vtable::property_::const_,
[](const auto& value) -> uint32_t { return value; });
demo_->initialize();
}
~Application()
{
objServer_.remove_interface(demo_);
}
uint32_t fatalErrors() const
{
return fatalErrors_;
}
auto logSystemErrorCode()
{
return [this](boost::system::error_code ec) {
std::cerr << "Error: " << ec << "\n";
++fatalErrors_;
};
}
void logException(const std::exception& e)
{
std::cerr << "Error: " << e.what() << "\n";
++fatalErrors_;
}
void logExpectedException(
const sdbusplus::exception::UnpackPropertyError& error)
{
std::cout << "As expected " << error.what() << " => "
<< error.propertyName << " is missing because "
<< error.reason << "\n";
}
void asyncGetAllPropertiesStringTypeOnly()
{
sdbusplus::asio::getAllProperties(
bus_, xyz::demo::name, xyz::demo::path, xyz::demo::interface,
logSystemErrorCode(),
[this](std::vector<std::pair<
std::string, std::variant<std::monostate, std::string>>>&
properties) {
try
{
std::string greetings;
std::string goodbyes;
sdbusplus::unpackProperties(properties, name::greetings,
greetings, name::goodbyes,
goodbyes);
std::cout << "value of greetings: " << greetings << "\n";
std::cout << "value of goodbyes: " << goodbyes << "\n";
}
catch (const sdbusplus::exception::UnpackPropertyError& error)
{
logException(error);
}
try
{
std::string value;
sdbusplus::unpackProperties(properties, name::value, value);
std::cerr << "Error: it should fail because of "
"not matched type\n";
++fatalErrors_;
}
catch (const sdbusplus::exception::UnpackPropertyError& error)
{
logExpectedException(error);
}
});
}
void asyncGetAllProperties()
{
sdbusplus::asio::getAllProperties(
bus_, xyz::demo::name, xyz::demo::path, xyz::demo::interface,
logSystemErrorCode(),
[this](
std::vector<std::pair<std::string,
std::variant<std::monostate, std::string,
uint32_t>>>& properties) {
try
{
std::string greetings;
std::string goodbyes;
uint32_t value = 0u;
sdbusplus::unpackProperties(properties, name::greetings,
greetings, name::goodbyes,
goodbyes, name::value, value);
std::cout << "value of greetings: " << greetings << "\n";
std::cout << "value of goodbyes: " << goodbyes << "\n";
std::cout << "value of value: " << value << "\n";
}
catch (const sdbusplus::exception::UnpackPropertyError& error)
{
logException(error);
}
try
{
std::string unknownProperty;
sdbusplus::unpackProperties(
properties, "UnknownPropertyName", unknownProperty);
std::cerr << "Error: it should fail because of "
"missing property\n";
++fatalErrors_;
}
catch (const sdbusplus::exception::UnpackPropertyError& error)
{
logExpectedException(error);
}
try
{
uint32_t notMatchingType;
sdbusplus::unpackProperties(properties, name::greetings,
notMatchingType);
std::cerr << "Error: it should fail because of "
"not matched type\n";
++fatalErrors_;
}
catch (const sdbusplus::exception::UnpackPropertyError& error)
{
logExpectedException(error);
}
});
}
private:
boost::asio::io_context& ioc_;
sdbusplus::asio::connection& bus_;
sdbusplus::asio::object_server& objServer_;
std::shared_ptr<sdbusplus::asio::dbus_interface> demo_;
std::string greetings_ = "Hello";
std::string goodbyes_ = "Bye";
uint32_t fatalErrors_ = 0u;
};
int main(int, char**)
{
boost::asio::io_context ioc;
boost::asio::signal_set signals(ioc, SIGINT, SIGTERM);
signals.async_wait(
[&ioc](const boost::system::error_code&, const int&) { ioc.stop(); });
auto bus = std::make_shared<sdbusplus::asio::connection>(ioc);
auto objServer = std::make_unique<sdbusplus::asio::object_server>(bus);
bus->request_name(xyz::demo::name.c_str());
Application app(ioc, *bus, *objServer);
boost::asio::post(ioc,
[&app] { app.asyncGetAllPropertiesStringTypeOnly(); });
boost::asio::post(ioc, [&app] { app.asyncGetAllProperties(); });
ioc.run();
std::cout << "Fatal errors count: " << app.fatalErrors() << "\n";
return app.fatalErrors();
}