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