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