blob: 530a004bdccd62edd54257a50106195488df8333 [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>
51 void async_set(T&& value, OnError&& onError, OnSuccess&& onSuccess)
Krzysztof Grobelny2be0e172020-07-27 11:12:07 +020052 {
Krzysztof Grobelny807419d2020-09-28 11:39:22 +020053 sdbusplus::asio::setProperty(
54 bus_, service_, path_, interface_, name_, std::forward<T>(value),
55 std::forward<OnError>(onError), 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 {
76 demo_ = objServer_.add_interface(xyz::demo::path, xyz::demo::name);
77
78 demo_->register_property_r(name::greetings, std::string(),
79 sdbusplus::vtable::property_::const_,
80 [this](const auto&) { return greetings_; });
81
82 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
91 demo_->initialize();
92 }
93
94 ~Application()
95 {
96 objServer_.remove_interface(demo_);
97 }
98
Krzysztof Grobelny807419d2020-09-28 11:39:22 +020099 uint32_t fatalErrors() const
100 {
101 return fatalErrors_;
102 }
103
104 auto getFailed()
105 {
106 return [this](boost::system::error_code error) {
107 std::cerr << "Error: getProperty failed " << error << "\n";
108 ++fatalErrors_;
109 };
110 }
111
112 void asyncReadPropertyWithIncorrectType()
113 {
114 utils::Property<uint32_t> propertyWithWrongType{
115 bus_, xyz::demo::name, xyz::demo::path, xyz::demo::name,
116 name::greetings};
117
118 propertyWithWrongType.async_get(
119 [](boost::system::error_code error) {
120 std::cout
121 << "As expected failed to getProperty with wrong type: "
122 << error << "\n";
123 },
124 [this](uint32_t) {
125 std::cerr << "Error: it was expected to fail getProperty due "
126 "to wrong type\n";
127 ++fatalErrors_;
128 });
129 }
130
Krzysztof Grobelny2be0e172020-07-27 11:12:07 +0200131 void asyncReadProperties()
132 {
Krzysztof Grobelny807419d2020-09-28 11:39:22 +0200133 propertyGreetings.async_get(getFailed(), [](std::string value) {
134 std::cout << "Greetings value is: " << value << "\n";
Krzysztof Grobelny2be0e172020-07-27 11:12:07 +0200135 });
136
Krzysztof Grobelny807419d2020-09-28 11:39:22 +0200137 propertyGoodbyes.async_get(getFailed(), [](std::string value) {
138 std::cout << "Goodbyes value is: " << value << "\n";
Krzysztof Grobelny2be0e172020-07-27 11:12:07 +0200139 });
140 }
141
142 void asyncChangeProperty()
143 {
144 propertyGreetings.async_set(
Krzysztof Grobelny807419d2020-09-28 11:39:22 +0200145 "Hi, hey, hello",
146 [](const boost::system::error_code& error) {
147 std::cout << "As expected, failed to set greetings property: "
148 << error << "\n";
149 },
150 [this]() {
151 std::cout
152 << "Error: it was expected to fail to change greetings\n";
153 ++fatalErrors_;
Krzysztof Grobelny2be0e172020-07-27 11:12:07 +0200154 });
155
156 propertyGoodbyes.async_set(
Krzysztof Grobelny807419d2020-09-28 11:39:22 +0200157 "Bye bye",
158 [this](const boost::system::error_code& error) {
159 std::cout << "Error: it supposed to be ok to change goodbyes "
160 "property: "
161 << error << "\n";
162 ++fatalErrors_;
163 },
164 [this]() {
165 std::cout << "Changed goodbyes property as expected\n";
Krzysztof Grobelny2be0e172020-07-27 11:12:07 +0200166 boost::asio::post(ioc_, [this] { asyncReadProperties(); });
167 });
168 }
169
170 private:
171 boost::asio::io_context& ioc_;
172 sdbusplus::asio::connection& bus_;
173 sdbusplus::asio::object_server& objServer_;
174
175 std::shared_ptr<sdbusplus::asio::dbus_interface> demo_;
176 std::string greetings_ = "Hello";
177 std::string goodbyes_ = "Bye";
178
Krzysztof Grobelny807419d2020-09-28 11:39:22 +0200179 uint32_t fatalErrors_ = 0u;
180
Krzysztof Grobelny2be0e172020-07-27 11:12:07 +0200181 utils::Property<std::string> propertyGreetings{
182 bus_, xyz::demo::name, xyz::demo::path, xyz::demo::name,
183 name::greetings};
184 utils::Property<std::string> propertyGoodbyes{
185 bus_, xyz::demo::name, xyz::demo::path, xyz::demo::name,
186 name::goodbyes};
187};
188
189int main(int, char**)
190{
191 boost::asio::io_context ioc;
192 boost::asio::signal_set signals(ioc, SIGINT, SIGTERM);
193
194 signals.async_wait(
195 [&ioc](const boost::system::error_code&, const int&) { ioc.stop(); });
196
197 auto bus = std::make_shared<sdbusplus::asio::connection>(ioc);
198 auto objServer = std::make_unique<sdbusplus::asio::object_server>(bus);
199
200 bus->request_name(xyz::demo::name.c_str());
201
202 Application app(ioc, *bus, *objServer);
203
Krzysztof Grobelny807419d2020-09-28 11:39:22 +0200204 boost::asio::post(ioc,
205 [&app] { app.asyncReadPropertyWithIncorrectType(); });
Krzysztof Grobelny2be0e172020-07-27 11:12:07 +0200206 boost::asio::post(ioc, [&app] { app.asyncReadProperties(); });
207 boost::asio::post(ioc, [&app] { app.asyncChangeProperty(); });
208
209 ioc.run();
210
Krzysztof Grobelny807419d2020-09-28 11:39:22 +0200211 std::cout << "Fatal errors count: " << app.fatalErrors() << "\n";
212
213 return app.fatalErrors();
Krzysztof Grobelny2be0e172020-07-27 11:12:07 +0200214}