blob: 6cee92eca301b471333ac5ea9786d22569ae9113 [file] [log] [blame]
Ed Tanouscc5a37f2017-05-11 10:27:23 -07001#define DBUS_API_SUBJECT_TO_CHANGE
2#include <dbus/dbus.h>
3#include <stdbool.h>
4#include <stdio.h>
5#include <stdlib.h>
6#include <unistd.h>
7#include <iostream>
8#include <string>
9#include <vector>
10#include <boost/iostreams/stream.hpp>
11#include <boost/property_tree/ptree.hpp>
12#include <boost/property_tree/xml_parser.hpp>
13
14/**
15 * Connect to the DBUS bus and send a broadcast signal
16 */
17void sendsignal(char* sigvalue) {
18 DBusMessage* msg;
19 DBusMessageIter args;
20 DBusConnection* conn;
21 DBusError err;
22 int ret;
23 dbus_uint32_t serial = 0;
24
25 printf("Sending signal with value %s\n", sigvalue);
26
27 // initialise the error value
28 dbus_error_init(&err);
29
30 // connect to the DBUS system bus, and check for errors
31 conn = dbus_bus_get(DBUS_BUS_SYSTEM, &err);
32 if (dbus_error_is_set(&err)) {
33 fprintf(stderr, "Connection Error (%s)\n", err.message);
34 dbus_error_free(&err);
35 }
36 if (NULL == conn) {
37 exit(1);
38 }
39
40 // register our name on the bus, and check for errors
41 ret = dbus_bus_request_name(conn, "test.signal.source",
42 DBUS_NAME_FLAG_REPLACE_EXISTING, &err);
43 if (dbus_error_is_set(&err)) {
44 fprintf(stderr, "Name Error (%s)\n", err.message);
45 dbus_error_free(&err);
46 }
47 if (DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER != ret) {
48 exit(1);
49 }
50
51 // create a signal & check for errors
52 msg = dbus_message_new_signal(
53 "/test/signal/Object", // object name of the signal
54 "test.signal.Type", // interface name of the signal
55 "Test"); // name of the signal
56 if (NULL == msg) {
57 fprintf(stderr, "Message Null\n");
58 exit(1);
59 }
60
61 // append arguments onto signal
62 dbus_message_iter_init_append(msg, &args);
63 if (!dbus_message_iter_append_basic(&args, DBUS_TYPE_STRING, &sigvalue)) {
64 fprintf(stderr, "Out Of Memory!\n");
65 exit(1);
66 }
67
68 // send the message and flush the connection
69 if (!dbus_connection_send(conn, msg, &serial)) {
70 fprintf(stderr, "Out Of Memory!\n");
71 exit(1);
72 }
73 dbus_connection_flush(conn);
74
75 printf("Signal Sent\n");
76
77 // free the message and close the connection
78 dbus_message_unref(msg);
79 dbus_connection_close(conn);
80}
81
82/**
83 * Call a method on a remote object
84 */
85void query(const char* param) {
86 DBusMessage* msg;
87 DBusMessageIter args;
88 DBusConnection* conn;
89 DBusError err;
90 DBusPendingCall* pending;
91 int ret;
92 bool stat;
93 dbus_uint32_t level;
94
95 printf("Calling remote method with %s\n", param);
96
97 // initialiset the errors
98 dbus_error_init(&err);
99
100 // connect to the system bus and check for errors
101 conn = dbus_bus_get(DBUS_BUS_SYSTEM, &err);
102 if (dbus_error_is_set(&err)) {
103 fprintf(stderr, "Connection Error (%s)\n", err.message);
104 dbus_error_free(&err);
105 }
106 if (NULL == conn) {
107 exit(1);
108 }
109 /*
110 // request our name on the bus
111 ret = dbus_bus_request_name(conn, "test.method.caller",
112 DBUS_NAME_FLAG_REPLACE_EXISTING , &err);
113 if (dbus_error_is_set(&err)) {
114 fprintf(stderr, "Name Error (%s)\n", err.message);
115 dbus_error_free(&err);
116 }
117 if (DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER != ret) {
118 exit(1);
119 }
120 */
121
122 // create a new method call and check for errors
123 msg = dbus_message_new_method_call(
124 "org.freedesktop.Avahi", // target for the method call
125 "/", // object to call on
126 "org.freedesktop.Avahi.Server", // interface to call on
127 "GetHostName"); // method name
128 if (NULL == msg) {
129 fprintf(stderr, "Message Null\n");
130 exit(1);
131 }
132
133 // append arguments
134 /*
135 dbus_message_iter_init_append(msg, &args);
136 if (!dbus_message_iter_append_basic(&args, DBUS_TYPE_STRING, &param)) {
137 fprintf(stderr, "Out Of Memory!\n");
138 exit(1);
139 }
140 */
141 // send message and get a handle for a reply
142 if (!dbus_connection_send_with_reply(conn, msg, &pending,
143 -1)) { // -1 is default timeout
144 fprintf(stderr, "Out Of Memory!\n");
145 exit(1);
146 }
147 if (NULL == pending) {
148 fprintf(stderr, "Pending Call Null\n");
149 exit(1);
150 }
151 dbus_connection_flush(conn);
152
153 printf("Request Sent\n");
154
155 // free message
156 dbus_message_unref(msg);
157
158 // block until we recieve a reply
159 dbus_pending_call_block(pending);
160
161 // get the reply message
162 msg = dbus_pending_call_steal_reply(pending);
163 if (NULL == msg) {
164 fprintf(stderr, "Reply Null\n");
165 exit(1);
166 }
167 // free the pending message handle
168 dbus_pending_call_unref(pending);
169
170 // read the parameters
171 char* str = NULL;
172 if (!dbus_message_iter_init(msg, &args))
173 fprintf(stderr, "Message has no arguments!\n");
174 else if (DBUS_TYPE_STRING != dbus_message_iter_get_arg_type(&args))
175 fprintf(stderr, "Argument is not boolean!\n");
176 else
177 dbus_message_iter_get_basic(&args, &str);
178
179 printf("Got Reply: %s\n", str);
180
181 // free reply and close connection
182 dbus_message_unref(msg);
183 dbus_connection_close(conn);
184}
185
186void list_names() {
187 DBusError err;
188
189 int ret;
190 bool stat;
191 dbus_uint32_t level;
192
193 // initialiset the errors
194 dbus_error_init(&err);
195
196 // connect to the system bus and check for errors
197 DBusConnection* conn = dbus_bus_get(DBUS_BUS_SYSTEM, &err);
198 if (dbus_error_is_set(&err)) {
199 fprintf(stderr, "Connection Error (%s)\n", err.message);
200 dbus_error_free(&err);
201 }
202 if (NULL == conn) {
203 exit(1);
204 }
205
206 // create a new method call and check for errors
207 DBusMessage* msg = dbus_message_new_method_call(
208 "org.freedesktop.DBus", // target for the method call
209 "/", // object to call on
210 "org.freedesktop.DBus", // interface to call on
211 "ListNames"); // method name
212 if (NULL == msg) {
213 fprintf(stderr, "Message Null\n");
214 exit(1);
215 }
216
217 DBusPendingCall* pending;
218 // send message and get a handle for a reply
219 if (!dbus_connection_send_with_reply(conn, msg, &pending,
220 -1)) { // -1 is default timeout
221 fprintf(stderr, "Out Of Memory!\n");
222 exit(1);
223 }
224 if (NULL == pending) {
225 fprintf(stderr, "Pending Call Null\n");
226 exit(1);
227 }
228 dbus_connection_flush(conn);
229
230 // free message
231 dbus_message_unref(msg);
232
233 // block until we recieve a reply
234 dbus_pending_call_block(pending);
235
236 // get the reply message
237 msg = dbus_pending_call_steal_reply(pending);
238 if (NULL == msg) {
239 fprintf(stderr, "Reply Null\n");
240 exit(1);
241 }
242 // free the pending message handle
243 dbus_pending_call_unref(pending);
244
245 // read the parameters
246 DBusMessageIter args;
247 DBusMessageIter strings;
248 char* paths = NULL;
249 if (!dbus_message_iter_init(msg, &args)) {
250 fprintf(stderr, "Message has no arguments!\n");
251 }
252 std::vector<std::string> names;
253 do {
254 dbus_message_iter_recurse(&args, &strings);
255 do {
256 dbus_message_iter_get_basic(&strings, &paths);
257 names.emplace_back(paths);
258 } while (dbus_message_iter_next(&strings));
259 } while (dbus_message_iter_next(&args));
260
261 // free reply and close connection
262 dbus_message_unref(msg);
263 dbus_connection_close(conn);
264}
265
266std::vector<std::string> read_dbus_xml_names(std::string& xml_data) {
267 std::vector<std::string> values;
268 // populate tree structure pt
269 using boost::property_tree::ptree;
270 ptree pt;
271 boost::iostreams::stream<boost::iostreams::array_source> stream(
272 xml_data.c_str(), xml_data.size());
273 read_xml(stream, pt);
274
275 // traverse node to find other nodes
276 for (const auto& interface : pt.get_child("node")) {
277 if (interface.first == "node") {
278 auto t = interface.second.get<std::string>("<xmlattr>", "default");
279 for (const auto& subnode : interface.second.get_child("<xmlattr>")) {
280 if (subnode.first == "name") {
281 auto t = subnode.second.get("", "unknown");
282 values.emplace_back(std::move(t));
283 }
284 }
285 }
286 }
287 return values;
288}
289
290using sensor_values=std::vector<std::pair<std::string, int32_t>>;
291
292sensor_values read_sensor_values() {
293 sensor_values values;
294 DBusError err;
295
296 int ret;
297 bool stat;
298 dbus_uint32_t level;
299
300 // initialiset the errors
301 dbus_error_init(&err);
302
303 // connect to the system bus and check for errors
304 DBusConnection* conn = dbus_bus_get(DBUS_BUS_SYSTEM, &err);
305 if (dbus_error_is_set(&err)) {
306 fprintf(stderr, "Connection Error (%s)\n", err.message);
307 dbus_error_free(&err);
308 }
309 if (NULL == conn) {
310 exit(1);
311 }
312
313 // create a new method call and check for errors
314 DBusMessage* msg = dbus_message_new_method_call(
315 "org.openbmc.Sensors", // target for the method call
316 "/org/openbmc/sensors/tach", // object to call on
317 "org.freedesktop.DBus.Introspectable", // interface to call on
318 "Introspect"); // method name
319 if (NULL == msg) {
320 fprintf(stderr, "Message Null\n");
321 exit(1);
322 }
323
324 DBusPendingCall* pending;
325 // send message and get a handle for a reply
326 if (!dbus_connection_send_with_reply(conn, msg, &pending,
327 -1)) { // -1 is default timeout
328 fprintf(stderr, "Out Of Memory!\n");
329 exit(1);
330 }
331 if (NULL == pending) {
332 fprintf(stderr, "Pending Call Null\n");
333 exit(1);
334 }
335 dbus_connection_flush(conn);
336
337 // free message
338 dbus_message_unref(msg);
339
340 // block until we recieve a reply
341 dbus_pending_call_block(pending);
342
343 // get the reply message
344 msg = dbus_pending_call_steal_reply(pending);
345 if (NULL == msg) {
346 fprintf(stderr, "Reply Null\n");
347 exit(1);
348 }
349 // free the pending message handle
350 dbus_pending_call_unref(pending);
351
352 // read the parameters
353 DBusMessageIter args;
354 char* xml_struct = NULL;
355 if (!dbus_message_iter_init(msg, &args)) {
356 fprintf(stderr, "Message has no arguments!\n");
357 }
358
359 // read the arguments
360 if (!dbus_message_iter_init(msg, &args)) {
361 fprintf(stderr, "Message has no arguments!\n");
362 } else if (DBUS_TYPE_STRING != dbus_message_iter_get_arg_type(&args)) {
363 fprintf(stderr, "Argument is not string!\n");
364 } else {
365 dbus_message_iter_get_basic(&args, &xml_struct);
366 }
367 std::vector<std::string> methods;
368 if (xml_struct != NULL) {
369 std::string xml_data(xml_struct);
370 methods = read_dbus_xml_names(xml_data);
371 }
372
373 fprintf(stdout, "Found %ld sensors \n", methods.size());
374
375 for (auto& method : methods) {
376 // TODO(Ed) make sure sensor exposes SensorValue interface
377 // create a new method call and check for errors
378 DBusMessage* msg = dbus_message_new_method_call(
379 "org.openbmc.Sensors", // target for the method call
380 ("/org/openbmc/sensors/tach/" + method).c_str(), // object to call on
381 "org.openbmc.SensorValue", // interface to call on
382 "getValue"); // method name
383 if (NULL == msg) {
384 fprintf(stderr, "Message Null\n");
385 exit(1);
386 }
387
388 DBusPendingCall* pending;
389 // send message and get a handle for a reply
390 if (!dbus_connection_send_with_reply(conn, msg, &pending,
391 -1)) { // -1 is default timeout
392 fprintf(stderr, "Out Of Memory!\n");
393 exit(1);
394 }
395 if (NULL == pending) {
396 fprintf(stderr, "Pending Call Null\n");
397 exit(1);
398 }
399 dbus_connection_flush(conn);
400
401 // free message
402 dbus_message_unref(msg);
403
404 // block until we recieve a reply
405 dbus_pending_call_block(pending);
406
407 // get the reply message
408 msg = dbus_pending_call_steal_reply(pending);
409 if (NULL == msg) {
410 fprintf(stderr, "Reply Null\n");
411 exit(1);
412 }
413 // free the pending message handle
414 dbus_pending_call_unref(pending);
415
416 // read the parameters
417 DBusMessageIter args;
418 int32_t value;
419 if (!dbus_message_iter_init(msg, &args)) {
420 fprintf(stderr, "Message has no arguments!\n");
421 }
422
423 // read the arguments
424 if (!dbus_message_iter_init(msg, &args)) {
425 fprintf(stderr, "Message has no arguments!\n");
426 } else if (DBUS_TYPE_VARIANT != dbus_message_iter_get_arg_type(&args)) {
427 fprintf(stderr, "Argument is not string!\n");
428 } else {
429 DBusMessageIter sub;
430 dbus_message_iter_recurse(&args, &sub);
431 auto type = dbus_message_iter_get_arg_type(&sub);
432 if (DBUS_TYPE_INT32 != type) {
433 fprintf(stderr, "Variant subType is not int32 it is %d\n", type);
434 } else {
435 dbus_message_iter_get_basic(&sub, &value);
436 values.emplace_back(method.c_str(), value);
437 }
438 }
439 }
440
441 // free reply and close connection
442 dbus_message_unref(msg);
443 return values;
444}
445
446
447int main(int argc, char** argv) {
448 auto values = read_sensor_values();
449
450 for (auto value: values){
451 std::cout << value.first << ": " << value.second << "\n";
452 }
453
454 return 0;
455}