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