| Cheng C Yang | 209ec56 | 2019-03-12 16:37:44 +0800 | [diff] [blame] | 1 | /* | 
 | 2 | // Copyright (c) 2019 Intel 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 | */ | 
| Josh Lehan | 0830c7b | 2019-10-08 16:35:09 -0700 | [diff] [blame] | 16 |  | 
| Patrick Venture | ca44b2f | 2019-10-31 11:02:26 -0700 | [diff] [blame] | 17 | #include "PSUEvent.hpp" | 
 | 18 | #include "PSUSensor.hpp" | 
 | 19 | #include "Utils.hpp" | 
 | 20 |  | 
| Patrick Venture | 96e97db | 2019-10-31 13:44:38 -0700 | [diff] [blame] | 21 | #include <array> | 
| Cheng C Yang | 209ec56 | 2019-03-12 16:37:44 +0800 | [diff] [blame] | 22 | #include <boost/algorithm/string/predicate.hpp> | 
 | 23 | #include <boost/algorithm/string/replace.hpp> | 
| Patrick Venture | 96e97db | 2019-10-31 13:44:38 -0700 | [diff] [blame] | 24 | #include <boost/container/flat_map.hpp> | 
| Cheng C Yang | 209ec56 | 2019-03-12 16:37:44 +0800 | [diff] [blame] | 25 | #include <boost/container/flat_set.hpp> | 
| Josh Lehan | 74d9bd9 | 2019-10-31 08:51:58 -0700 | [diff] [blame] | 26 | #include <cmath> | 
| James Feist | 24f02f2 | 2019-04-15 11:05:39 -0700 | [diff] [blame] | 27 | #include <filesystem> | 
| Cheng C Yang | 209ec56 | 2019-03-12 16:37:44 +0800 | [diff] [blame] | 28 | #include <fstream> | 
| Patrick Venture | 96e97db | 2019-10-31 13:44:38 -0700 | [diff] [blame] | 29 | #include <functional> | 
| Cheng C Yang | 58b2b53 | 2019-05-31 00:19:45 +0800 | [diff] [blame] | 30 | #include <iostream> | 
| Cheng C Yang | 209ec56 | 2019-03-12 16:37:44 +0800 | [diff] [blame] | 31 | #include <regex> | 
 | 32 | #include <sdbusplus/asio/connection.hpp> | 
 | 33 | #include <sdbusplus/asio/object_server.hpp> | 
| Patrick Venture | 96e97db | 2019-10-31 13:44:38 -0700 | [diff] [blame] | 34 | #include <sdbusplus/bus/match.hpp> | 
 | 35 | #include <string> | 
 | 36 | #include <utility> | 
 | 37 | #include <variant> | 
 | 38 | #include <vector> | 
| Cheng C Yang | 209ec56 | 2019-03-12 16:37:44 +0800 | [diff] [blame] | 39 |  | 
| Josh Lehan | 49cfba9 | 2019-10-08 16:50:42 -0700 | [diff] [blame] | 40 | static constexpr bool DEBUG = false; | 
 | 41 |  | 
| Alex Qiu | f5709b4 | 2020-01-29 13:29:50 -0800 | [diff] [blame] | 42 | static constexpr std::array<const char*, 8> sensorTypes = { | 
| Devjit Gopalpur | de65ef7 | 2019-10-30 04:47:35 -0700 | [diff] [blame] | 43 |     "xyz.openbmc_project.Configuration.INA230", | 
| Alex Qiu | 6690d8f | 2020-01-22 17:56:33 -0800 | [diff] [blame] | 44 |     "xyz.openbmc_project.Configuration.ISL68137", | 
| Alex Qiu | f5709b4 | 2020-01-29 13:29:50 -0800 | [diff] [blame] | 45 |     "xyz.openbmc_project.Configuration.MAX16601", | 
| Alex Qiu | 6690d8f | 2020-01-22 17:56:33 -0800 | [diff] [blame] | 46 |     "xyz.openbmc_project.Configuration.MAX20730", | 
 | 47 |     "xyz.openbmc_project.Configuration.MAX20734", | 
 | 48 |     "xyz.openbmc_project.Configuration.MAX20796", | 
 | 49 |     "xyz.openbmc_project.Configuration.MAX34451", | 
 | 50 |     "xyz.openbmc_project.Configuration.pmbus"}; | 
| Cheng C Yang | 209ec56 | 2019-03-12 16:37:44 +0800 | [diff] [blame] | 51 |  | 
| Alex Qiu | 6690d8f | 2020-01-22 17:56:33 -0800 | [diff] [blame] | 52 | static std::vector<std::string> pmbusNames = { | 
| Alex Qiu | f5709b4 | 2020-01-29 13:29:50 -0800 | [diff] [blame] | 53 |     "isl68137", "ina219",   "ina230",   "max16601", "max20730", | 
 | 54 |     "max20734", "max20796", "max34451", "pmbus",    "pxe1610"}; | 
| Josh Lehan | 0830c7b | 2019-10-08 16:35:09 -0700 | [diff] [blame] | 55 |  | 
| Cheng C Yang | 209ec56 | 2019-03-12 16:37:44 +0800 | [diff] [blame] | 56 | namespace fs = std::filesystem; | 
 | 57 |  | 
| Cheng C Yang | 916360b | 2019-05-07 18:47:16 +0800 | [diff] [blame] | 58 | static boost::container::flat_map<std::string, std::unique_ptr<PSUSensor>> | 
 | 59 |     sensors; | 
| Cheng C Yang | 58b2b53 | 2019-05-31 00:19:45 +0800 | [diff] [blame] | 60 | static boost::container::flat_map<std::string, std::unique_ptr<PSUCombineEvent>> | 
 | 61 |     combineEvents; | 
| Cheng C Yang | 916360b | 2019-05-07 18:47:16 +0800 | [diff] [blame] | 62 | static boost::container::flat_map<std::string, std::unique_ptr<PwmSensor>> | 
 | 63 |     pwmSensors; | 
 | 64 | static boost::container::flat_map<std::string, std::string> sensorTable; | 
 | 65 | static boost::container::flat_map<std::string, PSUProperty> labelMatch; | 
 | 66 | static boost::container::flat_map<std::string, std::string> pwmTable; | 
| Cheng C Yang | 58b2b53 | 2019-05-31 00:19:45 +0800 | [diff] [blame] | 67 | static boost::container::flat_map<std::string, std::vector<std::string>> | 
 | 68 |     eventMatch; | 
| Cheng C Yang | 202a1ff | 2020-01-09 09:34:22 +0800 | [diff] [blame] | 69 | static boost::container::flat_map< | 
 | 70 |     std::string, | 
 | 71 |     boost::container::flat_map<std::string, std::vector<std::string>>> | 
 | 72 |     groupEventMatch; | 
| Cheng C Yang | 58b2b53 | 2019-05-31 00:19:45 +0800 | [diff] [blame] | 73 | static boost::container::flat_map<std::string, std::vector<std::string>> | 
 | 74 |     limitEventMatch; | 
 | 75 |  | 
| Josh Lehan | 74d9bd9 | 2019-10-31 08:51:58 -0700 | [diff] [blame] | 76 | static std::vector<PSUProperty> psuProperties; | 
 | 77 |  | 
| Cheng C Yang | 58b2b53 | 2019-05-31 00:19:45 +0800 | [diff] [blame] | 78 | // Function CheckEvent will check each attribute from eventMatch table in the | 
 | 79 | // sysfs. If the attributes exists in sysfs, then store the complete path | 
 | 80 | // of the attribute into eventPathList. | 
 | 81 | void checkEvent( | 
 | 82 |     const std::string& directory, | 
 | 83 |     const boost::container::flat_map<std::string, std::vector<std::string>>& | 
 | 84 |         eventMatch, | 
 | 85 |     boost::container::flat_map<std::string, std::vector<std::string>>& | 
 | 86 |         eventPathList) | 
 | 87 | { | 
 | 88 |     for (const auto& match : eventMatch) | 
 | 89 |     { | 
 | 90 |         const std::vector<std::string>& eventAttrs = match.second; | 
 | 91 |         const std::string& eventName = match.first; | 
 | 92 |         for (const auto& eventAttr : eventAttrs) | 
 | 93 |         { | 
 | 94 |             auto eventPath = directory + "/" + eventAttr; | 
 | 95 |  | 
 | 96 |             std::ifstream eventFile(eventPath); | 
 | 97 |             if (!eventFile.good()) | 
 | 98 |             { | 
 | 99 |                 continue; | 
 | 100 |             } | 
 | 101 |  | 
 | 102 |             eventPathList[eventName].push_back(eventPath); | 
 | 103 |         } | 
 | 104 |     } | 
 | 105 | } | 
 | 106 |  | 
