blob: a95181c453a6b3fb977a82c0ffbb5feeace7bfb6 [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
Ed Tanous95874d92021-02-19 17:14:27 -080042 template <class Handler>
43 void async_get(Handler&& handler)
Krzysztof Grobelny2be0e172020-07-27 11:12:07 +020044 {
Krzysztof Grobelny807419d2020-09-28 11:39:22 +020045 sdbusplus::asio::getProperty<T>(bus_, service_, path_, interface_,
Ed Tanous95874d92021-02-19 17:14:27 -080046 name_, std::forward<Handler>(handler));
Krzysztof Grobelny2be0e172020-07-27 11:12:07 +020047 }
48
Ed Tanous95874d92021-02-19 17:14:27 -080049 template <class Handler>
50 void async_set(const T& value, Handler&& handler)
Krzysztof Grobelny2be0e172020-07-27 11:12:07 +020051 {
Krzysztof Grobelny4f651752020-12-18 14:09:00 +000052 sdbusplus::asio::setProperty(bus_, service_, path_, interface_, name_,
Ed Tanous95874d92021-02-19 17:14:27 -080053 value, std::forward<Handler>(handler));
Krzysztof Grobelny2be0e172020-07-27 11:12:07 +020054 }
55
56 private:
57 sdbusplus::asio::connection& bus_;
58 std::string service_;
59 std::string path_;
60 std::string interface_;
61 std::string name_;
62};
63
64} // namespace utils
65
66class Application
67{
68 public:
69 Application(boost::asio::io_context& ioc, sdbusplus::asio::connection& bus,
70 sdbusplus::asio::object_server& objServer) :
71 ioc_(ioc),
72 bus_(bus), objServer_(objServer)
73 {
Krzysztof Grobelny8fc06392020-09-28 13:11:22 +020074 demo_ = objServer_.add_unique_interface(
75 xyz::demo::path, xyz::demo::name,
76 [this](sdbusplus::asio::dbus_interface& demo) {
77 demo.register_property_r(
78 name::greetings, std::string(),
79 sdbusplus::vtable::property_::const_,
80 [this](const auto&) { return greetings_; });
Krzysztof Grobelny2be0e172020-07-27 11:12:07 +020081
Krzysztof Grobelny8fc06392020-09-28 13:11:22 +020082 demo.register_property_rw(
83 name::goodbyes, std::string(),
84 sdbusplus::vtable::property_::emits_change,
85 [this](const auto& newPropertyValue, const auto&) {
86 goodbyes_ = newPropertyValue;
87 return 1;
88 },
89 [this](const auto&) { return goodbyes_; });
90 });
Krzysztof Grobelny2be0e172020-07-27 11:12:07 +020091 }
92
Krzysztof Grobelny807419d2020-09-28 11:39:22 +020093 uint32_t fatalErrors() const
94 {
95 return fatalErrors_;
96 }
97
98 auto getFailed()
99 {
100 return [this](boost::system::error_code error) {
101 std::cerr << "Error: getProperty failed " << error << "\n";
102 ++fatalErrors_;
103 };
104 }
105
106 void asyncReadPropertyWithIncorrectType()
107 {
108 utils::Property<uint32_t> propertyWithWrongType{
109 bus_, xyz::demo::name, xyz::demo::path, xyz::demo::name,
110 name::greetings};
111
112 propertyWithWrongType.async_get(
Ed Tanous95874d92021-02-19 17:14:27 -0800113 [this](boost::system::error_code error, uint32_t) {
114 if (error)
115 {
116 std::cout
117 << "As expected failed to getProperty with wrong type: "
118 << error << "\n";
119 return;
120 }
121
Krzysztof Grobelny807419d2020-09-28 11:39:22 +0200122 std::cerr << "Error: it was expected to fail getProperty due "
123 "to wrong type\n";
124 ++fatalErrors_;
125 });
126 }
127
Krzysztof Grobelny2be0e172020-07-27 11:12:07 +0200128 void asyncReadProperties()
129 {
Ed Tanous95874d92021-02-19 17:14:27 -0800130 propertyGreetings.async_get(
131 [this](boost::system::error_code ec, std::string value) {
132 if (ec)
133 {
134 getFailed();
135 return;
136 }
137 std::cout << "Greetings value is: " << value << "\n";
138 });
Krzysztof Grobelny2be0e172020-07-27 11:12:07 +0200139
Ed Tanous95874d92021-02-19 17:14:27 -0800140 propertyGoodbyes.async_get(
141 [this](boost::system::error_code ec, std::string value) {
142 if (ec)
143 {
144 getFailed();
145 return;
146 }
147 std::cout << "Goodbyes value is: " << value << "\n";
148 });
Krzysztof Grobelny2be0e172020-07-27 11:12:07 +0200149 }
150
151 void asyncChangeProperty()
152 {
153 propertyGreetings.async_set(
Ed Tanous95874d92021-02-19 17:14:27 -0800154 "Hi, hey, hello", [this](const boost::system::error_code& error) {
155 if (error)
156 {
157 std::cout
158 << "As expected, failed to set greetings property: "
159 << error << "\n";
160 return;
161 }
162
Krzysztof Grobelny807419d2020-09-28 11:39:22 +0200163 std::cout
164 << "Error: it was expected to fail to change greetings\n";
165 ++fatalErrors_;
Krzysztof Grobelny2be0e172020-07-27 11:12:07 +0200166 });
167
168 propertyGoodbyes.async_set(
Ed Tanous95874d92021-02-19 17:14:27 -0800169 "Bye bye", [this](const boost::system::error_code& error) {
170 if (error)
171 {
172 std::cout
173 << "Error: it supposed to be ok to change goodbyes "
174 "property: "
175 << error << "\n";
176 ++fatalErrors_;
177 return;
178 }
Krzysztof Grobelny807419d2020-09-28 11:39:22 +0200179 std::cout << "Changed goodbyes property as expected\n";
Krzysztof Grobelny2be0e172020-07-27 11:12:07 +0200180 boost::asio::post(ioc_, [this] { asyncReadProperties(); });
181 });
182 }
183
Krzysztof Grobelny8fc06392020-09-28 13:11:22 +0200184 void syncChangeGoodbyes(std::string_view value)
185 {
186 goodbyes_ = value;
187 demo_->signal_property(name::goodbyes);
188 }
189
Krzysztof Grobelny2be0e172020-07-27 11:12:07 +0200190 private:
191 boost::asio::io_context& ioc_;
192 sdbusplus::asio::connection& bus_;
193 sdbusplus::asio::object_server& objServer_;
194
Krzysztof Grobelny8fc06392020-09-28 13:11:22 +0200195 std::unique_ptr<sdbusplus::asio::dbus_interface> demo_;
Krzysztof Grobelny2be0e172020-07-27 11:12:07 +0200196 std::string greetings_ = "Hello";
197 std::string goodbyes_ = "Bye";
198
Krzysztof Grobelny807419d2020-09-28 11:39:22 +0200199 uint32_t fatalErrors_ = 0u;
200
Krzysztof Grobelny2be0e172020-07-27 11:12:07 +0200201 utils::Property<std::string> propertyGreetings{
202 bus_, xyz::demo::name, xyz::demo::path, xyz::demo::name,
203 name::greetings};
204 utils::Property<std::string> propertyGoodbyes{
205 bus_, xyz::demo::name, xyz::demo::path, xyz::demo::name,
206 name::goodbyes};
207};
208
209int main(int, char**)
210{
211 boost::asio::io_context ioc;
212 boost::asio::signal_set signals(ioc, SIGINT, SIGTERM);
213
214 signals.async_wait(
215 [&ioc](const boost::system::error_code&, const int&) { ioc.stop(); });
216
217 auto bus = std::make_shared<sdbusplus::asio::connection>(ioc);
218 auto objServer = std::make_unique<sdbusplus::asio::object_server>(bus);
219
220 bus->request_name(xyz::demo::name.c_str());
221
222 Application app(ioc, *bus, *objServer);
223
Krzysztof Grobelny8fc06392020-09-28 13:11:22 +0200224 app.syncChangeGoodbyes("Good bye");
225
Krzysztof Grobelny807419d2020-09-28 11:39:22 +0200226 boost::asio::post(ioc,
227 [&app] { app.asyncReadPropertyWithIncorrectType(); });
Krzysztof Grobelny2be0e172020-07-27 11:12:07 +0200228 boost::asio::post(ioc, [&app] { app.asyncReadProperties(); });
229 boost::asio::post(ioc, [&app] { app.asyncChangeProperty(); });
230
231 ioc.run();
232
Krzysztof Grobelny807419d2020-09-28 11:39:22 +0200233 std::cout << "Fatal errors count: " << app.fatalErrors() << "\n";
234
235 return app.fatalErrors();
Krzysztof Grobelny2be0e172020-07-27 11:12:07 +0200236}