1 #include "occ_dbus.hpp" 2 3 #include "utils.hpp" 4 5 #include <phosphor-logging/log.hpp> 6 7 #include <format> 8 #include <iostream> 9 10 namespace open_power 11 { 12 namespace occ 13 { 14 namespace dbus 15 { 16 17 using namespace phosphor::logging; 18 using namespace std::string_literals; 19 const auto defaultChassisPath = 20 "/xyz/openbmc_project/inventory/system/chassis"s; 21 const auto chassisInterface = "xyz.openbmc_project.Inventory.Item.Chassis"s; 22 23 bool OccDBusSensors::setMaxValue(const std::string& path, double value) 24 { 25 if (path.empty()) 26 { 27 return false; 28 } 29 30 if (!sensors.contains(path)) 31 { 32 sensors.emplace( 33 path, std::make_unique<SensorIntf>(utils::getBus(), path.c_str())); 34 } 35 36 sensors.at(path)->maxValue(value); 37 return true; 38 } 39 40 double OccDBusSensors::getMaxValue(const std::string& path) const 41 { 42 if (sensors.find(path) != sensors.end()) 43 { 44 return sensors.at(path)->maxValue(); 45 } 46 47 throw std::invalid_argument("Failed to get MaxValue property."); 48 } 49 50 bool OccDBusSensors::setMinValue(const std::string& path, double value) 51 { 52 if (path.empty()) 53 { 54 return false; 55 } 56 57 if (!sensors.contains(path)) 58 { 59 sensors.emplace( 60 path, std::make_unique<SensorIntf>(utils::getBus(), path.c_str())); 61 } 62 63 sensors.at(path)->minValue(value); 64 return true; 65 } 66 67 double OccDBusSensors::getMinValue(const std::string& path) const 68 { 69 if (sensors.find(path) != sensors.end()) 70 { 71 return sensors.at(path)->minValue(); 72 } 73 74 throw std::invalid_argument("Failed to get MinValue property."); 75 } 76 77 bool OccDBusSensors::setValue(const std::string& path, double value) 78 { 79 if (path.empty()) 80 { 81 return false; 82 } 83 84 if (!sensors.contains(path)) 85 { 86 sensors.emplace( 87 path, std::make_unique<SensorIntf>(utils::getBus(), path.c_str())); 88 } 89 90 sensors.at(path)->value(value); 91 return true; 92 } 93 94 double OccDBusSensors::getValue(const std::string& path) const 95 { 96 if (sensors.find(path) != sensors.end()) 97 { 98 return sensors.at(path)->value(); 99 } 100 101 throw std::invalid_argument("Failed to get Value property."); 102 } 103 104 bool OccDBusSensors::setUnit(const std::string& path, const std::string& value) 105 { 106 if (path.empty()) 107 { 108 return false; 109 } 110 111 if (!sensors.contains(path)) 112 { 113 sensors.emplace( 114 path, std::make_unique<SensorIntf>(utils::getBus(), path.c_str())); 115 } 116 117 try 118 { 119 sensors.at(path)->unit(SensorIntf::convertUnitFromString(value)); 120 } 121 catch (const std::exception& e) 122 { 123 log<level::ERR>("set Unit propety failed", entry("ERROR=%s", e.what())); 124 return false; 125 } 126 127 return true; 128 } 129 130 std::string OccDBusSensors::getUnit(const std::string& path) const 131 { 132 if (sensors.find(path) != sensors.end()) 133 { 134 try 135 { 136 return SensorIntf::convertUnitToString(sensors.at(path)->unit()); 137 } 138 catch (const std::exception& e) 139 { 140 log<level::ERR>("get Unit propety failed", 141 entry("ERROR=%s", e.what())); 142 } 143 } 144 145 throw std::invalid_argument("Failed to get Unit property."); 146 } 147 148 bool OccDBusSensors::setOperationalStatus(const std::string& path, bool value) 149 { 150 if (path.empty()) 151 { 152 return false; 153 } 154 155 if (!operationalStatus.contains(path)) 156 { 157 operationalStatus.emplace(path, std::make_unique<OperationalStatusIntf>( 158 utils::getBus(), path.c_str())); 159 } 160 161 operationalStatus.at(path)->functional(value); 162 return true; 163 } 164 165 bool OccDBusSensors::getOperationalStatus(const std::string& path) const 166 { 167 if (operationalStatus.find(path) != operationalStatus.end()) 168 { 169 return operationalStatus.at(path)->functional(); 170 } 171 172 throw std::invalid_argument("Failed to get OperationalStatus property."); 173 } 174 175 void OccDBusSensors::setChassisAssociation( 176 const std::string& path, const std::vector<std::string>& fTypes) 177 { 178 using AssociationsEntry = std::tuple<std::string, std::string, std::string>; 179 using AssociationsProperty = std::vector<AssociationsEntry>; 180 using PropVariant = sdbusplus::xyz::openbmc_project::Association::server:: 181 Definitions::PropertiesVariant; 182 183 if (chassisPath.empty()) 184 { 185 chassisPath = getChassisPath(); 186 } 187 188 AssociationsProperty associations; 189 for (const auto& fType : fTypes) 190 { 191 associations.emplace_back("chassis", fType, chassisPath); 192 } 193 PropVariant value{std::move(associations)}; 194 195 std::map<std::string, PropVariant> properties; 196 properties.emplace("Associations", std::move(value)); 197 198 chassisAssociations.emplace( 199 path, std::make_unique<AssociationIntf>(utils::getBus(), path.c_str(), 200 properties)); 201 } 202 203 std::string OccDBusSensors::getChassisPath() 204 { 205 try 206 { 207 auto paths = utils::getSubtreePaths(std::vector{chassisInterface}); 208 209 // For now, support either 1 chassis, or multiple as long as one 210 // of them has the standard name, which we will use. If this ever 211 // fails, then someone would have to figure out how to identify the 212 // chassis the OCCs are on. 213 if (paths.size() == 1) 214 { 215 return paths[0]; 216 } 217 else if (std::find(paths.begin(), paths.end(), defaultChassisPath) == 218 paths.end()) 219 { 220 log<level::ERR>( 221 std::format( 222 "Could not find a chassis out of {} chassis objects", 223 paths.size()) 224 .c_str()); 225 // Can't throw an exception here, the sdeventplus timer 226 // just catches it. 227 abort(); 228 } 229 } 230 catch (const std::exception& e) 231 { 232 log<level::ERR>( 233 std::format("Error looking up chassis objects: {}", e.what()) 234 .c_str()); 235 abort(); 236 } 237 238 return defaultChassisPath; 239 } 240 241 bool OccDBusSensors::hasDvfsTemp(const std::string& path) const 242 { 243 return dvfsTemps.find(path) != dvfsTemps.end(); 244 } 245 246 void OccDBusSensors::setDvfsTemp(const std::string& path, double value) 247 { 248 dvfsTemps[path] = 249 std::make_unique<SensorIntf>(utils::getBus(), path.c_str()); 250 dvfsTemps[path]->value(value); 251 } 252 253 } // namespace dbus 254 } // namespace occ 255 } // namespace open_power 256