| Cheng C Yang | 202a1ff | 2020-01-09 09:34:22 +0800 | [diff] [blame] | 107 | // Check Group Events which contains more than one targets in each combine | 
 | 108 | // events. | 
 | 109 | void checkGroupEvent( | 
 | 110 |     const std::string& directory, | 
 | 111 |     const boost::container::flat_map< | 
 | 112 |         std::string, | 
 | 113 |         boost::container::flat_map<std::string, std::vector<std::string>>>& | 
 | 114 |         groupEventMatch, | 
 | 115 |     boost::container::flat_map< | 
 | 116 |         std::string, | 
 | 117 |         boost::container::flat_map<std::string, std::vector<std::string>>>& | 
 | 118 |         groupEventPathList) | 
 | 119 | { | 
 | 120 |     for (const auto& match : groupEventMatch) | 
 | 121 |     { | 
 | 122 |         const std::string& groupEventName = match.first; | 
 | 123 |         const boost::container::flat_map<std::string, std::vector<std::string>> | 
 | 124 |             events = match.second; | 
 | 125 |         boost::container::flat_map<std::string, std::vector<std::string>> | 
 | 126 |             pathList; | 
 | 127 |         for (const auto& match : events) | 
 | 128 |         { | 
 | 129 |             const std::string& eventName = match.first; | 
 | 130 |             const std::vector<std::string>& eventAttrs = match.second; | 
 | 131 |             for (const auto& eventAttr : eventAttrs) | 
 | 132 |             { | 
 | 133 |                 auto eventPath = directory + "/" + eventAttr; | 
 | 134 |                 std::ifstream eventFile(eventPath); | 
 | 135 |                 if (!eventFile.good()) | 
 | 136 |                 { | 
 | 137 |                     continue; | 
 | 138 |                 } | 
 | 139 |  | 
 | 140 |                 pathList[eventName].push_back(eventPath); | 
 | 141 |             } | 
 | 142 |         } | 
 | 143 |         groupEventPathList[groupEventName] = pathList; | 
 | 144 |     } | 
 | 145 | } | 
 | 146 |  | 
| Cheng C Yang | 58b2b53 | 2019-05-31 00:19:45 +0800 | [diff] [blame] | 147 | // Function checkEventLimits will check all the psu related xxx_input attributes | 
 | 148 | // in sysfs to see if xxx_crit_alarm xxx_lcrit_alarm xxx_max_alarm | 
 | 149 | // xxx_min_alarm exist, then store the existing paths of the alarm attributes | 
 | 150 | // to eventPathList. | 
 | 151 | void checkEventLimits( | 
 | 152 |     const std::string& sensorPathStr, | 
 | 153 |     const boost::container::flat_map<std::string, std::vector<std::string>>& | 
 | 154 |         limitEventMatch, | 
 | 155 |     boost::container::flat_map<std::string, std::vector<std::string>>& | 
 | 156 |         eventPathList) | 
 | 157 | { | 
 | 158 |     for (const auto& limitMatch : limitEventMatch) | 
 | 159 |     { | 
 | 160 |         const std::vector<std::string>& limitEventAttrs = limitMatch.second; | 
 | 161 |         const std::string& eventName = limitMatch.first; | 
 | 162 |         for (const auto& limitEventAttr : limitEventAttrs) | 
 | 163 |         { | 
 | 164 |             auto limitEventPath = | 
 | 165 |                 boost::replace_all_copy(sensorPathStr, "input", limitEventAttr); | 
 | 166 |             std::ifstream eventFile(limitEventPath); | 
 | 167 |             if (!eventFile.good()) | 
 | 168 |             { | 
 | 169 |                 continue; | 
 | 170 |             } | 
 | 171 |             eventPathList[eventName].push_back(limitEventPath); | 
 | 172 |         } | 
 | 173 |     } | 
 | 174 | } | 
| Cheng C Yang | 916360b | 2019-05-07 18:47:16 +0800 | [diff] [blame] | 175 |  | 
| AppaRao Puli | d9d8caf | 2020-02-27 20:56:59 +0530 | [diff] [blame] | 176 | static void | 
 | 177 |     checkPWMSensor(const fs::path& sensorPath, std::string& labelHead, | 
 | 178 |                    const std::string& interfacePath, | 
 | 179 |                    std::shared_ptr<sdbusplus::asio::connection>& dbusConnection, | 
 | 180 |                    sdbusplus::asio::object_server& objectServer, | 
 | 181 |                    const std::string& psuName) | 
| Cheng C Yang | 916360b | 2019-05-07 18:47:16 +0800 | [diff] [blame] | 182 | { | 
 | 183 |     for (const auto& pwmName : pwmTable) | 
 | 184 |     { | 
 | 185 |         if (pwmName.first != labelHead) | 
 | 186 |         { | 
 | 187 |             continue; | 
 | 188 |         } | 
 | 189 |  | 
 | 190 |         const std::string& sensorPathStr = sensorPath.string(); | 
 | 191 |         const std::string& pwmPathStr = | 
 | 192 |             boost::replace_all_copy(sensorPathStr, "input", "target"); | 
 | 193 |         std::ifstream pwmFile(pwmPathStr); | 
 | 194 |         if (!pwmFile.good()) | 
 | 195 |         { | 
 | 196 |             continue; | 
 | 197 |         } | 
 | 198 |  | 
 | 199 |         auto findPWMSensor = pwmSensors.find(psuName + labelHead); | 
 | 200 |         if (findPWMSensor != pwmSensors.end()) | 
 | 201 |         { | 
 | 202 |             continue; | 
 | 203 |         } | 
 | 204 |  | 
 | 205 |         pwmSensors[psuName + labelHead] = std::make_unique<PwmSensor>( | 
| AppaRao Puli | d9d8caf | 2020-02-27 20:56:59 +0530 | [diff] [blame] | 206 |             "Pwm_" + psuName + "_" + pwmName.second, pwmPathStr, dbusConnection, | 
 | 207 |             objectServer, interfacePath + "_" + pwmName.second, "PSU"); | 
| Cheng C Yang | 916360b | 2019-05-07 18:47:16 +0800 | [diff] [blame] | 208 |     } | 
 | 209 | } | 
 | 210 |  | 
 | 211 | void createSensors(boost::asio::io_service& io, | 
 | 212 |                    sdbusplus::asio::object_server& objectServer, | 
 | 213 |                    std::shared_ptr<sdbusplus::asio::connection>& dbusConnection) | 
