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