blob: 8a940b82c9c6d9a0efbb91765b07b3785de24039 [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
Josh Lehan0830c7b2019-10-08 16:35:09 -070032static constexpr std::array<const char*, 3> 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",
35 "xyz.openbmc_project.Configuration.ISL68137"};
Cheng C Yang209ec562019-03-12 16:37:44 +080036
Josh Lehan0830c7b2019-10-08 16:35:09 -070037static std::vector<std::string> pmbusNames = {"pmbus", "pxe1610", "ina219",
38 "ina230", "max34451", "isl68137"};
39
Cheng C Yang209ec562019-03-12 16:37:44 +080040namespace fs = std::filesystem;
41
Cheng C Yang916360b2019-05-07 18:47:16 +080042static boost::container::flat_map<std::string, std::unique_ptr<PSUSensor>>
43 sensors;
Cheng C Yang58b2b532019-05-31 00:19:45 +080044static boost::container::flat_map<std::string, std::unique_ptr<PSUCombineEvent>>
45 combineEvents;
Cheng C Yang916360b2019-05-07 18:47:16 +080046static boost::container::flat_map<std::string, std::unique_ptr<PwmSensor>>
47 pwmSensors;
48static boost::container::flat_map<std::string, std::string> sensorTable;
49static boost::container::flat_map<std::string, PSUProperty> labelMatch;
50static boost::container::flat_map<std::string, std::string> pwmTable;
Cheng C Yang58b2b532019-05-31 00:19:45 +080051static boost::container::flat_map<std::string, std::vector<std::string>>
52 eventMatch;
53static boost::container::flat_map<std::string, std::vector<std::string>>
54 limitEventMatch;
55
56// Function CheckEvent will check each attribute from eventMatch table in the
57// sysfs. If the attributes exists in sysfs, then store the complete path
58// of the attribute into eventPathList.
59void checkEvent(
60 const std::string& directory,
61 const boost::container::flat_map<std::string, std::vector<std::string>>&
62 eventMatch,
63 boost::container::flat_map<std::string, std::vector<std::string>>&
64 eventPathList)
65{
66 for (const auto& match : eventMatch)
67 {
68 const std::vector<std::string>& eventAttrs = match.second;
69 const std::string& eventName = match.first;
70 for (const auto& eventAttr : eventAttrs)
71 {
72 auto eventPath = directory + "/" + eventAttr;
73
74 std::ifstream eventFile(eventPath);
75 if (!eventFile.good())
76 {
77 continue;
78 }
79
80 eventPathList[eventName].push_back(eventPath);
81 }
82 }
83}
84
85// Function checkEventLimits will check all the psu related xxx_input attributes
86// in sysfs to see if xxx_crit_alarm xxx_lcrit_alarm xxx_max_alarm
87// xxx_min_alarm exist, then store the existing paths of the alarm attributes
88// to eventPathList.
89void checkEventLimits(
90 const std::string& sensorPathStr,
91 const boost::container::flat_map<std::string, std::vector<std::string>>&
92 limitEventMatch,
93 boost::container::flat_map<std::string, std::vector<std::string>>&
94 eventPathList)
95{
96 for (const auto& limitMatch : limitEventMatch)
97 {
98 const std::vector<std::string>& limitEventAttrs = limitMatch.second;
99 const std::string& eventName = limitMatch.first;
100 for (const auto& limitEventAttr : limitEventAttrs)
101 {
102 auto limitEventPath =
103 boost::replace_all_copy(sensorPathStr, "input", limitEventAttr);
104 std::ifstream eventFile(limitEventPath);
105 if (!eventFile.good())
106 {
107 continue;
108 }
109 eventPathList[eventName].push_back(limitEventPath);
110 }
111 }
112}
Cheng C Yang916360b2019-05-07 18:47:16 +0800113
114static void checkPWMSensor(const fs::path& sensorPath, std::string& labelHead,
115 const std::string& interfacePath,
116 sdbusplus::asio::object_server& objectServer,
117 std::string psuName)
118{
119 for (const auto& pwmName : pwmTable)
120 {
121 if (pwmName.first != labelHead)
122 {
123 continue;
124 }
125
126 const std::string& sensorPathStr = sensorPath.string();
127 const std::string& pwmPathStr =
128 boost::replace_all_copy(sensorPathStr, "input", "target");
129 std::ifstream pwmFile(pwmPathStr);
130 if (!pwmFile.good())
131 {
132 continue;
133 }
134
135 auto findPWMSensor = pwmSensors.find(psuName + labelHead);
136 if (findPWMSensor != pwmSensors.end())
137 {
138 continue;
139 }
140
141 pwmSensors[psuName + labelHead] = std::make_unique<PwmSensor>(
142 "Pwm_" + psuName + "_" + pwmName.second, pwmPathStr, objectServer,
Cheng C Yang15266a92019-06-12 08:42:52 +0800143 interfacePath + "_" + pwmName.second);
Cheng C Yang916360b2019-05-07 18:47:16 +0800144 }
145}
146
147void createSensors(boost::asio::io_service& io,
148 sdbusplus::asio::object_server& objectServer,
149 std::shared_ptr<sdbusplus::asio::connection>& dbusConnection)
Cheng C Yang209ec562019-03-12 16:37:44 +0800150{
151
152 ManagedObjectType sensorConfigs;
Josh Lehan49cfba92019-10-08 16:50:42 -0700153 int numCreated = 0;
Cheng C Yang209ec562019-03-12 16:37:44 +0800154 bool useCache = false;
155
Cheng C Yang58b2b532019-05-31 00:19:45 +0800156 // TODO may need only modify the ones that need to be changed.
157 sensors.clear();
Cheng C Yang92498eb2019-09-26 21:59:25 +0800158 combineEvents.clear();
Cheng C Yang209ec562019-03-12 16:37:44 +0800159 for (const char* type : sensorTypes)
160 {
161 if (!getSensorConfiguration(type, dbusConnection, sensorConfigs,
162 useCache))
163 {
164 std::cerr << "error get sensor config from entity manager\n";
165 return;
166 }
167 useCache = true;
168 }
169
170 std::vector<fs::path> pmbusPaths;
171 if (!findFiles(fs::path("/sys/class/hwmon"), "name", pmbusPaths))
172 {
173 std::cerr << "No PSU sensors in system\n";
174 return;
175 }
176
177 boost::container::flat_set<std::string> directories;
178 for (const auto& pmbusPath : pmbusPaths)
179 {
Cheng C Yang58b2b532019-05-31 00:19:45 +0800180 boost::container::flat_map<std::string, std::vector<std::string>>
181 eventPathList;
182
183 std::ifstream nameFile(pmbusPath);
184 if (!nameFile.good())
185 {
Josh Lehan49cfba92019-10-08 16:50:42 -0700186 std::cerr << "Failure finding pmbus path " << pmbusPath << "\n";
Cheng C Yang58b2b532019-05-31 00:19:45 +0800187 continue;
188 }
189
190 std::string pmbusName;
191 std::getline(nameFile, pmbusName);
192 nameFile.close();
Vijay Khemka996bad12019-05-28 15:15:16 -0700193
194 if (std::find(pmbusNames.begin(), pmbusNames.end(), pmbusName) ==
195 pmbusNames.end())
Cheng C Yang58b2b532019-05-31 00:19:45 +0800196 {
Josh Lehan49cfba92019-10-08 16:50:42 -0700197 // To avoid this error message, add your driver name to
198 // the pmbusNames vector at the top of this file.
199 std::cerr << "Driver name " << pmbusName
200 << " not found in sensor whitelist\n";
Cheng C Yang58b2b532019-05-31 00:19:45 +0800201 continue;
202 }
203
204 const std::string* psuName;
Cheng C Yang209ec562019-03-12 16:37:44 +0800205 auto directory = pmbusPath.parent_path();
206
207 auto ret = directories.insert(directory.string());
208 if (!ret.second)
209 {
Josh Lehan49cfba92019-10-08 16:50:42 -0700210 std::cerr << "Duplicate path " << directory.string() << "\n";
Cheng C Yang58b2b532019-05-31 00:19:45 +0800211 continue; // check if path has already been searched
Cheng C Yang209ec562019-03-12 16:37:44 +0800212 }
213
James Feistb6c0b912019-07-09 12:21:44 -0700214 fs::path device = directory / "device";
Cheng C Yang209ec562019-03-12 16:37:44 +0800215 std::string deviceName = fs::canonical(device).stem();
216 auto findHyphen = deviceName.find("-");
217 if (findHyphen == std::string::npos)
218 {
219 std::cerr << "found bad device" << deviceName << "\n";
220 continue;
221 }
222 std::string busStr = deviceName.substr(0, findHyphen);
223 std::string addrStr = deviceName.substr(findHyphen + 1);
224
225 size_t bus = 0;
226 size_t addr = 0;
227
228 try
229 {
230 bus = std::stoi(busStr);
231 addr = std::stoi(addrStr, 0, 16);
232 }
James Feistb6c0b912019-07-09 12:21:44 -0700233 catch (std::invalid_argument&)
Cheng C Yang209ec562019-03-12 16:37:44 +0800234 {
Josh Lehan49cfba92019-10-08 16:50:42 -0700235 std::cerr << "Error parsing bus " << busStr << " addr " << addrStr
236 << "\n";
Cheng C Yang209ec562019-03-12 16:37:44 +0800237 continue;
238 }
239
Cheng C Yang209ec562019-03-12 16:37:44 +0800240 const std::pair<std::string, boost::container::flat_map<
241 std::string, BasicVariantType>>*
242 baseConfig = nullptr;
243 const SensorData* sensorData = nullptr;
244 const std::string* interfacePath = nullptr;
245 const char* sensorType = nullptr;
246
247 for (const std::pair<sdbusplus::message::object_path, SensorData>&
248 sensor : sensorConfigs)
249 {
250 sensorData = &(sensor.second);
251 for (const char* type : sensorTypes)
252 {
253 auto sensorBase = sensorData->find(type);
254 if (sensorBase != sensorData->end())
255 {
256 baseConfig = &(*sensorBase);
257 sensorType = type;
258 break;
259 }
260 }
261 if (baseConfig == nullptr)
262 {
263 std::cerr << "error finding base configuration for "
264 << deviceName << "\n";
265 continue;
266 }
267
268 auto configBus = baseConfig->second.find("Bus");
269 auto configAddress = baseConfig->second.find("Address");
270
271 if (configBus == baseConfig->second.end() ||
272 configAddress == baseConfig->second.end())
273 {
Cheng C Yang58b2b532019-05-31 00:19:45 +0800274 std::cerr << "error finding necessary entry in configuration\n";
Cheng C Yang209ec562019-03-12 16:37:44 +0800275 continue;
276 }
277
Cheng C Yang58b2b532019-05-31 00:19:45 +0800278 const uint64_t* confBus;
279 const uint64_t* confAddr;
280 if (!(confBus = std::get_if<uint64_t>(&(configBus->second))) ||
281 !(confAddr = std::get_if<uint64_t>(&(configAddress->second))))
282 {
283 std::cerr
Josh Lehan49cfba92019-10-08 16:50:42 -0700284 << "Cannot get bus or address, invalid configuration\n";
Cheng C Yang58b2b532019-05-31 00:19:45 +0800285 continue;
286 }
287
288 if ((*confBus != bus) || (*confAddr != addr))
Cheng C Yang209ec562019-03-12 16:37:44 +0800289 {
Josh Lehan49cfba92019-10-08 16:50:42 -0700290 std::cerr << "Configuration mismatch of bus or addr\n";
Cheng C Yang209ec562019-03-12 16:37:44 +0800291 continue;
292 }
293
294 interfacePath = &(sensor.first.str);
295 break;
296 }
297 if (interfacePath == nullptr)
298 {
Josh Lehan49cfba92019-10-08 16:50:42 -0700299 // To avoid this error message, add your export map entry,
300 // from Entity Manager, to sensorTypes at the top of this file.
Cheng C Yang209ec562019-03-12 16:37:44 +0800301 std::cerr << "failed to find match for " << deviceName << "\n";
302 continue;
303 }
304
Cheng C Yange50345b2019-04-02 17:26:15 +0800305 auto findPSUName = baseConfig->second.find("Name");
306 if (findPSUName == baseConfig->second.end())
Cheng C Yang209ec562019-03-12 16:37:44 +0800307 {
308 std::cerr << "could not determine configuration name for "
309 << deviceName << "\n";
310 continue;
311 }
312
Cheng C Yang58b2b532019-05-31 00:19:45 +0800313 if (!(psuName = std::get_if<std::string>(&(findPSUName->second))))
314 {
315 std::cerr << "Cannot find psu name, invalid configuration\n";
316 continue;
317 }
318 checkEvent(directory.string(), eventMatch, eventPathList);
319
Vijay Khemka996bad12019-05-28 15:15:16 -0700320 /* Check if there are more sensors in the same interface */
321 int i = 1;
322 std::vector<std::string> psuNames;
323 do
324 {
Josh Lehan49cfba92019-10-08 16:50:42 -0700325 // Individual string fields: Name, Name1, Name2, Name3, ...
Vijay Khemka996bad12019-05-28 15:15:16 -0700326 psuNames.push_back(std::get<std::string>(findPSUName->second));
327 findPSUName = baseConfig->second.find("Name" + std::to_string(i++));
328 } while (findPSUName != baseConfig->second.end());
329
Cheng C Yange50345b2019-04-02 17:26:15 +0800330 std::vector<fs::path> sensorPaths;
James Feistb6c0b912019-07-09 12:21:44 -0700331 if (!findFiles(directory, R"(\w\d+_input$)", sensorPaths, 0))
Cheng C Yang209ec562019-03-12 16:37:44 +0800332 {
Cheng C Yange50345b2019-04-02 17:26:15 +0800333 std::cerr << "No PSU non-label sensor in PSU\n";
Cheng C Yang209ec562019-03-12 16:37:44 +0800334 continue;
335 }
336
Vijay Khemka996bad12019-05-28 15:15:16 -0700337 /* Find array of labels to be exposed if it is defined in config */
338 std::vector<std::string> findLabels;
339 auto findLabelObj = baseConfig->second.find("Labels");
340 if (findLabelObj != baseConfig->second.end())
341 {
342 findLabels =
343 std::get<std::vector<std::string>>(findLabelObj->second);
344 }
345
Jason Ling5747fab2019-10-02 16:46:23 -0700346 std::regex sensorNameRegEx("([A-Za-z]+)[0-9]*_");
347 std::smatch matches;
348
Cheng C Yange50345b2019-04-02 17:26:15 +0800349 for (const auto& sensorPath : sensorPaths)
Cheng C Yang209ec562019-03-12 16:37:44 +0800350 {
Cheng C Yang209ec562019-03-12 16:37:44 +0800351
Cheng C Yange50345b2019-04-02 17:26:15 +0800352 std::string labelHead;
353 std::string sensorPathStr = sensorPath.string();
354 std::string sensorNameStr = sensorPath.filename();
Jason Ling5747fab2019-10-02 16:46:23 -0700355 std::string sensorNameSubStr{""};
356 if (std::regex_search(sensorNameStr, matches, sensorNameRegEx))
357 {
358 sensorNameSubStr = matches[1];
359 }
360 else
361 {
362 std::cerr << "Couldn't extract the alpha prefix from "
363 << sensorNameStr;
364 continue;
365 }
Cheng C Yange50345b2019-04-02 17:26:15 +0800366
Cheng C Yangecba9de2019-09-12 23:41:50 +0800367 auto labelPath =
368 boost::replace_all_copy(sensorPathStr, "input", "label");
369 std::ifstream labelFile(labelPath);
370 if (!labelFile.good())
Cheng C Yang209ec562019-03-12 16:37:44 +0800371 {
Cheng C Yangecba9de2019-09-12 23:41:50 +0800372 std::cerr << "Failure reading " << sensorPath << "\n";
Cheng C Yange50345b2019-04-02 17:26:15 +0800373 labelHead = sensorNameStr.substr(0, sensorNameStr.find("_"));
Cheng C Yang209ec562019-03-12 16:37:44 +0800374 }
375 else
376 {
Cheng C Yange50345b2019-04-02 17:26:15 +0800377 std::string label;
378 std::getline(labelFile, label);
379 labelFile.close();
Cheng C Yange50345b2019-04-02 17:26:15 +0800380 auto findSensor = sensors.find(label);
381 if (findSensor != sensors.end())
382 {
383 continue;
384 }
385
386 labelHead = label.substr(0, label.find(" "));
387 }
388
Josh Lehan49cfba92019-10-08 16:50:42 -0700389 if constexpr (DEBUG)
390 {
391 std::cerr << "Sensor label head " << labelHead << "\n";
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]);
Vijay Khemka996bad12019-05-28 15:15:16 -0700415 }
416 else
James Feist17ab6e02019-06-25 12:28:13 -0700417 {
Vijay Khemka996bad12019-05-28 15:15:16 -0700418 nameIndex = 0;
James Feist17ab6e02019-06-25 12:28:13 -0700419 }
Cheng C Yange50345b2019-04-02 17:26:15 +0800420
Jason Ling5747fab2019-10-02 16:46:23 -0700421 if (psuNames.size() <= nameIndex)
422 {
423 std::cerr << "Could not pair " << labelHead
424 << " with a Name field\n";
425 continue;
426 }
427
Cheng C Yange50345b2019-04-02 17:26:15 +0800428 auto findProperty = labelMatch.find(labelHead);
429 if (findProperty == labelMatch.end())
Cheng C Yang209ec562019-03-12 16:37:44 +0800430 {
Jason Ling5747fab2019-10-02 16:46:23 -0700431 std::cerr << "Could not find " << labelHead << "\n";
Cheng C Yang209ec562019-03-12 16:37:44 +0800432 continue;
433 }
434
Cheng C Yang58b2b532019-05-31 00:19:45 +0800435 checkEventLimits(sensorPathStr, limitEventMatch, eventPathList);
436
Cheng C Yange50345b2019-04-02 17:26:15 +0800437 unsigned int factor =
438 std::pow(10, findProperty->second.sensorScaleFactor);
Vijay Khemka996bad12019-05-28 15:15:16 -0700439
Vijay Khemkadbdcfe02019-07-25 12:56:17 -0700440 /* Change first char of substring to uppercase */
441 char firstChar = sensorNameSubStr[0] - 0x20;
442 std::string strScaleFactor =
443 firstChar + sensorNameSubStr.substr(1) + "ScaleFactor";
444
445 auto findScaleFactor = baseConfig->second.find(strScaleFactor);
Vijay Khemka53ca4442019-07-23 11:03:55 -0700446 if (findScaleFactor != baseConfig->second.end())
447 {
448 factor =
449 std::visit(VariantToIntVisitor(), findScaleFactor->second);
450 }
451
Josh Lehan49cfba92019-10-08 16:50:42 -0700452 if constexpr (DEBUG)
453 {
454 std::cerr << "Sensor scaling factor " << factor << " string "
455 << strScaleFactor << "\n";
456 }
457
Vijay Khemka996bad12019-05-28 15:15:16 -0700458 std::vector<thresholds::Threshold> sensorThresholds;
459
James Feist17ab6e02019-06-25 12:28:13 -0700460 if (!parseThresholdsFromConfig(*sensorData, sensorThresholds))
Cheng C Yange50345b2019-04-02 17:26:15 +0800461 {
James Feist17ab6e02019-06-25 12:28:13 -0700462 std::cerr << "error populating thresholds for "
463 << sensorNameSubStr << "\n";
Cheng C Yange50345b2019-04-02 17:26:15 +0800464 }
465
466 auto findSensorType = sensorTable.find(sensorNameSubStr);
467 if (findSensorType == sensorTable.end())
468 {
Jason Ling5747fab2019-10-02 16:46:23 -0700469 std::cerr << sensorNameSubStr
470 << " is not a recognize sensor file\n";
Cheng C Yange50345b2019-04-02 17:26:15 +0800471 continue;
472 }
473
474 std::string sensorName =
Vijay Khemka996bad12019-05-28 15:15:16 -0700475 psuNames[nameIndex] + " " + findProperty->second.labelTypeName;
Cheng C Yange50345b2019-04-02 17:26:15 +0800476
Josh Lehan49cfba92019-10-08 16:50:42 -0700477 ++numCreated;
478 if constexpr (DEBUG)
479 {
480 std::cerr << "Created " << numCreated
481 << " sensors so far: " << sensorName << "\n";
482 }
483
Cheng C Yang58b2b532019-05-31 00:19:45 +0800484 sensors[sensorName] = std::make_unique<PSUSensor>(
Cheng C Yange50345b2019-04-02 17:26:15 +0800485 sensorPathStr, sensorType, objectServer, dbusConnection, io,
Cheng C Yang209ec562019-03-12 16:37:44 +0800486 sensorName, std::move(sensorThresholds), *interfacePath,
Cheng C Yange50345b2019-04-02 17:26:15 +0800487 findSensorType->second, factor, findProperty->second.maxReading,
488 findProperty->second.minReading);
Cheng C Yang209ec562019-03-12 16:37:44 +0800489 }
Cheng C Yang58b2b532019-05-31 00:19:45 +0800490
491 // OperationalStatus event
Cheng C Yang92498eb2019-09-26 21:59:25 +0800492 combineEvents[*psuName + "OperationalStatus"] = nullptr;
Cheng C Yang58b2b532019-05-31 00:19:45 +0800493 combineEvents[*psuName + "OperationalStatus"] =
494 std::make_unique<PSUCombineEvent>(
495 objectServer, io, *psuName, eventPathList, "OperationalStatus");
Cheng C Yang209ec562019-03-12 16:37:44 +0800496 }
Josh Lehan49cfba92019-10-08 16:50:42 -0700497
498 if constexpr (DEBUG)
499 {
500 std::cerr << "Created total of " << numCreated << " sensors\n";
501 }
Cheng C Yang209ec562019-03-12 16:37:44 +0800502 return;
503}
504
Cheng C Yang916360b2019-05-07 18:47:16 +0800505void propertyInitialize(void)
Cheng C Yang209ec562019-03-12 16:37:44 +0800506{
Cheng C Yange50345b2019-04-02 17:26:15 +0800507 sensorTable = {{"power", "power/"},
508 {"curr", "current/"},
509 {"temp", "temperature/"},
510 {"in", "voltage/"},
511 {"fan", "fan_tach/"}};
512
513 labelMatch = {{"pin", PSUProperty("Input Power", 3000, 0, 6)},
514 {"pout1", PSUProperty("Output Power", 3000, 0, 6)},
Vijay Khemka996bad12019-05-28 15:15:16 -0700515 {"pout2", PSUProperty("Output Power", 3000, 0, 6)},
516 {"pout3", PSUProperty("Output Power", 3000, 0, 6)},
Vijay Khemkabe664412019-06-28 12:10:04 -0700517 {"power1", PSUProperty("Output Power", 3000, 0, 6)},
Cheng C Yangbdbde962019-04-26 22:50:34 +0800518 {"vin", PSUProperty("Input Voltage", 300, 0, 3)},
Vijay Khemka996bad12019-05-28 15:15:16 -0700519 {"vout1", PSUProperty("Output Voltage", 255, 0, 3)},
520 {"vout2", PSUProperty("Output Voltage", 255, 0, 3)},
521 {"vout3", PSUProperty("Output Voltage", 255, 0, 3)},
Jason Ling5747fab2019-10-02 16:46:23 -0700522 {"vout4", PSUProperty("Output Voltage", 255, 0, 3)},
523 {"vout5", PSUProperty("Output Voltage", 255, 0, 3)},
524 {"vout6", PSUProperty("Output Voltage", 255, 0, 3)},
525 {"vout7", PSUProperty("Output Voltage", 255, 0, 3)},
526 {"vout8", PSUProperty("Output Voltage", 255, 0, 3)},
527 {"vout9", PSUProperty("Output Voltage", 255, 0, 3)},
528 {"vout10", PSUProperty("Output Voltage", 255, 0, 3)},
529 {"vout11", PSUProperty("Output Voltage", 255, 0, 3)},
530 {"vout12", PSUProperty("Output Voltage", 255, 0, 3)},
531 {"vout13", PSUProperty("Output Voltage", 255, 0, 3)},
532 {"vout14", PSUProperty("Output Voltage", 255, 0, 3)},
533 {"vout15", PSUProperty("Output Voltage", 255, 0, 3)},
534 {"vout16", PSUProperty("Output Voltage", 255, 0, 3)},
Vijay Khemkabe664412019-06-28 12:10:04 -0700535 {"in1", PSUProperty("Output Voltage", 255, 0, 3)},
Cheng C Yange50345b2019-04-02 17:26:15 +0800536 {"iin", PSUProperty("Input Current", 20, 0, 3)},
537 {"iout1", PSUProperty("Output Current", 255, 0, 3)},
Vijay Khemka996bad12019-05-28 15:15:16 -0700538 {"iout2", PSUProperty("Output Current", 255, 0, 3)},
539 {"iout3", PSUProperty("Output Current", 255, 0, 3)},
Vijay Khemkabe664412019-06-28 12:10:04 -0700540 {"curr1", PSUProperty("Output Current", 255, 0, 3)},
Cheng C Yange50345b2019-04-02 17:26:15 +0800541 {"temp1", PSUProperty("Temperature", 127, -128, 3)},
Vijay Khemka996bad12019-05-28 15:15:16 -0700542 {"temp2", PSUProperty("Temperature", 127, -128, 3)},
543 {"temp3", PSUProperty("Temperature", 127, -128, 3)},
Jason Ling5747fab2019-10-02 16:46:23 -0700544 {"temp4", PSUProperty("Temperature", 127, -128, 3)},
545 {"temp5", PSUProperty("Temperature", 127, -128, 3)},
Cheng C Yang8dbb3952019-05-23 00:03:12 +0800546 {"fan1", PSUProperty("Fan Speed 1", 30000, 0, 0)},
547 {"fan2", PSUProperty("Fan Speed 2", 30000, 0, 0)}};
Cheng C Yang916360b2019-05-07 18:47:16 +0800548
549 pwmTable = {{"fan1", "Fan_1"}, {"fan2", "Fan_2"}};
Cheng C Yang58b2b532019-05-31 00:19:45 +0800550
551 limitEventMatch = {{"PredictiveFailure", {"max_alarm", "min_alarm"}},
552 {"Failure", {"crit_alarm", "lcrit_alarm"}}};
553
554 eventMatch = {
555 {"PredictiveFailure", {"power1_alarm"}},
556 {"Failure", {"in2_alarm"}},
Cheng C Yang9c45e6b2019-08-13 07:21:32 +0800557 {"ACLost", {"in1_beep"}},
558 {"FanFault", {"fan1_alarm", "fan2_alarm", "fan1_fault", "fan2_fault"}},
559 {"ConfigureError", {"in1_fault"}}};
Cheng C Yang209ec562019-03-12 16:37:44 +0800560}
561
James Feistb6c0b912019-07-09 12:21:44 -0700562int main()
Cheng C Yang209ec562019-03-12 16:37:44 +0800563{
564 boost::asio::io_service io;
565 auto systemBus = std::make_shared<sdbusplus::asio::connection>(io);
566
567 systemBus->request_name("xyz.openbmc_project.PSUSensor");
568 sdbusplus::asio::object_server objectServer(systemBus);
Cheng C Yang209ec562019-03-12 16:37:44 +0800569 std::vector<std::unique_ptr<sdbusplus::bus::match::match>> matches;
Cheng C Yang209ec562019-03-12 16:37:44 +0800570
Cheng C Yang916360b2019-05-07 18:47:16 +0800571 propertyInitialize();
Cheng C Yang209ec562019-03-12 16:37:44 +0800572
Cheng C Yang916360b2019-05-07 18:47:16 +0800573 io.post([&]() { createSensors(io, objectServer, systemBus); });
Cheng C Yang209ec562019-03-12 16:37:44 +0800574 boost::asio::deadline_timer filterTimer(io);
575 std::function<void(sdbusplus::message::message&)> eventHandler =
576 [&](sdbusplus::message::message& message) {
577 if (message.is_method_error())
578 {
579 std::cerr << "callback method error\n";
580 return;
581 }
582 filterTimer.expires_from_now(boost::posix_time::seconds(1));
583 filterTimer.async_wait([&](const boost::system::error_code& ec) {
584 if (ec == boost::asio::error::operation_aborted)
585 {
586 return;
587 }
588 else if (ec)
589 {
590 std::cerr << "timer error\n";
591 }
Cheng C Yang916360b2019-05-07 18:47:16 +0800592 createSensors(io, objectServer, systemBus);
Cheng C Yang209ec562019-03-12 16:37:44 +0800593 });
594 };
595
596 for (const char* type : sensorTypes)
597 {
598 auto match = std::make_unique<sdbusplus::bus::match::match>(
599 static_cast<sdbusplus::bus::bus&>(*systemBus),
600 "type='signal',member='PropertiesChanged',path_namespace='" +
601 std::string(inventoryPath) + "',arg0namespace='" + type + "'",
602 eventHandler);
603 matches.emplace_back(std::move(match));
604 }
605 io.run();
606}