xref: /openbmc/dbus-sensors/src/EntityManagerInterface.cpp (revision 15dde8641baa1cb902d17f9857effb081e384944)
1 #include "EntityManagerInterface.hpp"
2 
3 #include "Utils.hpp"
4 
5 #include <phosphor-logging/lg2.hpp>
6 #include <sdbusplus/async.hpp>
7 #include <sdbusplus/message/native_types.hpp>
8 #include <xyz/openbmc_project/Inventory/Item/client.hpp>
9 
10 #include <algorithm>
11 #include <utility>
12 
13 namespace entity_manager
14 {
15 
16 PHOSPHOR_LOG2_USING;
17 
18 namespace rules_intf = sdbusplus::bus::match::rules;
19 
EntityManagerInterface(sdbusplus::async::context & ctx,const interface_list_t & interfaceNames,Callback_t addedCallback,Callback_t removedCallback)20 EntityManagerInterface::EntityManagerInterface(
21     sdbusplus::async::context& ctx, const interface_list_t& interfaceNames,
22     Callback_t addedCallback, Callback_t removedCallback) :
23     ctx(ctx), interfaceNames(interfaceNames),
24     addedCallback(std::move(addedCallback)),
25     removedCallback(std::move(removedCallback))
26 {
27     ctx.spawn(handleInventoryAdded());
28     ctx.spawn(handleInventoryRemoved());
29 }
30 
handleInventoryGet()31 auto EntityManagerInterface::handleInventoryGet() -> sdbusplus::async::task<>
32 {
33     if (!addedCallback)
34     {
35         error("addedCallback is not set");
36         co_return;
37     }
38 
39     using InventoryIntf =
40         sdbusplus::client::xyz::openbmc_project::inventory::Item<>;
41 
42     constexpr auto entityManager =
43         sdbusplus::async::proxy()
44             .service(serviceName)
45             .path(InventoryIntf::namespace_path)
46             .interface("org.freedesktop.DBus.ObjectManager");
47 
48     for (const auto& [objectPath, detectorConfig] :
49          co_await entityManager.call<ManagedObjectType>(ctx,
50                                                         "GetManagedObjects"))
51     {
52         for (const auto& interfaceName : interfaceNames)
53         {
54             if (detectorConfig.contains(interfaceName))
55             {
56                 addedCallback(objectPath, interfaceName);
57             }
58         }
59     }
60 
61     co_return;
62 }
63 
handleInventoryAdded()64 auto EntityManagerInterface::handleInventoryAdded() -> sdbusplus::async::task<>
65 {
66     if (!addedCallback)
67     {
68         error("addedCallback is not set");
69         co_return;
70     }
71 
72     auto addedMatch = sdbusplus::async::match(
73         ctx, rules_intf::interfacesAdded() + rules_intf::sender(serviceName));
74 
75     while (!ctx.stop_requested())
76     {
77         auto [objectPath, inventoryData] =
78             co_await addedMatch
79                 .next<sdbusplus::message::object_path, SensorData>();
80 
81         for (const auto& interfaceName : interfaceNames)
82         {
83             if (inventoryData.contains(interfaceName))
84             {
85                 addedCallback(objectPath, interfaceName);
86             }
87         }
88     }
89 
90     co_return;
91 }
92 
handleInventoryRemoved()93 auto EntityManagerInterface::handleInventoryRemoved()
94     -> sdbusplus::async::task<>
95 {
96     if (!removedCallback)
97     {
98         error("removedCallback is not set");
99         co_return;
100     }
101 
102     auto removedMatch = sdbusplus::async::match(
103         ctx, rules_intf::interfacesRemoved() + rules_intf::sender(serviceName));
104 
105     while (!ctx.stop_requested())
106     {
107         auto [objectPath, interfaces] =
108             co_await removedMatch
109                 .next<sdbusplus::message::object_path, interface_list_t>();
110 
111         for (const auto& interfaceName : interfaceNames)
112         {
113             if (std::ranges::find(interfaces, interfaceName) !=
114                 interfaces.end())
115             {
116                 removedCallback(objectPath, interfaceName);
117             }
118         }
119     }
120 
121     co_return;
122 }
123 
124 } // namespace entity_manager
125