xref: /openbmc/dbus-sensors/src/EntityManagerInterface.cpp (revision 0d2f96f1e95a6a37f00a3c458c8562d6af92e4a4)
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 result = co_await addedMatch
78                           .next<sdbusplus::message::object_path, SensorData>();
79         auto& [objectPath, inventoryData] = result;
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 result =
108             co_await removedMatch
109                 .next<sdbusplus::message::object_path, interface_list_t>();
110         auto& [objectPath, interfaces] = result;
111 
112         for (const auto& interfaceName : interfaceNames)
113         {
114             if (std::ranges::find(interfaces, interfaceName) !=
115                 interfaces.end())
116             {
117                 removedCallback(objectPath, interfaceName);
118             }
119         }
120     }
121 
122     co_return;
123 }
124 
125 } // namespace entity_manager
126