1 #include <boost/asio.hpp> 2 #include <sdbusplus/asio/connection.hpp> 3 #include <sdbusplus/asio/object_server.hpp> 4 #include <sdbusplus/asio/property.hpp> 5 #include <sdbusplus/bus.hpp> 6 #include <sdbusplus/unpack_properties.hpp> 7 8 #include <iostream> 9 10 namespace xyz 11 { 12 namespace demo 13 { 14 15 const std::string path = "/xyz/demo"; 16 const std::string name = "xyz.demo"; 17 const std::string interface = "xyz.demo.interface"; 18 19 } // namespace demo 20 } // namespace xyz 21 22 namespace name 23 { 24 25 const std::string greetings = "Greetings"; 26 const std::string goodbyes = "Goodbyes"; 27 const std::string value = "Value"; 28 29 } // namespace name 30 31 class Application 32 { 33 public: 34 Application(boost::asio::io_context& ioc, sdbusplus::asio::connection& bus, 35 sdbusplus::asio::object_server& objServer) : 36 ioc_(ioc), 37 bus_(bus), objServer_(objServer) 38 { 39 demo_ = objServer_.add_unique_interface(xyz::demo::path, 40 xyz::demo::interface); 41 42 demo_->register_property_r(name::greetings, std::string(), 43 sdbusplus::vtable::property_::const_, 44 [this](const auto&) { return greetings_; }); 45 46 demo_->register_property_rw( 47 name::goodbyes, std::string(), 48 sdbusplus::vtable::property_::emits_change, 49 [this](const auto& newPropertyValue, const auto&) { 50 goodbyes_ = newPropertyValue; 51 return 1; 52 }, 53 [this](const auto&) { return goodbyes_; }); 54 55 demo_->register_property_r( 56 name::value, uint32_t{42}, sdbusplus::vtable::property_::const_, 57 [](const auto& value) -> uint32_t { return value; }); 58 59 demo_->initialize(); 60 } 61 62 uint32_t fatalErrors() const 63 { 64 return fatalErrors_; 65 } 66 67 auto logSystemErrorCode() 68 { 69 return [this](boost::system::error_code ec) { 70 std::cerr << "Error: " << ec << "\n"; 71 ++fatalErrors_; 72 }; 73 } 74 75 void logException(const std::exception& e) 76 { 77 std::cerr << "Error: " << e.what() << "\n"; 78 ++fatalErrors_; 79 } 80 81 void logExpectedException( 82 const sdbusplus::exception::UnpackPropertyError& error) 83 { 84 std::cout << "As expected " << error.what() << " => " 85 << error.propertyName << " is missing because " 86 << error.reason << "\n"; 87 } 88 89 void asyncGetAllPropertiesStringTypeOnly() 90 { 91 sdbusplus::asio::getAllProperties( 92 bus_, xyz::demo::name, xyz::demo::path, xyz::demo::interface, 93 logSystemErrorCode(), 94 [this](std::vector<std::pair< 95 std::string, std::variant<std::monostate, std::string>>>& 96 properties) { 97 try 98 { 99 std::string greetings; 100 std::string goodbyes; 101 sdbusplus::unpackProperties(properties, name::greetings, 102 greetings, name::goodbyes, 103 goodbyes); 104 105 std::cout << "value of greetings: " << greetings << "\n"; 106 std::cout << "value of goodbyes: " << goodbyes << "\n"; 107 } 108 catch (const sdbusplus::exception::UnpackPropertyError& error) 109 { 110 logException(error); 111 } 112 113 try 114 { 115 std::string value; 116 sdbusplus::unpackProperties(properties, name::value, value); 117 118 std::cerr << "Error: it should fail because of " 119 "not matched type\n"; 120 ++fatalErrors_; 121 } 122 catch (const sdbusplus::exception::UnpackPropertyError& error) 123 { 124 logExpectedException(error); 125 } 126 }); 127 } 128 129 void asyncGetAllProperties() 130 { 131 sdbusplus::asio::getAllProperties( 132 bus_, xyz::demo::name, xyz::demo::path, xyz::demo::interface, 133 logSystemErrorCode(), 134 [this]( 135 std::vector<std::pair<std::string, 136 std::variant<std::monostate, std::string, 137 uint32_t>>>& properties) { 138 try 139 { 140 std::string greetings; 141 std::string goodbyes; 142 uint32_t value = 0u; 143 sdbusplus::unpackProperties(properties, name::greetings, 144 greetings, name::goodbyes, 145 goodbyes, name::value, value); 146 147 std::cout << "value of greetings: " << greetings << "\n"; 148 std::cout << "value of goodbyes: " << goodbyes << "\n"; 149 std::cout << "value of value: " << value << "\n"; 150 } 151 catch (const sdbusplus::exception::UnpackPropertyError& error) 152 { 153 logException(error); 154 } 155 156 try 157 { 158 std::string unknownProperty; 159 sdbusplus::unpackProperties( 160 properties, "UnknownPropertyName", unknownProperty); 161 162 std::cerr << "Error: it should fail because of " 163 "missing property\n"; 164 ++fatalErrors_; 165 } 166 catch (const sdbusplus::exception::UnpackPropertyError& error) 167 { 168 logExpectedException(error); 169 } 170 171 try 172 { 173 uint32_t notMatchingType; 174 sdbusplus::unpackProperties(properties, name::greetings, 175 notMatchingType); 176 177 std::cerr << "Error: it should fail because of " 178 "not matched type\n"; 179 ++fatalErrors_; 180 } 181 catch (const sdbusplus::exception::UnpackPropertyError& error) 182 { 183 logExpectedException(error); 184 } 185 }); 186 } 187 188 private: 189 boost::asio::io_context& ioc_; 190 sdbusplus::asio::connection& bus_; 191 sdbusplus::asio::object_server& objServer_; 192 193 std::unique_ptr<sdbusplus::asio::dbus_interface> demo_; 194 std::string greetings_ = "Hello"; 195 std::string goodbyes_ = "Bye"; 196 197 uint32_t fatalErrors_ = 0u; 198 }; 199 200 int main(int, char**) 201 { 202 boost::asio::io_context ioc; 203 boost::asio::signal_set signals(ioc, SIGINT, SIGTERM); 204 205 signals.async_wait( 206 [&ioc](const boost::system::error_code&, const int&) { ioc.stop(); }); 207 208 auto bus = std::make_shared<sdbusplus::asio::connection>(ioc); 209 auto objServer = std::make_unique<sdbusplus::asio::object_server>(bus); 210 211 bus->request_name(xyz::demo::name.c_str()); 212 213 Application app(ioc, *bus, *objServer); 214 215 boost::asio::post(ioc, 216 [&app] { app.asyncGetAllPropertiesStringTypeOnly(); }); 217 boost::asio::post(ioc, [&app] { app.asyncGetAllProperties(); }); 218 219 ioc.run(); 220 221 std::cout << "Fatal errors count: " << app.fatalErrors() << "\n"; 222 223 return app.fatalErrors(); 224 } 225