| Krzysztof Grobelny | 2be0e17 | 2020-07-27 11:12:07 +0200 | [diff] [blame] | 1 | #include <boost/asio.hpp> | 
|  | 2 | #include <sdbusplus/asio/connection.hpp> | 
|  | 3 | #include <sdbusplus/asio/object_server.hpp> | 
| Krzysztof Grobelny | 807419d | 2020-09-28 11:39:22 +0200 | [diff] [blame] | 4 | #include <sdbusplus/asio/property.hpp> | 
| Krzysztof Grobelny | 2be0e17 | 2020-07-27 11:12:07 +0200 | [diff] [blame] | 5 | #include <sdbusplus/bus.hpp> | 
|  | 6 |  | 
|  | 7 | #include <iostream> | 
|  | 8 |  | 
|  | 9 | namespace xyz | 
|  | 10 | { | 
|  | 11 | namespace demo | 
|  | 12 | { | 
|  | 13 |  | 
|  | 14 | const std::string path = "/xyz/demo"; | 
|  | 15 | const std::string name = "xyz.demo"; | 
|  | 16 |  | 
|  | 17 | } // namespace demo | 
|  | 18 | } // namespace xyz | 
|  | 19 |  | 
|  | 20 | namespace name | 
|  | 21 | { | 
|  | 22 |  | 
|  | 23 | const std::string greetings = "Greetings"; | 
|  | 24 | const std::string goodbyes = "Goodbyes"; | 
|  | 25 |  | 
|  | 26 | } // namespace name | 
|  | 27 |  | 
|  | 28 | namespace utils | 
|  | 29 | { | 
|  | 30 |  | 
|  | 31 | template <class T> | 
|  | 32 | class Property | 
|  | 33 | { | 
|  | 34 | public: | 
|  | 35 | Property(sdbusplus::asio::connection& bus, std::string_view service, | 
|  | 36 | std::string_view path, std::string_view interface, | 
|  | 37 | std::string_view name) : | 
|  | 38 | bus_(bus), | 
|  | 39 | service_(service), path_(path), interface_(interface), name_(name) | 
|  | 40 | {} | 
|  | 41 |  | 
| Krzysztof Grobelny | 807419d | 2020-09-28 11:39:22 +0200 | [diff] [blame] | 42 | template <class OnError, class OnSuccess> | 
|  | 43 | void async_get(OnError&& onError, OnSuccess&& onSuccess) | 
| Krzysztof Grobelny | 2be0e17 | 2020-07-27 11:12:07 +0200 | [diff] [blame] | 44 | { | 
| Krzysztof Grobelny | 807419d | 2020-09-28 11:39:22 +0200 | [diff] [blame] | 45 | sdbusplus::asio::getProperty<T>(bus_, service_, path_, interface_, | 
|  | 46 | name_, std::forward<OnError>(onError), | 
|  | 47 | std::forward<OnSuccess>(onSuccess)); | 
| Krzysztof Grobelny | 2be0e17 | 2020-07-27 11:12:07 +0200 | [diff] [blame] | 48 | } | 
|  | 49 |  | 
| Krzysztof Grobelny | 807419d | 2020-09-28 11:39:22 +0200 | [diff] [blame] | 50 | template <class OnError, class OnSuccess> | 
| Krzysztof Grobelny | 4f65175 | 2020-12-18 14:09:00 +0000 | [diff] [blame] | 51 | void async_set(const T& value, OnError&& onError, OnSuccess&& onSuccess) | 
| Krzysztof Grobelny | 2be0e17 | 2020-07-27 11:12:07 +0200 | [diff] [blame] | 52 | { | 
| Krzysztof Grobelny | 4f65175 | 2020-12-18 14:09:00 +0000 | [diff] [blame] | 53 | sdbusplus::asio::setProperty(bus_, service_, path_, interface_, name_, | 
|  | 54 | value, std::forward<OnError>(onError), | 
|  | 55 | std::forward<OnSuccess>(onSuccess)); | 
| Krzysztof Grobelny | 2be0e17 | 2020-07-27 11:12:07 +0200 | [diff] [blame] | 56 | } | 
|  | 57 |  | 
|  | 58 | private: | 
|  | 59 | sdbusplus::asio::connection& bus_; | 
|  | 60 | std::string service_; | 
|  | 61 | std::string path_; | 
|  | 62 | std::string interface_; | 
|  | 63 | std::string name_; | 
|  | 64 | }; | 
|  | 65 |  | 
|  | 66 | } // namespace utils | 
|  | 67 |  | 
|  | 68 | class Application | 
|  | 69 | { | 
|  | 70 | public: | 
|  | 71 | Application(boost::asio::io_context& ioc, sdbusplus::asio::connection& bus, | 
|  | 72 | sdbusplus::asio::object_server& objServer) : | 
|  | 73 | ioc_(ioc), | 
|  | 74 | bus_(bus), objServer_(objServer) | 
|  | 75 | { | 
| Krzysztof Grobelny | 8fc0639 | 2020-09-28 13:11:22 +0200 | [diff] [blame] | 76 | demo_ = objServer_.add_unique_interface( | 
|  | 77 | xyz::demo::path, xyz::demo::name, | 
|  | 78 | [this](sdbusplus::asio::dbus_interface& demo) { | 
|  | 79 | demo.register_property_r( | 
|  | 80 | name::greetings, std::string(), | 
|  | 81 | sdbusplus::vtable::property_::const_, | 
|  | 82 | [this](const auto&) { return greetings_; }); | 
| Krzysztof Grobelny | 2be0e17 | 2020-07-27 11:12:07 +0200 | [diff] [blame] | 83 |  | 
| Krzysztof Grobelny | 8fc0639 | 2020-09-28 13:11:22 +0200 | [diff] [blame] | 84 | demo.register_property_rw( | 
|  | 85 | name::goodbyes, std::string(), | 
|  | 86 | sdbusplus::vtable::property_::emits_change, | 
|  | 87 | [this](const auto& newPropertyValue, const auto&) { | 
|  | 88 | goodbyes_ = newPropertyValue; | 
|  | 89 | return 1; | 
|  | 90 | }, | 
|  | 91 | [this](const auto&) { return goodbyes_; }); | 
|  | 92 | }); | 
| Krzysztof Grobelny | 2be0e17 | 2020-07-27 11:12:07 +0200 | [diff] [blame] | 93 | } | 
|  | 94 |  | 
| Krzysztof Grobelny | 807419d | 2020-09-28 11:39:22 +0200 | [diff] [blame] | 95 | uint32_t fatalErrors() const | 
|  | 96 | { | 
|  | 97 | return fatalErrors_; | 
|  | 98 | } | 
|  | 99 |  | 
|  | 100 | auto getFailed() | 
|  | 101 | { | 
|  | 102 | return [this](boost::system::error_code error) { | 
|  | 103 | std::cerr << "Error: getProperty failed " << error << "\n"; | 
|  | 104 | ++fatalErrors_; | 
|  | 105 | }; | 
|  | 106 | } | 
|  | 107 |  | 
|  | 108 | void asyncReadPropertyWithIncorrectType() | 
|  | 109 | { | 
|  | 110 | utils::Property<uint32_t> propertyWithWrongType{ | 
|  | 111 | bus_, xyz::demo::name, xyz::demo::path, xyz::demo::name, | 
|  | 112 | name::greetings}; | 
|  | 113 |  | 
|  | 114 | propertyWithWrongType.async_get( | 
|  | 115 | [](boost::system::error_code error) { | 
|  | 116 | std::cout | 
|  | 117 | << "As expected failed to getProperty with wrong type: " | 
|  | 118 | << error << "\n"; | 
|  | 119 | }, | 
|  | 120 | [this](uint32_t) { | 
|  | 121 | std::cerr << "Error: it was expected to fail getProperty due " | 
|  | 122 | "to wrong type\n"; | 
|  | 123 | ++fatalErrors_; | 
|  | 124 | }); | 
|  | 125 | } | 
|  | 126 |  | 
| Krzysztof Grobelny | 2be0e17 | 2020-07-27 11:12:07 +0200 | [diff] [blame] | 127 | void asyncReadProperties() | 
|  | 128 | { | 
| Krzysztof Grobelny | 807419d | 2020-09-28 11:39:22 +0200 | [diff] [blame] | 129 | propertyGreetings.async_get(getFailed(), [](std::string value) { | 
|  | 130 | std::cout << "Greetings value is: " << value << "\n"; | 
| Krzysztof Grobelny | 2be0e17 | 2020-07-27 11:12:07 +0200 | [diff] [blame] | 131 | }); | 
|  | 132 |  | 
| Krzysztof Grobelny | 807419d | 2020-09-28 11:39:22 +0200 | [diff] [blame] | 133 | propertyGoodbyes.async_get(getFailed(), [](std::string value) { | 
|  | 134 | std::cout << "Goodbyes value is: " << value << "\n"; | 
| Krzysztof Grobelny | 2be0e17 | 2020-07-27 11:12:07 +0200 | [diff] [blame] | 135 | }); | 
|  | 136 | } | 
|  | 137 |  | 
|  | 138 | void asyncChangeProperty() | 
|  | 139 | { | 
|  | 140 | propertyGreetings.async_set( | 
| Krzysztof Grobelny | 807419d | 2020-09-28 11:39:22 +0200 | [diff] [blame] | 141 | "Hi, hey, hello", | 
|  | 142 | [](const boost::system::error_code& error) { | 
|  | 143 | std::cout << "As expected, failed to set greetings property: " | 
|  | 144 | << error << "\n"; | 
|  | 145 | }, | 
|  | 146 | [this]() { | 
|  | 147 | std::cout | 
|  | 148 | << "Error: it was expected to fail to change greetings\n"; | 
|  | 149 | ++fatalErrors_; | 
| Krzysztof Grobelny | 2be0e17 | 2020-07-27 11:12:07 +0200 | [diff] [blame] | 150 | }); | 
|  | 151 |  | 
|  | 152 | propertyGoodbyes.async_set( | 
| Krzysztof Grobelny | 807419d | 2020-09-28 11:39:22 +0200 | [diff] [blame] | 153 | "Bye bye", | 
|  | 154 | [this](const boost::system::error_code& error) { | 
|  | 155 | std::cout << "Error: it supposed to be ok to change goodbyes " | 
|  | 156 | "property: " | 
|  | 157 | << error << "\n"; | 
|  | 158 | ++fatalErrors_; | 
|  | 159 | }, | 
|  | 160 | [this]() { | 
|  | 161 | std::cout << "Changed goodbyes property as expected\n"; | 
| Krzysztof Grobelny | 2be0e17 | 2020-07-27 11:12:07 +0200 | [diff] [blame] | 162 | boost::asio::post(ioc_, [this] { asyncReadProperties(); }); | 
|  | 163 | }); | 
|  | 164 | } | 
|  | 165 |  | 
| Krzysztof Grobelny | 8fc0639 | 2020-09-28 13:11:22 +0200 | [diff] [blame] | 166 | void syncChangeGoodbyes(std::string_view value) | 
|  | 167 | { | 
|  | 168 | goodbyes_ = value; | 
|  | 169 | demo_->signal_property(name::goodbyes); | 
|  | 170 | } | 
|  | 171 |  | 
| Krzysztof Grobelny | 2be0e17 | 2020-07-27 11:12:07 +0200 | [diff] [blame] | 172 | private: | 
|  | 173 | boost::asio::io_context& ioc_; | 
|  | 174 | sdbusplus::asio::connection& bus_; | 
|  | 175 | sdbusplus::asio::object_server& objServer_; | 
|  | 176 |  | 
| Krzysztof Grobelny | 8fc0639 | 2020-09-28 13:11:22 +0200 | [diff] [blame] | 177 | std::unique_ptr<sdbusplus::asio::dbus_interface> demo_; | 
| Krzysztof Grobelny | 2be0e17 | 2020-07-27 11:12:07 +0200 | [diff] [blame] | 178 | std::string greetings_ = "Hello"; | 
|  | 179 | std::string goodbyes_ = "Bye"; | 
|  | 180 |  | 
| Krzysztof Grobelny | 807419d | 2020-09-28 11:39:22 +0200 | [diff] [blame] | 181 | uint32_t fatalErrors_ = 0u; | 
|  | 182 |  | 
| Krzysztof Grobelny | 2be0e17 | 2020-07-27 11:12:07 +0200 | [diff] [blame] | 183 | utils::Property<std::string> propertyGreetings{ | 
|  | 184 | bus_, xyz::demo::name, xyz::demo::path, xyz::demo::name, | 
|  | 185 | name::greetings}; | 
|  | 186 | utils::Property<std::string> propertyGoodbyes{ | 
|  | 187 | bus_, xyz::demo::name, xyz::demo::path, xyz::demo::name, | 
|  | 188 | name::goodbyes}; | 
|  | 189 | }; | 
|  | 190 |  | 
|  | 191 | int main(int, char**) | 
|  | 192 | { | 
|  | 193 | boost::asio::io_context ioc; | 
|  | 194 | boost::asio::signal_set signals(ioc, SIGINT, SIGTERM); | 
|  | 195 |  | 
|  | 196 | signals.async_wait( | 
|  | 197 | [&ioc](const boost::system::error_code&, const int&) { ioc.stop(); }); | 
|  | 198 |  | 
|  | 199 | auto bus = std::make_shared<sdbusplus::asio::connection>(ioc); | 
|  | 200 | auto objServer = std::make_unique<sdbusplus::asio::object_server>(bus); | 
|  | 201 |  | 
|  | 202 | bus->request_name(xyz::demo::name.c_str()); | 
|  | 203 |  | 
|  | 204 | Application app(ioc, *bus, *objServer); | 
|  | 205 |  | 
| Krzysztof Grobelny | 8fc0639 | 2020-09-28 13:11:22 +0200 | [diff] [blame] | 206 | app.syncChangeGoodbyes("Good bye"); | 
|  | 207 |  | 
| Krzysztof Grobelny | 807419d | 2020-09-28 11:39:22 +0200 | [diff] [blame] | 208 | boost::asio::post(ioc, | 
|  | 209 | [&app] { app.asyncReadPropertyWithIncorrectType(); }); | 
| Krzysztof Grobelny | 2be0e17 | 2020-07-27 11:12:07 +0200 | [diff] [blame] | 210 | boost::asio::post(ioc, [&app] { app.asyncReadProperties(); }); | 
|  | 211 | boost::asio::post(ioc, [&app] { app.asyncChangeProperty(); }); | 
|  | 212 |  | 
|  | 213 | ioc.run(); | 
|  | 214 |  | 
| Krzysztof Grobelny | 807419d | 2020-09-28 11:39:22 +0200 | [diff] [blame] | 215 | std::cout << "Fatal errors count: " << app.fatalErrors() << "\n"; | 
|  | 216 |  | 
|  | 217 | return app.fatalErrors(); | 
| Krzysztof Grobelny | 2be0e17 | 2020-07-27 11:12:07 +0200 | [diff] [blame] | 218 | } |