blob: 0306183df9814cefd0f6f9c0cdf3c78887f23f2c [file] [log] [blame]
#pragma once
#include <dbus/filter.hpp>
#include <dbus/match.hpp>
#include <dbus_singleton.hpp>
#include <crow/app.h>
#include <boost/container/flat_map.hpp>
namespace crow {
namespace dbus_monitor {
struct DbusWebsocketSession {
std::vector<std::unique_ptr<dbus::match>> matches;
std::vector<dbus::filter> filters;
};
static boost::container::flat_map<crow::websocket::connection*,
DbusWebsocketSession>
sessions;
void on_property_update(dbus::filter& filter, boost::system::error_code ec,
dbus::message s) {
if (!ec) {
std::string object_name;
std::vector<std::pair<std::string, dbus::dbus_variant>> values;
s.unpack(object_name, values);
nlohmann::json j;
for (auto& value : values) {
boost::apply_visitor([&](auto val) { j[s.get_path()] = val; },
value.second);
}
auto data_to_send = j.dump();
for (auto& session : sessions) {
session.first->send_text(data_to_send);
}
}
filter.async_dispatch([&](boost::system::error_code ec, dbus::message s) {
on_property_update(filter, ec, s);
});
};
template <typename... Middlewares>
void request_routes(Crow<Middlewares...>& app) {
CROW_ROUTE(app, "/dbus_monitor")
.websocket()
.onopen([&](crow::websocket::connection& conn) {
std::string path_namespace(conn.req.url_params.get("path_namespace"));
if (path_namespace.empty()) {
conn.send_text(
nlohmann::json({"error", "Did not specify path_namespace"}));
conn.close("error");
}
sessions[&conn] = DbusWebsocketSession();
std::string match_string(
"type='signal',"
"interface='org.freedesktop.DBus.Properties',"
"path_namespace='" +
path_namespace + "'");
sessions[&conn].matches.push_back(std::make_unique<dbus::match>(
crow::connections::system_bus, std::move(match_string)));
sessions[&conn].filters.emplace_back(
crow::connections::system_bus, [path_namespace](dbus::message m) {
return m.get_member() == "PropertiesChanged" &&
boost::starts_with(m.get_path(), path_namespace);
});
auto& this_filter = sessions[&conn].filters.back();
this_filter.async_dispatch(
[&](boost::system::error_code ec, dbus::message s) {
on_property_update(this_filter, ec, s);
});
})
.onclose([&](crow::websocket::connection& conn,
const std::string& reason) { sessions.erase(&conn); })
.onmessage([&](crow::websocket::connection& conn, const std::string& data,
bool is_binary) {
CROW_LOG_ERROR << "Got unexpected message from client on sensorws";
});
}
} // namespace redfish
} // namespace crow