blob: 7576e68165172680ad3a676df71a080b879f9266 [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
Ed Tanous8a57ec02020-10-09 12:46:52 -070017#include <PSUEvent.hpp>
18#include <PSUSensor.hpp>
19#include <Utils.hpp>
Cheng C Yang209ec562019-03-12 16:37:44 +080020#include <boost/algorithm/string/predicate.hpp>
21#include <boost/algorithm/string/replace.hpp>
Patrick Venture96e97db2019-10-31 13:44:38 -070022#include <boost/container/flat_map.hpp>
Cheng C Yang209ec562019-03-12 16:37:44 +080023#include <boost/container/flat_set.hpp>
James Feist38fb5982020-05-28 10:09:54 -070024#include <sdbusplus/asio/connection.hpp>
25#include <sdbusplus/asio/object_server.hpp>
26#include <sdbusplus/bus/match.hpp>
27
28#include <array>
Josh Lehan74d9bd92019-10-31 08:51:58 -070029#include <cmath>
James Feist24f02f22019-04-15 11:05:39 -070030#include <filesystem>
Cheng C Yang209ec562019-03-12 16:37:44 +080031#include <fstream>
Patrick Venture96e97db2019-10-31 13:44:38 -070032#include <functional>
Cheng C Yang58b2b532019-05-31 00:19:45 +080033#include <iostream>
Cheng C Yang209ec562019-03-12 16:37:44 +080034#include <regex>
Patrick Venture96e97db2019-10-31 13:44:38 -070035#include <string>
Lei YUa2c7cea2020-12-23 14:07:28 +080036#include <string_view>
Patrick Venture96e97db2019-10-31 13:44:38 -070037#include <utility>
38#include <variant>
39#include <vector>
Cheng C Yang209ec562019-03-12 16:37:44 +080040
Ed Tanous8a57ec02020-10-09 12:46:52 -070041static constexpr bool debug = false;
Josh Lehan49cfba92019-10-08 16:50:42 -070042
Lotus Xu33703af2021-09-08 13:56:29 +080043static constexpr std::array<const char*, 27> sensorTypes = {
Avenash Asai Thambif1ace502021-08-02 16:10:19 -050044 "xyz.openbmc_project.Configuration.ADM1266",
Josh Lehan62084c82020-06-22 15:27:12 -070045 "xyz.openbmc_project.Configuration.ADM1272",
Paul Fertser678f53b2021-04-06 07:06:28 +000046 "xyz.openbmc_project.Configuration.ADM1275",
Josh Lehan62084c82020-06-22 15:27:12 -070047 "xyz.openbmc_project.Configuration.ADM1278",
Jeff Lina0683a82021-02-22 13:56:55 +080048 "xyz.openbmc_project.Configuration.DPS800",
Josh Lehan62084c82020-06-22 15:27:12 -070049 "xyz.openbmc_project.Configuration.INA219",
Devjit Gopalpurde65ef72019-10-30 04:47:35 -070050 "xyz.openbmc_project.Configuration.INA230",
Lei YU8e0eccd2021-04-23 11:01:59 +080051 "xyz.openbmc_project.Configuration.IPSPS",
Alex Qiu6690d8f2020-01-22 17:56:33 -080052 "xyz.openbmc_project.Configuration.ISL68137",
Jason Lingdfad1ff2020-07-29 15:43:11 -070053 "xyz.openbmc_project.Configuration.ISL68220",
Gaurav Gandhi49585582020-12-22 01:01:24 +000054 "xyz.openbmc_project.Configuration.ISL68223",
55 "xyz.openbmc_project.Configuration.ISL69243",
Jeff Lina0683a82021-02-22 13:56:55 +080056 "xyz.openbmc_project.Configuration.ISL69260",
Zev Weisseb0b84d2021-04-22 15:03:38 -050057 "xyz.openbmc_project.Configuration.LM25066",
Alex Qiuf5709b42020-01-29 13:29:50 -080058 "xyz.openbmc_project.Configuration.MAX16601",
Gaurav Gandhi49585582020-12-22 01:01:24 +000059 "xyz.openbmc_project.Configuration.MAX20710",
Alex Qiu6690d8f2020-01-22 17:56:33 -080060 "xyz.openbmc_project.Configuration.MAX20730",
61 "xyz.openbmc_project.Configuration.MAX20734",
62 "xyz.openbmc_project.Configuration.MAX20796",
63 "xyz.openbmc_project.Configuration.MAX34451",
Josh Lehan62084c82020-06-22 15:27:12 -070064 "xyz.openbmc_project.Configuration.pmbus",
65 "xyz.openbmc_project.Configuration.PXE1610",
Jeff Lina0683a82021-02-22 13:56:55 +080066 "xyz.openbmc_project.Configuration.RAA228000",
67 "xyz.openbmc_project.Configuration.RAA228228",
68 "xyz.openbmc_project.Configuration.RAA229004",
Lotus Xu33703af2021-09-08 13:56:29 +080069 "xyz.openbmc_project.Configuration.TPS546D24",
70 "xyz.openbmc_project.Configuration.XDPE12284"};
Cheng C Yang209ec562019-03-12 16:37:44 +080071
Alex Qiu6690d8f2020-01-22 17:56:33 -080072static std::vector<std::string> pmbusNames = {
Lotus Xu33703af2021-09-08 13:56:29 +080073 "adm1266", "adm1272", "adm1275", "adm1278", "dps800", "ina219",
74 "ina230", "ipsps1", "isl68137", "isl68220", "isl68223", "isl69243",
75 "isl69260", "lm25066", "max16601", "max20710", "max20730", "max20734",
76 "max20796", "max34451", "pmbus", "pxe1610", "raa228000", "raa228228",
77 "raa229004", "tps546d24", "xdpe12284"};
Josh Lehan0830c7b2019-10-08 16:35:09 -070078
Cheng C Yang209ec562019-03-12 16:37:44 +080079namespace fs = std::filesystem;
80
Yong Libf8b1da2020-04-15 16:32:50 +080081static boost::container::flat_map<std::string, std::shared_ptr<PSUSensor>>
Cheng C Yang916360b2019-05-07 18:47:16 +080082 sensors;
Cheng C Yang58b2b532019-05-31 00:19:45 +080083static boost::container::flat_map<std::string, std::unique_ptr<PSUCombineEvent>>
84 combineEvents;
Cheng C Yang916360b2019-05-07 18:47:16 +080085static boost::container::flat_map<std::string, std::unique_ptr<PwmSensor>>
86 pwmSensors;
87static boost::container::flat_map<std::string, std::string> sensorTable;
88static boost::container::flat_map<std::string, PSUProperty> labelMatch;
89static boost::container::flat_map<std::string, std::string> pwmTable;
Cheng C Yang58b2b532019-05-31 00:19:45 +080090static boost::container::flat_map<std::string, std::vector<std::string>>
91 eventMatch;
Cheng C Yang202a1ff2020-01-09 09:34:22 +080092static boost::container::flat_map<
93 std::string,
94 boost::container::flat_map<std::string, std::vector<std::string>>>
95 groupEventMatch;
Cheng C Yang58b2b532019-05-31 00:19:45 +080096static boost::container::flat_map<std::string, std::vector<std::string>>
97 limitEventMatch;
98
Josh Lehan74d9bd92019-10-31 08:51:58 -070099static std::vector<PSUProperty> psuProperties;
100
Cheng C Yang58b2b532019-05-31 00:19:45 +0800101// Function CheckEvent will check each attribute from eventMatch table in the
102// sysfs. If the attributes exists in sysfs, then store the complete path
103// of the attribute into eventPathList.
104void checkEvent(
105 const std::string& directory,
106 const boost::container::flat_map<std::string, std::vector<std::string>>&
107 eventMatch,
108 boost::container::flat_map<std::string, std::vector<std::string>>&
109 eventPathList)
110{
111 for (const auto& match : eventMatch)
112 {
113 const std::vector<std::string>& eventAttrs = match.second;
114 const std::string& eventName = match.first;
115 for (const auto& eventAttr : eventAttrs)
116 {
Ed Tanous8a57ec02020-10-09 12:46:52 -0700117 std::string eventPath = directory;
118 eventPath += "/";
119 eventPath += eventAttr;
Cheng C Yang58b2b532019-05-31 00:19:45 +0800120
121 std::ifstream eventFile(eventPath);
122 if (!eventFile.good())
123 {
124 continue;
125 }
126
127 eventPathList[eventName].push_back(eventPath);
128 }
129 }
130}
131
Cheng C Yang202a1ff2020-01-09 09:34:22 +0800132// Check Group Events which contains more than one targets in each combine
133// events.
134void checkGroupEvent(
135 const std::string& directory,
136 const boost::container::flat_map<
137 std::string,
138 boost::container::flat_map<std::string, std::vector<std::string>>>&
139 groupEventMatch,
140 boost::container::flat_map<
141 std::string,
142 boost::container::flat_map<std::string, std::vector<std::string>>>&
143 groupEventPathList)
144{
145 for (const auto& match : groupEventMatch)
146 {
147 const std::string& groupEventName = match.first;
148 const boost::container::flat_map<std::string, std::vector<std::string>>
149 events = match.second;
150 boost::container::flat_map<std::string, std::vector<std::string>>
151 pathList;
152 for (const auto& match : events)
153 {
154 const std::string& eventName = match.first;
155 const std::vector<std::string>& eventAttrs = match.second;
156 for (const auto& eventAttr : eventAttrs)
157 {
Ed Tanous8a57ec02020-10-09 12:46:52 -0700158 std::string eventPath = directory;
159 eventPath += "/";
160 eventPath += eventAttr;
Cheng C Yang202a1ff2020-01-09 09:34:22 +0800161 std::ifstream eventFile(eventPath);
162 if (!eventFile.good())
163 {
164 continue;
165 }
166
167 pathList[eventName].push_back(eventPath);
168 }
169 }
170 groupEventPathList[groupEventName] = pathList;
171 }
172}
173
Cheng C Yang58b2b532019-05-31 00:19:45 +0800174// Function checkEventLimits will check all the psu related xxx_input attributes
175// in sysfs to see if xxx_crit_alarm xxx_lcrit_alarm xxx_max_alarm
176// xxx_min_alarm exist, then store the existing paths of the alarm attributes
177// to eventPathList.
178void checkEventLimits(
179 const std::string& sensorPathStr,
180 const boost::container::flat_map<std::string, std::vector<std::string>>&
181 limitEventMatch,
182 boost::container::flat_map<std::string, std::vector<std::string>>&
183 eventPathList)
184{
Lei YUa2c7cea2020-12-23 14:07:28 +0800185 auto attributePartPos = sensorPathStr.find_last_of('_');
186 if (attributePartPos == std::string::npos)
187 {
188 // There is no '_' in the string, skip it
189 return;
190 }
191 auto attributePart =
192 std::string_view(sensorPathStr).substr(attributePartPos + 1);
193 if (attributePart != "input")
194 {
195 // If the sensor is not xxx_input, skip it
196 return;
197 }
198
199 auto prefixPart = sensorPathStr.substr(0, attributePartPos + 1);
Cheng C Yang58b2b532019-05-31 00:19:45 +0800200 for (const auto& limitMatch : limitEventMatch)
201 {
202 const std::vector<std::string>& limitEventAttrs = limitMatch.second;
203 const std::string& eventName = limitMatch.first;
204 for (const auto& limitEventAttr : limitEventAttrs)
205 {
Lei YUa2c7cea2020-12-23 14:07:28 +0800206 auto limitEventPath = prefixPart + limitEventAttr;
Cheng C Yang58b2b532019-05-31 00:19:45 +0800207 std::ifstream eventFile(limitEventPath);
208 if (!eventFile.good())
209 {
210 continue;
211 }
212 eventPathList[eventName].push_back(limitEventPath);
213 }
214 }
215}
Cheng C Yang916360b2019-05-07 18:47:16 +0800216
AppaRao Pulid9d8caf2020-02-27 20:56:59 +0530217static void
218 checkPWMSensor(const fs::path& sensorPath, std::string& labelHead,
219 const std::string& interfacePath,
220 std::shared_ptr<sdbusplus::asio::connection>& dbusConnection,
221 sdbusplus::asio::object_server& objectServer,
222 const std::string& psuName)
Cheng C Yang916360b2019-05-07 18:47:16 +0800223{
224 for (const auto& pwmName : pwmTable)
225 {
226 if (pwmName.first != labelHead)
227 {
228 continue;
229 }
230
231 const std::string& sensorPathStr = sensorPath.string();
232 const std::string& pwmPathStr =
233 boost::replace_all_copy(sensorPathStr, "input", "target");
234 std::ifstream pwmFile(pwmPathStr);
235 if (!pwmFile.good())
236 {
237 continue;
238 }
239
240 auto findPWMSensor = pwmSensors.find(psuName + labelHead);
241 if (findPWMSensor != pwmSensors.end())
242 {
243 continue;
244 }
245
246 pwmSensors[psuName + labelHead] = std::make_unique<PwmSensor>(
AppaRao Pulid9d8caf2020-02-27 20:56:59 +0530247 "Pwm_" + psuName + "_" + pwmName.second, pwmPathStr, dbusConnection,
248 objectServer, interfacePath + "_" + pwmName.second, "PSU");
Cheng C Yang916360b2019-05-07 18:47:16 +0800249 }
250}
251
Zhikui Ren23c96e72020-11-05 22:32:28 -0800252static void createSensorsCallback(
253 boost::asio::io_service& io, sdbusplus::asio::object_server& objectServer,
254 std::shared_ptr<sdbusplus::asio::connection>& dbusConnection,
255 const ManagedObjectType& sensorConfigs,
256 const std::shared_ptr<boost::container::flat_set<std::string>>&
257 sensorsChanged)
Cheng C Yang209ec562019-03-12 16:37:44 +0800258{
Josh Lehan49cfba92019-10-08 16:50:42 -0700259 int numCreated = 0;
Zhikui Ren23c96e72020-11-05 22:32:28 -0800260 bool firstScan = sensorsChanged == nullptr;
Cheng C Yang209ec562019-03-12 16:37:44 +0800261
262 std::vector<fs::path> pmbusPaths;
263 if (!findFiles(fs::path("/sys/class/hwmon"), "name", pmbusPaths))
264 {
265 std::cerr << "No PSU sensors in system\n";
266 return;
267 }
268
269 boost::container::flat_set<std::string> directories;
270 for (const auto& pmbusPath : pmbusPaths)
271 {
Cheng C Yang58b2b532019-05-31 00:19:45 +0800272 boost::container::flat_map<std::string, std::vector<std::string>>
273 eventPathList;
Cheng C Yang202a1ff2020-01-09 09:34:22 +0800274 boost::container::flat_map<
275 std::string,
276 boost::container::flat_map<std::string, std::vector<std::string>>>
277 groupEventPathList;
Cheng C Yang58b2b532019-05-31 00:19:45 +0800278
279 std::ifstream nameFile(pmbusPath);
280 if (!nameFile.good())
281 {
Josh Lehan49cfba92019-10-08 16:50:42 -0700282 std::cerr << "Failure finding pmbus path " << pmbusPath << "\n";
Cheng C Yang58b2b532019-05-31 00:19:45 +0800283 continue;
284 }
285
286 std::string pmbusName;
287 std::getline(nameFile, pmbusName);
288 nameFile.close();
Vijay Khemka996bad12019-05-28 15:15:16 -0700289
290 if (std::find(pmbusNames.begin(), pmbusNames.end(), pmbusName) ==
291 pmbusNames.end())
Cheng C Yang58b2b532019-05-31 00:19:45 +0800292 {
Josh Lehan49cfba92019-10-08 16:50:42 -0700293 // To avoid this error message, add your driver name to
294 // the pmbusNames vector at the top of this file.
295 std::cerr << "Driver name " << pmbusName
296 << " not found in sensor whitelist\n";
Cheng C Yang58b2b532019-05-31 00:19:45 +0800297 continue;
298 }
299
300 const std::string* psuName;
Cheng C Yang209ec562019-03-12 16:37:44 +0800301 auto directory = pmbusPath.parent_path();
302
303 auto ret = directories.insert(directory.string());
304 if (!ret.second)
305 {
Josh Lehan49cfba92019-10-08 16:50:42 -0700306 std::cerr << "Duplicate path " << directory.string() << "\n";
Cheng C Yang58b2b532019-05-31 00:19:45 +0800307 continue; // check if path has already been searched
Cheng C Yang209ec562019-03-12 16:37:44 +0800308 }
309
James Feistb6c0b912019-07-09 12:21:44 -0700310 fs::path device = directory / "device";
Cheng C Yang209ec562019-03-12 16:37:44 +0800311 std::string deviceName = fs::canonical(device).stem();
Ed Tanous8a57ec02020-10-09 12:46:52 -0700312 auto findHyphen = deviceName.find('-');
Cheng C Yang209ec562019-03-12 16:37:44 +0800313 if (findHyphen == std::string::npos)
314 {
315 std::cerr << "found bad device" << deviceName << "\n";
316 continue;
317 }
318 std::string busStr = deviceName.substr(0, findHyphen);
319 std::string addrStr = deviceName.substr(findHyphen + 1);
320
321 size_t bus = 0;
322 size_t addr = 0;
323
324 try
325 {
326 bus = std::stoi(busStr);
Ed Tanous8a57ec02020-10-09 12:46:52 -0700327 addr = std::stoi(addrStr, nullptr, 16);
Cheng C Yang209ec562019-03-12 16:37:44 +0800328 }
Patrick Williams26601e82021-10-06 12:43:25 -0500329 catch (const std::invalid_argument&)
Cheng C Yang209ec562019-03-12 16:37:44 +0800330 {
Josh Lehan49cfba92019-10-08 16:50:42 -0700331 std::cerr << "Error parsing bus " << busStr << " addr " << addrStr
332 << "\n";
Cheng C Yang209ec562019-03-12 16:37:44 +0800333 continue;
334 }
335
Cheng C Yang209ec562019-03-12 16:37:44 +0800336 const std::pair<std::string, boost::container::flat_map<
337 std::string, BasicVariantType>>*
338 baseConfig = nullptr;
339 const SensorData* sensorData = nullptr;
340 const std::string* interfacePath = nullptr;
341 const char* sensorType = nullptr;
Cheng C Yang6b1247a2020-03-09 23:48:39 +0800342 size_t thresholdConfSize = 0;
Cheng C Yang209ec562019-03-12 16:37:44 +0800343
344 for (const std::pair<sdbusplus::message::object_path, SensorData>&
345 sensor : sensorConfigs)
346 {
347 sensorData = &(sensor.second);
348 for (const char* type : sensorTypes)
349 {
350 auto sensorBase = sensorData->find(type);
351 if (sensorBase != sensorData->end())
352 {
353 baseConfig = &(*sensorBase);
354 sensorType = type;
355 break;
356 }
357 }
358 if (baseConfig == nullptr)
359 {
360 std::cerr << "error finding base configuration for "
361 << deviceName << "\n";
362 continue;
363 }
364
365 auto configBus = baseConfig->second.find("Bus");
366 auto configAddress = baseConfig->second.find("Address");
367
368 if (configBus == baseConfig->second.end() ||
369 configAddress == baseConfig->second.end())
370 {
Cheng C Yang58b2b532019-05-31 00:19:45 +0800371 std::cerr << "error finding necessary entry in configuration\n";
Cheng C Yang209ec562019-03-12 16:37:44 +0800372 continue;
373 }
374
Cheng C Yang58b2b532019-05-31 00:19:45 +0800375 const uint64_t* confBus;
376 const uint64_t* confAddr;
377 if (!(confBus = std::get_if<uint64_t>(&(configBus->second))) ||
378 !(confAddr = std::get_if<uint64_t>(&(configAddress->second))))
379 {
380 std::cerr
Josh Lehan49cfba92019-10-08 16:50:42 -0700381 << "Cannot get bus or address, invalid configuration\n";
Cheng C Yang58b2b532019-05-31 00:19:45 +0800382 continue;
383 }
384
385 if ((*confBus != bus) || (*confAddr != addr))
Cheng C Yang209ec562019-03-12 16:37:44 +0800386 {
Josh Lehan432d1ed2019-10-16 12:23:31 -0700387 std::cerr << "Configuration skipping " << *confBus << "-"
388 << *confAddr << " because not " << bus << "-" << addr
389 << "\n";
Cheng C Yang209ec562019-03-12 16:37:44 +0800390 continue;
391 }
392
Cheng C Yang6b1247a2020-03-09 23:48:39 +0800393 std::vector<thresholds::Threshold> confThresholds;
394 if (!parseThresholdsFromConfig(*sensorData, confThresholds))
395 {
396 std::cerr << "error populating totoal thresholds\n";
397 }
398 thresholdConfSize = confThresholds.size();
399
Cheng C Yang209ec562019-03-12 16:37:44 +0800400 interfacePath = &(sensor.first.str);
401 break;
402 }
403 if (interfacePath == nullptr)
404 {
Josh Lehan49cfba92019-10-08 16:50:42 -0700405 // To avoid this error message, add your export map entry,
406 // from Entity Manager, to sensorTypes at the top of this file.
Cheng C Yang209ec562019-03-12 16:37:44 +0800407 std::cerr << "failed to find match for " << deviceName << "\n";
408 continue;
409 }
410
Cheng C Yange50345b2019-04-02 17:26:15 +0800411 auto findPSUName = baseConfig->second.find("Name");
412 if (findPSUName == baseConfig->second.end())
Cheng C Yang209ec562019-03-12 16:37:44 +0800413 {
414 std::cerr << "could not determine configuration name for "
415 << deviceName << "\n";
416 continue;
417 }
418
Cheng C Yang58b2b532019-05-31 00:19:45 +0800419 if (!(psuName = std::get_if<std::string>(&(findPSUName->second))))
420 {
421 std::cerr << "Cannot find psu name, invalid configuration\n";
422 continue;
423 }
Zhikui Ren23c96e72020-11-05 22:32:28 -0800424
425 // on rescans, only update sensors we were signaled by
426 if (!firstScan)
427 {
428 std::string psuNameStr = "/" + *psuName;
429 auto it =
430 std::find_if(sensorsChanged->begin(), sensorsChanged->end(),
431 [psuNameStr](std::string& s) {
432 return boost::ends_with(s, psuNameStr);
433 });
434
435 if (it == sensorsChanged->end())
436 {
437 continue;
438 }
439 sensorsChanged->erase(it);
440 }
Cheng C Yang58b2b532019-05-31 00:19:45 +0800441 checkEvent(directory.string(), eventMatch, eventPathList);
Cheng C Yang202a1ff2020-01-09 09:34:22 +0800442 checkGroupEvent(directory.string(), groupEventMatch,
443 groupEventPathList);
Cheng C Yang58b2b532019-05-31 00:19:45 +0800444
Konstantin Aladyshevc7a1ae62021-04-30 08:50:43 +0000445 PowerState readState = PowerState::always;
446 auto findPowerOn = baseConfig->second.find("PowerState");
447 if (findPowerOn != baseConfig->second.end())
448 {
449 std::string powerState =
450 std::visit(VariantToStringVisitor(), findPowerOn->second);
451 setReadState(powerState, readState);
452 }
453
Vijay Khemka996bad12019-05-28 15:15:16 -0700454 /* Check if there are more sensors in the same interface */
455 int i = 1;
456 std::vector<std::string> psuNames;
457 do
458 {
Josh Lehan49cfba92019-10-08 16:50:42 -0700459 // Individual string fields: Name, Name1, Name2, Name3, ...
Vijay Khemka996bad12019-05-28 15:15:16 -0700460 psuNames.push_back(std::get<std::string>(findPSUName->second));
461 findPSUName = baseConfig->second.find("Name" + std::to_string(i++));
462 } while (findPSUName != baseConfig->second.end());
463
Cheng C Yange50345b2019-04-02 17:26:15 +0800464 std::vector<fs::path> sensorPaths;
James Feistb6c0b912019-07-09 12:21:44 -0700465 if (!findFiles(directory, R"(\w\d+_input$)", sensorPaths, 0))
Cheng C Yang209ec562019-03-12 16:37:44 +0800466 {
Cheng C Yange50345b2019-04-02 17:26:15 +0800467 std::cerr << "No PSU non-label sensor in PSU\n";
Cheng C Yang209ec562019-03-12 16:37:44 +0800468 continue;
469 }
470
Manikandan Elumalaic7e95622020-06-03 20:22:01 +0530471 /* read max value in sysfs for in, curr, power, temp, ... */
472 if (!findFiles(directory, R"(\w\d+_max$)", sensorPaths, 0))
473 {
Ed Tanous8a57ec02020-10-09 12:46:52 -0700474 if constexpr (debug)
Manikandan Elumalaic7e95622020-06-03 20:22:01 +0530475 {
476 std::cerr << "No max name in PSU \n";
477 }
478 }
479
Lei YU7170a232021-02-04 16:19:27 +0800480 /* The poll rate for the sensors */
481 double pollRate = 0.0;
482 auto pollRateObj = baseConfig->second.find("PollRate");
483
484 if (pollRateObj != baseConfig->second.end())
485 {
486 pollRate =
487 std::visit(VariantToDoubleVisitor(), pollRateObj->second);
488 if (pollRate <= 0.0)
489 {
490 pollRate = PSUSensor::defaultSensorPoll;
491 }
492 }
493
Vijay Khemka996bad12019-05-28 15:15:16 -0700494 /* Find array of labels to be exposed if it is defined in config */
495 std::vector<std::string> findLabels;
496 auto findLabelObj = baseConfig->second.find("Labels");
497 if (findLabelObj != baseConfig->second.end())
498 {
499 findLabels =
500 std::get<std::vector<std::string>>(findLabelObj->second);
501 }
502
Jason Ling5747fab2019-10-02 16:46:23 -0700503 std::regex sensorNameRegEx("([A-Za-z]+)[0-9]*_");
504 std::smatch matches;
505
Cheng C Yange50345b2019-04-02 17:26:15 +0800506 for (const auto& sensorPath : sensorPaths)
Cheng C Yang209ec562019-03-12 16:37:44 +0800507 {
Manikandan Elumalaic7e95622020-06-03 20:22:01 +0530508 bool maxLabel = false;
Cheng C Yange50345b2019-04-02 17:26:15 +0800509 std::string labelHead;
510 std::string sensorPathStr = sensorPath.string();
511 std::string sensorNameStr = sensorPath.filename();
Jason Ling5747fab2019-10-02 16:46:23 -0700512 std::string sensorNameSubStr{""};
513 if (std::regex_search(sensorNameStr, matches, sensorNameRegEx))
514 {
Josh Lehan06494452019-10-31 09:49:16 -0700515 // hwmon *_input filename without number:
516 // in, curr, power, temp, ...
Jason Ling5747fab2019-10-02 16:46:23 -0700517 sensorNameSubStr = matches[1];
518 }
519 else
520 {
Josh Lehan06494452019-10-31 09:49:16 -0700521 std::cerr << "Could not extract the alpha prefix from "
Jason Ling5747fab2019-10-02 16:46:23 -0700522 << sensorNameStr;
523 continue;
524 }
Cheng C Yange50345b2019-04-02 17:26:15 +0800525
Manikandan Elumalaic7e95622020-06-03 20:22:01 +0530526 std::string labelPath;
527
528 /* find and differentiate _max and _input to replace "label" */
Ed Tanous8a57ec02020-10-09 12:46:52 -0700529 size_t pos = sensorPathStr.find('_');
Manikandan Elumalaic7e95622020-06-03 20:22:01 +0530530 if (pos != std::string::npos)
531 {
532
533 std::string sensorPathStrMax = sensorPathStr.substr(pos);
534 if (sensorPathStrMax.compare("_max") == 0)
535 {
536 labelPath =
537 boost::replace_all_copy(sensorPathStr, "max", "label");
538 maxLabel = true;
539 }
540 else
541 {
542 labelPath = boost::replace_all_copy(sensorPathStr, "input",
543 "label");
544 maxLabel = false;
545 }
546 }
547 else
548 {
549 continue;
550 }
551
Cheng C Yangecba9de2019-09-12 23:41:50 +0800552 std::ifstream labelFile(labelPath);
553 if (!labelFile.good())
Cheng C Yang209ec562019-03-12 16:37:44 +0800554 {
Ed Tanous8a57ec02020-10-09 12:46:52 -0700555 if constexpr (debug)
Cheng C Yang6b1247a2020-03-09 23:48:39 +0800556 {
557 std::cerr << "Input file " << sensorPath
558 << " has no corresponding label file\n";
559 }
Josh Lehan06494452019-10-31 09:49:16 -0700560 // hwmon *_input filename with number:
561 // temp1, temp2, temp3, ...
Ed Tanous8a57ec02020-10-09 12:46:52 -0700562 labelHead = sensorNameStr.substr(0, sensorNameStr.find('_'));
Cheng C Yang209ec562019-03-12 16:37:44 +0800563 }
564 else
565 {
Cheng C Yange50345b2019-04-02 17:26:15 +0800566 std::string label;
567 std::getline(labelFile, label);
568 labelFile.close();
Cheng C Yange50345b2019-04-02 17:26:15 +0800569 auto findSensor = sensors.find(label);
570 if (findSensor != sensors.end())
571 {
572 continue;
573 }
574
Josh Lehan06494452019-10-31 09:49:16 -0700575 // hwmon corresponding *_label file contents:
576 // vin1, vout1, ...
Ed Tanous8a57ec02020-10-09 12:46:52 -0700577 labelHead = label.substr(0, label.find(' '));
Cheng C Yange50345b2019-04-02 17:26:15 +0800578 }
579
Manikandan Elumalaic7e95622020-06-03 20:22:01 +0530580 /* append "max" for labelMatch */
581 if (maxLabel)
582 {
Ed Tanous8a57ec02020-10-09 12:46:52 -0700583 labelHead.insert(0, "max");
Manikandan Elumalaic7e95622020-06-03 20:22:01 +0530584 }
585
Ed Tanous8a57ec02020-10-09 12:46:52 -0700586 if constexpr (debug)
Josh Lehan74d9bd92019-10-31 08:51:58 -0700587 {
588 std::cerr << "Sensor type=\"" << sensorNameSubStr
589 << "\" label=\"" << labelHead << "\"\n";
590 }
591
AppaRao Pulid9d8caf2020-02-27 20:56:59 +0530592 checkPWMSensor(sensorPath, labelHead, *interfacePath,
593 dbusConnection, objectServer, psuNames[0]);
Cheng C Yang916360b2019-05-07 18:47:16 +0800594
Vijay Khemka996bad12019-05-28 15:15:16 -0700595 if (!findLabels.empty())
596 {
597 /* Check if this labelHead is enabled in config file */
598 if (std::find(findLabels.begin(), findLabels.end(),
599 labelHead) == findLabels.end())
600 {
Ed Tanous8a57ec02020-10-09 12:46:52 -0700601 if constexpr (debug)
Cheng C Yang6b1247a2020-03-09 23:48:39 +0800602 {
603 std::cerr << "could not find " << labelHead
604 << " in the Labels list\n";
605 }
Vijay Khemka996bad12019-05-28 15:15:16 -0700606 continue;
607 }
608 }
Cheng C Yange50345b2019-04-02 17:26:15 +0800609
Cheng C Yange50345b2019-04-02 17:26:15 +0800610 auto findProperty = labelMatch.find(labelHead);
611 if (findProperty == labelMatch.end())
Cheng C Yang209ec562019-03-12 16:37:44 +0800612 {
Ed Tanous8a57ec02020-10-09 12:46:52 -0700613 if constexpr (debug)
Josh Lehan74d9bd92019-10-31 08:51:58 -0700614 {
615 std::cerr << "Could not find matching default property for "
616 << labelHead << "\n";
617 }
Cheng C Yang209ec562019-03-12 16:37:44 +0800618 continue;
619 }
620
Josh Lehan74d9bd92019-10-31 08:51:58 -0700621 // Protect the hardcoded labelMatch list from changes,
622 // by making a copy and modifying that instead.
623 // Avoid bleedthrough of one device's customizations to
624 // the next device, as each should be independently customizable.
625 psuProperties.push_back(findProperty->second);
626 auto psuProperty = psuProperties.rbegin();
627
628 // Use label head as prefix for reading from config file,
629 // example if temp1: temp1_Name, temp1_Scale, temp1_Min, ...
630 std::string keyName = labelHead + "_Name";
631 std::string keyScale = labelHead + "_Scale";
632 std::string keyMin = labelHead + "_Min";
633 std::string keyMax = labelHead + "_Max";
Jeff Line41d52f2021-04-07 19:38:51 +0800634 std::string keyOffset = labelHead + "_Offset";
Josh Lehan74d9bd92019-10-31 08:51:58 -0700635
636 bool customizedName = false;
637 auto findCustomName = baseConfig->second.find(keyName);
638 if (findCustomName != baseConfig->second.end())
Josh Lehan432d1ed2019-10-16 12:23:31 -0700639 {
Josh Lehan74d9bd92019-10-31 08:51:58 -0700640 try
641 {
642 psuProperty->labelTypeName = std::visit(
643 VariantToStringVisitor(), findCustomName->second);
644 }
Patrick Williams26601e82021-10-06 12:43:25 -0500645 catch (const std::invalid_argument&)
Josh Lehan74d9bd92019-10-31 08:51:58 -0700646 {
647 std::cerr << "Unable to parse " << keyName << "\n";
648 continue;
649 }
650
651 // All strings are valid, including empty string
652 customizedName = true;
653 }
654
655 bool customizedScale = false;
656 auto findCustomScale = baseConfig->second.find(keyScale);
657 if (findCustomScale != baseConfig->second.end())
658 {
659 try
660 {
661 psuProperty->sensorScaleFactor = std::visit(
662 VariantToUnsignedIntVisitor(), findCustomScale->second);
663 }
Patrick Williams26601e82021-10-06 12:43:25 -0500664 catch (const std::invalid_argument&)
Josh Lehan74d9bd92019-10-31 08:51:58 -0700665 {
666 std::cerr << "Unable to parse " << keyScale << "\n";
667 continue;
668 }
669
670 // Avoid later division by zero
671 if (psuProperty->sensorScaleFactor > 0)
672 {
673 customizedScale = true;
674 }
675 else
676 {
677 std::cerr << "Unable to accept " << keyScale << "\n";
678 continue;
679 }
680 }
681
682 auto findCustomMin = baseConfig->second.find(keyMin);
683 if (findCustomMin != baseConfig->second.end())
684 {
685 try
686 {
687 psuProperty->minReading = std::visit(
688 VariantToDoubleVisitor(), findCustomMin->second);
689 }
Patrick Williams26601e82021-10-06 12:43:25 -0500690 catch (const std::invalid_argument&)
Josh Lehan74d9bd92019-10-31 08:51:58 -0700691 {
692 std::cerr << "Unable to parse " << keyMin << "\n";
693 continue;
694 }
695 }
696
697 auto findCustomMax = baseConfig->second.find(keyMax);
698 if (findCustomMax != baseConfig->second.end())
699 {
700 try
701 {
702 psuProperty->maxReading = std::visit(
703 VariantToDoubleVisitor(), findCustomMax->second);
704 }
Patrick Williams26601e82021-10-06 12:43:25 -0500705 catch (const std::invalid_argument&)
Josh Lehan74d9bd92019-10-31 08:51:58 -0700706 {
707 std::cerr << "Unable to parse " << keyMax << "\n";
708 continue;
709 }
710 }
711
Jeff Line41d52f2021-04-07 19:38:51 +0800712 auto findCustomOffset = baseConfig->second.find(keyOffset);
713 if (findCustomOffset != baseConfig->second.end())
714 {
715 try
716 {
717 psuProperty->sensorOffset = std::visit(
718 VariantToDoubleVisitor(), findCustomOffset->second);
719 }
Patrick Williams26601e82021-10-06 12:43:25 -0500720 catch (const std::invalid_argument&)
Jeff Line41d52f2021-04-07 19:38:51 +0800721 {
722 std::cerr << "Unable to parse " << keyOffset << "\n";
723 continue;
724 }
725 }
726
Josh Lehan74d9bd92019-10-31 08:51:58 -0700727 if (!(psuProperty->minReading < psuProperty->maxReading))
728 {
729 std::cerr << "Min must be less than Max\n";
730 continue;
731 }
732
733 // If the sensor name is being customized by config file,
734 // then prefix/suffix composition becomes not necessary,
735 // and in fact not wanted, because it gets in the way.
736 std::string psuNameFromIndex;
737 if (!customizedName)
738 {
739 /* Find out sensor name index for this label */
740 std::regex rgx("[A-Za-z]+([0-9]+)");
Brad Bishopfbb44ad2019-11-08 09:42:37 -0500741 size_t nameIndex{0};
Josh Lehan74d9bd92019-10-31 08:51:58 -0700742 if (std::regex_search(labelHead, matches, rgx))
743 {
744 nameIndex = std::stoi(matches[1]);
745
746 // Decrement to preserve alignment, because hwmon
747 // human-readable filenames and labels use 1-based
748 // numbering, but the "Name", "Name1", "Name2", etc. naming
749 // convention (the psuNames vector) uses 0-based numbering.
750 if (nameIndex > 0)
751 {
752 --nameIndex;
753 }
754 }
755 else
756 {
757 nameIndex = 0;
758 }
759
760 if (psuNames.size() <= nameIndex)
761 {
762 std::cerr << "Could not pair " << labelHead
763 << " with a Name field\n";
764 continue;
765 }
766
767 psuNameFromIndex = psuNames[nameIndex];
768
Ed Tanous8a57ec02020-10-09 12:46:52 -0700769 if constexpr (debug)
Josh Lehan74d9bd92019-10-31 08:51:58 -0700770 {
771 std::cerr << "Sensor label head " << labelHead
772 << " paired with " << psuNameFromIndex
773 << " at index " << nameIndex << "\n";
774 }
Josh Lehan432d1ed2019-10-16 12:23:31 -0700775 }
776
Cheng C Yang58b2b532019-05-31 00:19:45 +0800777 checkEventLimits(sensorPathStr, limitEventMatch, eventPathList);
778
Josh Lehan74d9bd92019-10-31 08:51:58 -0700779 // Similarly, if sensor scaling factor is being customized,
780 // then the below power-of-10 constraint becomes unnecessary,
781 // as config should be able to specify an arbitrary divisor.
782 unsigned int factor = psuProperty->sensorScaleFactor;
783 if (!customizedScale)
Vijay Khemka53ca4442019-07-23 11:03:55 -0700784 {
Josh Lehan74d9bd92019-10-31 08:51:58 -0700785 // Preserve existing usage of hardcoded labelMatch table below
786 factor = std::pow(10.0, factor);
Vijay Khemka53ca4442019-07-23 11:03:55 -0700787
Josh Lehan74d9bd92019-10-31 08:51:58 -0700788 /* Change first char of substring to uppercase */
Ed Tanous8a57ec02020-10-09 12:46:52 -0700789 char firstChar =
790 static_cast<char>(std::toupper(sensorNameSubStr[0]));
Josh Lehan74d9bd92019-10-31 08:51:58 -0700791 std::string strScaleFactor =
792 firstChar + sensorNameSubStr.substr(1) + "ScaleFactor";
793
794 // Preserve existing configs by accepting earlier syntax,
795 // example CurrScaleFactor, PowerScaleFactor, ...
796 auto findScaleFactor = baseConfig->second.find(strScaleFactor);
797 if (findScaleFactor != baseConfig->second.end())
798 {
799 factor = std::visit(VariantToIntVisitor(),
800 findScaleFactor->second);
801 }
802
Ed Tanous8a57ec02020-10-09 12:46:52 -0700803 if constexpr (debug)
Josh Lehan74d9bd92019-10-31 08:51:58 -0700804 {
805 std::cerr << "Sensor scaling factor " << factor
806 << " string " << strScaleFactor << "\n";
807 }
Josh Lehan49cfba92019-10-08 16:50:42 -0700808 }
809
Vijay Khemka996bad12019-05-28 15:15:16 -0700810 std::vector<thresholds::Threshold> sensorThresholds;
Joshi, Mansi14f0ad82019-11-21 10:52:30 +0530811 if (!parseThresholdsFromConfig(*sensorData, sensorThresholds,
812 &labelHead))
Cheng C Yange50345b2019-04-02 17:26:15 +0800813 {
James Feist17ab6e02019-06-25 12:28:13 -0700814 std::cerr << "error populating thresholds for "
815 << sensorNameSubStr << "\n";
Cheng C Yange50345b2019-04-02 17:26:15 +0800816 }
817
Zev Weiss6b6891c2021-04-22 02:46:21 -0500818 auto findSensorUnit = sensorTable.find(sensorNameSubStr);
819 if (findSensorUnit == sensorTable.end())
Cheng C Yange50345b2019-04-02 17:26:15 +0800820 {
Jason Ling5747fab2019-10-02 16:46:23 -0700821 std::cerr << sensorNameSubStr
Josh Lehan06494452019-10-31 09:49:16 -0700822 << " is not a recognized sensor type\n";
Cheng C Yange50345b2019-04-02 17:26:15 +0800823 continue;
824 }
825
Ed Tanous8a57ec02020-10-09 12:46:52 -0700826 if constexpr (debug)
Josh Lehan49cfba92019-10-08 16:50:42 -0700827 {
Josh Lehan74d9bd92019-10-31 08:51:58 -0700828 std::cerr << "Sensor properties: Name \""
829 << psuProperty->labelTypeName << "\" Scale "
830 << psuProperty->sensorScaleFactor << " Min "
831 << psuProperty->minReading << " Max "
Jeff Line41d52f2021-04-07 19:38:51 +0800832 << psuProperty->maxReading << " Offset "
833 << psuProperty->sensorOffset << "\n";
Josh Lehan74d9bd92019-10-31 08:51:58 -0700834 }
835
836 std::string sensorName = psuProperty->labelTypeName;
837 if (customizedName)
838 {
839 if (sensorName.empty())
840 {
841 // Allow selective disabling of an individual sensor,
842 // by customizing its name to an empty string.
843 std::cerr << "Sensor disabled, empty string\n";
844 continue;
845 }
846 }
847 else
848 {
849 // Sensor name not customized, do prefix/suffix composition,
850 // preserving default behavior by using psuNameFromIndex.
851 sensorName =
852 psuNameFromIndex + " " + psuProperty->labelTypeName;
853 }
854
Ed Tanous8a57ec02020-10-09 12:46:52 -0700855 if constexpr (debug)
Josh Lehan74d9bd92019-10-31 08:51:58 -0700856 {
857 std::cerr << "Sensor name \"" << sensorName << "\" path \""
858 << sensorPathStr << "\" type \"" << sensorType
859 << "\"\n";
Josh Lehan49cfba92019-10-08 16:50:42 -0700860 }
Zhikui Ren23c96e72020-11-05 22:32:28 -0800861 // destruct existing one first if already created
862 sensors[sensorName] = nullptr;
Yong Libf8b1da2020-04-15 16:32:50 +0800863 sensors[sensorName] = std::make_shared<PSUSensor>(
Cheng C Yange50345b2019-04-02 17:26:15 +0800864 sensorPathStr, sensorType, objectServer, dbusConnection, io,
Cheng C Yang209ec562019-03-12 16:37:44 +0800865 sensorName, std::move(sensorThresholds), *interfacePath,
Konstantin Aladyshevc7a1ae62021-04-30 08:50:43 +0000866 readState, findSensorUnit->second, factor,
867 psuProperty->maxReading, psuProperty->minReading,
868 psuProperty->sensorOffset, labelHead, thresholdConfSize,
869 pollRate);
Yong Libf8b1da2020-04-15 16:32:50 +0800870 sensors[sensorName]->setupRead();
Josh Lehan74d9bd92019-10-31 08:51:58 -0700871 ++numCreated;
Ed Tanous8a57ec02020-10-09 12:46:52 -0700872 if constexpr (debug)
Josh Lehan74d9bd92019-10-31 08:51:58 -0700873 {
874 std::cerr << "Created " << numCreated << " sensors so far\n";
875 }
Cheng C Yang209ec562019-03-12 16:37:44 +0800876 }
Cheng C Yang58b2b532019-05-31 00:19:45 +0800877
878 // OperationalStatus event
Cheng C Yang92498eb2019-09-26 21:59:25 +0800879 combineEvents[*psuName + "OperationalStatus"] = nullptr;
Cheng C Yang58b2b532019-05-31 00:19:45 +0800880 combineEvents[*psuName + "OperationalStatus"] =
Konstantin Aladyshevc7a1ae62021-04-30 08:50:43 +0000881 std::make_unique<PSUCombineEvent>(objectServer, dbusConnection, io,
882 *psuName, readState,
883 eventPathList, groupEventPathList,
884 "OperationalStatus", pollRate);
Cheng C Yang209ec562019-03-12 16:37:44 +0800885 }
Josh Lehan49cfba92019-10-08 16:50:42 -0700886
Ed Tanous8a57ec02020-10-09 12:46:52 -0700887 if constexpr (debug)
Josh Lehan49cfba92019-10-08 16:50:42 -0700888 {
889 std::cerr << "Created total of " << numCreated << " sensors\n";
890 }
Cheng C Yang209ec562019-03-12 16:37:44 +0800891 return;
892}
893
Zhikui Ren23c96e72020-11-05 22:32:28 -0800894void createSensors(
895 boost::asio::io_service& io, sdbusplus::asio::object_server& objectServer,
896 std::shared_ptr<sdbusplus::asio::connection>& dbusConnection,
897 const std::shared_ptr<boost::container::flat_set<std::string>>&
898 sensorsChanged)
899{
900 auto getter = std::make_shared<GetSensorConfiguration>(
901 dbusConnection, [&io, &objectServer, &dbusConnection, sensorsChanged](
902 const ManagedObjectType& sensorConfigs) {
903 createSensorsCallback(io, objectServer, dbusConnection,
904 sensorConfigs, sensorsChanged);
905 });
906 getter->getConfiguration(
907 std::vector<std::string>(sensorTypes.begin(), sensorTypes.end()));
908}
909
Cheng C Yang916360b2019-05-07 18:47:16 +0800910void propertyInitialize(void)
Cheng C Yang209ec562019-03-12 16:37:44 +0800911{
Zev Weiss6b6891c2021-04-22 02:46:21 -0500912 sensorTable = {{"power", sensor_paths::unitWatts},
913 {"curr", sensor_paths::unitAmperes},
914 {"temp", sensor_paths::unitDegreesC},
915 {"in", sensor_paths::unitVolts},
916 {"fan", sensor_paths::unitRPMs}};
Cheng C Yange50345b2019-04-02 17:26:15 +0800917
Jeff Line41d52f2021-04-07 19:38:51 +0800918 labelMatch = {
919 {"pin", PSUProperty("Input Power", 3000, 0, 6, 0)},
920 {"pout1", PSUProperty("Output Power", 3000, 0, 6, 0)},
921 {"pout2", PSUProperty("Output Power", 3000, 0, 6, 0)},
922 {"pout3", PSUProperty("Output Power", 3000, 0, 6, 0)},
923 {"power1", PSUProperty("Output Power", 3000, 0, 6, 0)},
924 {"maxpin", PSUProperty("Max Input Power", 3000, 0, 6, 0)},
925 {"vin", PSUProperty("Input Voltage", 300, 0, 3, 0)},
926 {"maxvin", PSUProperty("Max Input Voltage", 300, 0, 3, 0)},
927 {"vout1", PSUProperty("Output Voltage", 255, 0, 3, 0)},
928 {"vout2", PSUProperty("Output Voltage", 255, 0, 3, 0)},
929 {"vout3", PSUProperty("Output Voltage", 255, 0, 3, 0)},
930 {"vout4", PSUProperty("Output Voltage", 255, 0, 3, 0)},
931 {"vout5", PSUProperty("Output Voltage", 255, 0, 3, 0)},
932 {"vout6", PSUProperty("Output Voltage", 255, 0, 3, 0)},
933 {"vout7", PSUProperty("Output Voltage", 255, 0, 3, 0)},
934 {"vout8", PSUProperty("Output Voltage", 255, 0, 3, 0)},
935 {"vout9", PSUProperty("Output Voltage", 255, 0, 3, 0)},
936 {"vout10", PSUProperty("Output Voltage", 255, 0, 3, 0)},
937 {"vout11", PSUProperty("Output Voltage", 255, 0, 3, 0)},
938 {"vout12", PSUProperty("Output Voltage", 255, 0, 3, 0)},
939 {"vout13", PSUProperty("Output Voltage", 255, 0, 3, 0)},
940 {"vout14", PSUProperty("Output Voltage", 255, 0, 3, 0)},
941 {"vout15", PSUProperty("Output Voltage", 255, 0, 3, 0)},
942 {"vout16", PSUProperty("Output Voltage", 255, 0, 3, 0)},
943 {"vout17", PSUProperty("Output Voltage", 255, 0, 3, 0)},
944 {"vout18", PSUProperty("Output Voltage", 255, 0, 3, 0)},
945 {"vout19", PSUProperty("Output Voltage", 255, 0, 3, 0)},
946 {"vout20", PSUProperty("Output Voltage", 255, 0, 3, 0)},
947 {"vout21", PSUProperty("Output Voltage", 255, 0, 3, 0)},
948 {"vout22", PSUProperty("Output Voltage", 255, 0, 3, 0)},
949 {"vout23", PSUProperty("Output Voltage", 255, 0, 3, 0)},
950 {"vout24", PSUProperty("Output Voltage", 255, 0, 3, 0)},
951 {"vout25", PSUProperty("Output Voltage", 255, 0, 3, 0)},
952 {"vout26", PSUProperty("Output Voltage", 255, 0, 3, 0)},
953 {"vout27", PSUProperty("Output Voltage", 255, 0, 3, 0)},
954 {"vout28", PSUProperty("Output Voltage", 255, 0, 3, 0)},
955 {"vout29", PSUProperty("Output Voltage", 255, 0, 3, 0)},
956 {"vout30", PSUProperty("Output Voltage", 255, 0, 3, 0)},
957 {"vout31", PSUProperty("Output Voltage", 255, 0, 3, 0)},
958 {"vout32", PSUProperty("Output Voltage", 255, 0, 3, 0)},
959 {"vmon", PSUProperty("Auxiliary Input Voltage", 255, 0, 3, 0)},
960 {"in1", PSUProperty("Output Voltage", 255, 0, 3, 0)},
961 {"iin", PSUProperty("Input Current", 20, 0, 3, 0)},
962 {"iout1", PSUProperty("Output Current", 255, 0, 3, 0)},
963 {"iout2", PSUProperty("Output Current", 255, 0, 3, 0)},
964 {"iout3", PSUProperty("Output Current", 255, 0, 3, 0)},
965 {"iout4", PSUProperty("Output Current", 255, 0, 3, 0)},
966 {"iout5", PSUProperty("Output Current", 255, 0, 3, 0)},
967 {"iout6", PSUProperty("Output Current", 255, 0, 3, 0)},
968 {"iout7", PSUProperty("Output Current", 255, 0, 3, 0)},
969 {"iout8", PSUProperty("Output Current", 255, 0, 3, 0)},
970 {"iout9", PSUProperty("Output Current", 255, 0, 3, 0)},
971 {"iout10", PSUProperty("Output Current", 255, 0, 3, 0)},
972 {"iout11", PSUProperty("Output Current", 255, 0, 3, 0)},
973 {"iout12", PSUProperty("Output Current", 255, 0, 3, 0)},
974 {"iout13", PSUProperty("Output Current", 255, 0, 3, 0)},
975 {"iout14", PSUProperty("Output Current", 255, 0, 3, 0)},
976 {"curr1", PSUProperty("Output Current", 255, 0, 3, 0)},
977 {"maxiout1", PSUProperty("Max Output Current", 255, 0, 3, 0)},
978 {"temp1", PSUProperty("Temperature", 127, -128, 3, 0)},
979 {"temp2", PSUProperty("Temperature", 127, -128, 3, 0)},
980 {"temp3", PSUProperty("Temperature", 127, -128, 3, 0)},
981 {"temp4", PSUProperty("Temperature", 127, -128, 3, 0)},
982 {"temp5", PSUProperty("Temperature", 127, -128, 3, 0)},
983 {"temp6", PSUProperty("Temperature", 127, -128, 3, 0)},
984 {"maxtemp1", PSUProperty("Max Temperature", 127, -128, 3, 0)},
985 {"fan1", PSUProperty("Fan Speed 1", 30000, 0, 0, 0)},
986 {"fan2", PSUProperty("Fan Speed 2", 30000, 0, 0, 0)}};
Cheng C Yang916360b2019-05-07 18:47:16 +0800987
988 pwmTable = {{"fan1", "Fan_1"}, {"fan2", "Fan_2"}};
Cheng C Yang58b2b532019-05-31 00:19:45 +0800989
990 limitEventMatch = {{"PredictiveFailure", {"max_alarm", "min_alarm"}},
991 {"Failure", {"crit_alarm", "lcrit_alarm"}}};
992
Cheng C Yang202a1ff2020-01-09 09:34:22 +0800993 eventMatch = {{"PredictiveFailure", {"power1_alarm"}},
994 {"Failure", {"in2_alarm"}},
995 {"ACLost", {"in1_beep"}},
996 {"ConfigureError", {"in1_fault"}}};
997
998 groupEventMatch = {{"FanFault",
999 {{"fan1", {"fan1_alarm", "fan1_fault"}},
1000 {"fan2", {"fan2_alarm", "fan2_fault"}}}}};
Cheng C Yang209ec562019-03-12 16:37:44 +08001001}
1002
James Feistb6c0b912019-07-09 12:21:44 -07001003int main()
Cheng C Yang209ec562019-03-12 16:37:44 +08001004{
1005 boost::asio::io_service io;
1006 auto systemBus = std::make_shared<sdbusplus::asio::connection>(io);
1007
1008 systemBus->request_name("xyz.openbmc_project.PSUSensor");
1009 sdbusplus::asio::object_server objectServer(systemBus);
Cheng C Yang209ec562019-03-12 16:37:44 +08001010 std::vector<std::unique_ptr<sdbusplus::bus::match::match>> matches;
Zhikui Ren23c96e72020-11-05 22:32:28 -08001011 auto sensorsChanged =
1012 std::make_shared<boost::container::flat_set<std::string>>();
Cheng C Yang209ec562019-03-12 16:37:44 +08001013
Cheng C Yang916360b2019-05-07 18:47:16 +08001014 propertyInitialize();
Cheng C Yang209ec562019-03-12 16:37:44 +08001015
Zhikui Ren23c96e72020-11-05 22:32:28 -08001016 io.post([&]() { createSensors(io, objectServer, systemBus, nullptr); });
Cheng C Yang209ec562019-03-12 16:37:44 +08001017 boost::asio::deadline_timer filterTimer(io);
1018 std::function<void(sdbusplus::message::message&)> eventHandler =
1019 [&](sdbusplus::message::message& message) {
1020 if (message.is_method_error())
1021 {
1022 std::cerr << "callback method error\n";
1023 return;
1024 }
Zhikui Ren23c96e72020-11-05 22:32:28 -08001025 sensorsChanged->insert(message.get_path());
Cheng C Yanga97f1342020-02-11 15:10:41 +08001026 filterTimer.expires_from_now(boost::posix_time::seconds(3));
Cheng C Yang209ec562019-03-12 16:37:44 +08001027 filterTimer.async_wait([&](const boost::system::error_code& ec) {
1028 if (ec == boost::asio::error::operation_aborted)
1029 {
1030 return;
1031 }
Ed Tanous8a57ec02020-10-09 12:46:52 -07001032 if (ec)
Cheng C Yang209ec562019-03-12 16:37:44 +08001033 {
1034 std::cerr << "timer error\n";
1035 }
Zhikui Ren23c96e72020-11-05 22:32:28 -08001036 createSensors(io, objectServer, systemBus, sensorsChanged);
Cheng C Yang209ec562019-03-12 16:37:44 +08001037 });
1038 };
1039
1040 for (const char* type : sensorTypes)
1041 {
1042 auto match = std::make_unique<sdbusplus::bus::match::match>(
1043 static_cast<sdbusplus::bus::bus&>(*systemBus),
1044 "type='signal',member='PropertiesChanged',path_namespace='" +
1045 std::string(inventoryPath) + "',arg0namespace='" + type + "'",
1046 eventHandler);
1047 matches.emplace_back(std::move(match));
1048 }
Bruce Lee1263c3d2021-06-04 15:16:33 +08001049
1050 setupManufacturingModeMatch(*systemBus);
Cheng C Yang209ec562019-03-12 16:37:44 +08001051 io.run();
1052}