blob: 3b92ae7e29754a687c02a2cb12d03299f45a5558 [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
Avenash Asai Thambif1ace502021-08-02 16:10:19 -050043static constexpr std::array<const char*, 26> sensorTypes = {
44 "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",
69 "xyz.openbmc_project.Configuration.TPS546D24"};
Cheng C Yang209ec562019-03-12 16:37:44 +080070
Alex Qiu6690d8f2020-01-22 17:56:33 -080071static std::vector<std::string> pmbusNames = {
Avenash Asai Thambif1ace502021-08-02 16:10:19 -050072 "adm1266", "adm1272", "adm1275", "adm1278", "dps800", "ina219",
73 "ina230", "ipsps1", "isl68137", "isl68220", "isl68223", "isl69243",
74 "isl69260", "lm25066", "max16601", "max20710", "max20730", "max20734",
75 "max20796", "max34451", "pmbus", "pxe1610", "raa228000", "raa228228",
76 "raa229004", "tps546d24"};
Josh Lehan0830c7b2019-10-08 16:35:09 -070077
Cheng C Yang209ec562019-03-12 16:37:44 +080078namespace fs = std::filesystem;
79
Yong Libf8b1da2020-04-15 16:32:50 +080080static boost::container::flat_map<std::string, std::shared_ptr<PSUSensor>>
Cheng C Yang916360b2019-05-07 18:47:16 +080081 sensors;
Cheng C Yang58b2b532019-05-31 00:19:45 +080082static boost::container::flat_map<std::string, std::unique_ptr<PSUCombineEvent>>
83 combineEvents;
Cheng C Yang916360b2019-05-07 18:47:16 +080084static boost::container::flat_map<std::string, std::unique_ptr<PwmSensor>>
85 pwmSensors;
86static boost::container::flat_map<std::string, std::string> sensorTable;
87static boost::container::flat_map<std::string, PSUProperty> labelMatch;
88static boost::container::flat_map<std::string, std::string> pwmTable;
Cheng C Yang58b2b532019-05-31 00:19:45 +080089static boost::container::flat_map<std::string, std::vector<std::string>>
90 eventMatch;
Cheng C Yang202a1ff2020-01-09 09:34:22 +080091static boost::container::flat_map<
92 std::string,
93 boost::container::flat_map<std::string, std::vector<std::string>>>
94 groupEventMatch;
Cheng C Yang58b2b532019-05-31 00:19:45 +080095static boost::container::flat_map<std::string, std::vector<std::string>>
96 limitEventMatch;
97
Josh Lehan74d9bd92019-10-31 08:51:58 -070098static std::vector<PSUProperty> psuProperties;
99
Cheng C Yang58b2b532019-05-31 00:19:45 +0800100// Function CheckEvent will check each attribute from eventMatch table in the
101// sysfs. If the attributes exists in sysfs, then store the complete path
102// of the attribute into eventPathList.
103void checkEvent(
104 const std::string& directory,
105 const boost::container::flat_map<std::string, std::vector<std::string>>&
106 eventMatch,
107 boost::container::flat_map<std::string, std::vector<std::string>>&
108 eventPathList)
109{
110 for (const auto& match : eventMatch)
111 {
112 const std::vector<std::string>& eventAttrs = match.second;
113 const std::string& eventName = match.first;
114 for (const auto& eventAttr : eventAttrs)
115 {
Ed Tanous8a57ec02020-10-09 12:46:52 -0700116 std::string eventPath = directory;
117 eventPath += "/";
118 eventPath += eventAttr;
Cheng C Yang58b2b532019-05-31 00:19:45 +0800119
120 std::ifstream eventFile(eventPath);
121 if (!eventFile.good())
122 {
123 continue;
124 }
125
126 eventPathList[eventName].push_back(eventPath);
127 }
128 }
129}
130
Cheng C Yang202a1ff2020-01-09 09:34:22 +0800131// Check Group Events which contains more than one targets in each combine
132// events.
133void checkGroupEvent(
134 const std::string& directory,
135 const boost::container::flat_map<
136 std::string,
137 boost::container::flat_map<std::string, std::vector<std::string>>>&
138 groupEventMatch,
139 boost::container::flat_map<
140 std::string,
141 boost::container::flat_map<std::string, std::vector<std::string>>>&
142 groupEventPathList)
143{
144 for (const auto& match : groupEventMatch)
145 {
146 const std::string& groupEventName = match.first;
147 const boost::container::flat_map<std::string, std::vector<std::string>>
148 events = match.second;
149 boost::container::flat_map<std::string, std::vector<std::string>>
150 pathList;
151 for (const auto& match : events)
152 {
153 const std::string& eventName = match.first;
154 const std::vector<std::string>& eventAttrs = match.second;
155 for (const auto& eventAttr : eventAttrs)
156 {
Ed Tanous8a57ec02020-10-09 12:46:52 -0700157 std::string eventPath = directory;
158 eventPath += "/";
159 eventPath += eventAttr;
Cheng C Yang202a1ff2020-01-09 09:34:22 +0800160 std::ifstream eventFile(eventPath);
161 if (!eventFile.good())
162 {
163 continue;
164 }
165
166 pathList[eventName].push_back(eventPath);
167 }
168 }
169 groupEventPathList[groupEventName] = pathList;
170 }
171}
172
Cheng C Yang58b2b532019-05-31 00:19:45 +0800173// Function checkEventLimits will check all the psu related xxx_input attributes
174// in sysfs to see if xxx_crit_alarm xxx_lcrit_alarm xxx_max_alarm
175// xxx_min_alarm exist, then store the existing paths of the alarm attributes
176// to eventPathList.
177void checkEventLimits(
178 const std::string& sensorPathStr,
179 const boost::container::flat_map<std::string, std::vector<std::string>>&
180 limitEventMatch,
181 boost::container::flat_map<std::string, std::vector<std::string>>&
182 eventPathList)
183{
Lei YUa2c7cea2020-12-23 14:07:28 +0800184 auto attributePartPos = sensorPathStr.find_last_of('_');
185 if (attributePartPos == std::string::npos)
186 {
187 // There is no '_' in the string, skip it
188 return;
189 }
190 auto attributePart =
191 std::string_view(sensorPathStr).substr(attributePartPos + 1);
192 if (attributePart != "input")
193 {
194 // If the sensor is not xxx_input, skip it
195 return;
196 }
197
198 auto prefixPart = sensorPathStr.substr(0, attributePartPos + 1);
Cheng C Yang58b2b532019-05-31 00:19:45 +0800199 for (const auto& limitMatch : limitEventMatch)
200 {
201 const std::vector<std::string>& limitEventAttrs = limitMatch.second;
202 const std::string& eventName = limitMatch.first;
203 for (const auto& limitEventAttr : limitEventAttrs)
204 {
Lei YUa2c7cea2020-12-23 14:07:28 +0800205 auto limitEventPath = prefixPart + limitEventAttr;
Cheng C Yang58b2b532019-05-31 00:19:45 +0800206 std::ifstream eventFile(limitEventPath);
207 if (!eventFile.good())
208 {
209 continue;
210 }
211 eventPathList[eventName].push_back(limitEventPath);
212 }
213 }
214}
Cheng C Yang916360b2019-05-07 18:47:16 +0800215
AppaRao Pulid9d8caf2020-02-27 20:56:59 +0530216static void
217 checkPWMSensor(const fs::path& sensorPath, std::string& labelHead,
218 const std::string& interfacePath,
219 std::shared_ptr<sdbusplus::asio::connection>& dbusConnection,
220 sdbusplus::asio::object_server& objectServer,
221 const std::string& psuName)
Cheng C Yang916360b2019-05-07 18:47:16 +0800222{
223 for (const auto& pwmName : pwmTable)
224 {
225 if (pwmName.first != labelHead)
226 {
227 continue;
228 }
229
230 const std::string& sensorPathStr = sensorPath.string();
231 const std::string& pwmPathStr =
232 boost::replace_all_copy(sensorPathStr, "input", "target");
233 std::ifstream pwmFile(pwmPathStr);
234 if (!pwmFile.good())
235 {
236 continue;
237 }
238
239 auto findPWMSensor = pwmSensors.find(psuName + labelHead);
240 if (findPWMSensor != pwmSensors.end())
241 {
242 continue;
243 }
244
245 pwmSensors[psuName + labelHead] = std::make_unique<PwmSensor>(
AppaRao Pulid9d8caf2020-02-27 20:56:59 +0530246 "Pwm_" + psuName + "_" + pwmName.second, pwmPathStr, dbusConnection,
247 objectServer, interfacePath + "_" + pwmName.second, "PSU");
Cheng C Yang916360b2019-05-07 18:47:16 +0800248 }
249}
250
Zhikui Ren23c96e72020-11-05 22:32:28 -0800251static void createSensorsCallback(
252 boost::asio::io_service& io, sdbusplus::asio::object_server& objectServer,
253 std::shared_ptr<sdbusplus::asio::connection>& dbusConnection,
254 const ManagedObjectType& sensorConfigs,
255 const std::shared_ptr<boost::container::flat_set<std::string>>&
256 sensorsChanged)
Cheng C Yang209ec562019-03-12 16:37:44 +0800257{
Josh Lehan49cfba92019-10-08 16:50:42 -0700258 int numCreated = 0;
Zhikui Ren23c96e72020-11-05 22:32:28 -0800259 bool firstScan = sensorsChanged == nullptr;
Cheng C Yang209ec562019-03-12 16:37:44 +0800260
261 std::vector<fs::path> pmbusPaths;
262 if (!findFiles(fs::path("/sys/class/hwmon"), "name", pmbusPaths))
263 {
264 std::cerr << "No PSU sensors in system\n";
265 return;
266 }
267
268 boost::container::flat_set<std::string> directories;
269 for (const auto& pmbusPath : pmbusPaths)
270 {
Cheng C Yang58b2b532019-05-31 00:19:45 +0800271 boost::container::flat_map<std::string, std::vector<std::string>>
272 eventPathList;
Cheng C Yang202a1ff2020-01-09 09:34:22 +0800273 boost::container::flat_map<
274 std::string,
275 boost::container::flat_map<std::string, std::vector<std::string>>>
276 groupEventPathList;
Cheng C Yang58b2b532019-05-31 00:19:45 +0800277
278 std::ifstream nameFile(pmbusPath);
279 if (!nameFile.good())
280 {
Josh Lehan49cfba92019-10-08 16:50:42 -0700281 std::cerr << "Failure finding pmbus path " << pmbusPath << "\n";
Cheng C Yang58b2b532019-05-31 00:19:45 +0800282 continue;
283 }
284
285 std::string pmbusName;
286 std::getline(nameFile, pmbusName);
287 nameFile.close();
Vijay Khemka996bad12019-05-28 15:15:16 -0700288
289 if (std::find(pmbusNames.begin(), pmbusNames.end(), pmbusName) ==
290 pmbusNames.end())
Cheng C Yang58b2b532019-05-31 00:19:45 +0800291 {
Josh Lehan49cfba92019-10-08 16:50:42 -0700292 // To avoid this error message, add your driver name to
293 // the pmbusNames vector at the top of this file.
294 std::cerr << "Driver name " << pmbusName
295 << " not found in sensor whitelist\n";
Cheng C Yang58b2b532019-05-31 00:19:45 +0800296 continue;
297 }
298
299 const std::string* psuName;
Cheng C Yang209ec562019-03-12 16:37:44 +0800300 auto directory = pmbusPath.parent_path();
301
302 auto ret = directories.insert(directory.string());
303 if (!ret.second)
304 {
Josh Lehan49cfba92019-10-08 16:50:42 -0700305 std::cerr << "Duplicate path " << directory.string() << "\n";
Cheng C Yang58b2b532019-05-31 00:19:45 +0800306 continue; // check if path has already been searched
Cheng C Yang209ec562019-03-12 16:37:44 +0800307 }
308
James Feistb6c0b912019-07-09 12:21:44 -0700309 fs::path device = directory / "device";
Cheng C Yang209ec562019-03-12 16:37:44 +0800310 std::string deviceName = fs::canonical(device).stem();
Ed Tanous8a57ec02020-10-09 12:46:52 -0700311 auto findHyphen = deviceName.find('-');
Cheng C Yang209ec562019-03-12 16:37:44 +0800312 if (findHyphen == std::string::npos)
313 {
314 std::cerr << "found bad device" << deviceName << "\n";
315 continue;
316 }
317 std::string busStr = deviceName.substr(0, findHyphen);
318 std::string addrStr = deviceName.substr(findHyphen + 1);
319
320 size_t bus = 0;
321 size_t addr = 0;
322
323 try
324 {
325 bus = std::stoi(busStr);
Ed Tanous8a57ec02020-10-09 12:46:52 -0700326 addr = std::stoi(addrStr, nullptr, 16);
Cheng C Yang209ec562019-03-12 16:37:44 +0800327 }
James Feistb6c0b912019-07-09 12:21:44 -0700328 catch (std::invalid_argument&)
Cheng C Yang209ec562019-03-12 16:37:44 +0800329 {
Josh Lehan49cfba92019-10-08 16:50:42 -0700330 std::cerr << "Error parsing bus " << busStr << " addr " << addrStr
331 << "\n";
Cheng C Yang209ec562019-03-12 16:37:44 +0800332 continue;
333 }
334
Cheng C Yang209ec562019-03-12 16:37:44 +0800335 const std::pair<std::string, boost::container::flat_map<
336 std::string, BasicVariantType>>*
337 baseConfig = nullptr;
338 const SensorData* sensorData = nullptr;
339 const std::string* interfacePath = nullptr;
340 const char* sensorType = nullptr;
Cheng C Yang6b1247a2020-03-09 23:48:39 +0800341 size_t thresholdConfSize = 0;
Cheng C Yang209ec562019-03-12 16:37:44 +0800342
343 for (const std::pair<sdbusplus::message::object_path, SensorData>&
344 sensor : sensorConfigs)
345 {
346 sensorData = &(sensor.second);
347 for (const char* type : sensorTypes)
348 {
349 auto sensorBase = sensorData->find(type);
350 if (sensorBase != sensorData->end())
351 {
352 baseConfig = &(*sensorBase);
353 sensorType = type;
354 break;
355 }
356 }
357 if (baseConfig == nullptr)
358 {
359 std::cerr << "error finding base configuration for "
360 << deviceName << "\n";
361 continue;
362 }
363
364 auto configBus = baseConfig->second.find("Bus");
365 auto configAddress = baseConfig->second.find("Address");
366
367 if (configBus == baseConfig->second.end() ||
368 configAddress == baseConfig->second.end())
369 {
Cheng C Yang58b2b532019-05-31 00:19:45 +0800370 std::cerr << "error finding necessary entry in configuration\n";
Cheng C Yang209ec562019-03-12 16:37:44 +0800371 continue;
372 }
373
Cheng C Yang58b2b532019-05-31 00:19:45 +0800374 const uint64_t* confBus;
375 const uint64_t* confAddr;
376 if (!(confBus = std::get_if<uint64_t>(&(configBus->second))) ||
377 !(confAddr = std::get_if<uint64_t>(&(configAddress->second))))
378 {
379 std::cerr
Josh Lehan49cfba92019-10-08 16:50:42 -0700380 << "Cannot get bus or address, invalid configuration\n";
Cheng C Yang58b2b532019-05-31 00:19:45 +0800381 continue;
382 }
383
384 if ((*confBus != bus) || (*confAddr != addr))
Cheng C Yang209ec562019-03-12 16:37:44 +0800385 {
Josh Lehan432d1ed2019-10-16 12:23:31 -0700386 std::cerr << "Configuration skipping " << *confBus << "-"
387 << *confAddr << " because not " << bus << "-" << addr
388 << "\n";
Cheng C Yang209ec562019-03-12 16:37:44 +0800389 continue;
390 }
391
Cheng C Yang6b1247a2020-03-09 23:48:39 +0800392 std::vector<thresholds::Threshold> confThresholds;
393 if (!parseThresholdsFromConfig(*sensorData, confThresholds))
394 {
395 std::cerr << "error populating totoal thresholds\n";
396 }
397 thresholdConfSize = confThresholds.size();
398
Cheng C Yang209ec562019-03-12 16:37:44 +0800399 interfacePath = &(sensor.first.str);
400 break;
401 }
402 if (interfacePath == nullptr)
403 {
Josh Lehan49cfba92019-10-08 16:50:42 -0700404 // To avoid this error message, add your export map entry,
405 // from Entity Manager, to sensorTypes at the top of this file.
Cheng C Yang209ec562019-03-12 16:37:44 +0800406 std::cerr << "failed to find match for " << deviceName << "\n";
407 continue;
408 }
409
Cheng C Yange50345b2019-04-02 17:26:15 +0800410 auto findPSUName = baseConfig->second.find("Name");
411 if (findPSUName == baseConfig->second.end())
Cheng C Yang209ec562019-03-12 16:37:44 +0800412 {
413 std::cerr << "could not determine configuration name for "
414 << deviceName << "\n";
415 continue;
416 }
417
Cheng C Yang58b2b532019-05-31 00:19:45 +0800418 if (!(psuName = std::get_if<std::string>(&(findPSUName->second))))
419 {
420 std::cerr << "Cannot find psu name, invalid configuration\n";
421 continue;
422 }
Zhikui Ren23c96e72020-11-05 22:32:28 -0800423
424 // on rescans, only update sensors we were signaled by
425 if (!firstScan)
426 {
427 std::string psuNameStr = "/" + *psuName;
428 auto it =
429 std::find_if(sensorsChanged->begin(), sensorsChanged->end(),
430 [psuNameStr](std::string& s) {
431 return boost::ends_with(s, psuNameStr);
432 });
433
434 if (it == sensorsChanged->end())
435 {
436 continue;
437 }
438 sensorsChanged->erase(it);
439 }
Cheng C Yang58b2b532019-05-31 00:19:45 +0800440 checkEvent(directory.string(), eventMatch, eventPathList);
Cheng C Yang202a1ff2020-01-09 09:34:22 +0800441 checkGroupEvent(directory.string(), groupEventMatch,
442 groupEventPathList);
Cheng C Yang58b2b532019-05-31 00:19:45 +0800443
Konstantin Aladyshevc7a1ae62021-04-30 08:50:43 +0000444 PowerState readState = PowerState::always;
445 auto findPowerOn = baseConfig->second.find("PowerState");
446 if (findPowerOn != baseConfig->second.end())
447 {
448 std::string powerState =
449 std::visit(VariantToStringVisitor(), findPowerOn->second);
450 setReadState(powerState, readState);
451 }
452
Vijay Khemka996bad12019-05-28 15:15:16 -0700453 /* Check if there are more sensors in the same interface */
454 int i = 1;
455 std::vector<std::string> psuNames;
456 do
457 {
Josh Lehan49cfba92019-10-08 16:50:42 -0700458 // Individual string fields: Name, Name1, Name2, Name3, ...
Vijay Khemka996bad12019-05-28 15:15:16 -0700459 psuNames.push_back(std::get<std::string>(findPSUName->second));
460 findPSUName = baseConfig->second.find("Name" + std::to_string(i++));
461 } while (findPSUName != baseConfig->second.end());
462
Cheng C Yange50345b2019-04-02 17:26:15 +0800463 std::vector<fs::path> sensorPaths;
James Feistb6c0b912019-07-09 12:21:44 -0700464 if (!findFiles(directory, R"(\w\d+_input$)", sensorPaths, 0))
Cheng C Yang209ec562019-03-12 16:37:44 +0800465 {
Cheng C Yange50345b2019-04-02 17:26:15 +0800466 std::cerr << "No PSU non-label sensor in PSU\n";
Cheng C Yang209ec562019-03-12 16:37:44 +0800467 continue;
468 }
469
Manikandan Elumalaic7e95622020-06-03 20:22:01 +0530470 /* read max value in sysfs for in, curr, power, temp, ... */
471 if (!findFiles(directory, R"(\w\d+_max$)", sensorPaths, 0))
472 {
Ed Tanous8a57ec02020-10-09 12:46:52 -0700473 if constexpr (debug)
Manikandan Elumalaic7e95622020-06-03 20:22:01 +0530474 {
475 std::cerr << "No max name in PSU \n";
476 }
477 }
478
Lei YU7170a232021-02-04 16:19:27 +0800479 /* The poll rate for the sensors */
480 double pollRate = 0.0;
481 auto pollRateObj = baseConfig->second.find("PollRate");
482
483 if (pollRateObj != baseConfig->second.end())
484 {
485 pollRate =
486 std::visit(VariantToDoubleVisitor(), pollRateObj->second);
487 if (pollRate <= 0.0)
488 {
489 pollRate = PSUSensor::defaultSensorPoll;
490 }
491 }
492
Vijay Khemka996bad12019-05-28 15:15:16 -0700493 /* Find array of labels to be exposed if it is defined in config */
494 std::vector<std::string> findLabels;
495 auto findLabelObj = baseConfig->second.find("Labels");
496 if (findLabelObj != baseConfig->second.end())
497 {
498 findLabels =
499 std::get<std::vector<std::string>>(findLabelObj->second);
500 }
501
Jason Ling5747fab2019-10-02 16:46:23 -0700502 std::regex sensorNameRegEx("([A-Za-z]+)[0-9]*_");
503 std::smatch matches;
504
Cheng C Yange50345b2019-04-02 17:26:15 +0800505 for (const auto& sensorPath : sensorPaths)
Cheng C Yang209ec562019-03-12 16:37:44 +0800506 {
Manikandan Elumalaic7e95622020-06-03 20:22:01 +0530507 bool maxLabel = false;
Cheng C Yange50345b2019-04-02 17:26:15 +0800508 std::string labelHead;
509 std::string sensorPathStr = sensorPath.string();
510 std::string sensorNameStr = sensorPath.filename();
Jason Ling5747fab2019-10-02 16:46:23 -0700511 std::string sensorNameSubStr{""};
512 if (std::regex_search(sensorNameStr, matches, sensorNameRegEx))
513 {
Josh Lehan06494452019-10-31 09:49:16 -0700514 // hwmon *_input filename without number:
515 // in, curr, power, temp, ...
Jason Ling5747fab2019-10-02 16:46:23 -0700516 sensorNameSubStr = matches[1];
517 }
518 else
519 {
Josh Lehan06494452019-10-31 09:49:16 -0700520 std::cerr << "Could not extract the alpha prefix from "
Jason Ling5747fab2019-10-02 16:46:23 -0700521 << sensorNameStr;
522 continue;
523 }
Cheng C Yange50345b2019-04-02 17:26:15 +0800524
Manikandan Elumalaic7e95622020-06-03 20:22:01 +0530525 std::string labelPath;
526
527 /* find and differentiate _max and _input to replace "label" */
Ed Tanous8a57ec02020-10-09 12:46:52 -0700528 size_t pos = sensorPathStr.find('_');
Manikandan Elumalaic7e95622020-06-03 20:22:01 +0530529 if (pos != std::string::npos)
530 {
531
532 std::string sensorPathStrMax = sensorPathStr.substr(pos);
533 if (sensorPathStrMax.compare("_max") == 0)
534 {
535 labelPath =
536 boost::replace_all_copy(sensorPathStr, "max", "label");
537 maxLabel = true;
538 }
539 else
540 {
541 labelPath = boost::replace_all_copy(sensorPathStr, "input",
542 "label");
543 maxLabel = false;
544 }
545 }
546 else
547 {
548 continue;
549 }
550
Cheng C Yangecba9de2019-09-12 23:41:50 +0800551 std::ifstream labelFile(labelPath);
552 if (!labelFile.good())
Cheng C Yang209ec562019-03-12 16:37:44 +0800553 {
Ed Tanous8a57ec02020-10-09 12:46:52 -0700554 if constexpr (debug)
Cheng C Yang6b1247a2020-03-09 23:48:39 +0800555 {
556 std::cerr << "Input file " << sensorPath
557 << " has no corresponding label file\n";
558 }
Josh Lehan06494452019-10-31 09:49:16 -0700559 // hwmon *_input filename with number:
560 // temp1, temp2, temp3, ...
Ed Tanous8a57ec02020-10-09 12:46:52 -0700561 labelHead = sensorNameStr.substr(0, sensorNameStr.find('_'));
Cheng C Yang209ec562019-03-12 16:37:44 +0800562 }
563 else
564 {
Cheng C Yange50345b2019-04-02 17:26:15 +0800565 std::string label;
566 std::getline(labelFile, label);
567 labelFile.close();
Cheng C Yange50345b2019-04-02 17:26:15 +0800568 auto findSensor = sensors.find(label);
569 if (findSensor != sensors.end())
570 {
571 continue;
572 }
573
Josh Lehan06494452019-10-31 09:49:16 -0700574 // hwmon corresponding *_label file contents:
575 // vin1, vout1, ...
Ed Tanous8a57ec02020-10-09 12:46:52 -0700576 labelHead = label.substr(0, label.find(' '));
Cheng C Yange50345b2019-04-02 17:26:15 +0800577 }
578
Manikandan Elumalaic7e95622020-06-03 20:22:01 +0530579 /* append "max" for labelMatch */
580 if (maxLabel)
581 {
Ed Tanous8a57ec02020-10-09 12:46:52 -0700582 labelHead.insert(0, "max");
Manikandan Elumalaic7e95622020-06-03 20:22:01 +0530583 }
584
Ed Tanous8a57ec02020-10-09 12:46:52 -0700585 if constexpr (debug)
Josh Lehan74d9bd92019-10-31 08:51:58 -0700586 {
587 std::cerr << "Sensor type=\"" << sensorNameSubStr
588 << "\" label=\"" << labelHead << "\"\n";
589 }
590
AppaRao Pulid9d8caf2020-02-27 20:56:59 +0530591 checkPWMSensor(sensorPath, labelHead, *interfacePath,
592 dbusConnection, objectServer, psuNames[0]);
Cheng C Yang916360b2019-05-07 18:47:16 +0800593
Vijay Khemka996bad12019-05-28 15:15:16 -0700594 if (!findLabels.empty())
595 {
596 /* Check if this labelHead is enabled in config file */
597 if (std::find(findLabels.begin(), findLabels.end(),
598 labelHead) == findLabels.end())
599 {
Ed Tanous8a57ec02020-10-09 12:46:52 -0700600 if constexpr (debug)
Cheng C Yang6b1247a2020-03-09 23:48:39 +0800601 {
602 std::cerr << "could not find " << labelHead
603 << " in the Labels list\n";
604 }
Vijay Khemka996bad12019-05-28 15:15:16 -0700605 continue;
606 }
607 }
Cheng C Yange50345b2019-04-02 17:26:15 +0800608
Cheng C Yange50345b2019-04-02 17:26:15 +0800609 auto findProperty = labelMatch.find(labelHead);
610 if (findProperty == labelMatch.end())
Cheng C Yang209ec562019-03-12 16:37:44 +0800611 {
Ed Tanous8a57ec02020-10-09 12:46:52 -0700612 if constexpr (debug)
Josh Lehan74d9bd92019-10-31 08:51:58 -0700613 {
614 std::cerr << "Could not find matching default property for "
615 << labelHead << "\n";
616 }
Cheng C Yang209ec562019-03-12 16:37:44 +0800617 continue;
618 }
619
Josh Lehan74d9bd92019-10-31 08:51:58 -0700620 // Protect the hardcoded labelMatch list from changes,
621 // by making a copy and modifying that instead.
622 // Avoid bleedthrough of one device's customizations to
623 // the next device, as each should be independently customizable.
624 psuProperties.push_back(findProperty->second);
625 auto psuProperty = psuProperties.rbegin();
626
627 // Use label head as prefix for reading from config file,
628 // example if temp1: temp1_Name, temp1_Scale, temp1_Min, ...
629 std::string keyName = labelHead + "_Name";
630 std::string keyScale = labelHead + "_Scale";
631 std::string keyMin = labelHead + "_Min";
632 std::string keyMax = labelHead + "_Max";
Jeff Line41d52f2021-04-07 19:38:51 +0800633 std::string keyOffset = labelHead + "_Offset";
Josh Lehan74d9bd92019-10-31 08:51:58 -0700634
635 bool customizedName = false;
636 auto findCustomName = baseConfig->second.find(keyName);
637 if (findCustomName != baseConfig->second.end())
Josh Lehan432d1ed2019-10-16 12:23:31 -0700638 {
Josh Lehan74d9bd92019-10-31 08:51:58 -0700639 try
640 {
641 psuProperty->labelTypeName = std::visit(
642 VariantToStringVisitor(), findCustomName->second);
643 }
644 catch (std::invalid_argument&)
645 {
646 std::cerr << "Unable to parse " << keyName << "\n";
647 continue;
648 }
649
650 // All strings are valid, including empty string
651 customizedName = true;
652 }
653
654 bool customizedScale = false;
655 auto findCustomScale = baseConfig->second.find(keyScale);
656 if (findCustomScale != baseConfig->second.end())
657 {
658 try
659 {
660 psuProperty->sensorScaleFactor = std::visit(
661 VariantToUnsignedIntVisitor(), findCustomScale->second);
662 }
663 catch (std::invalid_argument&)
664 {
665 std::cerr << "Unable to parse " << keyScale << "\n";
666 continue;
667 }
668
669 // Avoid later division by zero
670 if (psuProperty->sensorScaleFactor > 0)
671 {
672 customizedScale = true;
673 }
674 else
675 {
676 std::cerr << "Unable to accept " << keyScale << "\n";
677 continue;
678 }
679 }
680
681 auto findCustomMin = baseConfig->second.find(keyMin);
682 if (findCustomMin != baseConfig->second.end())
683 {
684 try
685 {
686 psuProperty->minReading = std::visit(
687 VariantToDoubleVisitor(), findCustomMin->second);
688 }
689 catch (std::invalid_argument&)
690 {
691 std::cerr << "Unable to parse " << keyMin << "\n";
692 continue;
693 }
694 }
695
696 auto findCustomMax = baseConfig->second.find(keyMax);
697 if (findCustomMax != baseConfig->second.end())
698 {
699 try
700 {
701 psuProperty->maxReading = std::visit(
702 VariantToDoubleVisitor(), findCustomMax->second);
703 }
704 catch (std::invalid_argument&)
705 {
706 std::cerr << "Unable to parse " << keyMax << "\n";
707 continue;
708 }
709 }
710
Jeff Line41d52f2021-04-07 19:38:51 +0800711 auto findCustomOffset = baseConfig->second.find(keyOffset);
712 if (findCustomOffset != baseConfig->second.end())
713 {
714 try
715 {
716 psuProperty->sensorOffset = std::visit(
717 VariantToDoubleVisitor(), findCustomOffset->second);
718 }
719 catch (std::invalid_argument&)
720 {
721 std::cerr << "Unable to parse " << keyOffset << "\n";
722 continue;
723 }
724 }
725
Josh Lehan74d9bd92019-10-31 08:51:58 -0700726 if (!(psuProperty->minReading < psuProperty->maxReading))
727 {
728 std::cerr << "Min must be less than Max\n";
729 continue;
730 }
731
732 // If the sensor name is being customized by config file,
733 // then prefix/suffix composition becomes not necessary,
734 // and in fact not wanted, because it gets in the way.
735 std::string psuNameFromIndex;
736 if (!customizedName)
737 {
738 /* Find out sensor name index for this label */
739 std::regex rgx("[A-Za-z]+([0-9]+)");
Brad Bishopfbb44ad2019-11-08 09:42:37 -0500740 size_t nameIndex{0};
Josh Lehan74d9bd92019-10-31 08:51:58 -0700741 if (std::regex_search(labelHead, matches, rgx))
742 {
743 nameIndex = std::stoi(matches[1]);
744
745 // Decrement to preserve alignment, because hwmon
746 // human-readable filenames and labels use 1-based
747 // numbering, but the "Name", "Name1", "Name2", etc. naming
748 // convention (the psuNames vector) uses 0-based numbering.
749 if (nameIndex > 0)
750 {
751 --nameIndex;
752 }
753 }
754 else
755 {
756 nameIndex = 0;
757 }
758
759 if (psuNames.size() <= nameIndex)
760 {
761 std::cerr << "Could not pair " << labelHead
762 << " with a Name field\n";
763 continue;
764 }
765
766 psuNameFromIndex = psuNames[nameIndex];
767
Ed Tanous8a57ec02020-10-09 12:46:52 -0700768 if constexpr (debug)
Josh Lehan74d9bd92019-10-31 08:51:58 -0700769 {
770 std::cerr << "Sensor label head " << labelHead
771 << " paired with " << psuNameFromIndex
772 << " at index " << nameIndex << "\n";
773 }
Josh Lehan432d1ed2019-10-16 12:23:31 -0700774 }
775
Cheng C Yang58b2b532019-05-31 00:19:45 +0800776 checkEventLimits(sensorPathStr, limitEventMatch, eventPathList);
777
Josh Lehan74d9bd92019-10-31 08:51:58 -0700778 // Similarly, if sensor scaling factor is being customized,
779 // then the below power-of-10 constraint becomes unnecessary,
780 // as config should be able to specify an arbitrary divisor.
781 unsigned int factor = psuProperty->sensorScaleFactor;
782 if (!customizedScale)
Vijay Khemka53ca4442019-07-23 11:03:55 -0700783 {
Josh Lehan74d9bd92019-10-31 08:51:58 -0700784 // Preserve existing usage of hardcoded labelMatch table below
785 factor = std::pow(10.0, factor);
Vijay Khemka53ca4442019-07-23 11:03:55 -0700786
Josh Lehan74d9bd92019-10-31 08:51:58 -0700787 /* Change first char of substring to uppercase */
Ed Tanous8a57ec02020-10-09 12:46:52 -0700788 char firstChar =
789 static_cast<char>(std::toupper(sensorNameSubStr[0]));
Josh Lehan74d9bd92019-10-31 08:51:58 -0700790 std::string strScaleFactor =
791 firstChar + sensorNameSubStr.substr(1) + "ScaleFactor";
792
793 // Preserve existing configs by accepting earlier syntax,
794 // example CurrScaleFactor, PowerScaleFactor, ...
795 auto findScaleFactor = baseConfig->second.find(strScaleFactor);
796 if (findScaleFactor != baseConfig->second.end())
797 {
798 factor = std::visit(VariantToIntVisitor(),
799 findScaleFactor->second);
800 }
801
Ed Tanous8a57ec02020-10-09 12:46:52 -0700802 if constexpr (debug)
Josh Lehan74d9bd92019-10-31 08:51:58 -0700803 {
804 std::cerr << "Sensor scaling factor " << factor
805 << " string " << strScaleFactor << "\n";
806 }
Josh Lehan49cfba92019-10-08 16:50:42 -0700807 }
808
Vijay Khemka996bad12019-05-28 15:15:16 -0700809 std::vector<thresholds::Threshold> sensorThresholds;
Joshi, Mansi14f0ad82019-11-21 10:52:30 +0530810 if (!parseThresholdsFromConfig(*sensorData, sensorThresholds,
811 &labelHead))
Cheng C Yange50345b2019-04-02 17:26:15 +0800812 {
James Feist17ab6e02019-06-25 12:28:13 -0700813 std::cerr << "error populating thresholds for "
814 << sensorNameSubStr << "\n";
Cheng C Yange50345b2019-04-02 17:26:15 +0800815 }
816
Zev Weiss6b6891c2021-04-22 02:46:21 -0500817 auto findSensorUnit = sensorTable.find(sensorNameSubStr);
818 if (findSensorUnit == sensorTable.end())
Cheng C Yange50345b2019-04-02 17:26:15 +0800819 {
Jason Ling5747fab2019-10-02 16:46:23 -0700820 std::cerr << sensorNameSubStr
Josh Lehan06494452019-10-31 09:49:16 -0700821 << " is not a recognized sensor type\n";
Cheng C Yange50345b2019-04-02 17:26:15 +0800822 continue;
823 }
824
Ed Tanous8a57ec02020-10-09 12:46:52 -0700825 if constexpr (debug)
Josh Lehan49cfba92019-10-08 16:50:42 -0700826 {
Josh Lehan74d9bd92019-10-31 08:51:58 -0700827 std::cerr << "Sensor properties: Name \""
828 << psuProperty->labelTypeName << "\" Scale "
829 << psuProperty->sensorScaleFactor << " Min "
830 << psuProperty->minReading << " Max "
Jeff Line41d52f2021-04-07 19:38:51 +0800831 << psuProperty->maxReading << " Offset "
832 << psuProperty->sensorOffset << "\n";
Josh Lehan74d9bd92019-10-31 08:51:58 -0700833 }
834
835 std::string sensorName = psuProperty->labelTypeName;
836 if (customizedName)
837 {
838 if (sensorName.empty())
839 {
840 // Allow selective disabling of an individual sensor,
841 // by customizing its name to an empty string.
842 std::cerr << "Sensor disabled, empty string\n";
843 continue;
844 }
845 }
846 else
847 {
848 // Sensor name not customized, do prefix/suffix composition,
849 // preserving default behavior by using psuNameFromIndex.
850 sensorName =
851 psuNameFromIndex + " " + psuProperty->labelTypeName;
852 }
853
Ed Tanous8a57ec02020-10-09 12:46:52 -0700854 if constexpr (debug)
Josh Lehan74d9bd92019-10-31 08:51:58 -0700855 {
856 std::cerr << "Sensor name \"" << sensorName << "\" path \""
857 << sensorPathStr << "\" type \"" << sensorType
858 << "\"\n";
Josh Lehan49cfba92019-10-08 16:50:42 -0700859 }
Zhikui Ren23c96e72020-11-05 22:32:28 -0800860 // destruct existing one first if already created
861 sensors[sensorName] = nullptr;
Yong Libf8b1da2020-04-15 16:32:50 +0800862 sensors[sensorName] = std::make_shared<PSUSensor>(
Cheng C Yange50345b2019-04-02 17:26:15 +0800863 sensorPathStr, sensorType, objectServer, dbusConnection, io,
Cheng C Yang209ec562019-03-12 16:37:44 +0800864 sensorName, std::move(sensorThresholds), *interfacePath,
Konstantin Aladyshevc7a1ae62021-04-30 08:50:43 +0000865 readState, findSensorUnit->second, factor,
866 psuProperty->maxReading, psuProperty->minReading,
867 psuProperty->sensorOffset, labelHead, thresholdConfSize,
868 pollRate);
Yong Libf8b1da2020-04-15 16:32:50 +0800869 sensors[sensorName]->setupRead();
Josh Lehan74d9bd92019-10-31 08:51:58 -0700870 ++numCreated;
Ed Tanous8a57ec02020-10-09 12:46:52 -0700871 if constexpr (debug)
Josh Lehan74d9bd92019-10-31 08:51:58 -0700872 {
873 std::cerr << "Created " << numCreated << " sensors so far\n";
874 }
Cheng C Yang209ec562019-03-12 16:37:44 +0800875 }
Cheng C Yang58b2b532019-05-31 00:19:45 +0800876
877 // OperationalStatus event
Cheng C Yang92498eb2019-09-26 21:59:25 +0800878 combineEvents[*psuName + "OperationalStatus"] = nullptr;
Cheng C Yang58b2b532019-05-31 00:19:45 +0800879 combineEvents[*psuName + "OperationalStatus"] =
Konstantin Aladyshevc7a1ae62021-04-30 08:50:43 +0000880 std::make_unique<PSUCombineEvent>(objectServer, dbusConnection, io,
881 *psuName, readState,
882 eventPathList, groupEventPathList,
883 "OperationalStatus", pollRate);
Cheng C Yang209ec562019-03-12 16:37:44 +0800884 }
Josh Lehan49cfba92019-10-08 16:50:42 -0700885
Ed Tanous8a57ec02020-10-09 12:46:52 -0700886 if constexpr (debug)
Josh Lehan49cfba92019-10-08 16:50:42 -0700887 {
888 std::cerr << "Created total of " << numCreated << " sensors\n";
889 }
Cheng C Yang209ec562019-03-12 16:37:44 +0800890 return;
891}
892
Zhikui Ren23c96e72020-11-05 22:32:28 -0800893void createSensors(
894 boost::asio::io_service& io, sdbusplus::asio::object_server& objectServer,
895 std::shared_ptr<sdbusplus::asio::connection>& dbusConnection,
896 const std::shared_ptr<boost::container::flat_set<std::string>>&
897 sensorsChanged)
898{
899 auto getter = std::make_shared<GetSensorConfiguration>(
900 dbusConnection, [&io, &objectServer, &dbusConnection, sensorsChanged](
901 const ManagedObjectType& sensorConfigs) {
902 createSensorsCallback(io, objectServer, dbusConnection,
903 sensorConfigs, sensorsChanged);
904 });
905 getter->getConfiguration(
906 std::vector<std::string>(sensorTypes.begin(), sensorTypes.end()));
907}
908
Cheng C Yang916360b2019-05-07 18:47:16 +0800909void propertyInitialize(void)
Cheng C Yang209ec562019-03-12 16:37:44 +0800910{
Zev Weiss6b6891c2021-04-22 02:46:21 -0500911 sensorTable = {{"power", sensor_paths::unitWatts},
912 {"curr", sensor_paths::unitAmperes},
913 {"temp", sensor_paths::unitDegreesC},
914 {"in", sensor_paths::unitVolts},
915 {"fan", sensor_paths::unitRPMs}};
Cheng C Yange50345b2019-04-02 17:26:15 +0800916
Jeff Line41d52f2021-04-07 19:38:51 +0800917 labelMatch = {
918 {"pin", PSUProperty("Input Power", 3000, 0, 6, 0)},
919 {"pout1", PSUProperty("Output Power", 3000, 0, 6, 0)},
920 {"pout2", PSUProperty("Output Power", 3000, 0, 6, 0)},
921 {"pout3", PSUProperty("Output Power", 3000, 0, 6, 0)},
922 {"power1", PSUProperty("Output Power", 3000, 0, 6, 0)},
923 {"maxpin", PSUProperty("Max Input Power", 3000, 0, 6, 0)},
924 {"vin", PSUProperty("Input Voltage", 300, 0, 3, 0)},
925 {"maxvin", PSUProperty("Max Input Voltage", 300, 0, 3, 0)},
926 {"vout1", PSUProperty("Output Voltage", 255, 0, 3, 0)},
927 {"vout2", PSUProperty("Output Voltage", 255, 0, 3, 0)},
928 {"vout3", PSUProperty("Output Voltage", 255, 0, 3, 0)},
929 {"vout4", PSUProperty("Output Voltage", 255, 0, 3, 0)},
930 {"vout5", PSUProperty("Output Voltage", 255, 0, 3, 0)},
931 {"vout6", PSUProperty("Output Voltage", 255, 0, 3, 0)},
932 {"vout7", PSUProperty("Output Voltage", 255, 0, 3, 0)},
933 {"vout8", PSUProperty("Output Voltage", 255, 0, 3, 0)},
934 {"vout9", PSUProperty("Output Voltage", 255, 0, 3, 0)},
935 {"vout10", PSUProperty("Output Voltage", 255, 0, 3, 0)},
936 {"vout11", PSUProperty("Output Voltage", 255, 0, 3, 0)},
937 {"vout12", PSUProperty("Output Voltage", 255, 0, 3, 0)},
938 {"vout13", PSUProperty("Output Voltage", 255, 0, 3, 0)},
939 {"vout14", PSUProperty("Output Voltage", 255, 0, 3, 0)},
940 {"vout15", PSUProperty("Output Voltage", 255, 0, 3, 0)},
941 {"vout16", PSUProperty("Output Voltage", 255, 0, 3, 0)},
942 {"vout17", PSUProperty("Output Voltage", 255, 0, 3, 0)},
943 {"vout18", PSUProperty("Output Voltage", 255, 0, 3, 0)},
944 {"vout19", PSUProperty("Output Voltage", 255, 0, 3, 0)},
945 {"vout20", PSUProperty("Output Voltage", 255, 0, 3, 0)},
946 {"vout21", PSUProperty("Output Voltage", 255, 0, 3, 0)},
947 {"vout22", PSUProperty("Output Voltage", 255, 0, 3, 0)},
948 {"vout23", PSUProperty("Output Voltage", 255, 0, 3, 0)},
949 {"vout24", PSUProperty("Output Voltage", 255, 0, 3, 0)},
950 {"vout25", PSUProperty("Output Voltage", 255, 0, 3, 0)},
951 {"vout26", PSUProperty("Output Voltage", 255, 0, 3, 0)},
952 {"vout27", PSUProperty("Output Voltage", 255, 0, 3, 0)},
953 {"vout28", PSUProperty("Output Voltage", 255, 0, 3, 0)},
954 {"vout29", PSUProperty("Output Voltage", 255, 0, 3, 0)},
955 {"vout30", PSUProperty("Output Voltage", 255, 0, 3, 0)},
956 {"vout31", PSUProperty("Output Voltage", 255, 0, 3, 0)},
957 {"vout32", PSUProperty("Output Voltage", 255, 0, 3, 0)},
958 {"vmon", PSUProperty("Auxiliary Input Voltage", 255, 0, 3, 0)},
959 {"in1", PSUProperty("Output Voltage", 255, 0, 3, 0)},
960 {"iin", PSUProperty("Input Current", 20, 0, 3, 0)},
961 {"iout1", PSUProperty("Output Current", 255, 0, 3, 0)},
962 {"iout2", PSUProperty("Output Current", 255, 0, 3, 0)},
963 {"iout3", PSUProperty("Output Current", 255, 0, 3, 0)},
964 {"iout4", PSUProperty("Output Current", 255, 0, 3, 0)},
965 {"iout5", PSUProperty("Output Current", 255, 0, 3, 0)},
966 {"iout6", PSUProperty("Output Current", 255, 0, 3, 0)},
967 {"iout7", PSUProperty("Output Current", 255, 0, 3, 0)},
968 {"iout8", PSUProperty("Output Current", 255, 0, 3, 0)},
969 {"iout9", PSUProperty("Output Current", 255, 0, 3, 0)},
970 {"iout10", PSUProperty("Output Current", 255, 0, 3, 0)},
971 {"iout11", PSUProperty("Output Current", 255, 0, 3, 0)},
972 {"iout12", PSUProperty("Output Current", 255, 0, 3, 0)},
973 {"iout13", PSUProperty("Output Current", 255, 0, 3, 0)},
974 {"iout14", PSUProperty("Output Current", 255, 0, 3, 0)},
975 {"curr1", PSUProperty("Output Current", 255, 0, 3, 0)},
976 {"maxiout1", PSUProperty("Max Output Current", 255, 0, 3, 0)},
977 {"temp1", PSUProperty("Temperature", 127, -128, 3, 0)},
978 {"temp2", PSUProperty("Temperature", 127, -128, 3, 0)},
979 {"temp3", PSUProperty("Temperature", 127, -128, 3, 0)},
980 {"temp4", PSUProperty("Temperature", 127, -128, 3, 0)},
981 {"temp5", PSUProperty("Temperature", 127, -128, 3, 0)},
982 {"temp6", PSUProperty("Temperature", 127, -128, 3, 0)},
983 {"maxtemp1", PSUProperty("Max Temperature", 127, -128, 3, 0)},
984 {"fan1", PSUProperty("Fan Speed 1", 30000, 0, 0, 0)},
985 {"fan2", PSUProperty("Fan Speed 2", 30000, 0, 0, 0)}};
Cheng C Yang916360b2019-05-07 18:47:16 +0800986
987 pwmTable = {{"fan1", "Fan_1"}, {"fan2", "Fan_2"}};
Cheng C Yang58b2b532019-05-31 00:19:45 +0800988
989 limitEventMatch = {{"PredictiveFailure", {"max_alarm", "min_alarm"}},
990 {"Failure", {"crit_alarm", "lcrit_alarm"}}};
991
Cheng C Yang202a1ff2020-01-09 09:34:22 +0800992 eventMatch = {{"PredictiveFailure", {"power1_alarm"}},
993 {"Failure", {"in2_alarm"}},
994 {"ACLost", {"in1_beep"}},
995 {"ConfigureError", {"in1_fault"}}};
996
997 groupEventMatch = {{"FanFault",
998 {{"fan1", {"fan1_alarm", "fan1_fault"}},
999 {"fan2", {"fan2_alarm", "fan2_fault"}}}}};
Cheng C Yang209ec562019-03-12 16:37:44 +08001000}
1001
James Feistb6c0b912019-07-09 12:21:44 -07001002int main()
Cheng C Yang209ec562019-03-12 16:37:44 +08001003{
1004 boost::asio::io_service io;
1005 auto systemBus = std::make_shared<sdbusplus::asio::connection>(io);
1006
1007 systemBus->request_name("xyz.openbmc_project.PSUSensor");
1008 sdbusplus::asio::object_server objectServer(systemBus);
Cheng C Yang209ec562019-03-12 16:37:44 +08001009 std::vector<std::unique_ptr<sdbusplus::bus::match::match>> matches;
Zhikui Ren23c96e72020-11-05 22:32:28 -08001010 auto sensorsChanged =
1011 std::make_shared<boost::container::flat_set<std::string>>();
Cheng C Yang209ec562019-03-12 16:37:44 +08001012
Cheng C Yang916360b2019-05-07 18:47:16 +08001013 propertyInitialize();
Cheng C Yang209ec562019-03-12 16:37:44 +08001014
Zhikui Ren23c96e72020-11-05 22:32:28 -08001015 io.post([&]() { createSensors(io, objectServer, systemBus, nullptr); });
Cheng C Yang209ec562019-03-12 16:37:44 +08001016 boost::asio::deadline_timer filterTimer(io);
1017 std::function<void(sdbusplus::message::message&)> eventHandler =
1018 [&](sdbusplus::message::message& message) {
1019 if (message.is_method_error())
1020 {
1021 std::cerr << "callback method error\n";
1022 return;
1023 }
Zhikui Ren23c96e72020-11-05 22:32:28 -08001024 sensorsChanged->insert(message.get_path());
Cheng C Yanga97f1342020-02-11 15:10:41 +08001025 filterTimer.expires_from_now(boost::posix_time::seconds(3));
Cheng C Yang209ec562019-03-12 16:37:44 +08001026 filterTimer.async_wait([&](const boost::system::error_code& ec) {
1027 if (ec == boost::asio::error::operation_aborted)
1028 {
1029 return;
1030 }
Ed Tanous8a57ec02020-10-09 12:46:52 -07001031 if (ec)
Cheng C Yang209ec562019-03-12 16:37:44 +08001032 {
1033 std::cerr << "timer error\n";
1034 }
Zhikui Ren23c96e72020-11-05 22:32:28 -08001035 createSensors(io, objectServer, systemBus, sensorsChanged);
Cheng C Yang209ec562019-03-12 16:37:44 +08001036 });
1037 };
1038
1039 for (const char* type : sensorTypes)
1040 {
1041 auto match = std::make_unique<sdbusplus::bus::match::match>(
1042 static_cast<sdbusplus::bus::bus&>(*systemBus),
1043 "type='signal',member='PropertiesChanged',path_namespace='" +
1044 std::string(inventoryPath) + "',arg0namespace='" + type + "'",
1045 eventHandler);
1046 matches.emplace_back(std::move(match));
1047 }
Bruce Lee1263c3d2021-06-04 15:16:33 +08001048
1049 setupManufacturingModeMatch(*systemBus);
Cheng C Yang209ec562019-03-12 16:37:44 +08001050 io.run();
1051}