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(boost::system::error_code ec) 68 { 69 std::cerr << "Error: " << ec << "\n"; 70 ++fatalErrors_; 71 } 72 73 void logException(const std::exception& e) 74 { 75 std::cerr << "Error: " << e.what() << "\n"; 76 ++fatalErrors_; 77 } 78 79 void logExpectedException( 80 const sdbusplus::exception::UnpackPropertyError& error) 81 { 82 std::cout << "As expected " << error.what() << " => " 83 << error.propertyName << " is missing because " 84 << error.reason << "\n"; 85 } 86 87 void asyncGetAllPropertiesStringTypeOnly() 88 { 89 sdbusplus::asio::getAllProperties( 90 bus_, xyz::demo::name, xyz::demo::path, xyz::demo::interface, 91 [this](boost::system::error_code ec, 92 std::vector<std::pair< 93 std::string, std::variant<std::monostate, std::string>>>& 94 properties) -> void { 95 if (ec) 96 { 97 logSystemErrorCode(ec); 98 return; 99 } 100 try 101 { 102 std::string greetings; 103 std::string goodbyes; 104 sdbusplus::unpackProperties(properties, name::greetings, 105 greetings, name::goodbyes, 106 goodbyes); 107 108 std::cout << "value of greetings: " << greetings << "\n"; 109 std::cout << "value of goodbyes: " << goodbyes << "\n"; 110 } 111 catch (const sdbusplus::exception::UnpackPropertyError& error) 112 { 113 logException(error); 114 } 115 116 try 117 { 118 std::string value; 119 sdbusplus::unpackProperties(properties, name::value, 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_, xyz::demo::name, xyz::demo::path, xyz::demo::interface, 136 [this](boost::system::error_code ec, 137 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, name::greetings, 152 greetings, name::goodbyes, 153 goodbyes, name::value, 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(properties, name::greetings, 183 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 boost::asio::io_context& ioc_; 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(xyz::demo::name.c_str()); 220 221 Application app(ioc, *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