blob: 0306183df9814cefd0f6f9c0cdf3c78887f23f2c [file] [log] [blame]
Ed Tanous911ac312017-08-15 09:37:42 -07001#pragma once
2#include <dbus/filter.hpp>
3#include <dbus/match.hpp>
4#include <dbus_singleton.hpp>
5#include <crow/app.h>
6#include <boost/container/flat_map.hpp>
7
8namespace crow {
9namespace dbus_monitor {
10
11struct DbusWebsocketSession {
12 std::vector<std::unique_ptr<dbus::match>> matches;
13 std::vector<dbus::filter> filters;
14};
15
16static boost::container::flat_map<crow::websocket::connection*,
17 DbusWebsocketSession>
18 sessions;
19
20void on_property_update(dbus::filter& filter, boost::system::error_code ec,
21 dbus::message s) {
22 if (!ec) {
23 std::string object_name;
24 std::vector<std::pair<std::string, dbus::dbus_variant>> values;
25 s.unpack(object_name, values);
26 nlohmann::json j;
27 for (auto& value : values) {
28 boost::apply_visitor([&](auto val) { j[s.get_path()] = val; },
29 value.second);
30 }
31 auto data_to_send = j.dump();
32
33 for (auto& session : sessions) {
34 session.first->send_text(data_to_send);
35 }
36 }
37 filter.async_dispatch([&](boost::system::error_code ec, dbus::message s) {
38 on_property_update(filter, ec, s);
39 });
40};
41
42template <typename... Middlewares>
43void request_routes(Crow<Middlewares...>& app) {
44 CROW_ROUTE(app, "/dbus_monitor")
45 .websocket()
46 .onopen([&](crow::websocket::connection& conn) {
47 std::string path_namespace(conn.req.url_params.get("path_namespace"));
48 if (path_namespace.empty()) {
49 conn.send_text(
50 nlohmann::json({"error", "Did not specify path_namespace"}));
51 conn.close("error");
52 }
53 sessions[&conn] = DbusWebsocketSession();
54 std::string match_string(
55 "type='signal',"
56 "interface='org.freedesktop.DBus.Properties',"
57 "path_namespace='" +
58 path_namespace + "'");
59 sessions[&conn].matches.push_back(std::make_unique<dbus::match>(
60 crow::connections::system_bus, std::move(match_string)));
61
62 sessions[&conn].filters.emplace_back(
63 crow::connections::system_bus, [path_namespace](dbus::message m) {
64 return m.get_member() == "PropertiesChanged" &&
65 boost::starts_with(m.get_path(), path_namespace);
66 });
67 auto& this_filter = sessions[&conn].filters.back();
68 this_filter.async_dispatch(
69 [&](boost::system::error_code ec, dbus::message s) {
70 on_property_update(this_filter, ec, s);
71 });
72
73 })
74 .onclose([&](crow::websocket::connection& conn,
75 const std::string& reason) { sessions.erase(&conn); })
76 .onmessage([&](crow::websocket::connection& conn, const std::string& data,
77 bool is_binary) {
78 CROW_LOG_ERROR << "Got unexpected message from client on sensorws";
79 });
80}
81} // namespace redfish
82} // namespace crow