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 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 16 class Application 17 { 18 public: 19 Application(boost::asio::io_context& ioc, sdbusplus::asio::connection& bus, 20 sdbusplus::asio::object_server& objServer) : 21 ioc_(ioc), 22 bus_(bus), objServer_(objServer) 23 { 24 demo_ = objServer_.add_unique_interface( 25 demoObjectPath, demoInterfaceName, 26 [this](sdbusplus::asio::dbus_interface& demo) { 27 demo.register_property_r<std::string>( 28 propertyGrettingName, sdbusplus::vtable::property_::const_, 29 [this](const auto&) { return greetings_; }); 30 31 demo.register_property_rw<std::string>( 32 propertyGoodbyesName, 33 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 } 41 42 uint32_t fatalErrors() const 43 { 44 return fatalErrors_; 45 } 46 47 auto getFailed() 48 { 49 return [this](boost::system::error_code error) { 50 std::cerr << "Error: getProperty failed " << error << "\n"; 51 ++fatalErrors_; 52 }; 53 } 54 55 void asyncReadPropertyWithIncorrectType() 56 { 57 sdbusplus::asio::getProperty<uint32_t>( 58 bus_, demoServiceName, demoObjectPath, demoInterfaceName, 59 propertyGrettingName, 60 [this](boost::system::error_code ec, uint32_t) { 61 if (ec) 62 { 63 std::cout 64 << "As expected failed to getProperty with wrong type: " 65 << ec << "\n"; 66 return; 67 } 68 69 std::cerr << "Error: it was expected to fail getProperty due " 70 "to wrong type\n"; 71 ++fatalErrors_; 72 }); 73 } 74 75 void asyncReadProperties() 76 { 77 sdbusplus::asio::getProperty<std::string>( 78 bus_, demoServiceName, demoObjectPath, demoInterfaceName, 79 propertyGrettingName, 80 [this](boost::system::error_code ec, std::string value) { 81 if (ec) 82 { 83 getFailed(); 84 return; 85 } 86 std::cout << "Greetings value is: " << value << "\n"; 87 }); 88 89 sdbusplus::asio::getProperty<std::string>( 90 bus_, demoServiceName, demoObjectPath, demoInterfaceName, 91 propertyGoodbyesName, 92 [this](boost::system::error_code ec, std::string value) { 93 if (ec) 94 { 95 getFailed(); 96 return; 97 } 98 std::cout << "Goodbyes value is: " << value << "\n"; 99 }); 100 } 101 102 void asyncChangeProperty() 103 { 104 sdbusplus::asio::setProperty( 105 bus_, demoServiceName, demoObjectPath, demoInterfaceName, 106 propertyGrettingName, "Hi, hey, hello", 107 [this](const boost::system::error_code& ec) { 108 if (ec) 109 { 110 std::cout 111 << "As expected, failed to set greetings property: " 112 << ec << "\n"; 113 return; 114 } 115 116 std::cout 117 << "Error: it was expected to fail to change greetings\n"; 118 ++fatalErrors_; 119 }); 120 121 sdbusplus::asio::setProperty( 122 bus_, demoServiceName, demoObjectPath, demoInterfaceName, 123 propertyGoodbyesName, "Bye bye", 124 [this](const boost::system::error_code& ec) { 125 if (ec) 126 { 127 std::cout 128 << "Error: it supposed to be ok to change goodbyes " 129 "property: " 130 << ec << "\n"; 131 ++fatalErrors_; 132 return; 133 } 134 std::cout << "Changed goodbyes property as expected\n"; 135 boost::asio::post(ioc_, [this] { asyncReadProperties(); }); 136 }); 137 } 138 139 void syncChangeGoodbyes(std::string_view value) 140 { 141 goodbyes_ = value; 142 demo_->signal_property(propertyGoodbyesName); 143 } 144 145 private: 146 boost::asio::io_context& ioc_; 147 sdbusplus::asio::connection& bus_; 148 sdbusplus::asio::object_server& objServer_; 149 150 std::unique_ptr<sdbusplus::asio::dbus_interface> demo_; 151 std::string greetings_ = "Hello"; 152 std::string goodbyes_ = "Bye"; 153 154 uint32_t fatalErrors_ = 0u; 155 }; 156 157 int main(int, char**) 158 { 159 boost::asio::io_context ioc; 160 boost::asio::signal_set signals(ioc, SIGINT, SIGTERM); 161 162 signals.async_wait( 163 [&ioc](const boost::system::error_code&, const int&) { ioc.stop(); }); 164 165 auto bus = std::make_shared<sdbusplus::asio::connection>(ioc); 166 auto objServer = std::make_unique<sdbusplus::asio::object_server>(bus); 167 168 bus->request_name(demoServiceName.c_str()); 169 170 Application app(ioc, *bus, *objServer); 171 172 app.syncChangeGoodbyes("Good bye"); 173 174 boost::asio::post(ioc, 175 [&app] { app.asyncReadPropertyWithIncorrectType(); }); 176 boost::asio::post(ioc, [&app] { app.asyncReadProperties(); }); 177 boost::asio::post(ioc, [&app] { app.asyncChangeProperty(); }); 178 179 ioc.run(); 180 181 std::cout << "Fatal errors count: " << app.fatalErrors() << "\n"; 182 183 return app.fatalErrors(); 184 } 185