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