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