blob: e3007cdda21ddfbec0b52cbcf8e5528cad097002 [file] [log] [blame]
Cheng C Yang209ec562019-03-12 16:37:44 +08001/*
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 Lehan0830c7b2019-10-08 16:35:09 -070016
Patrick Ventureca44b2f2019-10-31 11:02:26 -070017#include "PSUEvent.hpp"
18#include "PSUSensor.hpp"
19#include "Utils.hpp"
20
Patrick Venture96e97db2019-10-31 13:44:38 -070021#include <array>
Cheng C Yang209ec562019-03-12 16:37:44 +080022#include <boost/algorithm/string/predicate.hpp>
23#include <boost/algorithm/string/replace.hpp>
Patrick Venture96e97db2019-10-31 13:44:38 -070024#include <boost/container/flat_map.hpp>
Cheng C Yang209ec562019-03-12 16:37:44 +080025#include <boost/container/flat_set.hpp>
James Feist24f02f22019-04-15 11:05:39 -070026#include <filesystem>
Cheng C Yang209ec562019-03-12 16:37:44 +080027#include <fstream>
Patrick Venture96e97db2019-10-31 13:44:38 -070028#include <functional>
Cheng C Yang58b2b532019-05-31 00:19:45 +080029#include <iostream>
Cheng C Yang209ec562019-03-12 16:37:44 +080030#include <regex>
31#include <sdbusplus/asio/connection.hpp>
32#include <sdbusplus/asio/object_server.hpp>
Patrick Venture96e97db2019-10-31 13:44:38 -070033#include <sdbusplus/bus/match.hpp>
34#include <string>
35#include <utility>
36#include <variant>
37#include <vector>
Cheng C Yang209ec562019-03-12 16:37:44 +080038
Josh Lehan49cfba92019-10-08 16:50:42 -070039static constexpr bool DEBUG = false;
40
Devjit Gopalpurde65ef72019-10-30 04:47:35 -070041static constexpr std::array<const char*, 4> sensorTypes = {
Jason Ling5747fab2019-10-02 16:46:23 -070042 "xyz.openbmc_project.Configuration.pmbus",
Josh Lehan0830c7b2019-10-08 16:35:09 -070043 "xyz.openbmc_project.Configuration.MAX34451",
Devjit Gopalpurde65ef72019-10-30 04:47:35 -070044 "xyz.openbmc_project.Configuration.INA230",
Josh Lehan0830c7b2019-10-08 16:35:09 -070045 "xyz.openbmc_project.Configuration.ISL68137"};
Cheng C Yang209ec562019-03-12 16:37:44 +080046
Josh Lehan0830c7b2019-10-08 16:35:09 -070047static std::vector<std::string> pmbusNames = {"pmbus", "pxe1610", "ina219",
48 "ina230", "max34451", "isl68137"};
49
Cheng C Yang209ec562019-03-12 16:37:44 +080050namespace fs = std::filesystem;
51
Cheng C Yang916360b2019-05-07 18:47:16 +080052static boost::container::flat_map<std::string, std::unique_ptr<PSUSensor>>
53 sensors;
Cheng C Yang58b2b532019-05-31 00:19:45 +080054static boost::container::flat_map<std::string, std::unique_ptr<PSUCombineEvent>>
55 combineEvents;
Cheng C Yang916360b2019-05-07 18:47:16 +080056static boost::container::flat_map<std::string, std::unique_ptr<PwmSensor>>
57 pwmSensors;
58static boost::container::flat_map<std::string, std::string> sensorTable;
59static boost::container::flat_map<std::string, PSUProperty> labelMatch;
60static boost::container::flat_map<std::string, std::string> pwmTable;
Cheng C Yang58b2b532019-05-31 00:19:45 +080061static boost::container::flat_map<std::string, std::vector<std::string>>
62 eventMatch;
63static boost::container::flat_map<std::string, std::vector<std::string>>
64 limitEventMatch;
65
66// Function CheckEvent will check each attribute from eventMatch table in the
67// sysfs. If the attributes exists in sysfs, then store the complete path
68// of the attribute into eventPathList.
69void checkEvent(
70 const std::string& directory,
71 const boost::container::flat_map<std::string, std::vector<std::string>>&
72 eventMatch,
73 boost::container::flat_map<std::string, std::vector<std::string>>&
74 eventPathList)
75{
76 for (const auto& match : eventMatch)
77 {
78 const std::vector<std::string>& eventAttrs = match.second;
79 const std::string& eventName = match.first;
80 for (const auto& eventAttr : eventAttrs)
81 {
82 auto eventPath = directory + "/" + eventAttr;
83
84 std::ifstream eventFile(eventPath);
85 if (!eventFile.good())
86 {
87 continue;
88 }
89
90 eventPathList[eventName].push_back(eventPath);
91 }
92 }
93}
94
95// Function checkEventLimits will check all the psu related xxx_input attributes
96// in sysfs to see if xxx_crit_alarm xxx_lcrit_alarm xxx_max_alarm
97// xxx_min_alarm exist, then store the existing paths of the alarm attributes
98// to eventPathList.
99void checkEventLimits(
100 const std::string& sensorPathStr,
101 const boost::container::flat_map<std::string, std::vector<std::string>>&
102 limitEventMatch,
103 boost::container::flat_map<std::string, std::vector<std::string>>&
104 eventPathList)
105{
106 for (const auto& limitMatch : limitEventMatch)
107 {
108 const std::vector<std::string>& limitEventAttrs = limitMatch.second;
109 const std::string& eventName = limitMatch.first;
110 for (const auto& limitEventAttr : limitEventAttrs)
111 {
112 auto limitEventPath =
113 boost::replace_all_copy(sensorPathStr, "input", limitEventAttr);
114 std::ifstream eventFile(limitEventPath);
115 if (!eventFile.good())
116 {
117 continue;
118 }
119 eventPathList[eventName].push_back(limitEventPath);
120 }
121 }
122}
Cheng C Yang916360b2019-05-07 18:47:16 +0800123
124static void checkPWMSensor(const fs::path& sensorPath, std::string& labelHead,
125 const std::string& interfacePath,
126 sdbusplus::asio::object_server& objectServer,
Patrick Venturea2b2d842019-10-11 07:48:47 -0700127 const std::string& psuName)
Cheng C Yang916360b2019-05-07 18:47:16 +0800128{
129 for (const auto& pwmName : pwmTable)
130 {
131 if (pwmName.first != labelHead)
132 {
133 continue;
134 }
135
136 const std::string& sensorPathStr = sensorPath.string();
137 const std::string& pwmPathStr =
138 boost::replace_all_copy(sensorPathStr, "input", "target");
139 std::ifstream pwmFile(pwmPathStr);
140 if (!pwmFile.good())
141 {
142 continue;
143 }
144
145 auto findPWMSensor = pwmSensors.find(psuName + labelHead);
146 if (findPWMSensor != pwmSensors.end())
147 {
148 continue;
149 }
150
151 pwmSensors[psuName + labelHead] = std::make_unique<PwmSensor>(
152 "Pwm_" + psuName + "_" + pwmName.second, pwmPathStr, objectServer,
Cheng C Yang15266a92019-06-12 08:42:52 +0800153 interfacePath + "_" + pwmName.second);
Cheng C Yang916360b2019-05-07 18:47:16 +0800154 }
155}
156
157void createSensors(boost::asio::io_service& io,
158 sdbusplus::asio::object_server& objectServer,
159 std::shared_ptr<sdbusplus::asio::connection>& dbusConnection)
Cheng C Yang209ec562019-03-12 16:37:44 +0800160{
161
162 ManagedObjectType sensorConfigs;
Josh Lehan49cfba92019-10-08 16:50:42 -0700163 int numCreated = 0;
Cheng C Yang209ec562019-03-12 16:37:44 +0800164 bool useCache = false;
165
Cheng C Yang58b2b532019-05-31 00:19:45 +0800166 // TODO may need only modify the ones that need to be changed.
167 sensors.clear();
Cheng C Yang92498eb2019-09-26 21:59:25 +0800168 combineEvents.clear();
Cheng C Yang209ec562019-03-12 16:37:44 +0800169 for (const char* type : sensorTypes)
170 {
171 if (!getSensorConfiguration(type, dbusConnection, sensorConfigs,
172 useCache))
173 {
174 std::cerr << "error get sensor config from entity manager\n";
175 return;
176 }
177 useCache = true;
178 }
179
180 std::vector<fs::path> pmbusPaths;
181 if (!findFiles(fs::path("/sys/class/hwmon"), "name", pmbusPaths))
182 {
183 std::cerr << "No PSU sensors in system\n";
184 return;
185 }
186
187 boost::container::flat_set<std::string> directories;
188 for (const auto& pmbusPath : pmbusPaths)
189 {
Cheng C Yang58b2b532019-05-31 00:19:45 +0800190 boost::container::flat_map<std::string, std::vector<std::string>>
191 eventPathList;
192
193 std::ifstream nameFile(pmbusPath);
194 if (!nameFile.good())
195 {
Josh Lehan49cfba92019-10-08 16:50:42 -0700196 std::cerr << "Failure finding pmbus path " << pmbusPath << "\n";
Cheng C Yang58b2b532019-05-31 00:19:45 +0800197 continue;
198 }
199
200 std::string pmbusName;
201 std::getline(nameFile, pmbusName);
202 nameFile.close();
Vijay Khemka996bad12019-05-28 15:15:16 -0700203
204 if (std::find(pmbusNames.begin(), pmbusNames.end(), pmbusName) ==
205 pmbusNames.end())
Cheng C Yang58b2b532019-05-31 00:19:45 +0800206 {
Josh Lehan49cfba92019-10-08 16:50:42 -0700207 // To avoid this error message, add your driver name to
208 // the pmbusNames vector at the top of this file.
209 std::cerr << "Driver name " << pmbusName
210 << " not found in sensor whitelist\n";
Cheng C Yang58b2b532019-05-31 00:19:45 +0800211 continue;
212 }
213
214 const std::string* psuName;
Cheng C Yang209ec562019-03-12 16:37:44 +0800215 auto directory = pmbusPath.parent_path();
216
217 auto ret = directories.insert(directory.string());
218 if (!ret.second)
219 {
Josh Lehan49cfba92019-10-08 16:50:42 -0700220 std::cerr << "Duplicate path " << directory.string() << "\n";
Cheng C Yang58b2b532019-05-31 00:19:45 +0800221 continue; // check if path has already been searched
Cheng C Yang209ec562019-03-12 16:37:44 +0800222 }
223
James Feistb6c0b912019-07-09 12:21:44 -0700224 fs::path device = directory / "device";
Cheng C Yang209ec562019-03-12 16:37:44 +0800225 std::string deviceName = fs::canonical(device).stem();
226 auto findHyphen = deviceName.find("-");
227 if (findHyphen == std::string::npos)
228 {
229 std::cerr << "found bad device" << deviceName << "\n";
230 continue;
231 }
232 std::string busStr = deviceName.substr(0, findHyphen);
233 std::string addrStr = deviceName.substr(findHyphen + 1);
234
235 size_t bus = 0;
236 size_t addr = 0;
237
238 try
239 {
240 bus = std::stoi(busStr);
241 addr = std::stoi(addrStr, 0, 16);
242 }
James Feistb6c0b912019-07-09 12:21:44 -0700243 catch (std::invalid_argument&)
Cheng C Yang209ec562019-03-12 16:37:44 +0800244 {
Josh Lehan49cfba92019-10-08 16:50:42 -0700245 std::cerr << "Error parsing bus " << busStr << " addr " << addrStr
246 << "\n";
Cheng C Yang209ec562019-03-12 16:37:44 +0800247 continue;
248 }
249
Cheng C Yang209ec562019-03-12 16:37:44 +0800250 const std::pair<std::string, boost::container::flat_map<
251 std::string, BasicVariantType>>*
252 baseConfig = nullptr;
253 const SensorData* sensorData = nullptr;
254 const std::string* interfacePath = nullptr;
255 const char* sensorType = nullptr;
256
257 for (const std::pair<sdbusplus::message::object_path, SensorData>&
258 sensor : sensorConfigs)
259 {
260 sensorData = &(sensor.second);
261 for (const char* type : sensorTypes)
262 {
263 auto sensorBase = sensorData->find(type);
264 if (sensorBase != sensorData->end())
265 {
266 baseConfig = &(*sensorBase);
267 sensorType = type;
268 break;
269 }
270 }
271 if (baseConfig == nullptr)
272 {
273 std::cerr << "error finding base configuration for "
274 << deviceName << "\n";
275 continue;
276 }
277
278 auto configBus = baseConfig->second.find("Bus");
279 auto configAddress = baseConfig->second.find("Address");
280
281 if (configBus == baseConfig->second.end() ||
282 configAddress == baseConfig->second.end())
283 {
Cheng C Yang58b2b532019-05-31 00:19:45 +0800284 std::cerr << "error finding necessary entry in configuration\n";
Cheng C Yang209ec562019-03-12 16:37:44 +0800285 continue;
286 }
287
Cheng C Yang58b2b532019-05-31 00:19:45 +0800288 const uint64_t* confBus;
289 const uint64_t* confAddr;
290 if (!(confBus = std::get_if<uint64_t>(&(configBus->second))) ||
291 !(confAddr = std::get_if<uint64_t>(&(configAddress->second))))
292 {
293 std::cerr
Josh Lehan49cfba92019-10-08 16:50:42 -0700294 << "Cannot get bus or address, invalid configuration\n";
Cheng C Yang58b2b532019-05-31 00:19:45 +0800295 continue;
296 }
297
298 if ((*confBus != bus) || (*confAddr != addr))
Cheng C Yang209ec562019-03-12 16:37:44 +0800299 {
Josh Lehan432d1ed2019-10-16 12:23:31 -0700300 std::cerr << "Configuration skipping " << *confBus << "-"
301 << *confAddr << " because not " << bus << "-" << addr
302 << "\n";
Cheng C Yang209ec562019-03-12 16:37:44 +0800303 continue;
304 }
305
306 interfacePath = &(sensor.first.str);
307 break;
308 }
309 if (interfacePath == nullptr)
310 {
Josh Lehan49cfba92019-10-08 16:50:42 -0700311 // To avoid this error message, add your export map entry,
312 // from Entity Manager, to sensorTypes at the top of this file.
Cheng C Yang209ec562019-03-12 16:37:44 +0800313 std::cerr << "failed to find match for " << deviceName << "\n";
314 continue;
315 }
316
Cheng C Yange50345b2019-04-02 17:26:15 +0800317 auto findPSUName = baseConfig->second.find("Name");
318 if (findPSUName == baseConfig->second.end())
Cheng C Yang209ec562019-03-12 16:37:44 +0800319 {
320 std::cerr << "could not determine configuration name for "
321 << deviceName << "\n";
322 continue;
323 }
324
Cheng C Yang58b2b532019-05-31 00:19:45 +0800325 if (!(psuName = std::get_if<std::string>(&(findPSUName->second))))
326 {
327 std::cerr << "Cannot find psu name, invalid configuration\n";
328 continue;
329 }
330 checkEvent(directory.string(), eventMatch, eventPathList);
331
Vijay Khemka996bad12019-05-28 15:15:16 -0700332 /* Check if there are more sensors in the same interface */
333 int i = 1;
334 std::vector<std::string> psuNames;
335 do
336 {
Josh Lehan49cfba92019-10-08 16:50:42 -0700337 // Individual string fields: Name, Name1, Name2, Name3, ...
Vijay Khemka996bad12019-05-28 15:15:16 -0700338 psuNames.push_back(std::get<std::string>(findPSUName->second));
339 findPSUName = baseConfig->second.find("Name" + std::to_string(i++));
340 } while (findPSUName != baseConfig->second.end());
341
Cheng C Yange50345b2019-04-02 17:26:15 +0800342 std::vector<fs::path> sensorPaths;
James Feistb6c0b912019-07-09 12:21:44 -0700343 if (!findFiles(directory, R"(\w\d+_input$)", sensorPaths, 0))
Cheng C Yang209ec562019-03-12 16:37:44 +0800344 {
Cheng C Yange50345b2019-04-02 17:26:15 +0800345 std::cerr << "No PSU non-label sensor in PSU\n";
Cheng C Yang209ec562019-03-12 16:37:44 +0800346 continue;
347 }
348
Vijay Khemka996bad12019-05-28 15:15:16 -0700349 /* Find array of labels to be exposed if it is defined in config */
350 std::vector<std::string> findLabels;
351 auto findLabelObj = baseConfig->second.find("Labels");
352 if (findLabelObj != baseConfig->second.end())
353 {
354 findLabels =
355 std::get<std::vector<std::string>>(findLabelObj->second);
356 }
357
Jason Ling5747fab2019-10-02 16:46:23 -0700358 std::regex sensorNameRegEx("([A-Za-z]+)[0-9]*_");
359 std::smatch matches;
360
Cheng C Yange50345b2019-04-02 17:26:15 +0800361 for (const auto& sensorPath : sensorPaths)
Cheng C Yang209ec562019-03-12 16:37:44 +0800362 {
Cheng C Yang209ec562019-03-12 16:37:44 +0800363
Cheng C Yange50345b2019-04-02 17:26:15 +0800364 std::string labelHead;
365 std::string sensorPathStr = sensorPath.string();
366 std::string sensorNameStr = sensorPath.filename();
Jason Ling5747fab2019-10-02 16:46:23 -0700367 std::string sensorNameSubStr{""};
368 if (std::regex_search(sensorNameStr, matches, sensorNameRegEx))
369 {
370 sensorNameSubStr = matches[1];
371 }
372 else
373 {
374 std::cerr << "Couldn't extract the alpha prefix from "
375 << sensorNameStr;
376 continue;
377 }
Cheng C Yange50345b2019-04-02 17:26:15 +0800378
Cheng C Yangecba9de2019-09-12 23:41:50 +0800379 auto labelPath =
380 boost::replace_all_copy(sensorPathStr, "input", "label");
381 std::ifstream labelFile(labelPath);
382 if (!labelFile.good())
Cheng C Yang209ec562019-03-12 16:37:44 +0800383 {
Josh Lehan432d1ed2019-10-16 12:23:31 -0700384 std::cerr << "Input file " << sensorPath
385 << " has no corresponding label file\n";
Cheng C Yange50345b2019-04-02 17:26:15 +0800386 labelHead = sensorNameStr.substr(0, sensorNameStr.find("_"));
Cheng C Yang209ec562019-03-12 16:37:44 +0800387 }
388 else
389 {
Cheng C Yange50345b2019-04-02 17:26:15 +0800390 std::string label;
391 std::getline(labelFile, label);
392 labelFile.close();
Cheng C Yange50345b2019-04-02 17:26:15 +0800393 auto findSensor = sensors.find(label);
394 if (findSensor != sensors.end())
395 {
396 continue;
397 }
398
399 labelHead = label.substr(0, label.find(" "));
400 }
401
Cheng C Yang916360b2019-05-07 18:47:16 +0800402 checkPWMSensor(sensorPath, labelHead, *interfacePath, objectServer,
Vijay Khemka996bad12019-05-28 15:15:16 -0700403 psuNames[0]);
Cheng C Yang916360b2019-05-07 18:47:16 +0800404
Vijay Khemka996bad12019-05-28 15:15:16 -0700405 if (!findLabels.empty())
406 {
407 /* Check if this labelHead is enabled in config file */
408 if (std::find(findLabels.begin(), findLabels.end(),
409 labelHead) == findLabels.end())
410 {
Jason Ling5747fab2019-10-02 16:46:23 -0700411 std::cerr << "couldn't find " << labelHead
412 << " in the Labels list\n";
Vijay Khemka996bad12019-05-28 15:15:16 -0700413 continue;
414 }
415 }
Cheng C Yange50345b2019-04-02 17:26:15 +0800416
Vijay Khemka996bad12019-05-28 15:15:16 -0700417 /* Find out sensor name index for this label */
Jason Ling5747fab2019-10-02 16:46:23 -0700418 std::regex rgx("[A-Za-z]+([0-9]+)");
419 int nameIndex{0};
420 if (std::regex_search(labelHead, matches, rgx))
Vijay Khemka996bad12019-05-28 15:15:16 -0700421 {
Jason Ling5747fab2019-10-02 16:46:23 -0700422 nameIndex = std::stoi(matches[1]);
Josh Lehan9fa25152019-10-16 16:52:38 -0700423
424 // Decrement to preserve alignment, because hwmon
425 // human-readable filenames and labels use 1-based numbering,
426 // but the "Name", "Name1", "Name2", etc. naming
427 // convention (the psuNames vector) uses 0-based numbering.
428 if (nameIndex > 0)
429 {
430 --nameIndex;
431 }
Vijay Khemka996bad12019-05-28 15:15:16 -0700432 }
433 else
James Feist17ab6e02019-06-25 12:28:13 -0700434 {
Vijay Khemka996bad12019-05-28 15:15:16 -0700435 nameIndex = 0;
James Feist17ab6e02019-06-25 12:28:13 -0700436 }
Cheng C Yange50345b2019-04-02 17:26:15 +0800437
Jason Ling5747fab2019-10-02 16:46:23 -0700438 if (psuNames.size() <= nameIndex)
439 {
440 std::cerr << "Could not pair " << labelHead
441 << " with a Name field\n";
442 continue;
443 }
444
Cheng C Yange50345b2019-04-02 17:26:15 +0800445 auto findProperty = labelMatch.find(labelHead);
446 if (findProperty == labelMatch.end())
Cheng C Yang209ec562019-03-12 16:37:44 +0800447 {
Jason Ling5747fab2019-10-02 16:46:23 -0700448 std::cerr << "Could not find " << labelHead << "\n";
Cheng C Yang209ec562019-03-12 16:37:44 +0800449 continue;
450 }
451
Josh Lehan432d1ed2019-10-16 12:23:31 -0700452 if constexpr (DEBUG)
453 {
454 std::cerr << "Sensor label head " << labelHead
455 << " paired with " << psuNames[nameIndex] << "\n";
456 }
457
Cheng C Yang58b2b532019-05-31 00:19:45 +0800458 checkEventLimits(sensorPathStr, limitEventMatch, eventPathList);
459
Cheng C Yange50345b2019-04-02 17:26:15 +0800460 unsigned int factor =
461 std::pow(10, findProperty->second.sensorScaleFactor);
Vijay Khemka996bad12019-05-28 15:15:16 -0700462
Vijay Khemkadbdcfe02019-07-25 12:56:17 -0700463 /* Change first char of substring to uppercase */
464 char firstChar = sensorNameSubStr[0] - 0x20;
465 std::string strScaleFactor =
466 firstChar + sensorNameSubStr.substr(1) + "ScaleFactor";
467
468 auto findScaleFactor = baseConfig->second.find(strScaleFactor);
Vijay Khemka53ca4442019-07-23 11:03:55 -0700469 if (findScaleFactor != baseConfig->second.end())
470 {
471 factor =
472 std::visit(VariantToIntVisitor(), findScaleFactor->second);
473 }
474
Josh Lehan49cfba92019-10-08 16:50:42 -0700475 if constexpr (DEBUG)
476 {
477 std::cerr << "Sensor scaling factor " << factor << " string "
478 << strScaleFactor << "\n";
479 }
480
Vijay Khemka996bad12019-05-28 15:15:16 -0700481 std::vector<thresholds::Threshold> sensorThresholds;
482
James Feist17ab6e02019-06-25 12:28:13 -0700483 if (!parseThresholdsFromConfig(*sensorData, sensorThresholds))
Cheng C Yange50345b2019-04-02 17:26:15 +0800484 {
James Feist17ab6e02019-06-25 12:28:13 -0700485 std::cerr << "error populating thresholds for "
486 << sensorNameSubStr << "\n";
Cheng C Yange50345b2019-04-02 17:26:15 +0800487 }
488
489 auto findSensorType = sensorTable.find(sensorNameSubStr);
490 if (findSensorType == sensorTable.end())
491 {
Jason Ling5747fab2019-10-02 16:46:23 -0700492 std::cerr << sensorNameSubStr
493 << " is not a recognize sensor file\n";
Cheng C Yange50345b2019-04-02 17:26:15 +0800494 continue;
495 }
496
497 std::string sensorName =
Vijay Khemka996bad12019-05-28 15:15:16 -0700498 psuNames[nameIndex] + " " + findProperty->second.labelTypeName;
Cheng C Yange50345b2019-04-02 17:26:15 +0800499
Josh Lehan49cfba92019-10-08 16:50:42 -0700500 ++numCreated;
501 if constexpr (DEBUG)
502 {
503 std::cerr << "Created " << numCreated
504 << " sensors so far: " << sensorName << "\n";
505 }
506
Cheng C Yang58b2b532019-05-31 00:19:45 +0800507 sensors[sensorName] = std::make_unique<PSUSensor>(
Cheng C Yange50345b2019-04-02 17:26:15 +0800508 sensorPathStr, sensorType, objectServer, dbusConnection, io,
Cheng C Yang209ec562019-03-12 16:37:44 +0800509 sensorName, std::move(sensorThresholds), *interfacePath,
Cheng C Yange50345b2019-04-02 17:26:15 +0800510 findSensorType->second, factor, findProperty->second.maxReading,
511 findProperty->second.minReading);
Cheng C Yang209ec562019-03-12 16:37:44 +0800512 }
Cheng C Yang58b2b532019-05-31 00:19:45 +0800513
514 // OperationalStatus event
Cheng C Yang92498eb2019-09-26 21:59:25 +0800515 combineEvents[*psuName + "OperationalStatus"] = nullptr;
Cheng C Yang58b2b532019-05-31 00:19:45 +0800516 combineEvents[*psuName + "OperationalStatus"] =
517 std::make_unique<PSUCombineEvent>(
518 objectServer, io, *psuName, eventPathList, "OperationalStatus");
Cheng C Yang209ec562019-03-12 16:37:44 +0800519 }
Josh Lehan49cfba92019-10-08 16:50:42 -0700520
521 if constexpr (DEBUG)
522 {
523 std::cerr << "Created total of " << numCreated << " sensors\n";
524 }
Cheng C Yang209ec562019-03-12 16:37:44 +0800525 return;
526}
527
Cheng C Yang916360b2019-05-07 18:47:16 +0800528void propertyInitialize(void)
Cheng C Yang209ec562019-03-12 16:37:44 +0800529{
Cheng C Yange50345b2019-04-02 17:26:15 +0800530 sensorTable = {{"power", "power/"},
531 {"curr", "current/"},
532 {"temp", "temperature/"},
533 {"in", "voltage/"},
534 {"fan", "fan_tach/"}};
535
536 labelMatch = {{"pin", PSUProperty("Input Power", 3000, 0, 6)},
537 {"pout1", PSUProperty("Output Power", 3000, 0, 6)},
Vijay Khemka996bad12019-05-28 15:15:16 -0700538 {"pout2", PSUProperty("Output Power", 3000, 0, 6)},
539 {"pout3", PSUProperty("Output Power", 3000, 0, 6)},
Vijay Khemkabe664412019-06-28 12:10:04 -0700540 {"power1", PSUProperty("Output Power", 3000, 0, 6)},
Cheng C Yangbdbde962019-04-26 22:50:34 +0800541 {"vin", PSUProperty("Input Voltage", 300, 0, 3)},
Vijay Khemka996bad12019-05-28 15:15:16 -0700542 {"vout1", PSUProperty("Output Voltage", 255, 0, 3)},
543 {"vout2", PSUProperty("Output Voltage", 255, 0, 3)},
544 {"vout3", PSUProperty("Output Voltage", 255, 0, 3)},
Jason Ling5747fab2019-10-02 16:46:23 -0700545 {"vout4", PSUProperty("Output Voltage", 255, 0, 3)},
546 {"vout5", PSUProperty("Output Voltage", 255, 0, 3)},
547 {"vout6", PSUProperty("Output Voltage", 255, 0, 3)},
548 {"vout7", PSUProperty("Output Voltage", 255, 0, 3)},
549 {"vout8", PSUProperty("Output Voltage", 255, 0, 3)},
550 {"vout9", PSUProperty("Output Voltage", 255, 0, 3)},
551 {"vout10", PSUProperty("Output Voltage", 255, 0, 3)},
552 {"vout11", PSUProperty("Output Voltage", 255, 0, 3)},
553 {"vout12", PSUProperty("Output Voltage", 255, 0, 3)},
554 {"vout13", PSUProperty("Output Voltage", 255, 0, 3)},
555 {"vout14", PSUProperty("Output Voltage", 255, 0, 3)},
556 {"vout15", PSUProperty("Output Voltage", 255, 0, 3)},
557 {"vout16", PSUProperty("Output Voltage", 255, 0, 3)},
Vijay Khemkabe664412019-06-28 12:10:04 -0700558 {"in1", PSUProperty("Output Voltage", 255, 0, 3)},
Cheng C Yange50345b2019-04-02 17:26:15 +0800559 {"iin", PSUProperty("Input Current", 20, 0, 3)},
560 {"iout1", PSUProperty("Output Current", 255, 0, 3)},
Vijay Khemka996bad12019-05-28 15:15:16 -0700561 {"iout2", PSUProperty("Output Current", 255, 0, 3)},
562 {"iout3", PSUProperty("Output Current", 255, 0, 3)},
Vijay Khemkabe664412019-06-28 12:10:04 -0700563 {"curr1", PSUProperty("Output Current", 255, 0, 3)},
Cheng C Yange50345b2019-04-02 17:26:15 +0800564 {"temp1", PSUProperty("Temperature", 127, -128, 3)},
Vijay Khemka996bad12019-05-28 15:15:16 -0700565 {"temp2", PSUProperty("Temperature", 127, -128, 3)},
566 {"temp3", PSUProperty("Temperature", 127, -128, 3)},
Jason Ling5747fab2019-10-02 16:46:23 -0700567 {"temp4", PSUProperty("Temperature", 127, -128, 3)},
568 {"temp5", PSUProperty("Temperature", 127, -128, 3)},
Cheng C Yang8dbb3952019-05-23 00:03:12 +0800569 {"fan1", PSUProperty("Fan Speed 1", 30000, 0, 0)},
570 {"fan2", PSUProperty("Fan Speed 2", 30000, 0, 0)}};
Cheng C Yang916360b2019-05-07 18:47:16 +0800571
572 pwmTable = {{"fan1", "Fan_1"}, {"fan2", "Fan_2"}};
Cheng C Yang58b2b532019-05-31 00:19:45 +0800573
574 limitEventMatch = {{"PredictiveFailure", {"max_alarm", "min_alarm"}},
575 {"Failure", {"crit_alarm", "lcrit_alarm"}}};
576
577 eventMatch = {
578 {"PredictiveFailure", {"power1_alarm"}},
579 {"Failure", {"in2_alarm"}},
Cheng C Yang9c45e6b2019-08-13 07:21:32 +0800580 {"ACLost", {"in1_beep"}},
581 {"FanFault", {"fan1_alarm", "fan2_alarm", "fan1_fault", "fan2_fault"}},
582 {"ConfigureError", {"in1_fault"}}};
Cheng C Yang209ec562019-03-12 16:37:44 +0800583}
584
James Feistb6c0b912019-07-09 12:21:44 -0700585int main()
Cheng C Yang209ec562019-03-12 16:37:44 +0800586{
587 boost::asio::io_service io;
588 auto systemBus = std::make_shared<sdbusplus::asio::connection>(io);
589
590 systemBus->request_name("xyz.openbmc_project.PSUSensor");
591 sdbusplus::asio::object_server objectServer(systemBus);
Cheng C Yang209ec562019-03-12 16:37:44 +0800592 std::vector<std::unique_ptr<sdbusplus::bus::match::match>> matches;
Cheng C Yang209ec562019-03-12 16:37:44 +0800593
Cheng C Yang916360b2019-05-07 18:47:16 +0800594 propertyInitialize();
Cheng C Yang209ec562019-03-12 16:37:44 +0800595
Cheng C Yang916360b2019-05-07 18:47:16 +0800596 io.post([&]() { createSensors(io, objectServer, systemBus); });
Cheng C Yang209ec562019-03-12 16:37:44 +0800597 boost::asio::deadline_timer filterTimer(io);
598 std::function<void(sdbusplus::message::message&)> eventHandler =
599 [&](sdbusplus::message::message& message) {
600 if (message.is_method_error())
601 {
602 std::cerr << "callback method error\n";
603 return;
604 }
605 filterTimer.expires_from_now(boost::posix_time::seconds(1));
606 filterTimer.async_wait([&](const boost::system::error_code& ec) {
607 if (ec == boost::asio::error::operation_aborted)
608 {
609 return;
610 }
611 else if (ec)
612 {
613 std::cerr << "timer error\n";
614 }
Cheng C Yang916360b2019-05-07 18:47:16 +0800615 createSensors(io, objectServer, systemBus);
Cheng C Yang209ec562019-03-12 16:37:44 +0800616 });
617 };
618
619 for (const char* type : sensorTypes)
620 {
621 auto match = std::make_unique<sdbusplus::bus::match::match>(
622 static_cast<sdbusplus::bus::bus&>(*systemBus),
623 "type='signal',member='PropertiesChanged',path_namespace='" +
624 std::string(inventoryPath) + "',arg0namespace='" + type + "'",
625 eventHandler);
626 matches.emplace_back(std::move(match));
627 }
628 io.run();
629}