xref: /openbmc/phosphor-power/chassis_status_monitor.cpp (revision b0f94e07b98fba012040c311c6e2789c6141c028)
1*b0f94e07SShawn McCarney /**
2*b0f94e07SShawn McCarney  * Copyright © 2025 IBM Corporation
3*b0f94e07SShawn McCarney  *
4*b0f94e07SShawn McCarney  * Licensed under the Apache License, Version 2.0 (the "License");
5*b0f94e07SShawn McCarney  * you may not use this file except in compliance with the License.
6*b0f94e07SShawn McCarney  * You may obtain a copy of the License at
7*b0f94e07SShawn McCarney  *
8*b0f94e07SShawn McCarney  *     http://www.apache.org/licenses/LICENSE-2.0
9*b0f94e07SShawn McCarney  *
10*b0f94e07SShawn McCarney  * Unless required by applicable law or agreed to in writing, software
11*b0f94e07SShawn McCarney  * distributed under the License is distributed on an "AS IS" BASIS,
12*b0f94e07SShawn McCarney  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*b0f94e07SShawn McCarney  * See the License for the specific language governing permissions and
14*b0f94e07SShawn McCarney  * limitations under the License.
15*b0f94e07SShawn McCarney  */
16*b0f94e07SShawn McCarney 
17*b0f94e07SShawn McCarney #include "chassis_status_monitor.hpp"
18*b0f94e07SShawn McCarney 
19*b0f94e07SShawn McCarney #include "types.hpp"
20*b0f94e07SShawn McCarney 
21*b0f94e07SShawn McCarney #include <format>
22*b0f94e07SShawn McCarney 
23*b0f94e07SShawn McCarney namespace phosphor::power::util
24*b0f94e07SShawn McCarney {
25*b0f94e07SShawn McCarney 
26*b0f94e07SShawn McCarney constexpr auto INVENTORY_MGR_SERVICE = "xyz.openbmc_project.Inventory.Manager";
27*b0f94e07SShawn McCarney constexpr auto POWER_SEQUENCER_SERVICE = "org.openbmc.control.Power";
28*b0f94e07SShawn McCarney constexpr auto CHASSIS_INPUT_POWER_SERVICE =
29*b0f94e07SShawn McCarney     "xyz.openbmc_project.Power.Chassis";
30*b0f94e07SShawn McCarney constexpr auto POWER_SUPPLY_SERVICE = "xyz.openbmc_project.Power.PSUMonitor";
31*b0f94e07SShawn McCarney 
32*b0f94e07SShawn McCarney constexpr auto CHASSIS_POWER_PATH = "/org/openbmc/control/power{}";
33*b0f94e07SShawn McCarney constexpr auto CHASSIS_INPUT_POWER_STATUS_PATH =
34*b0f94e07SShawn McCarney     "/xyz/openbmc_project/power/chassis/chassis{}";
35*b0f94e07SShawn McCarney constexpr auto POWER_SUPPLIES_STATUS_PATH =
36*b0f94e07SShawn McCarney     "/xyz/openbmc_project/power/power_supplies/chassis{}/psus";
37*b0f94e07SShawn McCarney 
38*b0f94e07SShawn McCarney BMCChassisStatusMonitor::BMCChassisStatusMonitor(
39*b0f94e07SShawn McCarney     sdbusplus::bus_t& bus, size_t number, const std::string& inventoryPath,
40*b0f94e07SShawn McCarney     const ChassisStatusMonitorOptions& options) :
41*b0f94e07SShawn McCarney     bus{bus}, number{number}, inventoryPath{inventoryPath}, options{options}
42*b0f94e07SShawn McCarney {
43*b0f94e07SShawn McCarney     chassisPowerPath = std::format(CHASSIS_POWER_PATH, number);
44*b0f94e07SShawn McCarney     chassisInputPowerStatusPath =
45*b0f94e07SShawn McCarney         std::format(CHASSIS_INPUT_POWER_STATUS_PATH, number);
46*b0f94e07SShawn McCarney     powerSuppliesStatusPath = std::format(POWER_SUPPLIES_STATUS_PATH, number);
47*b0f94e07SShawn McCarney     addMatches();
48*b0f94e07SShawn McCarney     getAllProperties();
49*b0f94e07SShawn McCarney }
50*b0f94e07SShawn McCarney 
51*b0f94e07SShawn McCarney void BMCChassisStatusMonitor::addMatches()
52*b0f94e07SShawn McCarney {
53*b0f94e07SShawn McCarney     if (options.isPresentMonitored || options.isAvailableMonitored ||
54*b0f94e07SShawn McCarney         options.isEnabledMonitored)
55*b0f94e07SShawn McCarney     {
56*b0f94e07SShawn McCarney         addNameOwnerChangedMatch(INVENTORY_MGR_SERVICE);
57*b0f94e07SShawn McCarney         addInterfacesAddedMatch(inventoryPath);
58*b0f94e07SShawn McCarney         if (options.isPresentMonitored)
59*b0f94e07SShawn McCarney         {
60*b0f94e07SShawn McCarney             addPropertiesChangedMatch(inventoryPath, INVENTORY_IFACE);
61*b0f94e07SShawn McCarney         }
62*b0f94e07SShawn McCarney         if (options.isAvailableMonitored)
63*b0f94e07SShawn McCarney         {
64*b0f94e07SShawn McCarney             addPropertiesChangedMatch(inventoryPath, AVAILABILITY_IFACE);
65*b0f94e07SShawn McCarney         }
66*b0f94e07SShawn McCarney         if (options.isEnabledMonitored)
67*b0f94e07SShawn McCarney         {
68*b0f94e07SShawn McCarney             addPropertiesChangedMatch(inventoryPath, ENABLE_IFACE);
69*b0f94e07SShawn McCarney         }
70*b0f94e07SShawn McCarney     }
71*b0f94e07SShawn McCarney 
72*b0f94e07SShawn McCarney     if (options.isPowerStateMonitored || options.isPowerGoodMonitored)
73*b0f94e07SShawn McCarney     {
74*b0f94e07SShawn McCarney         addNameOwnerChangedMatch(POWER_SEQUENCER_SERVICE);
75*b0f94e07SShawn McCarney         addInterfacesAddedMatch(chassisPowerPath);
76*b0f94e07SShawn McCarney         addPropertiesChangedMatch(chassisPowerPath, POWER_IFACE);
77*b0f94e07SShawn McCarney     }
78*b0f94e07SShawn McCarney 
79*b0f94e07SShawn McCarney     if (options.isInputPowerStatusMonitored)
80*b0f94e07SShawn McCarney     {
81*b0f94e07SShawn McCarney         addNameOwnerChangedMatch(CHASSIS_INPUT_POWER_SERVICE);
82*b0f94e07SShawn McCarney         addInterfacesAddedMatch(chassisInputPowerStatusPath);
83*b0f94e07SShawn McCarney         addPropertiesChangedMatch(chassisInputPowerStatusPath,
84*b0f94e07SShawn McCarney                                   POWER_SYSTEM_INPUTS_IFACE);
85*b0f94e07SShawn McCarney     }
86*b0f94e07SShawn McCarney 
87*b0f94e07SShawn McCarney     if (options.isPowerSuppliesStatusMonitored)
88*b0f94e07SShawn McCarney     {
89*b0f94e07SShawn McCarney         addNameOwnerChangedMatch(POWER_SUPPLY_SERVICE);
90*b0f94e07SShawn McCarney         addInterfacesAddedMatch(powerSuppliesStatusPath);
91*b0f94e07SShawn McCarney         addPropertiesChangedMatch(powerSuppliesStatusPath,
92*b0f94e07SShawn McCarney                                   POWER_SYSTEM_INPUTS_IFACE);
93*b0f94e07SShawn McCarney     }
94*b0f94e07SShawn McCarney }
95*b0f94e07SShawn McCarney 
96*b0f94e07SShawn McCarney template <typename T>
97*b0f94e07SShawn McCarney void BMCChassisStatusMonitor::getProperty(
98*b0f94e07SShawn McCarney     const std::string& service, const std::string& path,
99*b0f94e07SShawn McCarney     const std::string& interface, const std::string& propertyName,
100*b0f94e07SShawn McCarney     std::optional<T>& optionalValue)
101*b0f94e07SShawn McCarney {
102*b0f94e07SShawn McCarney     try
103*b0f94e07SShawn McCarney     {
104*b0f94e07SShawn McCarney         T value;
105*b0f94e07SShawn McCarney         util::getProperty(interface, propertyName, path, service, bus, value);
106*b0f94e07SShawn McCarney         optionalValue = value;
107*b0f94e07SShawn McCarney     }
108*b0f94e07SShawn McCarney     catch (...)
109*b0f94e07SShawn McCarney     {}
110*b0f94e07SShawn McCarney }
111*b0f94e07SShawn McCarney 
112*b0f94e07SShawn McCarney void BMCChassisStatusMonitor::getInventoryManagerProperties()
113*b0f94e07SShawn McCarney {
114*b0f94e07SShawn McCarney     if (options.isPresentMonitored)
115*b0f94e07SShawn McCarney     {
116*b0f94e07SShawn McCarney         getProperty(INVENTORY_MGR_SERVICE, inventoryPath, INVENTORY_IFACE,
117*b0f94e07SShawn McCarney                     PRESENT_PROP, isPresentValue);
118*b0f94e07SShawn McCarney     }
119*b0f94e07SShawn McCarney 
120*b0f94e07SShawn McCarney     if (options.isAvailableMonitored)
121*b0f94e07SShawn McCarney     {
122*b0f94e07SShawn McCarney         getProperty(INVENTORY_MGR_SERVICE, inventoryPath, AVAILABILITY_IFACE,
123*b0f94e07SShawn McCarney                     AVAILABLE_PROP, isAvailableValue);
124*b0f94e07SShawn McCarney     }
125*b0f94e07SShawn McCarney 
126*b0f94e07SShawn McCarney     if (options.isEnabledMonitored)
127*b0f94e07SShawn McCarney     {
128*b0f94e07SShawn McCarney         getProperty(INVENTORY_MGR_SERVICE, inventoryPath, ENABLE_IFACE,
129*b0f94e07SShawn McCarney                     ENABLED_PROP, isEnabledValue);
130*b0f94e07SShawn McCarney     }
131*b0f94e07SShawn McCarney }
132*b0f94e07SShawn McCarney 
133*b0f94e07SShawn McCarney void BMCChassisStatusMonitor::getPowerSequencerProperties()
134*b0f94e07SShawn McCarney {
135*b0f94e07SShawn McCarney     if (options.isPowerStateMonitored)
136*b0f94e07SShawn McCarney     {
137*b0f94e07SShawn McCarney         getProperty(POWER_SEQUENCER_SERVICE, chassisPowerPath, POWER_IFACE,
138*b0f94e07SShawn McCarney                     POWER_STATE_PROP, powerStateValue);
139*b0f94e07SShawn McCarney     }
140*b0f94e07SShawn McCarney 
141*b0f94e07SShawn McCarney     if (options.isPowerGoodMonitored)
142*b0f94e07SShawn McCarney     {
143*b0f94e07SShawn McCarney         getProperty(POWER_SEQUENCER_SERVICE, chassisPowerPath, POWER_IFACE,
144*b0f94e07SShawn McCarney                     POWER_GOOD_PROP, powerGoodValue);
145*b0f94e07SShawn McCarney     }
146*b0f94e07SShawn McCarney }
147*b0f94e07SShawn McCarney 
148*b0f94e07SShawn McCarney void BMCChassisStatusMonitor::getChassisInputPowerProperties()
149*b0f94e07SShawn McCarney {
150*b0f94e07SShawn McCarney     if (options.isInputPowerStatusMonitored)
151*b0f94e07SShawn McCarney     {
152*b0f94e07SShawn McCarney         getProperty(CHASSIS_INPUT_POWER_SERVICE, chassisInputPowerStatusPath,
153*b0f94e07SShawn McCarney                     POWER_SYSTEM_INPUTS_IFACE, STATUS_PROP,
154*b0f94e07SShawn McCarney                     inputPowerStatusValue);
155*b0f94e07SShawn McCarney     }
156*b0f94e07SShawn McCarney }
157*b0f94e07SShawn McCarney 
158*b0f94e07SShawn McCarney void BMCChassisStatusMonitor::getPowerSupplyProperties()
159*b0f94e07SShawn McCarney {
160*b0f94e07SShawn McCarney     if (options.isPowerSuppliesStatusMonitored)
161*b0f94e07SShawn McCarney     {
162*b0f94e07SShawn McCarney         getProperty(POWER_SUPPLY_SERVICE, powerSuppliesStatusPath,
163*b0f94e07SShawn McCarney                     POWER_SYSTEM_INPUTS_IFACE, STATUS_PROP,
164*b0f94e07SShawn McCarney                     powerSuppliesStatusValue);
165*b0f94e07SShawn McCarney     }
166*b0f94e07SShawn McCarney }
167*b0f94e07SShawn McCarney 
168*b0f94e07SShawn McCarney template <typename T>
169*b0f94e07SShawn McCarney void BMCChassisStatusMonitor::storeProperty(const DbusPropertyMap& properties,
170*b0f94e07SShawn McCarney                                             const std::string& propertyName,
171*b0f94e07SShawn McCarney                                             std::optional<T>& optionalValue)
172*b0f94e07SShawn McCarney {
173*b0f94e07SShawn McCarney     try
174*b0f94e07SShawn McCarney     {
175*b0f94e07SShawn McCarney         auto it = properties.find(propertyName);
176*b0f94e07SShawn McCarney         if (it != properties.end())
177*b0f94e07SShawn McCarney         {
178*b0f94e07SShawn McCarney             optionalValue = std::get<T>(it->second);
179*b0f94e07SShawn McCarney         }
180*b0f94e07SShawn McCarney     }
181*b0f94e07SShawn McCarney     catch (...)
182*b0f94e07SShawn McCarney     {}
183*b0f94e07SShawn McCarney }
184*b0f94e07SShawn McCarney 
185*b0f94e07SShawn McCarney void BMCChassisStatusMonitor::storeProperties(const DbusPropertyMap& properties,
186*b0f94e07SShawn McCarney                                               const std::string& path,
187*b0f94e07SShawn McCarney                                               const std::string& interface)
188*b0f94e07SShawn McCarney {
189*b0f94e07SShawn McCarney     try
190*b0f94e07SShawn McCarney     {
191*b0f94e07SShawn McCarney         if (interface == INVENTORY_IFACE)
192*b0f94e07SShawn McCarney         {
193*b0f94e07SShawn McCarney             storeProperty(properties, PRESENT_PROP, isPresentValue);
194*b0f94e07SShawn McCarney         }
195*b0f94e07SShawn McCarney         else if (interface == AVAILABILITY_IFACE)
196*b0f94e07SShawn McCarney         {
197*b0f94e07SShawn McCarney             storeProperty(properties, AVAILABLE_PROP, isAvailableValue);
198*b0f94e07SShawn McCarney         }
199*b0f94e07SShawn McCarney         else if (interface == ENABLE_IFACE)
200*b0f94e07SShawn McCarney         {
201*b0f94e07SShawn McCarney             storeProperty(properties, ENABLED_PROP, isEnabledValue);
202*b0f94e07SShawn McCarney         }
203*b0f94e07SShawn McCarney         else if (interface == POWER_IFACE)
204*b0f94e07SShawn McCarney         {
205*b0f94e07SShawn McCarney             storeProperty(properties, POWER_STATE_PROP, powerStateValue);
206*b0f94e07SShawn McCarney             storeProperty(properties, POWER_GOOD_PROP, powerGoodValue);
207*b0f94e07SShawn McCarney         }
208*b0f94e07SShawn McCarney         else if (interface == POWER_SYSTEM_INPUTS_IFACE)
209*b0f94e07SShawn McCarney         {
210*b0f94e07SShawn McCarney             if (path == chassisInputPowerStatusPath)
211*b0f94e07SShawn McCarney             {
212*b0f94e07SShawn McCarney                 storeProperty(properties, STATUS_PROP, inputPowerStatusValue);
213*b0f94e07SShawn McCarney             }
214*b0f94e07SShawn McCarney             else if (path == powerSuppliesStatusPath)
215*b0f94e07SShawn McCarney             {
216*b0f94e07SShawn McCarney                 storeProperty(properties, STATUS_PROP,
217*b0f94e07SShawn McCarney                               powerSuppliesStatusValue);
218*b0f94e07SShawn McCarney             }
219*b0f94e07SShawn McCarney         }
220*b0f94e07SShawn McCarney     }
221*b0f94e07SShawn McCarney     catch (...)
222*b0f94e07SShawn McCarney     {}
223*b0f94e07SShawn McCarney }
224*b0f94e07SShawn McCarney 
225*b0f94e07SShawn McCarney void BMCChassisStatusMonitor::nameOwnerChangedCallback(
226*b0f94e07SShawn McCarney     sdbusplus::message_t& message)
227*b0f94e07SShawn McCarney {
228*b0f94e07SShawn McCarney     try
229*b0f94e07SShawn McCarney     {
230*b0f94e07SShawn McCarney         std::string name, oldOwner, newOwner;
231*b0f94e07SShawn McCarney         message.read(name, oldOwner, newOwner);
232*b0f94e07SShawn McCarney         if (!newOwner.empty())
233*b0f94e07SShawn McCarney         {
234*b0f94e07SShawn McCarney             if (name == INVENTORY_MGR_SERVICE)
235*b0f94e07SShawn McCarney             {
236*b0f94e07SShawn McCarney                 getInventoryManagerProperties();
237*b0f94e07SShawn McCarney             }
238*b0f94e07SShawn McCarney             else if (name == POWER_SEQUENCER_SERVICE)
239*b0f94e07SShawn McCarney             {
240*b0f94e07SShawn McCarney                 getPowerSequencerProperties();
241*b0f94e07SShawn McCarney             }
242*b0f94e07SShawn McCarney             else if (name == CHASSIS_INPUT_POWER_SERVICE)
243*b0f94e07SShawn McCarney             {
244*b0f94e07SShawn McCarney                 getChassisInputPowerProperties();
245*b0f94e07SShawn McCarney             }
246*b0f94e07SShawn McCarney             else if (name == POWER_SUPPLY_SERVICE)
247*b0f94e07SShawn McCarney             {
248*b0f94e07SShawn McCarney                 getPowerSupplyProperties();
249*b0f94e07SShawn McCarney             }
250*b0f94e07SShawn McCarney         }
251*b0f94e07SShawn McCarney     }
252*b0f94e07SShawn McCarney     catch (...)
253*b0f94e07SShawn McCarney     {}
254*b0f94e07SShawn McCarney }
255*b0f94e07SShawn McCarney 
256*b0f94e07SShawn McCarney void BMCChassisStatusMonitor::interfacesAddedCallback(
257*b0f94e07SShawn McCarney     sdbusplus::message_t& message)
258*b0f94e07SShawn McCarney {
259*b0f94e07SShawn McCarney     try
260*b0f94e07SShawn McCarney     {
261*b0f94e07SShawn McCarney         sdbusplus::message::object_path path;
262*b0f94e07SShawn McCarney         std::map<std::string, DbusPropertyMap> interfaces;
263*b0f94e07SShawn McCarney         message.read(path, interfaces);
264*b0f94e07SShawn McCarney         for (const auto& [interface, properties] : interfaces)
265*b0f94e07SShawn McCarney         {
266*b0f94e07SShawn McCarney             storeProperties(properties, path, interface);
267*b0f94e07SShawn McCarney         }
268*b0f94e07SShawn McCarney     }
269*b0f94e07SShawn McCarney     catch (...)
270*b0f94e07SShawn McCarney     {}
271*b0f94e07SShawn McCarney }
272*b0f94e07SShawn McCarney 
273*b0f94e07SShawn McCarney void BMCChassisStatusMonitor::propertiesChangedCallback(
274*b0f94e07SShawn McCarney     sdbusplus::message_t& message)
275*b0f94e07SShawn McCarney {
276*b0f94e07SShawn McCarney     try
277*b0f94e07SShawn McCarney     {
278*b0f94e07SShawn McCarney         std::string interface;
279*b0f94e07SShawn McCarney         DbusPropertyMap changedProperties;
280*b0f94e07SShawn McCarney         std::vector<std::string> invalidatedProperties;
281*b0f94e07SShawn McCarney         message.read(interface, changedProperties, invalidatedProperties);
282*b0f94e07SShawn McCarney         storeProperties(changedProperties, message.get_path(), interface);
283*b0f94e07SShawn McCarney     }
284*b0f94e07SShawn McCarney     catch (...)
285*b0f94e07SShawn McCarney     {}
286*b0f94e07SShawn McCarney }
287*b0f94e07SShawn McCarney 
288*b0f94e07SShawn McCarney } // namespace phosphor::power::util
289