| Cheng C Yang | 209ec56 | 2019-03-12 16:37:44 +0800 | [diff] [blame] | 214 | { | 
 | 215 |  | 
 | 216 |     ManagedObjectType sensorConfigs; | 
| Josh Lehan | 49cfba9 | 2019-10-08 16:50:42 -0700 | [diff] [blame] | 217 |     int numCreated = 0; | 
| Cheng C Yang | 209ec56 | 2019-03-12 16:37:44 +0800 | [diff] [blame] | 218 |     bool useCache = false; | 
 | 219 |  | 
| Cheng C Yang | 58b2b53 | 2019-05-31 00:19:45 +0800 | [diff] [blame] | 220 |     // TODO may need only modify the ones that need to be changed. | 
 | 221 |     sensors.clear(); | 
| Cheng C Yang | 209ec56 | 2019-03-12 16:37:44 +0800 | [diff] [blame] | 222 |     for (const char* type : sensorTypes) | 
 | 223 |     { | 
 | 224 |         if (!getSensorConfiguration(type, dbusConnection, sensorConfigs, | 
 | 225 |                                     useCache)) | 
 | 226 |         { | 
 | 227 |             std::cerr << "error get sensor config from entity manager\n"; | 
 | 228 |             return; | 
 | 229 |         } | 
 | 230 |         useCache = true; | 
 | 231 |     } | 
 | 232 |  | 
 | 233 |     std::vector<fs::path> pmbusPaths; | 
 | 234 |     if (!findFiles(fs::path("/sys/class/hwmon"), "name", pmbusPaths)) | 
 | 235 |     { | 
 | 236 |         std::cerr << "No PSU sensors in system\n"; | 
 | 237 |         return; | 
 | 238 |     } | 
 | 239 |  | 
 | 240 |     boost::container::flat_set<std::string> directories; | 
 | 241 |     for (const auto& pmbusPath : pmbusPaths) | 
 | 242 |     { | 
| Cheng C Yang | 58b2b53 | 2019-05-31 00:19:45 +0800 | [diff] [blame] | 243 |         boost::container::flat_map<std::string, std::vector<std::string>> | 
 | 244 |             eventPathList; | 
| Cheng C Yang | 202a1ff | 2020-01-09 09:34:22 +0800 | [diff] [blame] | 245 |         boost::container::flat_map< | 
 | 246 |             std::string, | 
 | 247 |             boost::container::flat_map<std::string, std::vector<std::string>>> | 
 | 248 |             groupEventPathList; | 
| Cheng C Yang | 58b2b53 | 2019-05-31 00:19:45 +0800 | [diff] [blame] | 249 |  | 
 | 250 |         std::ifstream nameFile(pmbusPath); | 
 | 251 |         if (!nameFile.good()) | 
 | 252 |         { | 
| Josh Lehan | 49cfba9 | 2019-10-08 16:50:42 -0700 | [diff] [blame] | 253 |             std::cerr << "Failure finding pmbus path " << pmbusPath << "\n"; | 
| Cheng C Yang | 58b2b53 | 2019-05-31 00:19:45 +0800 | [diff] [blame] | 254 |             continue; | 
 | 255 |         } | 
 | 256 |  | 
 | 257 |         std::string pmbusName; | 
 | 258 |         std::getline(nameFile, pmbusName); | 
 | 259 |         nameFile.close(); | 
| Vijay Khemka | 996bad1 | 2019-05-28 15:15:16 -0700 | [diff] [blame] | 260 |  | 
 | 261 |         if (std::find(pmbusNames.begin(), pmbusNames.end(), pmbusName) == | 
 | 262 |             pmbusNames.end()) | 
| Cheng C Yang | 58b2b53 | 2019-05-31 00:19:45 +0800 | [diff] [blame] | 263 |         { | 
| Josh Lehan | 49cfba9 | 2019-10-08 16:50:42 -0700 | [diff] [blame] | 264 |             // To avoid this error message, add your driver name to | 
 | 265 |             // the pmbusNames vector at the top of this file. | 
 | 266 |             std::cerr << "Driver name " << pmbusName | 
 | 267 |                       << " not found in sensor whitelist\n"; | 
| Cheng C Yang | 58b2b53 | 2019-05-31 00:19:45 +0800 | [diff] [blame] | 268 |             continue; | 
 | 269 |         } | 
 | 270 |  | 
 | 271 |         const std::string* psuName; | 
| Cheng C Yang | 209ec56 | 2019-03-12 16:37:44 +0800 | [diff] [blame] | 272 |         auto directory = pmbusPath.parent_path(); | 
 | 273 |  | 
 | 274 |         auto ret = directories.insert(directory.string()); | 
 | 275 |         if (!ret.second) | 
 | 276 |         { | 
| Josh Lehan | 49cfba9 | 2019-10-08 16:50:42 -0700 | [diff] [blame] | 277 |             std::cerr << "Duplicate path " << directory.string() << "\n"; | 
| Cheng C Yang | 58b2b53 | 2019-05-31 00:19:45 +0800 | [diff] [blame] | 278 |             continue; // check if path has already been searched | 
| Cheng C Yang | 209ec56 | 2019-03-12 16:37:44 +0800 | [diff] [blame] | 279 |         } | 
 | 280 |  | 
| James Feist | b6c0b91 | 2019-07-09 12:21:44 -0700 | [diff] [blame] | 281 |         fs::path device = directory / "device"; | 
| Cheng C Yang | 209ec56 | 2019-03-12 16:37:44 +0800 | [diff] [blame] | 282 |         std::string deviceName = fs::canonical(device).stem(); | 
 | 283 |         auto findHyphen = deviceName.find("-"); | 
 | 284 |         if (findHyphen == std::string::npos) | 
 | 285 |         { | 
 | 286 |             std::cerr << "found bad device" << deviceName << "\n"; | 
 | 287 |             continue; | 
 | 288 |         } | 
 | 289 |         std::string busStr = deviceName.substr(0, findHyphen); | 
 | 290 |         std::string addrStr = deviceName.substr(findHyphen + 1); | 
 | 291 |  | 
 | 292 |         size_t bus = 0; | 
 | 293 |         size_t addr = 0; | 
 | 294 |  | 
 | 295 |         try | 
 | 296 |         { | 
 | 297 |             bus = std::stoi(busStr); | 
 | 298 |             addr = std::stoi(addrStr, 0, 16); | 
 | 299 |         } | 
| James Feist | b6c0b91 | 2019-07-09 12:21:44 -0700 | [diff] [blame] | 300 |         catch (std::invalid_argument&) | 
| Cheng C Yang | 209ec56 | 2019-03-12 16:37:44 +0800 | [diff] [blame] | 301 |         { | 
| Josh Lehan | 49cfba9 | 2019-10-08 16:50:42 -0700 | [diff] [blame] | 302 |             std::cerr << "Error parsing bus " << busStr << " addr " << addrStr | 
 | 303 |                       << "\n"; | 
| Cheng C Yang | 209ec56 | 2019-03-12 16:37:44 +0800 | [diff] [blame] | 304 |             continue; | 
 | 305 |         } | 
 | 306 |  | 
| Cheng C Yang | 209ec56 | 2019-03-12 16:37:44 +0800 | [diff] [blame] | 307 |         const std::pair<std::string, boost::container::flat_map< | 
 | 308 |                                          std::string, BasicVariantType>>* | 
 | 309 |             baseConfig = nullptr; | 
 | 310 |         const SensorData* sensorData = nullptr; | 
 | 311 |         const std::string* interfacePath = nullptr; | 
 | 312 |         const char* sensorType = nullptr; | 
| Cheng C Yang | 6b1247a | 2020-03-09 23:48:39 +0800 | [diff] [blame] | 313 |         size_t thresholdConfSize = 0; | 
| Cheng C Yang | 209ec56 | 2019-03-12 16:37:44 +0800 | [diff] [blame] | 314 |  | 
 | 315 |         for (const std::pair<sdbusplus::message::object_path, SensorData>& | 
 | 316 |                  sensor : sensorConfigs) | 
 | 317 |         { | 
 | 318 |             sensorData = &(sensor.second); | 
 | 319 |             for (const char* type : sensorTypes) | 
 | 320 |             { | 
 | 321 |                 auto sensorBase = sensorData->find(type); | 
 | 322 |                 if (sensorBase != sensorData->end()) | 
 | 323 |                 { | 
 | 324 |                     baseConfig = &(*sensorBase); | 
 | 325 |                     sensorType = type; | 
 | 326 |                     break; | 
 | 327 |                 } | 
 | 328 |             } | 
 | 329 |             if (baseConfig == nullptr) | 
 | 330 |             { | 
 | 331 |                 std::cerr << "error finding base configuration for " | 
 | 332 |                           << deviceName << "\n"; | 
 | 333 |                 continue; | 
 | 334 |             } | 
 | 335 |  | 
 | 336 |             auto configBus = baseConfig->second.find("Bus"); | 
 | 337 |             auto configAddress = baseConfig->second.find("Address"); | 
 | 338 |  | 
 | 339 |             if (configBus == baseConfig->second.end() || | 
 | 340 |                 configAddress == baseConfig->second.end()) | 
 | 341 |             { | 
| Cheng C Yang | 58b2b53 | 2019-05-31 00:19:45 +0800 | [diff] [blame] | 342 |                 std::cerr << "error finding necessary entry in configuration\n"; | 
| Cheng C Yang | 209ec56 | 2019-03-12 16:37:44 +0800 | [diff] [blame] | 343 |                 continue; | 
 | 344 |             } | 
 | 345 |  | 
| Cheng C Yang | 58b2b53 | 2019-05-31 00:19:45 +0800 | [diff] [blame] | 346 |             const uint64_t* confBus; | 
 | 347 |             const uint64_t* confAddr; | 
 | 348 |             if (!(confBus = std::get_if<uint64_t>(&(configBus->second))) || | 
 | 349 |                 !(confAddr = std::get_if<uint64_t>(&(configAddress->second)))) | 
 | 350 |             { | 
 | 351 |                 std::cerr | 
| Josh Lehan | 49cfba9 | 2019-10-08 16:50:42 -0700 | [diff] [blame] | 352 |                     << "Cannot get bus or address, invalid configuration\n"; | 
| Cheng C Yang | 58b2b53 | 2019-05-31 00:19:45 +0800 | [diff] [blame] | 353 |                 continue; | 
 | 354 |             } | 
 | 355 |  | 
 | 356 |             if ((*confBus != bus) || (*confAddr != addr)) | 
| Cheng C Yang | 209ec56 | 2019-03-12 16:37:44 +0800 | [diff] [blame] | 357 |             { | 
| Josh Lehan | 432d1ed | 2019-10-16 12:23:31 -0700 | [diff] [blame] | 358 |                 std::cerr << "Configuration skipping " << *confBus << "-" | 
 | 359 |                           << *confAddr << " because not " << bus << "-" << addr | 
 | 360 |                           << "\n"; | 
| Cheng C Yang | 209ec56 | 2019-03-12 16:37:44 +0800 | [diff] [blame] | 361 |                 continue; | 
 | 362 |             } | 
 | 363 |  | 
| Cheng C Yang | 6b1247a | 2020-03-09 23:48:39 +0800 | [diff] [blame] | 364 |             std::vector<thresholds::Threshold> confThresholds; | 
 | 365 |             if (!parseThresholdsFromConfig(*sensorData, confThresholds)) | 
 | 366 |             { | 
 | 367 |                 std::cerr << "error populating totoal thresholds\n"; | 
 | 368 |             } | 
 | 369 |             thresholdConfSize = confThresholds.size(); | 
 | 370 |  | 
| Cheng C Yang | 209ec56 | 2019-03-12 16:37:44 +0800 | [diff] [blame] | 371 |             interfacePath = &(sensor.first.str); | 
 | 372 |             break; | 
 | 373 |         } | 
 | 374 |         if (interfacePath == nullptr) | 
 | 375 |         { | 
| Josh Lehan | 49cfba9 | 2019-10-08 16:50:42 -0700 | [diff] [blame] | 376 |             // To avoid this error message, add your export map entry, | 
 | 377 |             // from Entity Manager, to sensorTypes at the top of this file. | 
| Cheng C Yang | 209ec56 | 2019-03-12 16:37:44 +0800 | [diff] [blame] | 378 |             std::cerr << "failed to find match for " << deviceName << "\n"; | 
 | 379 |             continue; | 
 | 380 |         } | 
 | 381 |  | 
| Cheng C Yang | e50345b | 2019-04-02 17:26:15 +0800 | [diff] [blame] | 382 |         auto findPSUName = baseConfig->second.find("Name"); | 
 | 383 |         if (findPSUName == baseConfig->second.end()) | 
| Cheng C Yang | 209ec56 | 2019-03-12 16:37:44 +0800 | [diff] [blame] | 384 |         { | 
 | 385 |             std::cerr << "could not determine configuration name for " | 
 | 386 |                       << deviceName << "\n"; | 
 | 387 |             continue; | 
 | 388 |         } | 
 | 389 |  | 
| Cheng C Yang | 58b2b53 | 2019-05-31 00:19:45 +0800 | [diff] [blame] | 390 |         if (!(psuName = std::get_if<std::string>(&(findPSUName->second)))) | 
 | 391 |         { | 
 | 392 |             std::cerr << "Cannot find psu name, invalid configuration\n"; | 
 | 393 |             continue; | 
 | 394 |         } | 
 | 395 |         checkEvent(directory.string(), eventMatch, eventPathList); | 
| Cheng C Yang | 202a1ff | 2020-01-09 09:34:22 +0800 | [diff] [blame] | 396 |         checkGroupEvent(directory.string(), groupEventMatch, | 
 | 397 |                         groupEventPathList); | 
| Cheng C Yang | 58b2b53 | 2019-05-31 00:19:45 +0800 | [diff] [blame] | 398 |  | 
| Vijay Khemka | 996bad1 | 2019-05-28 15:15:16 -0700 | [diff] [blame] | 399 |         /* Check if there are more sensors in the same interface */ | 
 | 400 |         int i = 1; | 
 | 401 |         std::vector<std::string> psuNames; | 
 | 402 |         do | 
 | 403 |         { | 
| Josh Lehan | 49cfba9 | 2019-10-08 16:50:42 -0700 | [diff] [blame] | 404 |             // Individual string fields: Name, Name1, Name2, Name3, ... | 
| Vijay Khemka | 996bad1 | 2019-05-28 15:15:16 -0700 | [diff] [blame] | 405 |             psuNames.push_back(std::get<std::string>(findPSUName->second)); | 
 | 406 |             findPSUName = baseConfig->second.find("Name" + std::to_string(i++)); | 
 | 407 |         } while (findPSUName != baseConfig->second.end()); | 
 | 408 |  | 
| Cheng C Yang | e50345b | 2019-04-02 17:26:15 +0800 | [diff] [blame] | 409 |         std::vector<fs::path> sensorPaths; | 
| James Feist | b6c0b91 | 2019-07-09 12:21:44 -0700 | [diff] [blame] | 410 |         if (!findFiles(directory, R"(\w\d+_input$)", sensorPaths, 0)) | 
| Cheng C Yang | 209ec56 | 2019-03-12 16:37:44 +0800 | [diff] [blame] | 411 |         { | 
| Cheng C Yang | e50345b | 2019-04-02 17:26:15 +0800 | [diff] [blame] | 412 |             std::cerr << "No PSU non-label sensor in PSU\n"; | 
| Cheng C Yang | 209ec56 | 2019-03-12 16:37:44 +0800 | [diff] [blame] | 413 |             continue; | 
 | 414 |         } | 
 | 415 |  | 
| Vijay Khemka | 996bad1 | 2019-05-28 15:15:16 -0700 | [diff] [blame] | 416 |         /* Find array of labels to be exposed if it is defined in config */ | 
 | 417 |         std::vector<std::string> findLabels; | 
 | 418 |         auto findLabelObj = baseConfig->second.find("Labels"); | 
 | 419 |         if (findLabelObj != baseConfig->second.end()) | 
 | 420 |         { | 
 | 421 |             findLabels = | 
 | 422 |                 std::get<std::vector<std::string>>(findLabelObj->second); | 
 | 423 |         } | 
 | 424 |  | 
| Jason Ling | 5747fab | 2019-10-02 16:46:23 -0700 | [diff] [blame] | 425 |         std::regex sensorNameRegEx("([A-Za-z]+)[0-9]*_"); | 
 | 426 |         std::smatch matches; | 
 | 427 |  | 
| Cheng C Yang | e50345b | 2019-04-02 17:26:15 +0800 | [diff] [blame] | 428 |         for (const auto& sensorPath : sensorPaths) | 
| Cheng C Yang | 209ec56 | 2019-03-12 16:37:44 +0800 | [diff] [blame] | 429 |         { | 
| Cheng C Yang | e50345b | 2019-04-02 17:26:15 +0800 | [diff] [blame] | 430 |             std::string labelHead; | 
 | 431 |             std::string sensorPathStr = sensorPath.string(); | 
 | 432 |             std::string sensorNameStr = sensorPath.filename(); | 
| Jason Ling | 5747fab | 2019-10-02 16:46:23 -0700 | [diff] [blame] | 433 |             std::string sensorNameSubStr{""}; | 
 | 434 |             if (std::regex_search(sensorNameStr, matches, sensorNameRegEx)) | 
 | 435 |             { | 
| Josh Lehan | 0649445 | 2019-10-31 09:49:16 -0700 | [diff] [blame] | 436 |                 // hwmon *_input filename without number: | 
 | 437 |                 // in, curr, power, temp, ... | 
| Jason Ling | 5747fab | 2019-10-02 16:46:23 -0700 | [diff] [blame] | 438 |                 sensorNameSubStr = matches[1]; | 
 | 439 |             } | 
 | 440 |             else | 
 | 441 |             { | 
| Josh Lehan | 0649445 | 2019-10-31 09:49:16 -0700 | [diff] [blame] | 442 |                 std::cerr << "Could not extract the alpha prefix from " | 
| Jason Ling | 5747fab | 2019-10-02 16:46:23 -0700 | [diff] [blame] | 443 |                           << sensorNameStr; | 
 | 444 |                 continue; | 
 | 445 |             } | 
| Cheng C Yang | e50345b | 2019-04-02 17:26:15 +0800 | [diff] [blame] | 446 |  | 
| Cheng C Yang | ecba9de | 2019-09-12 23:41:50 +0800 | [diff] [blame] | 447 |             auto labelPath = | 
 | 448 |                 boost::replace_all_copy(sensorPathStr, "input", "label"); | 
 | 449 |             std::ifstream labelFile(labelPath); | 
 | 450 |             if (!labelFile.good()) | 
| Cheng C Yang | 209ec56 | 2019-03-12 16:37:44 +0800 | [diff] [blame] | 451 |             { | 
| Cheng C Yang | 6b1247a | 2020-03-09 23:48:39 +0800 | [diff] [blame] | 452 |                 if constexpr (DEBUG) | 
 | 453 |                 { | 
 | 454 |                     std::cerr << "Input file " << sensorPath | 
 | 455 |                               << " has no corresponding label file\n"; | 
 | 456 |                 } | 
| Josh Lehan | 0649445 | 2019-10-31 09:49:16 -0700 | [diff] [blame] | 457 |                 // hwmon *_input filename with number: | 
 | 458 |                 // temp1, temp2, temp3, ... | 
| Cheng C Yang | e50345b | 2019-04-02 17:26:15 +0800 | [diff] [blame] | 459 |                 labelHead = sensorNameStr.substr(0, sensorNameStr.find("_")); | 
| Cheng C Yang | 209ec56 | 2019-03-12 16:37:44 +0800 | [diff] [blame] | 460 |             } | 
 | 461 |             else | 
 | 462 |             { | 
| Cheng C Yang | e50345b | 2019-04-02 17:26:15 +0800 | [diff] [blame] | 463 |                 std::string label; | 
 | 464 |                 std::getline(labelFile, label); | 
 | 465 |                 labelFile.close(); | 
| Cheng C Yang | e50345b | 2019-04-02 17:26:15 +0800 | [diff] [blame] | 466 |                 auto findSensor = sensors.find(label); | 
 | 467 |                 if (findSensor != sensors.end()) | 
 | 468 |                 { | 
 | 469 |                     continue; | 
 | 470 |                 } | 
 | 471 |  | 
| Josh Lehan | 0649445 | 2019-10-31 09:49:16 -0700 | [diff] [blame] | 472 |                 // hwmon corresponding *_label file contents: | 
 | 473 |                 // vin1, vout1, ... | 
| Cheng C Yang | e50345b | 2019-04-02 17:26:15 +0800 | [diff] [blame] | 474 |                 labelHead = label.substr(0, label.find(" ")); | 
 | 475 |             } | 
 | 476 |  | 
| Josh Lehan | 74d9bd9 | 2019-10-31 08:51:58 -0700 | [diff] [blame] | 477 |             if constexpr (DEBUG) | 
 | 478 |             { | 
 | 479 |                 std::cerr << "Sensor type=\"" << sensorNameSubStr | 
 | 480 |                           << "\" label=\"" << labelHead << "\"\n"; | 
 | 481 |             } | 
 | 482 |  | 
| AppaRao Puli | d9d8caf | 2020-02-27 20:56:59 +0530 | [diff] [blame] | 483 |             checkPWMSensor(sensorPath, labelHead, *interfacePath, | 
 | 484 |                            dbusConnection, objectServer, psuNames[0]); | 
| Cheng C Yang | 916360b | 2019-05-07 18:47:16 +0800 | [diff] [blame] | 485 |  | 
| Vijay Khemka | 996bad1 | 2019-05-28 15:15:16 -0700 | [diff] [blame] | 486 |             if (!findLabels.empty()) | 
 | 487 |             { | 
 | 488 |                 /* Check if this labelHead is enabled in config file */ | 
 | 489 |                 if (std::find(findLabels.begin(), findLabels.end(), | 
 | 490 |                               labelHead) == findLabels.end()) | 
 | 491 |                 { | 
| Cheng C Yang | 6b1247a | 2020-03-09 23:48:39 +0800 | [diff] [blame] | 492 |                     if constexpr (DEBUG) | 
 | 493 |                     { | 
 | 494 |                         std::cerr << "could not find " << labelHead | 
 | 495 |                                   << " in the Labels list\n"; | 
 | 496 |                     } | 
| Vijay Khemka | 996bad1 | 2019-05-28 15:15:16 -0700 | [diff] [blame] | 497 |                     continue; | 
 | 498 |                 } | 
 | 499 |             } | 
| Cheng C Yang | e50345b | 2019-04-02 17:26:15 +0800 | [diff] [blame] | 500 |  | 
| Cheng C Yang | e50345b | 2019-04-02 17:26:15 +0800 | [diff] [blame] | 501 |             auto findProperty = labelMatch.find(labelHead); | 
 | 502 |             if (findProperty == labelMatch.end()) | 
| Cheng C Yang | 209ec56 | 2019-03-12 16:37:44 +0800 | [diff] [blame] | 503 |             { | 
| Josh Lehan | 74d9bd9 | 2019-10-31 08:51:58 -0700 | [diff] [blame] | 504 |                 if constexpr (DEBUG) | 
 | 505 |                 { | 
 | 506 |                     std::cerr << "Could not find matching default property for " | 
 | 507 |                               << labelHead << "\n"; | 
 | 508 |                 } | 
| Cheng C Yang | 209ec56 | 2019-03-12 16:37:44 +0800 | [diff] [blame] | 509 |                 continue; | 
 | 510 |             } | 
 | 511 |  | 
| Josh Lehan | 74d9bd9 | 2019-10-31 08:51:58 -0700 | [diff] [blame] | 512 |             // Protect the hardcoded labelMatch list from changes, | 
 | 513 |             // by making a copy and modifying that instead. | 
 | 514 |             // Avoid bleedthrough of one device's customizations to | 
 | 515 |             // the next device, as each should be independently customizable. | 
 | 516 |             psuProperties.push_back(findProperty->second); | 
 | 517 |             auto psuProperty = psuProperties.rbegin(); | 
 | 518 |  | 
 | 519 |             // Use label head as prefix for reading from config file, | 
 | 520 |             // example if temp1: temp1_Name, temp1_Scale, temp1_Min, ... | 
 | 521 |             std::string keyName = labelHead + "_Name"; | 
 | 522 |             std::string keyScale = labelHead + "_Scale"; | 
 | 523 |             std::string keyMin = labelHead + "_Min"; | 
 | 524 |             std::string keyMax = labelHead + "_Max"; | 
 | 525 |  | 
 | 526 |             bool customizedName = false; | 
 | 527 |             auto findCustomName = baseConfig->second.find(keyName); | 
 | 528 |             if (findCustomName != baseConfig->second.end()) | 
| Josh Lehan | 432d1ed | 2019-10-16 12:23:31 -0700 | [diff] [blame] | 529 |             { | 
| Josh Lehan | 74d9bd9 | 2019-10-31 08:51:58 -0700 | [diff] [blame] | 530 |                 try | 
 | 531 |                 { | 
 | 532 |                     psuProperty->labelTypeName = std::visit( | 
 | 533 |                         VariantToStringVisitor(), findCustomName->second); | 
 | 534 |                 } | 
 | 535 |                 catch (std::invalid_argument&) | 
 | 536 |                 { | 
 | 537 |                     std::cerr << "Unable to parse " << keyName << "\n"; | 
 | 538 |                     continue; | 
 | 539 |                 } | 
 | 540 |  | 
 | 541 |                 // All strings are valid, including empty string | 
 | 542 |                 customizedName = true; | 
 | 543 |             } | 
 | 544 |  | 
 | 545 |             bool customizedScale = false; | 
 | 546 |             auto findCustomScale = baseConfig->second.find(keyScale); | 
 | 547 |             if (findCustomScale != baseConfig->second.end()) | 
 | 548 |             { | 
 | 549 |                 try | 
 | 550 |                 { | 
 | 551 |                     psuProperty->sensorScaleFactor = std::visit( | 
 | 552 |                         VariantToUnsignedIntVisitor(), findCustomScale->second); | 
 | 553 |                 } | 
 | 554 |                 catch (std::invalid_argument&) | 
 | 555 |                 { | 
 | 556 |                     std::cerr << "Unable to parse " << keyScale << "\n"; | 
 | 557 |                     continue; | 
 | 558 |                 } | 
 | 559 |  | 
 | 560 |                 // Avoid later division by zero | 
 | 561 |                 if (psuProperty->sensorScaleFactor > 0) | 
 | 562 |                 { | 
 | 563 |                     customizedScale = true; | 
 | 564 |                 } | 
 | 565 |                 else | 
 | 566 |                 { | 
 | 567 |                     std::cerr << "Unable to accept " << keyScale << "\n"; | 
 | 568 |                     continue; | 
 | 569 |                 } | 
 | 570 |             } | 
 | 571 |  | 
 | 572 |             auto findCustomMin = baseConfig->second.find(keyMin); | 
 | 573 |             if (findCustomMin != baseConfig->second.end()) | 
 | 574 |             { | 
 | 575 |                 try | 
 | 576 |                 { | 
 | 577 |                     psuProperty->minReading = std::visit( | 
 | 578 |                         VariantToDoubleVisitor(), findCustomMin->second); | 
 | 579 |                 } | 
 | 580 |                 catch (std::invalid_argument&) | 
 | 581 |                 { | 
 | 582 |                     std::cerr << "Unable to parse " << keyMin << "\n"; | 
 | 583 |                     continue; | 
 | 584 |                 } | 
 | 585 |             } | 
 | 586 |  | 
 | 587 |             auto findCustomMax = baseConfig->second.find(keyMax); | 
 | 588 |             if (findCustomMax != baseConfig->second.end()) | 
 | 589 |             { | 
 | 590 |                 try | 
 | 591 |                 { | 
 | 592 |                     psuProperty->maxReading = std::visit( | 
 | 593 |                         VariantToDoubleVisitor(), findCustomMax->second); | 
 | 594 |                 } | 
 | 595 |                 catch (std::invalid_argument&) | 
 | 596 |                 { | 
 | 597 |                     std::cerr << "Unable to parse " << keyMax << "\n"; | 
 | 598 |                     continue; | 
 | 599 |                 } | 
 | 600 |             } | 
 | 601 |  | 
 | 602 |             if (!(psuProperty->minReading < psuProperty->maxReading)) | 
 | 603 |             { | 
 | 604 |                 std::cerr << "Min must be less than Max\n"; | 
 | 605 |                 continue; | 
 | 606 |             } | 
 | 607 |  | 
 | 608 |             // If the sensor name is being customized by config file, | 
 | 609 |             // then prefix/suffix composition becomes not necessary, | 
 | 610 |             // and in fact not wanted, because it gets in the way. | 
 | 611 |             std::string psuNameFromIndex; | 
 | 612 |             if (!customizedName) | 
 | 613 |             { | 
 | 614 |                 /* Find out sensor name index for this label */ | 
 | 615 |                 std::regex rgx("[A-Za-z]+([0-9]+)"); | 
| Brad Bishop | fbb44ad | 2019-11-08 09:42:37 -0500 | [diff] [blame] | 616 |                 size_t nameIndex{0}; | 
| Josh Lehan | 74d9bd9 | 2019-10-31 08:51:58 -0700 | [diff] [blame] | 617 |                 if (std::regex_search(labelHead, matches, rgx)) | 
 | 618 |                 { | 
 | 619 |                     nameIndex = std::stoi(matches[1]); | 
 | 620 |  | 
 | 621 |                     // Decrement to preserve alignment, because hwmon | 
 | 622 |                     // human-readable filenames and labels use 1-based | 
 | 623 |                     // numbering, but the "Name", "Name1", "Name2", etc. naming | 
 | 624 |                     // convention (the psuNames vector) uses 0-based numbering. | 
 | 625 |                     if (nameIndex > 0) | 
 | 626 |                     { | 
 | 627 |                         --nameIndex; | 
 | 628 |                     } | 
 | 629 |                 } | 
 | 630 |                 else | 
 | 631 |                 { | 
 | 632 |                     nameIndex = 0; | 
 | 633 |                 } | 
 | 634 |  | 
 | 635 |                 if (psuNames.size() <= nameIndex) | 
 | 636 |                 { | 
 | 637 |                     std::cerr << "Could not pair " << labelHead | 
 | 638 |                               << " with a Name field\n"; | 
 | 639 |                     continue; | 
 | 640 |                 } | 
 | 641 |  | 
 | 642 |                 psuNameFromIndex = psuNames[nameIndex]; | 
 | 643 |  | 
 | 644 |                 if constexpr (DEBUG) | 
 | 645 |                 { | 
 | 646 |                     std::cerr << "Sensor label head " << labelHead | 
 | 647 |                               << " paired with " << psuNameFromIndex | 
 | 648 |                               << " at index " << nameIndex << "\n"; | 
 | 649 |                 } | 
| Josh Lehan | 432d1ed | 2019-10-16 12:23:31 -0700 | [diff] [blame] | 650 |             } | 
 | 651 |  | 
| Cheng C Yang | 58b2b53 | 2019-05-31 00:19:45 +0800 | [diff] [blame] | 652 |             checkEventLimits(sensorPathStr, limitEventMatch, eventPathList); | 
 | 653 |  | 
| Josh Lehan | 74d9bd9 | 2019-10-31 08:51:58 -0700 | [diff] [blame] | 654 |             // Similarly, if sensor scaling factor is being customized, | 
 | 655 |             // then the below power-of-10 constraint becomes unnecessary, | 
 | 656 |             // as config should be able to specify an arbitrary divisor. | 
 | 657 |             unsigned int factor = psuProperty->sensorScaleFactor; | 
 | 658 |             if (!customizedScale) | 
| Vijay Khemka | 53ca444 | 2019-07-23 11:03:55 -0700 | [diff] [blame] | 659 |             { | 
| Josh Lehan | 74d9bd9 | 2019-10-31 08:51:58 -0700 | [diff] [blame] | 660 |                 // Preserve existing usage of hardcoded labelMatch table below | 
 | 661 |                 factor = std::pow(10.0, factor); | 
| Vijay Khemka | 53ca444 | 2019-07-23 11:03:55 -0700 | [diff] [blame] | 662 |  | 
| Josh Lehan | 74d9bd9 | 2019-10-31 08:51:58 -0700 | [diff] [blame] | 663 |                 /* Change first char of substring to uppercase */ | 
 | 664 |                 char firstChar = sensorNameSubStr[0] - 0x20; | 
 | 665 |                 std::string strScaleFactor = | 
 | 666 |                     firstChar + sensorNameSubStr.substr(1) + "ScaleFactor"; | 
 | 667 |  | 
 | 668 |                 // Preserve existing configs by accepting earlier syntax, | 
 | 669 |                 // example CurrScaleFactor, PowerScaleFactor, ... | 
 | 670 |                 auto findScaleFactor = baseConfig->second.find(strScaleFactor); | 
 | 671 |                 if (findScaleFactor != baseConfig->second.end()) | 
 | 672 |                 { | 
 | 673 |                     factor = std::visit(VariantToIntVisitor(), | 
 | 674 |                                         findScaleFactor->second); | 
 | 675 |                 } | 
 | 676 |  | 
 | 677 |                 if constexpr (DEBUG) | 
 | 678 |                 { | 
 | 679 |                     std::cerr << "Sensor scaling factor " << factor | 
 | 680 |                               << " string " << strScaleFactor << "\n"; | 
 | 681 |                 } | 
| Josh Lehan | 49cfba9 | 2019-10-08 16:50:42 -0700 | [diff] [blame] | 682 |             } | 
 | 683 |  | 
| Vijay Khemka | 996bad1 | 2019-05-28 15:15:16 -0700 | [diff] [blame] | 684 |             std::vector<thresholds::Threshold> sensorThresholds; | 
| Joshi, Mansi | 14f0ad8 | 2019-11-21 10:52:30 +0530 | [diff] [blame] | 685 |             if (!parseThresholdsFromConfig(*sensorData, sensorThresholds, | 
 | 686 |                                            &labelHead)) | 
| Cheng C Yang | e50345b | 2019-04-02 17:26:15 +0800 | [diff] [blame] | 687 |             { | 
| James Feist | 17ab6e0 | 2019-06-25 12:28:13 -0700 | [diff] [blame] | 688 |                 std::cerr << "error populating thresholds for " | 
 | 689 |                           << sensorNameSubStr << "\n"; | 
| Cheng C Yang | e50345b | 2019-04-02 17:26:15 +0800 | [diff] [blame] | 690 |             } | 
 | 691 |  | 
 | 692 |             auto findSensorType = sensorTable.find(sensorNameSubStr); | 
 | 693 |             if (findSensorType == sensorTable.end()) | 
 | 694 |             { | 
| Jason Ling | 5747fab | 2019-10-02 16:46:23 -0700 | [diff] [blame] | 695 |                 std::cerr << sensorNameSubStr | 
| Josh Lehan | 0649445 | 2019-10-31 09:49:16 -0700 | [diff] [blame] | 696 |                           << " is not a recognized sensor type\n"; | 
| Cheng C Yang | e50345b | 2019-04-02 17:26:15 +0800 | [diff] [blame] | 697 |                 continue; | 
 | 698 |             } | 
 | 699 |  | 
| Josh Lehan | 49cfba9 | 2019-10-08 16:50:42 -0700 | [diff] [blame] | 700 |             if constexpr (DEBUG) | 
 | 701 |             { | 
| Josh Lehan | 74d9bd9 | 2019-10-31 08:51:58 -0700 | [diff] [blame] | 702 |                 std::cerr << "Sensor properties: Name \"" | 
 | 703 |                           << psuProperty->labelTypeName << "\" Scale " | 
 | 704 |                           << psuProperty->sensorScaleFactor << " Min " | 
 | 705 |                           << psuProperty->minReading << " Max " | 
 | 706 |                           << psuProperty->maxReading << "\n"; | 
 | 707 |             } | 
 | 708 |  | 
 | 709 |             std::string sensorName = psuProperty->labelTypeName; | 
 | 710 |             if (customizedName) | 
 | 711 |             { | 
 | 712 |                 if (sensorName.empty()) | 
 | 713 |                 { | 
 | 714 |                     // Allow selective disabling of an individual sensor, | 
 | 715 |                     // by customizing its name to an empty string. | 
 | 716 |                     std::cerr << "Sensor disabled, empty string\n"; | 
 | 717 |                     continue; | 
 | 718 |                 } | 
 | 719 |             } | 
 | 720 |             else | 
 | 721 |             { | 
 | 722 |                 // Sensor name not customized, do prefix/suffix composition, | 
 | 723 |                 // preserving default behavior by using psuNameFromIndex. | 
 | 724 |                 sensorName = | 
 | 725 |                     psuNameFromIndex + " " + psuProperty->labelTypeName; | 
 | 726 |             } | 
 | 727 |  | 
 | 728 |             if constexpr (DEBUG) | 
 | 729 |             { | 
 | 730 |                 std::cerr << "Sensor name \"" << sensorName << "\" path \"" | 
 | 731 |                           << sensorPathStr << "\" type \"" << sensorType | 
 | 732 |                           << "\"\n"; | 
| Josh Lehan | 49cfba9 | 2019-10-08 16:50:42 -0700 | [diff] [blame] | 733 |             } | 
 | 734 |  | 
| Cheng C Yang | 58b2b53 | 2019-05-31 00:19:45 +0800 | [diff] [blame] | 735 |             sensors[sensorName] = std::make_unique<PSUSensor>( | 
| Cheng C Yang | e50345b | 2019-04-02 17:26:15 +0800 | [diff] [blame] | 736 |                 sensorPathStr, sensorType, objectServer, dbusConnection, io, | 
| Cheng C Yang | 209ec56 | 2019-03-12 16:37:44 +0800 | [diff] [blame] | 737 |                 sensorName, std::move(sensorThresholds), *interfacePath, | 
| Josh Lehan | 74d9bd9 | 2019-10-31 08:51:58 -0700 | [diff] [blame] | 738 |                 findSensorType->second, factor, psuProperty->maxReading, | 
| Cheng C Yang | 6b1247a | 2020-03-09 23:48:39 +0800 | [diff] [blame] | 739 |                 psuProperty->minReading, labelHead, thresholdConfSize); | 
| Josh Lehan | 74d9bd9 | 2019-10-31 08:51:58 -0700 | [diff] [blame] | 740 |  | 
 | 741 |             ++numCreated; | 
 | 742 |             if constexpr (DEBUG) | 
 | 743 |             { | 
 | 744 |                 std::cerr << "Created " << numCreated << " sensors so far\n"; | 
 | 745 |             } | 
| Cheng C Yang | 209ec56 | 2019-03-12 16:37:44 +0800 | [diff] [blame] | 746 |         } | 
| Cheng C Yang | 58b2b53 | 2019-05-31 00:19:45 +0800 | [diff] [blame] | 747 |  | 
 | 748 |         // OperationalStatus event | 
| Cheng C Yang | 92498eb | 2019-09-26 21:59:25 +0800 | [diff] [blame] | 749 |         combineEvents[*psuName + "OperationalStatus"] = nullptr; | 
| Cheng C Yang | 58b2b53 | 2019-05-31 00:19:45 +0800 | [diff] [blame] | 750 |         combineEvents[*psuName + "OperationalStatus"] = | 
| Yong Li | 3046a02 | 2020-04-03 13:01:02 +0800 | [diff] [blame] | 751 |             std::make_unique<PSUCombineEvent>( | 
 | 752 |                 objectServer, dbusConnection, io, *psuName, eventPathList, | 
 | 753 |                 groupEventPathList, "OperationalStatus"); | 
| Cheng C Yang | 209ec56 | 2019-03-12 16:37:44 +0800 | [diff] [blame] | 754 |     } | 
| Josh Lehan | 49cfba9 | 2019-10-08 16:50:42 -0700 | [diff] [blame] | 755 |  | 
 | 756 |     if constexpr (DEBUG) | 
 | 757 |     { | 
 | 758 |         std::cerr << "Created total of " << numCreated << " sensors\n"; | 
 | 759 |     } | 
| Cheng C Yang | 209ec56 | 2019-03-12 16:37:44 +0800 | [diff] [blame] | 760 |     return; | 
 | 761 | } | 
 | 762 |  | 
