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