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