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