| Cheng C Yang | 916360b | 2019-05-07 18:47:16 +0800 | [diff] [blame] | 763 | void propertyInitialize(void) | 
| Cheng C Yang | 209ec56 | 2019-03-12 16:37:44 +0800 | [diff] [blame] | 764 | { | 
| Cheng C Yang | e50345b | 2019-04-02 17:26:15 +0800 | [diff] [blame] | 765 |     sensorTable = {{"power", "power/"}, | 
 | 766 |                    {"curr", "current/"}, | 
 | 767 |                    {"temp", "temperature/"}, | 
 | 768 |                    {"in", "voltage/"}, | 
 | 769 |                    {"fan", "fan_tach/"}}; | 
 | 770 |  | 
 | 771 |     labelMatch = {{"pin", PSUProperty("Input Power", 3000, 0, 6)}, | 
 | 772 |                   {"pout1", PSUProperty("Output Power", 3000, 0, 6)}, | 
| Vijay Khemka | 996bad1 | 2019-05-28 15:15:16 -0700 | [diff] [blame] | 773 |                   {"pout2", PSUProperty("Output Power", 3000, 0, 6)}, | 
 | 774 |                   {"pout3", PSUProperty("Output Power", 3000, 0, 6)}, | 
| Vijay Khemka | be66441 | 2019-06-28 12:10:04 -0700 | [diff] [blame] | 775 |                   {"power1", PSUProperty("Output Power", 3000, 0, 6)}, | 
| Cheng C Yang | bdbde96 | 2019-04-26 22:50:34 +0800 | [diff] [blame] | 776 |                   {"vin", PSUProperty("Input Voltage", 300, 0, 3)}, | 
| Vijay Khemka | 996bad1 | 2019-05-28 15:15:16 -0700 | [diff] [blame] | 777 |                   {"vout1", PSUProperty("Output Voltage", 255, 0, 3)}, | 
 | 778 |                   {"vout2", PSUProperty("Output Voltage", 255, 0, 3)}, | 
 | 779 |                   {"vout3", PSUProperty("Output Voltage", 255, 0, 3)}, | 
| Jason Ling | 5747fab | 2019-10-02 16:46:23 -0700 | [diff] [blame] | 780 |                   {"vout4", PSUProperty("Output Voltage", 255, 0, 3)}, | 
 | 781 |                   {"vout5", PSUProperty("Output Voltage", 255, 0, 3)}, | 
 | 782 |                   {"vout6", PSUProperty("Output Voltage", 255, 0, 3)}, | 
 | 783 |                   {"vout7", PSUProperty("Output Voltage", 255, 0, 3)}, | 
 | 784 |                   {"vout8", PSUProperty("Output Voltage", 255, 0, 3)}, | 
 | 785 |                   {"vout9", PSUProperty("Output Voltage", 255, 0, 3)}, | 
 | 786 |                   {"vout10", PSUProperty("Output Voltage", 255, 0, 3)}, | 
 | 787 |                   {"vout11", PSUProperty("Output Voltage", 255, 0, 3)}, | 
 | 788 |                   {"vout12", PSUProperty("Output Voltage", 255, 0, 3)}, | 
 | 789 |                   {"vout13", PSUProperty("Output Voltage", 255, 0, 3)}, | 
 | 790 |                   {"vout14", PSUProperty("Output Voltage", 255, 0, 3)}, | 
 | 791 |                   {"vout15", PSUProperty("Output Voltage", 255, 0, 3)}, | 
 | 792 |                   {"vout16", PSUProperty("Output Voltage", 255, 0, 3)}, | 
| Vijay Khemka | be66441 | 2019-06-28 12:10:04 -0700 | [diff] [blame] | 793 |                   {"in1", PSUProperty("Output Voltage", 255, 0, 3)}, | 
| Cheng C Yang | e50345b | 2019-04-02 17:26:15 +0800 | [diff] [blame] | 794 |                   {"iin", PSUProperty("Input Current", 20, 0, 3)}, | 
 | 795 |                   {"iout1", PSUProperty("Output Current", 255, 0, 3)}, | 
| Vijay Khemka | 996bad1 | 2019-05-28 15:15:16 -0700 | [diff] [blame] | 796 |                   {"iout2", PSUProperty("Output Current", 255, 0, 3)}, | 
 | 797 |                   {"iout3", PSUProperty("Output Current", 255, 0, 3)}, | 
| Peter Lundgren | 48b4423 | 2020-01-30 16:02:11 -0800 | [diff] [blame] | 798 |                   {"iout4", PSUProperty("Output Current", 255, 0, 3)}, | 
 | 799 |                   {"iout5", PSUProperty("Output Current", 255, 0, 3)}, | 
 | 800 |                   {"iout6", PSUProperty("Output Current", 255, 0, 3)}, | 
 | 801 |                   {"iout7", PSUProperty("Output Current", 255, 0, 3)}, | 
 | 802 |                   {"iout8", PSUProperty("Output Current", 255, 0, 3)}, | 
 | 803 |                   {"iout9", PSUProperty("Output Current", 255, 0, 3)}, | 
 | 804 |                   {"iout10", PSUProperty("Output Current", 255, 0, 3)}, | 
 | 805 |                   {"iout11", PSUProperty("Output Current", 255, 0, 3)}, | 
 | 806 |                   {"iout12", PSUProperty("Output Current", 255, 0, 3)}, | 
 | 807 |                   {"iout13", PSUProperty("Output Current", 255, 0, 3)}, | 
 | 808 |                   {"iout14", PSUProperty("Output Current", 255, 0, 3)}, | 
| Vijay Khemka | be66441 | 2019-06-28 12:10:04 -0700 | [diff] [blame] | 809 |                   {"curr1", PSUProperty("Output Current", 255, 0, 3)}, | 
| Cheng C Yang | e50345b | 2019-04-02 17:26:15 +0800 | [diff] [blame] | 810 |                   {"temp1", PSUProperty("Temperature", 127, -128, 3)}, | 
| Vijay Khemka | 996bad1 | 2019-05-28 15:15:16 -0700 | [diff] [blame] | 811 |                   {"temp2", PSUProperty("Temperature", 127, -128, 3)}, | 
 | 812 |                   {"temp3", PSUProperty("Temperature", 127, -128, 3)}, | 
| Jason Ling | 5747fab | 2019-10-02 16:46:23 -0700 | [diff] [blame] | 813 |                   {"temp4", PSUProperty("Temperature", 127, -128, 3)}, | 
 | 814 |                   {"temp5", PSUProperty("Temperature", 127, -128, 3)}, | 
| Alex Qiu | f5709b4 | 2020-01-29 13:29:50 -0800 | [diff] [blame] | 815 |                   {"temp6", PSUProperty("Temperature", 127, -128, 3)}, | 
| Cheng C Yang | 8dbb395 | 2019-05-23 00:03:12 +0800 | [diff] [blame] | 816 |                   {"fan1", PSUProperty("Fan Speed 1", 30000, 0, 0)}, | 
 | 817 |                   {"fan2", PSUProperty("Fan Speed 2", 30000, 0, 0)}}; | 
| Cheng C Yang | 916360b | 2019-05-07 18:47:16 +0800 | [diff] [blame] | 818 |  | 
 | 819 |     pwmTable = {{"fan1", "Fan_1"}, {"fan2", "Fan_2"}}; | 
| Cheng C Yang | 58b2b53 | 2019-05-31 00:19:45 +0800 | [diff] [blame] | 820 |  | 
 | 821 |     limitEventMatch = {{"PredictiveFailure", {"max_alarm", "min_alarm"}}, | 
 | 822 |                        {"Failure", {"crit_alarm", "lcrit_alarm"}}}; | 
 | 823 |  | 
| Cheng C Yang | 202a1ff | 2020-01-09 09:34:22 +0800 | [diff] [blame] | 824 |     eventMatch = {{"PredictiveFailure", {"power1_alarm"}}, | 
 | 825 |                   {"Failure", {"in2_alarm"}}, | 
 | 826 |                   {"ACLost", {"in1_beep"}}, | 
 | 827 |                   {"ConfigureError", {"in1_fault"}}}; | 
 | 828 |  | 
 | 829 |     groupEventMatch = {{"FanFault", | 
 | 830 |                         {{"fan1", {"fan1_alarm", "fan1_fault"}}, | 
 | 831 |                          {"fan2", {"fan2_alarm", "fan2_fault"}}}}}; | 
| Cheng C Yang | 209ec56 | 2019-03-12 16:37:44 +0800 | [diff] [blame] | 832 | } | 
 | 833 |  | 
