blob: d0e225beb395c815bafdd0420d05e0ce511e998b [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
Cheng C Yang58b2b532019-05-31 00:19:45 +080017#include <PSUEvent.hpp>
Cheng C Yang209ec562019-03-12 16:37:44 +080018#include <PSUSensor.hpp>
19#include <Utils.hpp>
20#include <boost/algorithm/string/predicate.hpp>
21#include <boost/algorithm/string/replace.hpp>
22#include <boost/container/flat_set.hpp>
James Feist24f02f22019-04-15 11:05:39 -070023#include <filesystem>
Cheng C Yang209ec562019-03-12 16:37:44 +080024#include <fstream>
Cheng C Yang58b2b532019-05-31 00:19:45 +080025#include <iostream>
Cheng C Yang209ec562019-03-12 16:37:44 +080026#include <regex>
27#include <sdbusplus/asio/connection.hpp>
28#include <sdbusplus/asio/object_server.hpp>
29
Josh Lehan49cfba92019-10-08 16:50:42 -070030static constexpr bool DEBUG = false;
31
Devjit Gopalpurde65ef72019-10-30 04:47:35 -070032static constexpr std::array<const char*, 4> sensorTypes = {
Jason Ling5747fab2019-10-02 16:46:23 -070033 "xyz.openbmc_project.Configuration.pmbus",
Josh Lehan0830c7b2019-10-08 16:35:09 -070034 "xyz.openbmc_project.Configuration.MAX34451",
Devjit Gopalpurde65ef72019-10-30 04:47:35 -070035 "xyz.openbmc_project.Configuration.INA230",
Josh Lehan0830c7b2019-10-08 16:35:09 -070036 "xyz.openbmc_project.Configuration.ISL68137"};
Cheng C Yang209ec562019-03-12 16:37:44 +080037
Josh Lehan0830c7b2019-10-08 16:35:09 -070038static std::vector<std::string> pmbusNames = {"pmbus", "pxe1610", "ina219",
39 "ina230", "max34451", "isl68137"};
40
Cheng C Yang209ec562019-03-12 16:37:44 +080041namespace fs = std::filesystem;
42
Cheng C Yang916360b2019-05-07 18:47:16 +080043static boost::container::flat_map<std::string, std::unique_ptr<PSUSensor>>
44 sensors;
Cheng C Yang58b2b532019-05-31 00:19:45 +080045static boost::container::flat_map<std::string, std::unique_ptr<PSUCombineEvent>>
46 combineEvents;
Cheng C Yang916360b2019-05-07 18:47:16 +080047static boost::container::flat_map<std::string, std::unique_ptr<PwmSensor>>
48 pwmSensors;
49static boost::container::flat_map<std::string, std::string> sensorTable;
50static boost::container::flat_map<std::string, PSUProperty> labelMatch;
51static boost::container::flat_map<std::string, std::string> pwmTable;
Cheng C Yang58b2b532019-05-31 00:19:45 +080052static boost::container::flat_map<std::string, std::vector<std::string>>
53 eventMatch;
54static boost::container::flat_map<std::string, std::vector<std::string>>
55 limitEventMatch;
56
57// Function CheckEvent will check each attribute from eventMatch table in the
58// sysfs. If the attributes exists in sysfs, then store the complete path
59// of the attribute into eventPathList.
60void checkEvent(
61 const std::string& directory,
62 const boost::container::flat_map<std::string, std::vector<std::string>>&
63 eventMatch,
64 boost::container::flat_map<std::string, std::vector<std::string>>&
65 eventPathList)
66{
67 for (const auto& match : eventMatch)
68 {
69 const std::vector<std::string>& eventAttrs = match.second;
70 const std::string& eventName = match.first;
71 for (const auto& eventAttr : eventAttrs)
72 {
73 auto eventPath = directory + "/" + eventAttr;
74
75 std::ifstream eventFile(eventPath);
76 if (!eventFile.good())
77 {
78 continue;
79 }
80
81 eventPathList[eventName].push_back(eventPath);
82 }
83 }
84}
85
86// Function checkEventLimits will check all the psu related xxx_input attributes
87// in sysfs to see if xxx_crit_alarm xxx_lcrit_alarm xxx_max_alarm
88// xxx_min_alarm exist, then store the existing paths of the alarm attributes
89// to eventPathList.
90void checkEventLimits(
91 const std::string& sensorPathStr,
92 const boost::container::flat_map<std::string, std::vector<std::string>>&
93 limitEventMatch,
94 boost::container::flat_map<std::string, std::vector<std::string>>&
95 eventPathList)
96{
97 for (const auto& limitMatch : limitEventMatch)
98 {
99 const std::vector<std::string>& limitEventAttrs = limitMatch.second;
100 const std::string& eventName = limitMatch.first;
101 for (const auto& limitEventAttr : limitEventAttrs)
102 {
103 auto limitEventPath =
104 boost::replace_all_copy(sensorPathStr, "input", limitEventAttr);
105 std::ifstream eventFile(limitEventPath);
106 if (!eventFile.good())
107 {
108 continue;
109 }
110 eventPathList[eventName].push_back(limitEventPath);
111 }
112 }
113}
Cheng C Yang916360b2019-05-07 18:47:16 +0800114
115static void checkPWMSensor(const fs::path& sensorPath, std::string& labelHead,
116 const std::string& interfacePath,
117 sdbusplus::asio::object_server& objectServer,
Patrick Venturea2b2d842019-10-11 07:48:47 -0700118 const std::string& psuName)
Cheng C Yang916360b2019-05-07 18:47:16 +0800119{
120 for (const auto& pwmName : pwmTable)
121 {
122 if (pwmName.first != labelHead)
123 {
124 continue;
125 }
126
127 const std::string& sensorPathStr = sensorPath.string();
128 const std::string& pwmPathStr =
129 boost::replace_all_copy(sensorPathStr, "input", "target");
130 std::ifstream pwmFile(pwmPathStr);
131 if (!pwmFile.good())
132 {
133 continue;
134 }
135
136 auto findPWMSensor = pwmSensors.find(psuName + labelHead);
137 if (findPWMSensor != pwmSensors.end())
138 {
139 continue;
140 }
141
142 pwmSensors[psuName + labelHead] = std::make_unique<PwmSensor>(
143 "Pwm_" + psuName + "_" + pwmName.second, pwmPathStr, objectServer,
Cheng C Yang15266a92019-06-12 08:42:52 +0800144 interfacePath + "_" + pwmName.second);
Cheng C Yang916360b2019-05-07 18:47:16 +0800145 }
146}
147
148void createSensors(boost::asio::io_service& io,
149 sdbusplus::asio::object_server& objectServer,
150 std::shared_ptr<sdbusplus::asio::connection>& dbusConnection)
Cheng C Yang209ec562019-03-12 16:37:44 +0800151{
152
153 ManagedObjectType sensorConfigs;
Josh Lehan49cfba92019-10-08 16:50:42 -0700154 int numCreated = 0;
Cheng C Yang209ec562019-03-12 16:37:44 +0800155 bool useCache = false;
156
Cheng C Yang58b2b532019-05-31 00:19:45 +0800157 // TODO may need only modify the ones that need to be changed.
158 sensors.clear();
Cheng C Yang92498eb2019-09-26 21:59:25 +0800159 combineEvents.clear();
Cheng C Yang209ec562019-03-12 16:37:44 +0800160 for (const char* type : sensorTypes)
161 {
162 if (!getSensorConfiguration(type, dbusConnection, sensorConfigs,
163 useCache))
164 {
165 std::cerr << "error get sensor config from entity manager\n";
166 return;
167 }
168 useCache = true;
169 }
170
171 std::vector<fs::path> pmbusPaths;
172 if (!findFiles(fs::path("/sys/class/hwmon"), "name", pmbusPaths))
173 {
174 std::cerr << "No PSU sensors in system\n";
175 return;
176 }
177
178 boost::container::flat_set<std::string> directories;
179 for (const auto& pmbusPath : pmbusPaths)
180 {
Cheng C Yang58b2b532019-05-31 00:19:45 +0800181 boost::container::flat_map<std::string, std::vector<std::string>>
182 eventPathList;
183
184 std::ifstream nameFile(pmbusPath);
185 if (!nameFile.good())
186 {
Josh Lehan49cfba92019-10-08 16:50:42 -0700187 std::cerr << "Failure finding pmbus path " << pmbusPath << "\n";
Cheng C Yang58b2b532019-05-31 00:19:45 +0800188 continue;
189 }
190
191 std::string pmbusName;
192 std::getline(nameFile, pmbusName);
193 nameFile.close();
Vijay Khemka996bad12019-05-28 15:15:16 -0700194
195 if (std::find(pmbusNames.begin(), pmbusNames.end(), pmbusName) ==
196 pmbusNames.end())
Cheng C Yang58b2b532019-05-31 00:19:45 +0800197 {
Josh Lehan49cfba92019-10-08 16:50:42 -0700198 // To avoid this error message, add your driver name to
199 // the pmbusNames vector at the top of this file.
200 std::cerr << "Driver name " << pmbusName
201 << " not found in sensor whitelist\n";
Cheng C Yang58b2b532019-05-31 00:19:45 +0800202 continue;
203 }
204
205 const std::string* psuName;
Cheng C Yang209ec562019-03-12 16:37:44 +0800206 auto directory = pmbusPath.parent_path();
207
208 auto ret = directories.insert(directory.string());
209 if (!ret.second)
210 {
Josh Lehan49cfba92019-10-08 16:50:42 -0700211 std::cerr << "Duplicate path " << directory.string() << "\n";
Cheng C Yang58b2b532019-05-31 00:19:45 +0800212 continue; // check if path has already been searched
Cheng C Yang209ec562019-03-12 16:37:44 +0800213 }
214
James Feistb6c0b912019-07-09 12:21:44 -0700215 fs::path device = directory / "device";
Cheng C Yang209ec562019-03-12 16:37:44 +0800216 std::string deviceName = fs::canonical(device).stem();
217 auto findHyphen = deviceName.find("-");
218 if (findHyphen == std::string::npos)
219 {
220 std::cerr << "found bad device" << deviceName << "\n";
221 continue;
222 }
223 std::string busStr = deviceName.substr(0, findHyphen);
224 std::string addrStr = deviceName.substr(findHyphen + 1);
225
226 size_t bus = 0;
227 size_t addr = 0;
228
229 try
230 {
231 bus = std::stoi(busStr);
232 addr = std::stoi(addrStr, 0, 16);
233 }
James Feistb6c0b912019-07-09 12:21:44 -0700234 catch (std::invalid_argument&)
Cheng C Yang209ec562019-03-12 16:37:44 +0800235 {
Josh Lehan49cfba92019-10-08 16:50:42 -0700236 std::cerr << "Error parsing bus " << busStr << " addr " << addrStr
237 << "\n";
Cheng C Yang209ec562019-03-12 16:37:44 +0800238 continue;
239 }
240
Cheng C Yang209ec562019-03-12 16:37:44 +0800241 const std::pair<std::string, boost::container::flat_map<
242 std::string, BasicVariantType>>*
243 baseConfig = nullptr;
244 const SensorData* sensorData = nullptr;
245 const std::string* interfacePath = nullptr;
246 const char* sensorType = nullptr;
247
248 for (const std::pair<sdbusplus::message::object_path, SensorData>&
249 sensor : sensorConfigs)
250 {
251 sensorData = &(sensor.second);
252 for (const char* type : sensorTypes)
253 {
254 auto sensorBase = sensorData->find(type);
255 if (sensorBase != sensorData->end())
256 {
257 baseConfig = &(*sensorBase);
258 sensorType = type;
259 break;
260 }
261 }
262 if (baseConfig == nullptr)
263 {
264 std::cerr << "error finding base configuration for "
265 << deviceName << "\n";
266 continue;
267 }
268
269 auto configBus = baseConfig->second.find("Bus");
270 auto configAddress = baseConfig->second.find("Address");
271
272 if (configBus == baseConfig->second.end() ||
273 configAddress == baseConfig->second.end())
274 {
Cheng C Yang58b2b532019-05-31 00:19:45 +0800275 std::cerr << "error finding necessary entry in configuration\n";
Cheng C Yang209ec562019-03-12 16:37:44 +0800276 continue;
277 }
278
Cheng C Yang58b2b532019-05-31 00:19:45 +0800279 const uint64_t* confBus;
280 const uint64_t* confAddr;
281 if (!(confBus = std::get_if<uint64_t>(&(configBus->second))) ||
282 !(confAddr = std::get_if<uint64_t>(&(configAddress->second))))
283 {
284 std::cerr
Josh Lehan49cfba92019-10-08 16:50:42 -0700285 << "Cannot get bus or address, invalid configuration\n";
Cheng C Yang58b2b532019-05-31 00:19:45 +0800286 continue;
287 }
288
289 if ((*confBus != bus) || (*confAddr != addr))
Cheng C Yang209ec562019-03-12 16:37:44 +0800290 {
Josh Lehan432d1ed2019-10-16 12:23:31 -0700291 std::cerr << "Configuration skipping " << *confBus << "-"
292 << *confAddr << " because not " << bus << "-" << addr
293 << "\n";
Cheng C Yang209ec562019-03-12 16:37:44 +0800294 continue;
295 }
296
297 interfacePath = &(sensor.first.str);
298 break;
299 }
300 if (interfacePath == nullptr)
301 {
Josh Lehan49cfba92019-10-08 16:50:42 -0700302 // To avoid this error message, add your export map entry,
303 // from Entity Manager, to sensorTypes at the top of this file.
Cheng C Yang209ec562019-03-12 16:37:44 +0800304 std::cerr << "failed to find match for " << deviceName << "\n";
305 continue;
306 }
307
Cheng C Yange50345b2019-04-02 17:26:15 +0800308 auto findPSUName = baseConfig->second.find("Name");
309 if (findPSUName == baseConfig->second.end())
Cheng C Yang209ec562019-03-12 16:37:44 +0800310 {
311 std::cerr << "could not determine configuration name for "
312 << deviceName << "\n";
313 continue;
314 }
315
Cheng C Yang58b2b532019-05-31 00:19:45 +0800316 if (!(psuName = std::get_if<std::string>(&(findPSUName->second))))
317 {
318 std::cerr << "Cannot find psu name, invalid configuration\n";
319 continue;
320 }
321 checkEvent(directory.string(), eventMatch, eventPathList);
322
Vijay Khemka996bad12019-05-28 15:15:16 -0700323 /* Check if there are more sensors in the same interface */
324 int i = 1;
325 std::vector<std::string> psuNames;
326 do
327 {
Josh Lehan49cfba92019-10-08 16:50:42 -0700328 // Individual string fields: Name, Name1, Name2, Name3, ...
Vijay Khemka996bad12019-05-28 15:15:16 -0700329 psuNames.push_back(std::get<std::string>(findPSUName->second));
330 findPSUName = baseConfig->second.find("Name" + std::to_string(i++));
331 } while (findPSUName != baseConfig->second.end());
332
Cheng C Yange50345b2019-04-02 17:26:15 +0800333 std::vector<fs::path> sensorPaths;
James Feistb6c0b912019-07-09 12:21:44 -0700334 if (!findFiles(directory, R"(\w\d+_input$)", sensorPaths, 0))
Cheng C Yang209ec562019-03-12 16:37:44 +0800335 {
Cheng C Yange50345b2019-04-02 17:26:15 +0800336 std::cerr << "No PSU non-label sensor in PSU\n";
Cheng C Yang209ec562019-03-12 16:37:44 +0800337 continue;
338 }
339
Vijay Khemka996bad12019-05-28 15:15:16 -0700340 /* Find array of labels to be exposed if it is defined in config */
341 std::vector<std::string> findLabels;
342 auto findLabelObj = baseConfig->second.find("Labels");
343 if (findLabelObj != baseConfig->second.end())
344 {
345 findLabels =
346 std::get<std::vector<std::string>>(findLabelObj->second);
347 }
348
Jason Ling5747fab2019-10-02 16:46:23 -0700349 std::regex sensorNameRegEx("([A-Za-z]+)[0-9]*_");
350 std::smatch matches;
351
Cheng C Yange50345b2019-04-02 17:26:15 +0800352 for (const auto& sensorPath : sensorPaths)
Cheng C Yang209ec562019-03-12 16:37:44 +0800353 {
Cheng C Yang209ec562019-03-12 16:37:44 +0800354
Cheng C Yange50345b2019-04-02 17:26:15 +0800355 std::string labelHead;
356 std::string sensorPathStr = sensorPath.string();
357 std::string sensorNameStr = sensorPath.filename();
Jason Ling5747fab2019-10-02 16:46:23 -0700358 std::string sensorNameSubStr{""};
359 if (std::regex_search(sensorNameStr, matches, sensorNameRegEx))
360 {
361 sensorNameSubStr = matches[1];
362 }
363 else
364 {
365 std::cerr << "Couldn't extract the alpha prefix from "
366 << sensorNameStr;
367 continue;
368 }
Cheng C Yange50345b2019-04-02 17:26:15 +0800369
Cheng C Yangecba9de2019-09-12 23:41:50 +0800370 auto labelPath =
371 boost::replace_all_copy(sensorPathStr, "input", "label");
372 std::ifstream labelFile(labelPath);
373 if (!labelFile.good())
Cheng C Yang209ec562019-03-12 16:37:44 +0800374 {
Josh Lehan432d1ed2019-10-16 12:23:31 -0700375 std::cerr << "Input file " << sensorPath
376 << " has no corresponding label file\n";
Cheng C Yange50345b2019-04-02 17:26:15 +0800377 labelHead = sensorNameStr.substr(0, sensorNameStr.find("_"));
Cheng C Yang209ec562019-03-12 16:37:44 +0800378 }
379 else
380 {
Cheng C Yange50345b2019-04-02 17:26:15 +0800381 std::string label;
382 std::getline(labelFile, label);
383 labelFile.close();
Cheng C Yange50345b2019-04-02 17:26:15 +0800384 auto findSensor = sensors.find(label);
385 if (findSensor != sensors.end())
386 {
387 continue;
388 }
389
390 labelHead = label.substr(0, label.find(" "));
391 }
392
Cheng C Yang916360b2019-05-07 18:47:16 +0800393 checkPWMSensor(sensorPath, labelHead, *interfacePath, objectServer,
Vijay Khemka996bad12019-05-28 15:15:16 -0700394 psuNames[0]);
Cheng C Yang916360b2019-05-07 18:47:16 +0800395
Vijay Khemka996bad12019-05-28 15:15:16 -0700396 if (!findLabels.empty())
397 {
398 /* Check if this labelHead is enabled in config file */
399 if (std::find(findLabels.begin(), findLabels.end(),
400 labelHead) == findLabels.end())
401 {
Jason Ling5747fab2019-10-02 16:46:23 -0700402 std::cerr << "couldn't find " << labelHead
403 << " in the Labels list\n";
Vijay Khemka996bad12019-05-28 15:15:16 -0700404 continue;
405 }
406 }
Cheng C Yange50345b2019-04-02 17:26:15 +0800407
Vijay Khemka996bad12019-05-28 15:15:16 -0700408 /* Find out sensor name index for this label */
Jason Ling5747fab2019-10-02 16:46:23 -0700409 std::regex rgx("[A-Za-z]+([0-9]+)");
410 int nameIndex{0};
411 if (std::regex_search(labelHead, matches, rgx))
Vijay Khemka996bad12019-05-28 15:15:16 -0700412 {
Jason Ling5747fab2019-10-02 16:46:23 -0700413 nameIndex = std::stoi(matches[1]);
Josh Lehan9fa25152019-10-16 16:52:38 -0700414
415 // Decrement to preserve alignment, because hwmon
416 // human-readable filenames and labels use 1-based numbering,
417 // but the "Name", "Name1", "Name2", etc. naming
418 // convention (the psuNames vector) uses 0-based numbering.
419 if (nameIndex > 0)
420 {
421 --nameIndex;
422 }
Vijay Khemka996bad12019-05-28 15:15:16 -0700423 }
424 else
James Feist17ab6e02019-06-25 12:28:13 -0700425 {
Vijay Khemka996bad12019-05-28 15:15:16 -0700426 nameIndex = 0;
James Feist17ab6e02019-06-25 12:28:13 -0700427 }
Cheng C Yange50345b2019-04-02 17:26:15 +0800428
Jason Ling5747fab2019-10-02 16:46:23 -0700429 if (psuNames.size() <= nameIndex)
430 {
431 std::cerr << "Could not pair " << labelHead
432 << " with a Name field\n";
433 continue;
434 }
435
Cheng C Yange50345b2019-04-02 17:26:15 +0800436 auto findProperty = labelMatch.find(labelHead);
437 if (findProperty == labelMatch.end())
Cheng C Yang209ec562019-03-12 16:37:44 +0800438 {
Jason Ling5747fab2019-10-02 16:46:23 -0700439 std::cerr << "Could not find " << labelHead << "\n";
Cheng C Yang209ec562019-03-12 16:37:44 +0800440 continue;
441 }
442
Josh Lehan432d1ed2019-10-16 12:23:31 -0700443 if constexpr (DEBUG)
444 {
445 std::cerr << "Sensor label head " << labelHead
446 << " paired with " << psuNames[nameIndex] << "\n";
447 }
448
Cheng C Yang58b2b532019-05-31 00:19:45 +0800449 checkEventLimits(sensorPathStr, limitEventMatch, eventPathList);
450
Cheng C Yange50345b2019-04-02 17:26:15 +0800451 unsigned int factor =
452 std::pow(10, findProperty->second.sensorScaleFactor);
Vijay Khemka996bad12019-05-28 15:15:16 -0700453
Vijay Khemkadbdcfe02019-07-25 12:56:17 -0700454 /* Change first char of substring to uppercase */
455 char firstChar = sensorNameSubStr[0] - 0x20;
456 std::string strScaleFactor =
457 firstChar + sensorNameSubStr.substr(1) + "ScaleFactor";
458
459 auto findScaleFactor = baseConfig->second.find(strScaleFactor);
Vijay Khemka53ca4442019-07-23 11:03:55 -0700460 if (findScaleFactor != baseConfig->second.end())
461 {
462 factor =
463 std::visit(VariantToIntVisitor(), findScaleFactor->second);
464 }
465
Josh Lehan49cfba92019-10-08 16:50:42 -0700466 if constexpr (DEBUG)
467 {
468 std::cerr << "Sensor scaling factor " << factor << " string "
469 << strScaleFactor << "\n";
470 }
471
Vijay Khemka996bad12019-05-28 15:15:16 -0700472 std::vector<thresholds::Threshold> sensorThresholds;
473
James Feist17ab6e02019-06-25 12:28:13 -0700474 if (!parseThresholdsFromConfig(*sensorData, sensorThresholds))
Cheng C Yange50345b2019-04-02 17:26:15 +0800475 {
James Feist17ab6e02019-06-25 12:28:13 -0700476 std::cerr << "error populating thresholds for "
477 << sensorNameSubStr << "\n";
Cheng C Yange50345b2019-04-02 17:26:15 +0800478 }
479
480 auto findSensorType = sensorTable.find(sensorNameSubStr);
481 if (findSensorType == sensorTable.end())
482 {
Jason Ling5747fab2019-10-02 16:46:23 -0700483 std::cerr << sensorNameSubStr
484 << " is not a recognize sensor file\n";
Cheng C Yange50345b2019-04-02 17:26:15 +0800485 continue;
486 }
487
488 std::string sensorName =
Vijay Khemka996bad12019-05-28 15:15:16 -0700489 psuNames[nameIndex] + " " + findProperty->second.labelTypeName;
Cheng C Yange50345b2019-04-02 17:26:15 +0800490
Josh Lehan49cfba92019-10-08 16:50:42 -0700491 ++numCreated;
492 if constexpr (DEBUG)
493 {
494 std::cerr << "Created " << numCreated
495 << " sensors so far: " << sensorName << "\n";
496 }
497
Cheng C Yang58b2b532019-05-31 00:19:45 +0800498 sensors[sensorName] = std::make_unique<PSUSensor>(
Cheng C Yange50345b2019-04-02 17:26:15 +0800499 sensorPathStr, sensorType, objectServer, dbusConnection, io,
Cheng C Yang209ec562019-03-12 16:37:44 +0800500 sensorName, std::move(sensorThresholds), *interfacePath,
Cheng C Yange50345b2019-04-02 17:26:15 +0800501 findSensorType->second, factor, findProperty->second.maxReading,
502 findProperty->second.minReading);
Cheng C Yang209ec562019-03-12 16:37:44 +0800503 }
Cheng C Yang58b2b532019-05-31 00:19:45 +0800504
505 // OperationalStatus event
Cheng C Yang92498eb2019-09-26 21:59:25 +0800506 combineEvents[*psuName + "OperationalStatus"] = nullptr;
Cheng C Yang58b2b532019-05-31 00:19:45 +0800507 combineEvents[*psuName + "OperationalStatus"] =
508 std::make_unique<PSUCombineEvent>(
509 objectServer, io, *psuName, eventPathList, "OperationalStatus");
Cheng C Yang209ec562019-03-12 16:37:44 +0800510 }
Josh Lehan49cfba92019-10-08 16:50:42 -0700511
512 if constexpr (DEBUG)
513 {
514 std::cerr << "Created total of " << numCreated << " sensors\n";
515 }
Cheng C Yang209ec562019-03-12 16:37:44 +0800516 return;
517}
518
Cheng C Yang916360b2019-05-07 18:47:16 +0800519void propertyInitialize(void)
Cheng C Yang209ec562019-03-12 16:37:44 +0800520{
Cheng C Yange50345b2019-04-02 17:26:15 +0800521 sensorTable = {{"power", "power/"},
522 {"curr", "current/"},
523 {"temp", "temperature/"},
524 {"in", "voltage/"},
525 {"fan", "fan_tach/"}};
526
527 labelMatch = {{"pin", PSUProperty("Input Power", 3000, 0, 6)},
528 {"pout1", PSUProperty("Output Power", 3000, 0, 6)},
Vijay Khemka996bad12019-05-28 15:15:16 -0700529 {"pout2", PSUProperty("Output Power", 3000, 0, 6)},
530 {"pout3", PSUProperty("Output Power", 3000, 0, 6)},
Vijay Khemkabe664412019-06-28 12:10:04 -0700531 {"power1", PSUProperty("Output Power", 3000, 0, 6)},
Cheng C Yangbdbde962019-04-26 22:50:34 +0800532 {"vin", PSUProperty("Input Voltage", 300, 0, 3)},
Vijay Khemka996bad12019-05-28 15:15:16 -0700533 {"vout1", PSUProperty("Output Voltage", 255, 0, 3)},
534 {"vout2", PSUProperty("Output Voltage", 255, 0, 3)},
535 {"vout3", PSUProperty("Output Voltage", 255, 0, 3)},
Jason Ling5747fab2019-10-02 16:46:23 -0700536 {"vout4", PSUProperty("Output Voltage", 255, 0, 3)},
537 {"vout5", PSUProperty("Output Voltage", 255, 0, 3)},
538 {"vout6", PSUProperty("Output Voltage", 255, 0, 3)},
539 {"vout7", PSUProperty("Output Voltage", 255, 0, 3)},
540 {"vout8", PSUProperty("Output Voltage", 255, 0, 3)},
541 {"vout9", PSUProperty("Output Voltage", 255, 0, 3)},
542 {"vout10", PSUProperty("Output Voltage", 255, 0, 3)},
543 {"vout11", PSUProperty("Output Voltage", 255, 0, 3)},
544 {"vout12", PSUProperty("Output Voltage", 255, 0, 3)},
545 {"vout13", PSUProperty("Output Voltage", 255, 0, 3)},
546 {"vout14", PSUProperty("Output Voltage", 255, 0, 3)},
547 {"vout15", PSUProperty("Output Voltage", 255, 0, 3)},
548 {"vout16", PSUProperty("Output Voltage", 255, 0, 3)},
Vijay Khemkabe664412019-06-28 12:10:04 -0700549 {"in1", PSUProperty("Output Voltage", 255, 0, 3)},
Cheng C Yange50345b2019-04-02 17:26:15 +0800550 {"iin", PSUProperty("Input Current", 20, 0, 3)},
551 {"iout1", PSUProperty("Output Current", 255, 0, 3)},
Vijay Khemka996bad12019-05-28 15:15:16 -0700552 {"iout2", PSUProperty("Output Current", 255, 0, 3)},
553 {"iout3", PSUProperty("Output Current", 255, 0, 3)},
Vijay Khemkabe664412019-06-28 12:10:04 -0700554 {"curr1", PSUProperty("Output Current", 255, 0, 3)},
Cheng C Yange50345b2019-04-02 17:26:15 +0800555 {"temp1", PSUProperty("Temperature", 127, -128, 3)},
Vijay Khemka996bad12019-05-28 15:15:16 -0700556 {"temp2", PSUProperty("Temperature", 127, -128, 3)},
557 {"temp3", PSUProperty("Temperature", 127, -128, 3)},
Jason Ling5747fab2019-10-02 16:46:23 -0700558 {"temp4", PSUProperty("Temperature", 127, -128, 3)},
559 {"temp5", PSUProperty("Temperature", 127, -128, 3)},
Cheng C Yang8dbb3952019-05-23 00:03:12 +0800560 {"fan1", PSUProperty("Fan Speed 1", 30000, 0, 0)},
561 {"fan2", PSUProperty("Fan Speed 2", 30000, 0, 0)}};
Cheng C Yang916360b2019-05-07 18:47:16 +0800562
563 pwmTable = {{"fan1", "Fan_1"}, {"fan2", "Fan_2"}};
Cheng C Yang58b2b532019-05-31 00:19:45 +0800564
565 limitEventMatch = {{"PredictiveFailure", {"max_alarm", "min_alarm"}},
566 {"Failure", {"crit_alarm", "lcrit_alarm"}}};
567
568 eventMatch = {
569 {"PredictiveFailure", {"power1_alarm"}},
570 {"Failure", {"in2_alarm"}},
Cheng C Yang9c45e6b2019-08-13 07:21:32 +0800571 {"ACLost", {"in1_beep"}},
572 {"FanFault", {"fan1_alarm", "fan2_alarm", "fan1_fault", "fan2_fault"}},
573 {"ConfigureError", {"in1_fault"}}};
Cheng C Yang209ec562019-03-12 16:37:44 +0800574}
575
James Feistb6c0b912019-07-09 12:21:44 -0700576int main()
Cheng C Yang209ec562019-03-12 16:37:44 +0800577{
578 boost::asio::io_service io;
579 auto systemBus = std::make_shared<sdbusplus::asio::connection>(io);
580
581 systemBus->request_name("xyz.openbmc_project.PSUSensor");
582 sdbusplus::asio::object_server objectServer(systemBus);
Cheng C Yang209ec562019-03-12 16:37:44 +0800583 std::vector<std::unique_ptr<sdbusplus::bus::match::match>> matches;
Cheng C Yang209ec562019-03-12 16:37:44 +0800584
Cheng C Yang916360b2019-05-07 18:47:16 +0800585 propertyInitialize();
Cheng C Yang209ec562019-03-12 16:37:44 +0800586
Cheng C Yang916360b2019-05-07 18:47:16 +0800587 io.post([&]() { createSensors(io, objectServer, systemBus); });
Cheng C Yang209ec562019-03-12 16:37:44 +0800588 boost::asio::deadline_timer filterTimer(io);
589 std::function<void(sdbusplus::message::message&)> eventHandler =
590 [&](sdbusplus::message::message& message) {
591 if (message.is_method_error())
592 {
593 std::cerr << "callback method error\n";
594 return;
595 }
596 filterTimer.expires_from_now(boost::posix_time::seconds(1));
597 filterTimer.async_wait([&](const boost::system::error_code& ec) {
598 if (ec == boost::asio::error::operation_aborted)
599 {
600 return;
601 }
602 else if (ec)
603 {
604 std::cerr << "timer error\n";
605 }
Cheng C Yang916360b2019-05-07 18:47:16 +0800606 createSensors(io, objectServer, systemBus);
Cheng C Yang209ec562019-03-12 16:37:44 +0800607 });
608 };
609
610 for (const char* type : sensorTypes)
611 {
612 auto match = std::make_unique<sdbusplus::bus::match::match>(
613 static_cast<sdbusplus::bus::bus&>(*systemBus),
614 "type='signal',member='PropertiesChanged',path_namespace='" +
615 std::string(inventoryPath) + "',arg0namespace='" + type + "'",
616 eventHandler);
617 matches.emplace_back(std::move(match));
618 }
619 io.run();
620}