blob: 9abde115dfb1469c9fd4eb750114b2a691a7e939 [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
Cheng C Yang209ec562019-03-12 16:37:44 +080021#include <boost/algorithm/string/predicate.hpp>
22#include <boost/algorithm/string/replace.hpp>
23#include <boost/container/flat_set.hpp>
James Feist24f02f22019-04-15 11:05:39 -070024#include <filesystem>
Cheng C Yang209ec562019-03-12 16:37:44 +080025#include <fstream>
Cheng C Yang58b2b532019-05-31 00:19:45 +080026#include <iostream>
Cheng C Yang209ec562019-03-12 16:37:44 +080027#include <regex>
28#include <sdbusplus/asio/connection.hpp>
29#include <sdbusplus/asio/object_server.hpp>
30
Josh Lehan49cfba92019-10-08 16:50:42 -070031static constexpr bool DEBUG = false;
32
Devjit Gopalpurde65ef72019-10-30 04:47:35 -070033static constexpr std::array<const char*, 4> sensorTypes = {
Jason Ling5747fab2019-10-02 16:46:23 -070034 "xyz.openbmc_project.Configuration.pmbus",
Josh Lehan0830c7b2019-10-08 16:35:09 -070035 "xyz.openbmc_project.Configuration.MAX34451",
Devjit Gopalpurde65ef72019-10-30 04:47:35 -070036 "xyz.openbmc_project.Configuration.INA230",
Josh Lehan0830c7b2019-10-08 16:35:09 -070037 "xyz.openbmc_project.Configuration.ISL68137"};
Cheng C Yang209ec562019-03-12 16:37:44 +080038
Josh Lehan0830c7b2019-10-08 16:35:09 -070039static std::vector<std::string> pmbusNames = {"pmbus", "pxe1610", "ina219",
40 "ina230", "max34451", "isl68137"};
41
Cheng C Yang209ec562019-03-12 16:37:44 +080042namespace fs = std::filesystem;
43
Cheng C Yang916360b2019-05-07 18:47:16 +080044static boost::container::flat_map<std::string, std::unique_ptr<PSUSensor>>
45 sensors;
Cheng C Yang58b2b532019-05-31 00:19:45 +080046static boost::container::flat_map<std::string, std::unique_ptr<PSUCombineEvent>>
47 combineEvents;
Cheng C Yang916360b2019-05-07 18:47:16 +080048static boost::container::flat_map<std::string, std::unique_ptr<PwmSensor>>
49 pwmSensors;
50static boost::container::flat_map<std::string, std::string> sensorTable;
51static boost::container::flat_map<std::string, PSUProperty> labelMatch;
52static boost::container::flat_map<std::string, std::string> pwmTable;
Cheng C Yang58b2b532019-05-31 00:19:45 +080053static boost::container::flat_map<std::string, std::vector<std::string>>
54 eventMatch;
55static boost::container::flat_map<std::string, std::vector<std::string>>
56 limitEventMatch;
57
58// Function CheckEvent will check each attribute from eventMatch table in the
59// sysfs. If the attributes exists in sysfs, then store the complete path
60// of the attribute into eventPathList.
61void checkEvent(
62 const std::string& directory,
63 const boost::container::flat_map<std::string, std::vector<std::string>>&
64 eventMatch,
65 boost::container::flat_map<std::string, std::vector<std::string>>&
66 eventPathList)
67{
68 for (const auto& match : eventMatch)
69 {
70 const std::vector<std::string>& eventAttrs = match.second;
71 const std::string& eventName = match.first;
72 for (const auto& eventAttr : eventAttrs)
73 {
74 auto eventPath = directory + "/" + eventAttr;
75
76 std::ifstream eventFile(eventPath);
77 if (!eventFile.good())
78 {
79 continue;
80 }
81
82 eventPathList[eventName].push_back(eventPath);
83 }
84 }
85}
86
87// Function checkEventLimits will check all the psu related xxx_input attributes
88// in sysfs to see if xxx_crit_alarm xxx_lcrit_alarm xxx_max_alarm
89// xxx_min_alarm exist, then store the existing paths of the alarm attributes
90// to eventPathList.
91void checkEventLimits(
92 const std::string& sensorPathStr,
93 const boost::container::flat_map<std::string, std::vector<std::string>>&
94 limitEventMatch,
95 boost::container::flat_map<std::string, std::vector<std::string>>&
96 eventPathList)
97{
98 for (const auto& limitMatch : limitEventMatch)
99 {
100 const std::vector<std::string>& limitEventAttrs = limitMatch.second;
101 const std::string& eventName = limitMatch.first;
102 for (const auto& limitEventAttr : limitEventAttrs)
103 {
104 auto limitEventPath =
105 boost::replace_all_copy(sensorPathStr, "input", limitEventAttr);
106 std::ifstream eventFile(limitEventPath);
107 if (!eventFile.good())
108 {
109 continue;
110 }
111 eventPathList[eventName].push_back(limitEventPath);
112 }
113 }
114}
Cheng C Yang916360b2019-05-07 18:47:16 +0800115
116static void checkPWMSensor(const fs::path& sensorPath, std::string& labelHead,
117 const std::string& interfacePath,
118 sdbusplus::asio::object_server& objectServer,
Patrick Venturea2b2d842019-10-11 07:48:47 -0700119 const std::string& psuName)
Cheng C Yang916360b2019-05-07 18:47:16 +0800120{
121 for (const auto& pwmName : pwmTable)
122 {
123 if (pwmName.first != labelHead)
124 {
125 continue;
126 }
127
128 const std::string& sensorPathStr = sensorPath.string();
129 const std::string& pwmPathStr =
130 boost::replace_all_copy(sensorPathStr, "input", "target");
131 std::ifstream pwmFile(pwmPathStr);
132 if (!pwmFile.good())
133 {
134 continue;
135 }
136
137 auto findPWMSensor = pwmSensors.find(psuName + labelHead);
138 if (findPWMSensor != pwmSensors.end())
139 {
140 continue;
141 }
142
143 pwmSensors[psuName + labelHead] = std::make_unique<PwmSensor>(
144 "Pwm_" + psuName + "_" + pwmName.second, pwmPathStr, objectServer,
Cheng C Yang15266a92019-06-12 08:42:52 +0800145 interfacePath + "_" + pwmName.second);
Cheng C Yang916360b2019-05-07 18:47:16 +0800146 }
147}
148
149void createSensors(boost::asio::io_service& io,
150 sdbusplus::asio::object_server& objectServer,
151 std::shared_ptr<sdbusplus::asio::connection>& dbusConnection)
Cheng C Yang209ec562019-03-12 16:37:44 +0800152{
153
154 ManagedObjectType sensorConfigs;
Josh Lehan49cfba92019-10-08 16:50:42 -0700155 int numCreated = 0;
Cheng C Yang209ec562019-03-12 16:37:44 +0800156 bool useCache = false;
157
Cheng C Yang58b2b532019-05-31 00:19:45 +0800158 // TODO may need only modify the ones that need to be changed.
159 sensors.clear();
Cheng C Yang92498eb2019-09-26 21:59:25 +0800160 combineEvents.clear();
Cheng C Yang209ec562019-03-12 16:37:44 +0800161 for (const char* type : sensorTypes)
162 {
163 if (!getSensorConfiguration(type, dbusConnection, sensorConfigs,
164 useCache))
165 {
166 std::cerr << "error get sensor config from entity manager\n";
167 return;
168 }
169 useCache = true;
170 }
171
172 std::vector<fs::path> pmbusPaths;
173 if (!findFiles(fs::path("/sys/class/hwmon"), "name", pmbusPaths))
174 {
175 std::cerr << "No PSU sensors in system\n";
176 return;
177 }
178
179 boost::container::flat_set<std::string> directories;
180 for (const auto& pmbusPath : pmbusPaths)
181 {
Cheng C Yang58b2b532019-05-31 00:19:45 +0800182 boost::container::flat_map<std::string, std::vector<std::string>>
183 eventPathList;
184
185 std::ifstream nameFile(pmbusPath);
186 if (!nameFile.good())
187 {
Josh Lehan49cfba92019-10-08 16:50:42 -0700188 std::cerr << "Failure finding pmbus path " << pmbusPath << "\n";
Cheng C Yang58b2b532019-05-31 00:19:45 +0800189 continue;
190 }
191
192 std::string pmbusName;
193 std::getline(nameFile, pmbusName);
194 nameFile.close();
Vijay Khemka996bad12019-05-28 15:15:16 -0700195
196 if (std::find(pmbusNames.begin(), pmbusNames.end(), pmbusName) ==
197 pmbusNames.end())
Cheng C Yang58b2b532019-05-31 00:19:45 +0800198 {
Josh Lehan49cfba92019-10-08 16:50:42 -0700199 // To avoid this error message, add your driver name to
200 // the pmbusNames vector at the top of this file.
201 std::cerr << "Driver name " << pmbusName
202 << " not found in sensor whitelist\n";
Cheng C Yang58b2b532019-05-31 00:19:45 +0800203 continue;
204 }
205
206 const std::string* psuName;
Cheng C Yang209ec562019-03-12 16:37:44 +0800207 auto directory = pmbusPath.parent_path();
208
209 auto ret = directories.insert(directory.string());
210 if (!ret.second)
211 {
Josh Lehan49cfba92019-10-08 16:50:42 -0700212 std::cerr << "Duplicate path " << directory.string() << "\n";
Cheng C Yang58b2b532019-05-31 00:19:45 +0800213 continue; // check if path has already been searched
Cheng C Yang209ec562019-03-12 16:37:44 +0800214 }
215
James Feistb6c0b912019-07-09 12:21:44 -0700216 fs::path device = directory / "device";
Cheng C Yang209ec562019-03-12 16:37:44 +0800217 std::string deviceName = fs::canonical(device).stem();
218 auto findHyphen = deviceName.find("-");
219 if (findHyphen == std::string::npos)
220 {
221 std::cerr << "found bad device" << deviceName << "\n";
222 continue;
223 }
224 std::string busStr = deviceName.substr(0, findHyphen);
225 std::string addrStr = deviceName.substr(findHyphen + 1);
226
227 size_t bus = 0;
228 size_t addr = 0;
229
230 try
231 {
232 bus = std::stoi(busStr);
233 addr = std::stoi(addrStr, 0, 16);
234 }
James Feistb6c0b912019-07-09 12:21:44 -0700235 catch (std::invalid_argument&)
Cheng C Yang209ec562019-03-12 16:37:44 +0800236 {
Josh Lehan49cfba92019-10-08 16:50:42 -0700237 std::cerr << "Error parsing bus " << busStr << " addr " << addrStr
238 << "\n";
Cheng C Yang209ec562019-03-12 16:37:44 +0800239 continue;
240 }
241
Cheng C Yang209ec562019-03-12 16:37:44 +0800242 const std::pair<std::string, boost::container::flat_map<
243 std::string, BasicVariantType>>*
244 baseConfig = nullptr;
245 const SensorData* sensorData = nullptr;
246 const std::string* interfacePath = nullptr;
247 const char* sensorType = nullptr;
248
249 for (const std::pair<sdbusplus::message::object_path, SensorData>&
250 sensor : sensorConfigs)
251 {
252 sensorData = &(sensor.second);
253 for (const char* type : sensorTypes)
254 {
255 auto sensorBase = sensorData->find(type);
256 if (sensorBase != sensorData->end())
257 {
258 baseConfig = &(*sensorBase);
259 sensorType = type;
260 break;
261 }
262 }
263 if (baseConfig == nullptr)
264 {
265 std::cerr << "error finding base configuration for "
266 << deviceName << "\n";
267 continue;
268 }
269
270 auto configBus = baseConfig->second.find("Bus");
271 auto configAddress = baseConfig->second.find("Address");
272
273 if (configBus == baseConfig->second.end() ||
274 configAddress == baseConfig->second.end())
275 {
Cheng C Yang58b2b532019-05-31 00:19:45 +0800276 std::cerr << "error finding necessary entry in configuration\n";
Cheng C Yang209ec562019-03-12 16:37:44 +0800277 continue;
278 }
279
Cheng C Yang58b2b532019-05-31 00:19:45 +0800280 const uint64_t* confBus;
281 const uint64_t* confAddr;
282 if (!(confBus = std::get_if<uint64_t>(&(configBus->second))) ||
283 !(confAddr = std::get_if<uint64_t>(&(configAddress->second))))
284 {
285 std::cerr
Josh Lehan49cfba92019-10-08 16:50:42 -0700286 << "Cannot get bus or address, invalid configuration\n";
Cheng C Yang58b2b532019-05-31 00:19:45 +0800287 continue;
288 }
289
290 if ((*confBus != bus) || (*confAddr != addr))
Cheng C Yang209ec562019-03-12 16:37:44 +0800291 {
Josh Lehan432d1ed2019-10-16 12:23:31 -0700292 std::cerr << "Configuration skipping " << *confBus << "-"
293 << *confAddr << " because not " << bus << "-" << addr
294 << "\n";
Cheng C Yang209ec562019-03-12 16:37:44 +0800295 continue;
296 }
297
298 interfacePath = &(sensor.first.str);
299 break;
300 }
301 if (interfacePath == nullptr)
302 {
Josh Lehan49cfba92019-10-08 16:50:42 -0700303 // To avoid this error message, add your export map entry,
304 // from Entity Manager, to sensorTypes at the top of this file.
Cheng C Yang209ec562019-03-12 16:37:44 +0800305 std::cerr << "failed to find match for " << deviceName << "\n";
306 continue;
307 }
308
Cheng C Yange50345b2019-04-02 17:26:15 +0800309 auto findPSUName = baseConfig->second.find("Name");
310 if (findPSUName == baseConfig->second.end())
Cheng C Yang209ec562019-03-12 16:37:44 +0800311 {
312 std::cerr << "could not determine configuration name for "
313 << deviceName << "\n";
314 continue;
315 }
316
Cheng C Yang58b2b532019-05-31 00:19:45 +0800317 if (!(psuName = std::get_if<std::string>(&(findPSUName->second))))
318 {
319 std::cerr << "Cannot find psu name, invalid configuration\n";
320 continue;
321 }
322 checkEvent(directory.string(), eventMatch, eventPathList);
323
Vijay Khemka996bad12019-05-28 15:15:16 -0700324 /* Check if there are more sensors in the same interface */
325 int i = 1;
326 std::vector<std::string> psuNames;
327 do
328 {
Josh Lehan49cfba92019-10-08 16:50:42 -0700329 // Individual string fields: Name, Name1, Name2, Name3, ...
Vijay Khemka996bad12019-05-28 15:15:16 -0700330 psuNames.push_back(std::get<std::string>(findPSUName->second));
331 findPSUName = baseConfig->second.find("Name" + std::to_string(i++));
332 } while (findPSUName != baseConfig->second.end());
333
Cheng C Yange50345b2019-04-02 17:26:15 +0800334 std::vector<fs::path> sensorPaths;
James Feistb6c0b912019-07-09 12:21:44 -0700335 if (!findFiles(directory, R"(\w\d+_input$)", sensorPaths, 0))
Cheng C Yang209ec562019-03-12 16:37:44 +0800336 {
Cheng C Yange50345b2019-04-02 17:26:15 +0800337 std::cerr << "No PSU non-label sensor in PSU\n";
Cheng C Yang209ec562019-03-12 16:37:44 +0800338 continue;
339 }
340
Vijay Khemka996bad12019-05-28 15:15:16 -0700341 /* Find array of labels to be exposed if it is defined in config */
342 std::vector<std::string> findLabels;
343 auto findLabelObj = baseConfig->second.find("Labels");
344 if (findLabelObj != baseConfig->second.end())
345 {
346 findLabels =
347 std::get<std::vector<std::string>>(findLabelObj->second);
348 }
349
Jason Ling5747fab2019-10-02 16:46:23 -0700350 std::regex sensorNameRegEx("([A-Za-z]+)[0-9]*_");
351 std::smatch matches;
352
Cheng C Yange50345b2019-04-02 17:26:15 +0800353 for (const auto& sensorPath : sensorPaths)
Cheng C Yang209ec562019-03-12 16:37:44 +0800354 {
Cheng C Yang209ec562019-03-12 16:37:44 +0800355
Cheng C Yange50345b2019-04-02 17:26:15 +0800356 std::string labelHead;
357 std::string sensorPathStr = sensorPath.string();
358 std::string sensorNameStr = sensorPath.filename();
Jason Ling5747fab2019-10-02 16:46:23 -0700359 std::string sensorNameSubStr{""};
360 if (std::regex_search(sensorNameStr, matches, sensorNameRegEx))
361 {
362 sensorNameSubStr = matches[1];
363 }
364 else
365 {
366 std::cerr << "Couldn't extract the alpha prefix from "
367 << sensorNameStr;
368 continue;
369 }
Cheng C Yange50345b2019-04-02 17:26:15 +0800370
Cheng C Yangecba9de2019-09-12 23:41:50 +0800371 auto labelPath =
372 boost::replace_all_copy(sensorPathStr, "input", "label");
373 std::ifstream labelFile(labelPath);
374 if (!labelFile.good())
Cheng C Yang209ec562019-03-12 16:37:44 +0800375 {
Josh Lehan432d1ed2019-10-16 12:23:31 -0700376 std::cerr << "Input file " << sensorPath
377 << " has no corresponding label file\n";
Cheng C Yange50345b2019-04-02 17:26:15 +0800378 labelHead = sensorNameStr.substr(0, sensorNameStr.find("_"));
Cheng C Yang209ec562019-03-12 16:37:44 +0800379 }
380 else
381 {
Cheng C Yange50345b2019-04-02 17:26:15 +0800382 std::string label;
383 std::getline(labelFile, label);
384 labelFile.close();
Cheng C Yange50345b2019-04-02 17:26:15 +0800385 auto findSensor = sensors.find(label);
386 if (findSensor != sensors.end())
387 {
388 continue;
389 }
390
391 labelHead = label.substr(0, label.find(" "));
392 }
393
Cheng C Yang916360b2019-05-07 18:47:16 +0800394 checkPWMSensor(sensorPath, labelHead, *interfacePath, objectServer,
Vijay Khemka996bad12019-05-28 15:15:16 -0700395 psuNames[0]);
Cheng C Yang916360b2019-05-07 18:47:16 +0800396
Vijay Khemka996bad12019-05-28 15:15:16 -0700397 if (!findLabels.empty())
398 {
399 /* Check if this labelHead is enabled in config file */
400 if (std::find(findLabels.begin(), findLabels.end(),
401 labelHead) == findLabels.end())
402 {
Jason Ling5747fab2019-10-02 16:46:23 -0700403 std::cerr << "couldn't find " << labelHead
404 << " in the Labels list\n";
Vijay Khemka996bad12019-05-28 15:15:16 -0700405 continue;
406 }
407 }
Cheng C Yange50345b2019-04-02 17:26:15 +0800408
Vijay Khemka996bad12019-05-28 15:15:16 -0700409 /* Find out sensor name index for this label */
Jason Ling5747fab2019-10-02 16:46:23 -0700410 std::regex rgx("[A-Za-z]+([0-9]+)");
411 int nameIndex{0};
412 if (std::regex_search(labelHead, matches, rgx))
Vijay Khemka996bad12019-05-28 15:15:16 -0700413 {
Jason Ling5747fab2019-10-02 16:46:23 -0700414 nameIndex = std::stoi(matches[1]);
Josh Lehan9fa25152019-10-16 16:52:38 -0700415
416 // Decrement to preserve alignment, because hwmon
417 // human-readable filenames and labels use 1-based numbering,
418 // but the "Name", "Name1", "Name2", etc. naming
419 // convention (the psuNames vector) uses 0-based numbering.
420 if (nameIndex > 0)
421 {
422 --nameIndex;
423 }
Vijay Khemka996bad12019-05-28 15:15:16 -0700424 }
425 else
James Feist17ab6e02019-06-25 12:28:13 -0700426 {
Vijay Khemka996bad12019-05-28 15:15:16 -0700427 nameIndex = 0;
James Feist17ab6e02019-06-25 12:28:13 -0700428 }
Cheng C Yange50345b2019-04-02 17:26:15 +0800429
Jason Ling5747fab2019-10-02 16:46:23 -0700430 if (psuNames.size() <= nameIndex)
431 {
432 std::cerr << "Could not pair " << labelHead
433 << " with a Name field\n";
434 continue;
435 }
436
Cheng C Yange50345b2019-04-02 17:26:15 +0800437 auto findProperty = labelMatch.find(labelHead);
438 if (findProperty == labelMatch.end())
Cheng C Yang209ec562019-03-12 16:37:44 +0800439 {
Jason Ling5747fab2019-10-02 16:46:23 -0700440 std::cerr << "Could not find " << labelHead << "\n";
Cheng C Yang209ec562019-03-12 16:37:44 +0800441 continue;
442 }
443
Josh Lehan432d1ed2019-10-16 12:23:31 -0700444 if constexpr (DEBUG)
445 {
446 std::cerr << "Sensor label head " << labelHead
447 << " paired with " << psuNames[nameIndex] << "\n";
448 }
449
Cheng C Yang58b2b532019-05-31 00:19:45 +0800450 checkEventLimits(sensorPathStr, limitEventMatch, eventPathList);
451
Cheng C Yange50345b2019-04-02 17:26:15 +0800452 unsigned int factor =
453 std::pow(10, findProperty->second.sensorScaleFactor);
Vijay Khemka996bad12019-05-28 15:15:16 -0700454
Vijay Khemkadbdcfe02019-07-25 12:56:17 -0700455 /* Change first char of substring to uppercase */
456 char firstChar = sensorNameSubStr[0] - 0x20;
457 std::string strScaleFactor =
458 firstChar + sensorNameSubStr.substr(1) + "ScaleFactor";
459
460 auto findScaleFactor = baseConfig->second.find(strScaleFactor);
Vijay Khemka53ca4442019-07-23 11:03:55 -0700461 if (findScaleFactor != baseConfig->second.end())
462 {
463 factor =
464 std::visit(VariantToIntVisitor(), findScaleFactor->second);
465 }
466
Josh Lehan49cfba92019-10-08 16:50:42 -0700467 if constexpr (DEBUG)
468 {
469 std::cerr << "Sensor scaling factor " << factor << " string "
470 << strScaleFactor << "\n";
471 }
472
Vijay Khemka996bad12019-05-28 15:15:16 -0700473 std::vector<thresholds::Threshold> sensorThresholds;
474
James Feist17ab6e02019-06-25 12:28:13 -0700475 if (!parseThresholdsFromConfig(*sensorData, sensorThresholds))
Cheng C Yange50345b2019-04-02 17:26:15 +0800476 {
James Feist17ab6e02019-06-25 12:28:13 -0700477 std::cerr << "error populating thresholds for "
478 << sensorNameSubStr << "\n";
Cheng C Yange50345b2019-04-02 17:26:15 +0800479 }
480
481 auto findSensorType = sensorTable.find(sensorNameSubStr);
482 if (findSensorType == sensorTable.end())
483 {
Jason Ling5747fab2019-10-02 16:46:23 -0700484 std::cerr << sensorNameSubStr
485 << " is not a recognize sensor file\n";
Cheng C Yange50345b2019-04-02 17:26:15 +0800486 continue;
487 }
488
489 std::string sensorName =
Vijay Khemka996bad12019-05-28 15:15:16 -0700490 psuNames[nameIndex] + " " + findProperty->second.labelTypeName;
Cheng C Yange50345b2019-04-02 17:26:15 +0800491
Josh Lehan49cfba92019-10-08 16:50:42 -0700492 ++numCreated;
493 if constexpr (DEBUG)
494 {
495 std::cerr << "Created " << numCreated
496 << " sensors so far: " << sensorName << "\n";
497 }
498
Cheng C Yang58b2b532019-05-31 00:19:45 +0800499 sensors[sensorName] = std::make_unique<PSUSensor>(
Cheng C Yange50345b2019-04-02 17:26:15 +0800500 sensorPathStr, sensorType, objectServer, dbusConnection, io,
Cheng C Yang209ec562019-03-12 16:37:44 +0800501 sensorName, std::move(sensorThresholds), *interfacePath,
Cheng C Yange50345b2019-04-02 17:26:15 +0800502 findSensorType->second, factor, findProperty->second.maxReading,
503 findProperty->second.minReading);
Cheng C Yang209ec562019-03-12 16:37:44 +0800504 }
Cheng C Yang58b2b532019-05-31 00:19:45 +0800505
506 // OperationalStatus event
Cheng C Yang92498eb2019-09-26 21:59:25 +0800507 combineEvents[*psuName + "OperationalStatus"] = nullptr;
Cheng C Yang58b2b532019-05-31 00:19:45 +0800508 combineEvents[*psuName + "OperationalStatus"] =
509 std::make_unique<PSUCombineEvent>(
510 objectServer, io, *psuName, eventPathList, "OperationalStatus");
Cheng C Yang209ec562019-03-12 16:37:44 +0800511 }
Josh Lehan49cfba92019-10-08 16:50:42 -0700512
513 if constexpr (DEBUG)
514 {
515 std::cerr << "Created total of " << numCreated << " sensors\n";
516 }
Cheng C Yang209ec562019-03-12 16:37:44 +0800517 return;
518}
519
Cheng C Yang916360b2019-05-07 18:47:16 +0800520void propertyInitialize(void)
Cheng C Yang209ec562019-03-12 16:37:44 +0800521{
Cheng C Yange50345b2019-04-02 17:26:15 +0800522 sensorTable = {{"power", "power/"},
523 {"curr", "current/"},
524 {"temp", "temperature/"},
525 {"in", "voltage/"},
526 {"fan", "fan_tach/"}};
527
528 labelMatch = {{"pin", PSUProperty("Input Power", 3000, 0, 6)},
529 {"pout1", PSUProperty("Output Power", 3000, 0, 6)},
Vijay Khemka996bad12019-05-28 15:15:16 -0700530 {"pout2", PSUProperty("Output Power", 3000, 0, 6)},
531 {"pout3", PSUProperty("Output Power", 3000, 0, 6)},
Vijay Khemkabe664412019-06-28 12:10:04 -0700532 {"power1", PSUProperty("Output Power", 3000, 0, 6)},
Cheng C Yangbdbde962019-04-26 22:50:34 +0800533 {"vin", PSUProperty("Input Voltage", 300, 0, 3)},
Vijay Khemka996bad12019-05-28 15:15:16 -0700534 {"vout1", PSUProperty("Output Voltage", 255, 0, 3)},
535 {"vout2", PSUProperty("Output Voltage", 255, 0, 3)},
536 {"vout3", PSUProperty("Output Voltage", 255, 0, 3)},
Jason Ling5747fab2019-10-02 16:46:23 -0700537 {"vout4", PSUProperty("Output Voltage", 255, 0, 3)},
538 {"vout5", PSUProperty("Output Voltage", 255, 0, 3)},
539 {"vout6", PSUProperty("Output Voltage", 255, 0, 3)},
540 {"vout7", PSUProperty("Output Voltage", 255, 0, 3)},
541 {"vout8", PSUProperty("Output Voltage", 255, 0, 3)},
542 {"vout9", PSUProperty("Output Voltage", 255, 0, 3)},
543 {"vout10", PSUProperty("Output Voltage", 255, 0, 3)},
544 {"vout11", PSUProperty("Output Voltage", 255, 0, 3)},
545 {"vout12", PSUProperty("Output Voltage", 255, 0, 3)},
546 {"vout13", PSUProperty("Output Voltage", 255, 0, 3)},
547 {"vout14", PSUProperty("Output Voltage", 255, 0, 3)},
548 {"vout15", PSUProperty("Output Voltage", 255, 0, 3)},
549 {"vout16", PSUProperty("Output Voltage", 255, 0, 3)},
Vijay Khemkabe664412019-06-28 12:10:04 -0700550 {"in1", PSUProperty("Output Voltage", 255, 0, 3)},
Cheng C Yange50345b2019-04-02 17:26:15 +0800551 {"iin", PSUProperty("Input Current", 20, 0, 3)},
552 {"iout1", PSUProperty("Output Current", 255, 0, 3)},
Vijay Khemka996bad12019-05-28 15:15:16 -0700553 {"iout2", PSUProperty("Output Current", 255, 0, 3)},
554 {"iout3", PSUProperty("Output Current", 255, 0, 3)},
Vijay Khemkabe664412019-06-28 12:10:04 -0700555 {"curr1", PSUProperty("Output Current", 255, 0, 3)},
Cheng C Yange50345b2019-04-02 17:26:15 +0800556 {"temp1", PSUProperty("Temperature", 127, -128, 3)},
Vijay Khemka996bad12019-05-28 15:15:16 -0700557 {"temp2", PSUProperty("Temperature", 127, -128, 3)},
558 {"temp3", PSUProperty("Temperature", 127, -128, 3)},
Jason Ling5747fab2019-10-02 16:46:23 -0700559 {"temp4", PSUProperty("Temperature", 127, -128, 3)},
560 {"temp5", PSUProperty("Temperature", 127, -128, 3)},
Cheng C Yang8dbb3952019-05-23 00:03:12 +0800561 {"fan1", PSUProperty("Fan Speed 1", 30000, 0, 0)},
562 {"fan2", PSUProperty("Fan Speed 2", 30000, 0, 0)}};
Cheng C Yang916360b2019-05-07 18:47:16 +0800563
564 pwmTable = {{"fan1", "Fan_1"}, {"fan2", "Fan_2"}};
Cheng C Yang58b2b532019-05-31 00:19:45 +0800565
566 limitEventMatch = {{"PredictiveFailure", {"max_alarm", "min_alarm"}},
567 {"Failure", {"crit_alarm", "lcrit_alarm"}}};
568
569 eventMatch = {
570 {"PredictiveFailure", {"power1_alarm"}},
571 {"Failure", {"in2_alarm"}},
Cheng C Yang9c45e6b2019-08-13 07:21:32 +0800572 {"ACLost", {"in1_beep"}},
573 {"FanFault", {"fan1_alarm", "fan2_alarm", "fan1_fault", "fan2_fault"}},
574 {"ConfigureError", {"in1_fault"}}};
Cheng C Yang209ec562019-03-12 16:37:44 +0800575}
576
James Feistb6c0b912019-07-09 12:21:44 -0700577int main()
Cheng C Yang209ec562019-03-12 16:37:44 +0800578{
579 boost::asio::io_service io;
580 auto systemBus = std::make_shared<sdbusplus::asio::connection>(io);
581
582 systemBus->request_name("xyz.openbmc_project.PSUSensor");
583 sdbusplus::asio::object_server objectServer(systemBus);
Cheng C Yang209ec562019-03-12 16:37:44 +0800584 std::vector<std::unique_ptr<sdbusplus::bus::match::match>> matches;
Cheng C Yang209ec562019-03-12 16:37:44 +0800585
Cheng C Yang916360b2019-05-07 18:47:16 +0800586 propertyInitialize();
Cheng C Yang209ec562019-03-12 16:37:44 +0800587
Cheng C Yang916360b2019-05-07 18:47:16 +0800588 io.post([&]() { createSensors(io, objectServer, systemBus); });
Cheng C Yang209ec562019-03-12 16:37:44 +0800589 boost::asio::deadline_timer filterTimer(io);
590 std::function<void(sdbusplus::message::message&)> eventHandler =
591 [&](sdbusplus::message::message& message) {
592 if (message.is_method_error())
593 {
594 std::cerr << "callback method error\n";
595 return;
596 }
597 filterTimer.expires_from_now(boost::posix_time::seconds(1));
598 filterTimer.async_wait([&](const boost::system::error_code& ec) {
599 if (ec == boost::asio::error::operation_aborted)
600 {
601 return;
602 }
603 else if (ec)
604 {
605 std::cerr << "timer error\n";
606 }
Cheng C Yang916360b2019-05-07 18:47:16 +0800607 createSensors(io, objectServer, systemBus);
Cheng C Yang209ec562019-03-12 16:37:44 +0800608 });
609 };
610
611 for (const char* type : sensorTypes)
612 {
613 auto match = std::make_unique<sdbusplus::bus::match::match>(
614 static_cast<sdbusplus::bus::bus&>(*systemBus),
615 "type='signal',member='PropertiesChanged',path_namespace='" +
616 std::string(inventoryPath) + "',arg0namespace='" + type + "'",
617 eventHandler);
618 matches.emplace_back(std::move(match));
619 }
620 io.run();
621}