| James Feist | b6c0b91 | 2019-07-09 12:21:44 -0700 | [diff] [blame] | 834 | int main() | 
| Cheng C Yang | 209ec56 | 2019-03-12 16:37:44 +0800 | [diff] [blame] | 835 | { | 
 | 836 |     boost::asio::io_service io; | 
 | 837 |     auto systemBus = std::make_shared<sdbusplus::asio::connection>(io); | 
 | 838 |  | 
 | 839 |     systemBus->request_name("xyz.openbmc_project.PSUSensor"); | 
 | 840 |     sdbusplus::asio::object_server objectServer(systemBus); | 
| Cheng C Yang | 209ec56 | 2019-03-12 16:37:44 +0800 | [diff] [blame] | 841 |     std::vector<std::unique_ptr<sdbusplus::bus::match::match>> matches; | 
| Cheng C Yang | 209ec56 | 2019-03-12 16:37:44 +0800 | [diff] [blame] | 842 |  | 
| Cheng C Yang | 916360b | 2019-05-07 18:47:16 +0800 | [diff] [blame] | 843 |     propertyInitialize(); | 
| Cheng C Yang | 209ec56 | 2019-03-12 16:37:44 +0800 | [diff] [blame] | 844 |  | 
| Cheng C Yang | 916360b | 2019-05-07 18:47:16 +0800 | [diff] [blame] | 845 |     io.post([&]() { createSensors(io, objectServer, systemBus); }); | 
| Cheng C Yang | 209ec56 | 2019-03-12 16:37:44 +0800 | [diff] [blame] | 846 |     boost::asio::deadline_timer filterTimer(io); | 
 | 847 |     std::function<void(sdbusplus::message::message&)> eventHandler = | 
 | 848 |         [&](sdbusplus::message::message& message) { | 
 | 849 |             if (message.is_method_error()) | 
 | 850 |             { | 
 | 851 |                 std::cerr << "callback method error\n"; | 
 | 852 |                 return; | 
 | 853 |             } | 
| Cheng C Yang | a97f134 | 2020-02-11 15:10:41 +0800 | [diff] [blame] | 854 |             filterTimer.expires_from_now(boost::posix_time::seconds(3)); | 
| Cheng C Yang | 209ec56 | 2019-03-12 16:37:44 +0800 | [diff] [blame] | 855 |             filterTimer.async_wait([&](const boost::system::error_code& ec) { | 
 | 856 |                 if (ec == boost::asio::error::operation_aborted) | 
 | 857 |                 { | 
 | 858 |                     return; | 
 | 859 |                 } | 
 | 860 |                 else if (ec) | 
 | 861 |                 { | 
 | 862 |                     std::cerr << "timer error\n"; | 
 | 863 |                 } | 
| Cheng C Yang | 916360b | 2019-05-07 18:47:16 +0800 | [diff] [blame] | 864 |                 createSensors(io, objectServer, systemBus); | 
| Cheng C Yang | 209ec56 | 2019-03-12 16:37:44 +0800 | [diff] [blame] | 865 |             }); | 
 | 866 |         }; | 
 | 867 |  | 
 | 868 |     for (const char* type : sensorTypes) | 
 | 869 |     { | 
 | 870 |         auto match = std::make_unique<sdbusplus::bus::match::match>( | 
 | 871 |             static_cast<sdbusplus::bus::bus&>(*systemBus), | 
 | 872 |             "type='signal',member='PropertiesChanged',path_namespace='" + | 
 | 873 |                 std::string(inventoryPath) + "',arg0namespace='" + type + "'", | 
 | 874 |             eventHandler); | 
 | 875 |         matches.emplace_back(std::move(match)); | 
 | 876 |     } | 
 | 877 |     io.run(); | 
 | 878 | } |