blob: 6fd4c89ec2d40c0ec06bb1f36d3c16a1ac74c8a1 [file] [log] [blame]
Krzysztof Grobelny2be0e172020-07-27 11:12:07 +02001#include <boost/asio.hpp>
2#include <sdbusplus/asio/connection.hpp>
3#include <sdbusplus/asio/object_server.hpp>
Krzysztof Grobelny807419d2020-09-28 11:39:22 +02004#include <sdbusplus/asio/property.hpp>
Krzysztof Grobelny2be0e172020-07-27 11:12:07 +02005#include <sdbusplus/bus.hpp>
6
7#include <iostream>
8
9namespace xyz
10{
11namespace demo
12{
13
14const std::string path = "/xyz/demo";
15const std::string name = "xyz.demo";
16
17} // namespace demo
18} // namespace xyz
19
20namespace name
21{
22
23const std::string greetings = "Greetings";
24const std::string goodbyes = "Goodbyes";
25
26} // namespace name
27
28namespace utils
29{
30
31template <class T>
32class 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 Grobelny807419d2020-09-28 11:39:22 +020042 template <class OnError, class OnSuccess>
43 void async_get(OnError&& onError, OnSuccess&& onSuccess)
Krzysztof Grobelny2be0e172020-07-27 11:12:07 +020044 {
Krzysztof Grobelny807419d2020-09-28 11:39:22 +020045 sdbusplus::asio::getProperty<T>(bus_, service_, path_, interface_,
46 name_, std::forward<OnError>(onError),
47 std::forward<OnSuccess>(onSuccess));
Krzysztof Grobelny2be0e172020-07-27 11:12:07 +020048 }
49
Krzysztof Grobelny807419d2020-09-28 11:39:22 +020050 template <class OnError, class OnSuccess>
Krzysztof Grobelny4f651752020-12-18 14:09:00 +000051 void async_set(const T& value, OnError&& onError, OnSuccess&& onSuccess)
Krzysztof Grobelny2be0e172020-07-27 11:12:07 +020052 {
Krzysztof Grobelny4f651752020-12-18 14:09:00 +000053 sdbusplus::asio::setProperty(bus_, service_, path_, interface_, name_,
54 value, std::forward<OnError>(onError),
55 std::forward<OnSuccess>(onSuccess));
Krzysztof Grobelny2be0e172020-07-27 11:12:07 +020056 }
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
68class 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 Grobelny8fc06392020-09-28 13:11:22 +020076 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 Grobelny2be0e172020-07-27 11:12:07 +020083
Krzysztof Grobelny8fc06392020-09-28 13:11:22 +020084 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 Grobelny2be0e172020-07-27 11:12:07 +020093 }
94
Krzysztof Grobelny807419d2020-09-28 11:39:22 +020095 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 Grobelny2be0e172020-07-27 11:12:07 +0200127 void asyncReadProperties()
128 {
Krzysztof Grobelny807419d2020-09-28 11:39:22 +0200129 propertyGreetings.async_get(getFailed(), [](std::string value) {
130 std::cout << "Greetings value is: " << value << "\n";
Krzysztof Grobelny2be0e172020-07-27 11:12:07 +0200131 });
132
Krzysztof Grobelny807419d2020-09-28 11:39:22 +0200133 propertyGoodbyes.async_get(getFailed(), [](std::string value) {
134 std::cout << "Goodbyes value is: " << value << "\n";
Krzysztof Grobelny2be0e172020-07-27 11:12:07 +0200135 });
136 }
137
138 void asyncChangeProperty()
139 {
140 propertyGreetings.async_set(
Krzysztof Grobelny807419d2020-09-28 11:39:22 +0200141 "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 Grobelny2be0e172020-07-27 11:12:07 +0200150 });
151
152 propertyGoodbyes.async_set(
Krzysztof Grobelny807419d2020-09-28 11:39:22 +0200153 "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 Grobelny2be0e172020-07-27 11:12:07 +0200162 boost::asio::post(ioc_, [this] { asyncReadProperties(); });
163 });
164 }
165
Krzysztof Grobelny8fc06392020-09-28 13:11:22 +0200166 void syncChangeGoodbyes(std::string_view value)
167 {
168 goodbyes_ = value;
169 demo_->signal_property(name::goodbyes);
170 }
171
Krzysztof Grobelny2be0e172020-07-27 11:12:07 +0200172 private:
173 boost::asio::io_context& ioc_;
174 sdbusplus::asio::connection& bus_;
175 sdbusplus::asio::object_server& objServer_;
176
Krzysztof Grobelny8fc06392020-09-28 13:11:22 +0200177 std::unique_ptr<sdbusplus::asio::dbus_interface> demo_;
Krzysztof Grobelny2be0e172020-07-27 11:12:07 +0200178 std::string greetings_ = "Hello";
179 std::string goodbyes_ = "Bye";
180
Krzysztof Grobelny807419d2020-09-28 11:39:22 +0200181 uint32_t fatalErrors_ = 0u;
182
Krzysztof Grobelny2be0e172020-07-27 11:12:07 +0200183 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
191int 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 Grobelny8fc06392020-09-28 13:11:22 +0200206 app.syncChangeGoodbyes("Good bye");
207
Krzysztof Grobelny807419d2020-09-28 11:39:22 +0200208 boost::asio::post(ioc,
209 [&app] { app.asyncReadPropertyWithIncorrectType(); });
Krzysztof Grobelny2be0e172020-07-27 11:12:07 +0200210 boost::asio::post(ioc, [&app] { app.asyncReadProperties(); });
211 boost::asio::post(ioc, [&app] { app.asyncChangeProperty(); });
212
213 ioc.run();
214
Krzysztof Grobelny807419d2020-09-28 11:39:22 +0200215 std::cout << "Fatal errors count: " << app.fatalErrors() << "\n";
216
217 return app.fatalErrors();
Krzysztof Grobelny2be0e172020-07-27 11:12:07 +0200218}