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 << "As expected, failed to set greetings property: " 111 << ec << "\n"; 112 return; 113 } 114 115 std::cout << "Error: it was expected to fail to change greetings\n"; 116 ++fatalErrors_; 117 }); 118 119 sdbusplus::asio::setProperty( 120 bus_, demoServiceName, demoObjectPath, demoInterfaceName, 121 propertyGoodbyesName, "Bye bye", 122 [this](const boost::system::error_code& ec) { 123 if (ec) 124 { 125 std::cout << "Error: it supposed to be ok to change goodbyes " 126 "property: " 127 << ec << "\n"; 128 ++fatalErrors_; 129 return; 130 } 131 std::cout << "Changed goodbyes property as expected\n"; 132 boost::asio::post(ioc_, [this] { asyncReadProperties(); }); 133 }); 134 } 135 136 void syncChangeGoodbyes(std::string_view value) 137 { 138 goodbyes_ = value; 139 demo_->signal_property(propertyGoodbyesName); 140 } 141 142 private: 143 boost::asio::io_context& ioc_; 144 sdbusplus::asio::connection& bus_; 145 sdbusplus::asio::object_server& objServer_; 146 147 std::unique_ptr<sdbusplus::asio::dbus_interface> demo_; 148 std::string greetings_ = "Hello"; 149 std::string goodbyes_ = "Bye"; 150 151 uint32_t fatalErrors_ = 0u; 152 }; 153 154 int main(int, char**) 155 { 156 boost::asio::io_context ioc; 157 boost::asio::signal_set signals(ioc, SIGINT, SIGTERM); 158 159 signals.async_wait( 160 [&ioc](const boost::system::error_code&, const int&) { ioc.stop(); }); 161 162 auto bus = std::make_shared<sdbusplus::asio::connection>(ioc); 163 auto objServer = std::make_unique<sdbusplus::asio::object_server>(bus); 164 165 bus->request_name(demoServiceName.c_str()); 166 167 Application app(ioc, *bus, *objServer); 168 169 app.syncChangeGoodbyes("Good bye"); 170 171 boost::asio::post(ioc, 172 [&app] { app.asyncReadPropertyWithIncorrectType(); }); 173 boost::asio::post(ioc, [&app] { app.asyncReadProperties(); }); 174 boost::asio::post(ioc, [&app] { app.asyncChangeProperty(); }); 175 176 ioc.run(); 177 178 std::cout << "Fatal errors count: " << app.fatalErrors() << "\n"; 179 180 return app.fatalErrors(); 181 } 182