blob: 651e9747f4732fb22de377479f7b3064a6a8082e [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>
4#include <sdbusplus/bus.hpp>
5
6#include <iostream>
7
8namespace xyz
9{
10namespace demo
11{
12
13const std::string path = "/xyz/demo";
14const std::string name = "xyz.demo";
15
16} // namespace demo
17} // namespace xyz
18
19namespace name
20{
21
22const std::string greetings = "Greetings";
23const std::string goodbyes = "Goodbyes";
24
25} // namespace name
26
27namespace utils
28{
29
30template <class T>
31class Property
32{
33 public:
34 Property(sdbusplus::asio::connection& bus, std::string_view service,
35 std::string_view path, std::string_view interface,
36 std::string_view name) :
37 bus_(bus),
38 service_(service), path_(path), interface_(interface), name_(name)
39 {}
40
41 template <class F>
42 void async_get(F&& callback)
43 {
44 bus_.async_method_call(
45 [callback =
46 std::move(callback)](const boost::system::error_code& error,
47 const std::variant<T>& valueVariant) {
48 if (error)
49 {
50 callback(std::nullopt);
51 return;
52 }
53
54 if (auto value = std::get_if<T>(&valueVariant))
55 {
56 callback(*value);
57 return;
58 }
59
60 callback(std::nullopt);
61 },
62 service_, path_, "org.freedesktop.DBus.Properties", "Get",
63 interface_, name_);
64 }
65
66 template <class F>
67 void async_set(const T& value, F&& callback)
68 {
69 bus_.async_method_call(
70 [callback = std::move(callback)](
71 const boost::system::error_code& error) { callback(error); },
72 service_, path_, "org.freedesktop.DBus.Properties", "Set",
73 interface_, name_, value);
74 }
75
76 private:
77 sdbusplus::asio::connection& bus_;
78 std::string service_;
79 std::string path_;
80 std::string interface_;
81 std::string name_;
82};
83
84} // namespace utils
85
86class Application
87{
88 public:
89 Application(boost::asio::io_context& ioc, sdbusplus::asio::connection& bus,
90 sdbusplus::asio::object_server& objServer) :
91 ioc_(ioc),
92 bus_(bus), objServer_(objServer)
93 {
94 demo_ = objServer_.add_interface(xyz::demo::path, xyz::demo::name);
95
96 demo_->register_property_r(name::greetings, std::string(),
97 sdbusplus::vtable::property_::const_,
98 [this](const auto&) { return greetings_; });
99
100 demo_->register_property_rw(
101 name::goodbyes, std::string(),
102 sdbusplus::vtable::property_::emits_change,
103 [this](const auto& newPropertyValue, const auto&) {
104 goodbyes_ = newPropertyValue;
105 return 1;
106 },
107 [this](const auto&) { return goodbyes_; });
108
109 demo_->initialize();
110 }
111
112 ~Application()
113 {
114 objServer_.remove_interface(demo_);
115 }
116
117 void asyncReadProperties()
118 {
119 propertyGreetings.async_get([](std::optional<std::string> value) {
120 std::cout << "Greetings value is: "
121 << value.value_or("std::nullopt") << "\n";
122 });
123
124 propertyGoodbyes.async_get([](std::optional<std::string> value) {
125 std::cout << "Goodbyes value is: " << value.value_or("std::nullopt")
126 << "\n";
127 });
128 }
129
130 void asyncChangeProperty()
131 {
132 propertyGreetings.async_set(
133 "Hi, hey, hello", [](const boost::system::error_code& error) {
134 if (error)
135 {
136 std::cout
137 << "As expected, failed to set greetings property\n";
138 }
139 });
140
141 propertyGoodbyes.async_set(
142 "Bye bye", [this](const boost::system::error_code& error) {
143 if (!error)
144 {
145 std::cout << "Changed goodbyes property as expected\n";
146 }
147 boost::asio::post(ioc_, [this] { asyncReadProperties(); });
148 });
149 }
150
151 private:
152 boost::asio::io_context& ioc_;
153 sdbusplus::asio::connection& bus_;
154 sdbusplus::asio::object_server& objServer_;
155
156 std::shared_ptr<sdbusplus::asio::dbus_interface> demo_;
157 std::string greetings_ = "Hello";
158 std::string goodbyes_ = "Bye";
159
160 utils::Property<std::string> propertyGreetings{
161 bus_, xyz::demo::name, xyz::demo::path, xyz::demo::name,
162 name::greetings};
163 utils::Property<std::string> propertyGoodbyes{
164 bus_, xyz::demo::name, xyz::demo::path, xyz::demo::name,
165 name::goodbyes};
166};
167
168int main(int, char**)
169{
170 boost::asio::io_context ioc;
171 boost::asio::signal_set signals(ioc, SIGINT, SIGTERM);
172
173 signals.async_wait(
174 [&ioc](const boost::system::error_code&, const int&) { ioc.stop(); });
175
176 auto bus = std::make_shared<sdbusplus::asio::connection>(ioc);
177 auto objServer = std::make_unique<sdbusplus::asio::object_server>(bus);
178
179 bus->request_name(xyz::demo::name.c_str());
180
181 Application app(ioc, *bus, *objServer);
182
183 boost::asio::post(ioc, [&app] { app.asyncReadProperties(); });
184 boost::asio::post(ioc, [&app] { app.asyncChangeProperty(); });
185
186 ioc.run();
187
188 return 0;
189}