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