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), 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 true; 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 logUnpackError(const sdbusplus::UnpackErrorReason reason, 65 const std::string& property) 66 { 67 std::cerr << "UnpackError: " << static_cast<int>(reason) << ", " 68 << property << "\n"; 69 ++fatalErrors_; 70 } 71 72 void logExpectedException( 73 const sdbusplus::exception::UnpackPropertyError& error) 74 { 75 std::cout << "As expected " << error.what() << "\n"; 76 } 77 78 void asyncGetAllPropertiesStringTypeOnly() 79 { 80 sdbusplus::asio::getAllProperties( 81 bus_, demoServiceName, demoObjectPath, demoInterfaceName, 82 [this](const boost::system::error_code ec, 83 const 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 const std::string* greetings = nullptr; 93 const std::string* goodbyes = nullptr; 94 const bool success = sdbusplus::unpackPropertiesNoThrow( 95 [this](const sdbusplus::UnpackErrorReason reason, 96 const std::string& property) { 97 logUnpackError(reason, property); 98 }, 99 properties, propertyGrettingName, greetings, 100 propertyGoodbyesName, goodbyes); 101 102 if (success) 103 { 104 std::cout 105 << "value of greetings: " << *greetings << "\n"; 106 std::cout << "value of goodbyes: " << *goodbyes << "\n"; 107 } 108 else 109 { 110 ++fatalErrors_; 111 } 112 } 113 114 try 115 { 116 std::string value; 117 sdbusplus::unpackProperties(properties, propertyValueName, 118 value); 119 120 std::cerr << "Error: it should fail because of " 121 "not matched type\n"; 122 ++fatalErrors_; 123 } 124 catch (const sdbusplus::exception::UnpackPropertyError& error) 125 { 126 logExpectedException(error); 127 } 128 }); 129 } 130 131 void asyncGetAllProperties() 132 { 133 sdbusplus::asio::getAllProperties( 134 bus_, demoServiceName, demoObjectPath, demoInterfaceName, 135 [this](const boost::system::error_code ec, 136 const std::vector<std::pair< 137 std::string, 138 std::variant<std::monostate, std::string, uint32_t>>>& 139 properties) -> void { 140 if (ec) 141 { 142 logSystemErrorCode(ec); 143 return; 144 } 145 try 146 { 147 std::string greetings; 148 std::string goodbyes; 149 uint32_t value = 0u; 150 sdbusplus::unpackProperties( 151 properties, propertyGrettingName, greetings, 152 propertyGoodbyesName, goodbyes, propertyValueName, 153 value); 154 155 std::cout << "value of greetings: " << greetings << "\n"; 156 std::cout << "value of goodbyes: " << goodbyes << "\n"; 157 std::cout << "value of value: " << value << "\n"; 158 } 159 catch (const sdbusplus::exception::UnpackPropertyError& error) 160 { 161 logException(error); 162 } 163 164 try 165 { 166 std::string unknownProperty; 167 sdbusplus::unpackProperties( 168 properties, "UnknownPropertyName", unknownProperty); 169 170 std::cerr << "Error: it should fail because of " 171 "missing property\n"; 172 ++fatalErrors_; 173 } 174 catch (const sdbusplus::exception::UnpackPropertyError& error) 175 { 176 logExpectedException(error); 177 } 178 179 try 180 { 181 uint32_t notMatchingType; 182 sdbusplus::unpackProperties( 183 properties, propertyGrettingName, notMatchingType); 184 185 std::cerr << "Error: it should fail because of " 186 "not matched type\n"; 187 ++fatalErrors_; 188 } 189 catch (const sdbusplus::exception::UnpackPropertyError& error) 190 { 191 logExpectedException(error); 192 } 193 }); 194 } 195 196 private: 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([&ioc](const boost::system::error_code&, const int&) { 213 ioc.stop(); 214 }); 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