1 #pragma once 2 #include <dbus_singleton.hpp> 3 #include <sdbusplus/bus/match.hpp> 4 #include <crow/app.h> 5 #include <boost/container/flat_map.hpp> 6 7 namespace crow { 8 namespace dbus_monitor { 9 10 struct DbusWebsocketSession { 11 std::vector<std::unique_ptr<sdbusplus::bus::match::match>> matches; 12 }; 13 14 static boost::container::flat_map<crow::websocket::Connection*, 15 DbusWebsocketSession> 16 sessions; 17 18 int onPropertyUpdate(sd_bus_message* m, void* userdata, 19 sd_bus_error* ret_error) { 20 if (ret_error == nullptr || sd_bus_error_is_set(ret_error)) { 21 BMCWEB_LOG_ERROR << "Sdbus error in on_property_update"; 22 return 0; 23 } 24 sdbusplus::message::message message(m); 25 std::string objectName; 26 std::vector< 27 std::pair<std::string, sdbusplus::message::variant< 28 std::string, bool, int64_t, uint64_t, double>>> 29 values; 30 message.read(objectName, values); 31 nlohmann::json j; 32 const std::string& path = message.get_path(); 33 for (auto& value : values) { 34 mapbox::util::apply_visitor([&](auto&& val) { j[path] = val; }, 35 value.second); 36 } 37 std::string dataToSend = j.dump(); 38 39 for (const std::pair<crow::websocket::Connection*, DbusWebsocketSession>& 40 session : sessions) { 41 session.first->sendText(dataToSend); 42 } 43 }; 44 45 template <typename... Middlewares> 46 void requestRoutes(Crow<Middlewares...>& app) { 47 BMCWEB_ROUTE(app, "/dbus_monitor") 48 .websocket() 49 .onopen([&](crow::websocket::Connection& conn) { 50 std::string pathNamespace(conn.req.urlParams.get("path_namespace")); 51 if (pathNamespace.empty()) { 52 conn.sendText( 53 nlohmann::json({"error", "Did not specify path_namespace"}) 54 .dump()); 55 conn.close("error"); 56 } 57 sessions[&conn] = DbusWebsocketSession(); 58 std::string matchString( 59 "type='signal'," 60 "interface='org.freedesktop.DBus.Properties'," 61 "path_namespace='" + 62 pathNamespace + "'"); 63 sessions[&conn].matches.emplace_back( 64 std::make_unique<sdbusplus::bus::match::match>( 65 *crow::connections::systemBus, matchString, onPropertyUpdate)); 66 }) 67 .onclose([&](crow::websocket::Connection& conn, 68 const std::string& reason) { sessions.erase(&conn); }) 69 .onmessage([&](crow::websocket::Connection& conn, const std::string& data, 70 bool is_binary) { 71 BMCWEB_LOG_ERROR << "Got unexpected message from client on sensorws"; 72 }); 73 } 74 } // namespace dbus_monitor 75 } // namespace crow 76