blob: b27cecc614eb1d8e3b298159af6ab76df0d7d271 [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
Brandon Kim66558232021-11-09 16:53:08 -080043static constexpr auto sensorTypes{std::to_array<const char*>(
44 {"xyz.openbmc_project.Configuration.ADM1266",
45 "xyz.openbmc_project.Configuration.ADM1272",
46 "xyz.openbmc_project.Configuration.ADM1275",
47 "xyz.openbmc_project.Configuration.ADM1278",
48 "xyz.openbmc_project.Configuration.DPS800",
49 "xyz.openbmc_project.Configuration.INA219",
50 "xyz.openbmc_project.Configuration.INA230",
51 "xyz.openbmc_project.Configuration.IPSPS",
52 "xyz.openbmc_project.Configuration.ISL68137",
53 "xyz.openbmc_project.Configuration.ISL68220",
54 "xyz.openbmc_project.Configuration.ISL68223",
55 "xyz.openbmc_project.Configuration.ISL69243",
56 "xyz.openbmc_project.Configuration.ISL69260",
57 "xyz.openbmc_project.Configuration.LM25066",
58 "xyz.openbmc_project.Configuration.MAX16601",
59 "xyz.openbmc_project.Configuration.MAX20710",
60 "xyz.openbmc_project.Configuration.MAX20730",
61 "xyz.openbmc_project.Configuration.MAX20734",
62 "xyz.openbmc_project.Configuration.MAX20796",
63 "xyz.openbmc_project.Configuration.MAX34451",
64 "xyz.openbmc_project.Configuration.pmbus",
65 "xyz.openbmc_project.Configuration.PXE1610",
66 "xyz.openbmc_project.Configuration.RAA228000",
67 "xyz.openbmc_project.Configuration.RAA228228",
68 "xyz.openbmc_project.Configuration.RAA229004",
69 "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 {
Zhikui Renda98f092021-11-01 09:41:08 -0700428 std::string psuNameStr = "/" + escapeName(*psuName);
Zhikui Ren23c96e72020-11-05 22:32:28 -0800429 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, ...
Zhikui Renda98f092021-11-01 09:41:08 -0700460 psuNames.push_back(
461 escapeName(std::get<std::string>(findPSUName->second)));
Vijay Khemka996bad12019-05-28 15:15:16 -0700462 findPSUName = baseConfig->second.find("Name" + std::to_string(i++));
463 } while (findPSUName != baseConfig->second.end());
464
Cheng C Yange50345b2019-04-02 17:26:15 +0800465 std::vector<fs::path> sensorPaths;
James Feistb6c0b912019-07-09 12:21:44 -0700466 if (!findFiles(directory, R"(\w\d+_input$)", sensorPaths, 0))
Cheng C Yang209ec562019-03-12 16:37:44 +0800467 {
Cheng C Yange50345b2019-04-02 17:26:15 +0800468 std::cerr << "No PSU non-label sensor in PSU\n";
Cheng C Yang209ec562019-03-12 16:37:44 +0800469 continue;
470 }
471
Manikandan Elumalaic7e95622020-06-03 20:22:01 +0530472 /* read max value in sysfs for in, curr, power, temp, ... */
473 if (!findFiles(directory, R"(\w\d+_max$)", sensorPaths, 0))
474 {
Ed Tanous8a57ec02020-10-09 12:46:52 -0700475 if constexpr (debug)
Manikandan Elumalaic7e95622020-06-03 20:22:01 +0530476 {
477 std::cerr << "No max name in PSU \n";
478 }
479 }
480
Lei YU7170a232021-02-04 16:19:27 +0800481 /* The poll rate for the sensors */
482 double pollRate = 0.0;
483 auto pollRateObj = baseConfig->second.find("PollRate");
484
485 if (pollRateObj != baseConfig->second.end())
486 {
487 pollRate =
488 std::visit(VariantToDoubleVisitor(), pollRateObj->second);
489 if (pollRate <= 0.0)
490 {
491 pollRate = PSUSensor::defaultSensorPoll;
492 }
493 }
494
Vijay Khemka996bad12019-05-28 15:15:16 -0700495 /* Find array of labels to be exposed if it is defined in config */
496 std::vector<std::string> findLabels;
497 auto findLabelObj = baseConfig->second.find("Labels");
498 if (findLabelObj != baseConfig->second.end())
499 {
500 findLabels =
501 std::get<std::vector<std::string>>(findLabelObj->second);
502 }
503
Jason Ling5747fab2019-10-02 16:46:23 -0700504 std::regex sensorNameRegEx("([A-Za-z]+)[0-9]*_");
505 std::smatch matches;
506
Cheng C Yange50345b2019-04-02 17:26:15 +0800507 for (const auto& sensorPath : sensorPaths)
Cheng C Yang209ec562019-03-12 16:37:44 +0800508 {
Manikandan Elumalaic7e95622020-06-03 20:22:01 +0530509 bool maxLabel = false;
Cheng C Yange50345b2019-04-02 17:26:15 +0800510 std::string labelHead;
511 std::string sensorPathStr = sensorPath.string();
512 std::string sensorNameStr = sensorPath.filename();
Jason Ling5747fab2019-10-02 16:46:23 -0700513 std::string sensorNameSubStr{""};
514 if (std::regex_search(sensorNameStr, matches, sensorNameRegEx))
515 {
Josh Lehan06494452019-10-31 09:49:16 -0700516 // hwmon *_input filename without number:
517 // in, curr, power, temp, ...
Jason Ling5747fab2019-10-02 16:46:23 -0700518 sensorNameSubStr = matches[1];
519 }
520 else
521 {
Josh Lehan06494452019-10-31 09:49:16 -0700522 std::cerr << "Could not extract the alpha prefix from "
Jason Ling5747fab2019-10-02 16:46:23 -0700523 << sensorNameStr;
524 continue;
525 }
Cheng C Yange50345b2019-04-02 17:26:15 +0800526
Manikandan Elumalaic7e95622020-06-03 20:22:01 +0530527 std::string labelPath;
528
529 /* find and differentiate _max and _input to replace "label" */
Ed Tanous8a57ec02020-10-09 12:46:52 -0700530 size_t pos = sensorPathStr.find('_');
Manikandan Elumalaic7e95622020-06-03 20:22:01 +0530531 if (pos != std::string::npos)
532 {
533
534 std::string sensorPathStrMax = sensorPathStr.substr(pos);
535 if (sensorPathStrMax.compare("_max") == 0)
536 {
537 labelPath =
538 boost::replace_all_copy(sensorPathStr, "max", "label");
539 maxLabel = true;
540 }
541 else
542 {
543 labelPath = boost::replace_all_copy(sensorPathStr, "input",
544 "label");
545 maxLabel = false;
546 }
547 }
548 else
549 {
550 continue;
551 }
552
Cheng C Yangecba9de2019-09-12 23:41:50 +0800553 std::ifstream labelFile(labelPath);
554 if (!labelFile.good())
Cheng C Yang209ec562019-03-12 16:37:44 +0800555 {
Ed Tanous8a57ec02020-10-09 12:46:52 -0700556 if constexpr (debug)
Cheng C Yang6b1247a2020-03-09 23:48:39 +0800557 {
558 std::cerr << "Input file " << sensorPath
559 << " has no corresponding label file\n";
560 }
Josh Lehan06494452019-10-31 09:49:16 -0700561 // hwmon *_input filename with number:
562 // temp1, temp2, temp3, ...
Ed Tanous8a57ec02020-10-09 12:46:52 -0700563 labelHead = sensorNameStr.substr(0, sensorNameStr.find('_'));
Cheng C Yang209ec562019-03-12 16:37:44 +0800564 }
565 else
566 {
Cheng C Yange50345b2019-04-02 17:26:15 +0800567 std::string label;
568 std::getline(labelFile, label);
569 labelFile.close();
Cheng C Yange50345b2019-04-02 17:26:15 +0800570 auto findSensor = sensors.find(label);
571 if (findSensor != sensors.end())
572 {
573 continue;
574 }
575
Josh Lehan06494452019-10-31 09:49:16 -0700576 // hwmon corresponding *_label file contents:
577 // vin1, vout1, ...
Ed Tanous8a57ec02020-10-09 12:46:52 -0700578 labelHead = label.substr(0, label.find(' '));
Cheng C Yange50345b2019-04-02 17:26:15 +0800579 }
580
Manikandan Elumalaic7e95622020-06-03 20:22:01 +0530581 /* append "max" for labelMatch */
582 if (maxLabel)
583 {
Ed Tanous8a57ec02020-10-09 12:46:52 -0700584 labelHead.insert(0, "max");
Manikandan Elumalaic7e95622020-06-03 20:22:01 +0530585 }
586
Ed Tanous8a57ec02020-10-09 12:46:52 -0700587 if constexpr (debug)
Josh Lehan74d9bd92019-10-31 08:51:58 -0700588 {
589 std::cerr << "Sensor type=\"" << sensorNameSubStr
590 << "\" label=\"" << labelHead << "\"\n";
591 }
592
AppaRao Pulid9d8caf2020-02-27 20:56:59 +0530593 checkPWMSensor(sensorPath, labelHead, *interfacePath,
594 dbusConnection, objectServer, psuNames[0]);
Cheng C Yang916360b2019-05-07 18:47:16 +0800595
Vijay Khemka996bad12019-05-28 15:15:16 -0700596 if (!findLabels.empty())
597 {
598 /* Check if this labelHead is enabled in config file */
599 if (std::find(findLabels.begin(), findLabels.end(),
600 labelHead) == findLabels.end())
601 {
Ed Tanous8a57ec02020-10-09 12:46:52 -0700602 if constexpr (debug)
Cheng C Yang6b1247a2020-03-09 23:48:39 +0800603 {
604 std::cerr << "could not find " << labelHead
605 << " in the Labels list\n";
606 }
Vijay Khemka996bad12019-05-28 15:15:16 -0700607 continue;
608 }
609 }
Cheng C Yange50345b2019-04-02 17:26:15 +0800610
Cheng C Yange50345b2019-04-02 17:26:15 +0800611 auto findProperty = labelMatch.find(labelHead);
612 if (findProperty == labelMatch.end())
Cheng C Yang209ec562019-03-12 16:37:44 +0800613 {
Ed Tanous8a57ec02020-10-09 12:46:52 -0700614 if constexpr (debug)
Josh Lehan74d9bd92019-10-31 08:51:58 -0700615 {
616 std::cerr << "Could not find matching default property for "
617 << labelHead << "\n";
618 }
Cheng C Yang209ec562019-03-12 16:37:44 +0800619 continue;
620 }
621
Josh Lehan74d9bd92019-10-31 08:51:58 -0700622 // Protect the hardcoded labelMatch list from changes,
623 // by making a copy and modifying that instead.
624 // Avoid bleedthrough of one device's customizations to
625 // the next device, as each should be independently customizable.
626 psuProperties.push_back(findProperty->second);
627 auto psuProperty = psuProperties.rbegin();
628
629 // Use label head as prefix for reading from config file,
630 // example if temp1: temp1_Name, temp1_Scale, temp1_Min, ...
631 std::string keyName = labelHead + "_Name";
632 std::string keyScale = labelHead + "_Scale";
633 std::string keyMin = labelHead + "_Min";
634 std::string keyMax = labelHead + "_Max";
Jeff Line41d52f2021-04-07 19:38:51 +0800635 std::string keyOffset = labelHead + "_Offset";
Lotus Xucb5af732021-09-10 15:18:50 +0800636 std::string keyPowerState = labelHead + "_PowerState";
Josh Lehan74d9bd92019-10-31 08:51:58 -0700637
638 bool customizedName = false;
639 auto findCustomName = baseConfig->second.find(keyName);
640 if (findCustomName != baseConfig->second.end())
Josh Lehan432d1ed2019-10-16 12:23:31 -0700641 {
Josh Lehan74d9bd92019-10-31 08:51:58 -0700642 try
643 {
644 psuProperty->labelTypeName = std::visit(
645 VariantToStringVisitor(), findCustomName->second);
646 }
Patrick Williams26601e82021-10-06 12:43:25 -0500647 catch (const std::invalid_argument&)
Josh Lehan74d9bd92019-10-31 08:51:58 -0700648 {
649 std::cerr << "Unable to parse " << keyName << "\n";
650 continue;
651 }
652
653 // All strings are valid, including empty string
654 customizedName = true;
655 }
656
657 bool customizedScale = false;
658 auto findCustomScale = baseConfig->second.find(keyScale);
659 if (findCustomScale != baseConfig->second.end())
660 {
661 try
662 {
663 psuProperty->sensorScaleFactor = std::visit(
664 VariantToUnsignedIntVisitor(), findCustomScale->second);
665 }
Patrick Williams26601e82021-10-06 12:43:25 -0500666 catch (const std::invalid_argument&)
Josh Lehan74d9bd92019-10-31 08:51:58 -0700667 {
668 std::cerr << "Unable to parse " << keyScale << "\n";
669 continue;
670 }
671
672 // Avoid later division by zero
673 if (psuProperty->sensorScaleFactor > 0)
674 {
675 customizedScale = true;
676 }
677 else
678 {
679 std::cerr << "Unable to accept " << keyScale << "\n";
680 continue;
681 }
682 }
683
684 auto findCustomMin = baseConfig->second.find(keyMin);
685 if (findCustomMin != baseConfig->second.end())
686 {
687 try
688 {
689 psuProperty->minReading = std::visit(
690 VariantToDoubleVisitor(), findCustomMin->second);
691 }
Patrick Williams26601e82021-10-06 12:43:25 -0500692 catch (const std::invalid_argument&)
Josh Lehan74d9bd92019-10-31 08:51:58 -0700693 {
694 std::cerr << "Unable to parse " << keyMin << "\n";
695 continue;
696 }
697 }
698
699 auto findCustomMax = baseConfig->second.find(keyMax);
700 if (findCustomMax != baseConfig->second.end())
701 {
702 try
703 {
704 psuProperty->maxReading = std::visit(
705 VariantToDoubleVisitor(), findCustomMax->second);
706 }
Patrick Williams26601e82021-10-06 12:43:25 -0500707 catch (const std::invalid_argument&)
Josh Lehan74d9bd92019-10-31 08:51:58 -0700708 {
709 std::cerr << "Unable to parse " << keyMax << "\n";
710 continue;
711 }
712 }
713
Jeff Line41d52f2021-04-07 19:38:51 +0800714 auto findCustomOffset = baseConfig->second.find(keyOffset);
715 if (findCustomOffset != baseConfig->second.end())
716 {
717 try
718 {
719 psuProperty->sensorOffset = std::visit(
720 VariantToDoubleVisitor(), findCustomOffset->second);
721 }
Patrick Williams26601e82021-10-06 12:43:25 -0500722 catch (const std::invalid_argument&)
Jeff Line41d52f2021-04-07 19:38:51 +0800723 {
724 std::cerr << "Unable to parse " << keyOffset << "\n";
725 continue;
726 }
727 }
728
Lotus Xucb5af732021-09-10 15:18:50 +0800729 // if we find label head power state set ,override the powerstate.
730 auto findPowerState = baseConfig->second.find(keyPowerState);
731 if (findPowerState != baseConfig->second.end())
732 {
733 std::string powerState = std::visit(VariantToStringVisitor(),
734 findPowerState->second);
735 setReadState(powerState, readState);
736 }
Josh Lehan74d9bd92019-10-31 08:51:58 -0700737 if (!(psuProperty->minReading < psuProperty->maxReading))
738 {
739 std::cerr << "Min must be less than Max\n";
740 continue;
741 }
742
743 // If the sensor name is being customized by config file,
744 // then prefix/suffix composition becomes not necessary,
745 // and in fact not wanted, because it gets in the way.
746 std::string psuNameFromIndex;
747 if (!customizedName)
748 {
749 /* Find out sensor name index for this label */
750 std::regex rgx("[A-Za-z]+([0-9]+)");
Brad Bishopfbb44ad2019-11-08 09:42:37 -0500751 size_t nameIndex{0};
Josh Lehan74d9bd92019-10-31 08:51:58 -0700752 if (std::regex_search(labelHead, matches, rgx))
753 {
754 nameIndex = std::stoi(matches[1]);
755
756 // Decrement to preserve alignment, because hwmon
757 // human-readable filenames and labels use 1-based
758 // numbering, but the "Name", "Name1", "Name2", etc. naming
759 // convention (the psuNames vector) uses 0-based numbering.
760 if (nameIndex > 0)
761 {
762 --nameIndex;
763 }
764 }
765 else
766 {
767 nameIndex = 0;
768 }
769
770 if (psuNames.size() <= nameIndex)
771 {
772 std::cerr << "Could not pair " << labelHead
773 << " with a Name field\n";
774 continue;
775 }
776
777 psuNameFromIndex = psuNames[nameIndex];
778
Ed Tanous8a57ec02020-10-09 12:46:52 -0700779 if constexpr (debug)
Josh Lehan74d9bd92019-10-31 08:51:58 -0700780 {
781 std::cerr << "Sensor label head " << labelHead
782 << " paired with " << psuNameFromIndex
783 << " at index " << nameIndex << "\n";
784 }
Josh Lehan432d1ed2019-10-16 12:23:31 -0700785 }
786
Cheng C Yang58b2b532019-05-31 00:19:45 +0800787 checkEventLimits(sensorPathStr, limitEventMatch, eventPathList);
788
Josh Lehan74d9bd92019-10-31 08:51:58 -0700789 // Similarly, if sensor scaling factor is being customized,
790 // then the below power-of-10 constraint becomes unnecessary,
791 // as config should be able to specify an arbitrary divisor.
792 unsigned int factor = psuProperty->sensorScaleFactor;
793 if (!customizedScale)
Vijay Khemka53ca4442019-07-23 11:03:55 -0700794 {
Josh Lehan74d9bd92019-10-31 08:51:58 -0700795 // Preserve existing usage of hardcoded labelMatch table below
796 factor = std::pow(10.0, factor);
Vijay Khemka53ca4442019-07-23 11:03:55 -0700797
Josh Lehan74d9bd92019-10-31 08:51:58 -0700798 /* Change first char of substring to uppercase */
Ed Tanous8a57ec02020-10-09 12:46:52 -0700799 char firstChar =
800 static_cast<char>(std::toupper(sensorNameSubStr[0]));
Josh Lehan74d9bd92019-10-31 08:51:58 -0700801 std::string strScaleFactor =
802 firstChar + sensorNameSubStr.substr(1) + "ScaleFactor";
803
804 // Preserve existing configs by accepting earlier syntax,
805 // example CurrScaleFactor, PowerScaleFactor, ...
806 auto findScaleFactor = baseConfig->second.find(strScaleFactor);
807 if (findScaleFactor != baseConfig->second.end())
808 {
809 factor = std::visit(VariantToIntVisitor(),
810 findScaleFactor->second);
811 }
812
Ed Tanous8a57ec02020-10-09 12:46:52 -0700813 if constexpr (debug)
Josh Lehan74d9bd92019-10-31 08:51:58 -0700814 {
815 std::cerr << "Sensor scaling factor " << factor
816 << " string " << strScaleFactor << "\n";
817 }
Josh Lehan49cfba92019-10-08 16:50:42 -0700818 }
819
Vijay Khemka996bad12019-05-28 15:15:16 -0700820 std::vector<thresholds::Threshold> sensorThresholds;
Joshi, Mansi14f0ad82019-11-21 10:52:30 +0530821 if (!parseThresholdsFromConfig(*sensorData, sensorThresholds,
822 &labelHead))
Cheng C Yange50345b2019-04-02 17:26:15 +0800823 {
James Feist17ab6e02019-06-25 12:28:13 -0700824 std::cerr << "error populating thresholds for "
825 << sensorNameSubStr << "\n";
Cheng C Yange50345b2019-04-02 17:26:15 +0800826 }
827
Zev Weiss6b6891c2021-04-22 02:46:21 -0500828 auto findSensorUnit = sensorTable.find(sensorNameSubStr);
829 if (findSensorUnit == sensorTable.end())
Cheng C Yange50345b2019-04-02 17:26:15 +0800830 {
Jason Ling5747fab2019-10-02 16:46:23 -0700831 std::cerr << sensorNameSubStr
Josh Lehan06494452019-10-31 09:49:16 -0700832 << " is not a recognized sensor type\n";
Cheng C Yange50345b2019-04-02 17:26:15 +0800833 continue;
834 }
835
Ed Tanous8a57ec02020-10-09 12:46:52 -0700836 if constexpr (debug)
Josh Lehan49cfba92019-10-08 16:50:42 -0700837 {
Josh Lehan74d9bd92019-10-31 08:51:58 -0700838 std::cerr << "Sensor properties: Name \""
839 << psuProperty->labelTypeName << "\" Scale "
840 << psuProperty->sensorScaleFactor << " Min "
841 << psuProperty->minReading << " Max "
Jeff Line41d52f2021-04-07 19:38:51 +0800842 << psuProperty->maxReading << " Offset "
843 << psuProperty->sensorOffset << "\n";
Josh Lehan74d9bd92019-10-31 08:51:58 -0700844 }
845
846 std::string sensorName = psuProperty->labelTypeName;
847 if (customizedName)
848 {
849 if (sensorName.empty())
850 {
851 // Allow selective disabling of an individual sensor,
852 // by customizing its name to an empty string.
853 std::cerr << "Sensor disabled, empty string\n";
854 continue;
855 }
856 }
857 else
858 {
859 // Sensor name not customized, do prefix/suffix composition,
860 // preserving default behavior by using psuNameFromIndex.
861 sensorName =
862 psuNameFromIndex + " " + psuProperty->labelTypeName;
863 }
864
Ed Tanous8a57ec02020-10-09 12:46:52 -0700865 if constexpr (debug)
Josh Lehan74d9bd92019-10-31 08:51:58 -0700866 {
867 std::cerr << "Sensor name \"" << sensorName << "\" path \""
868 << sensorPathStr << "\" type \"" << sensorType
869 << "\"\n";
Josh Lehan49cfba92019-10-08 16:50:42 -0700870 }
Zhikui Ren23c96e72020-11-05 22:32:28 -0800871 // destruct existing one first if already created
872 sensors[sensorName] = nullptr;
Yong Libf8b1da2020-04-15 16:32:50 +0800873 sensors[sensorName] = std::make_shared<PSUSensor>(
Cheng C Yange50345b2019-04-02 17:26:15 +0800874 sensorPathStr, sensorType, objectServer, dbusConnection, io,
Cheng C Yang209ec562019-03-12 16:37:44 +0800875 sensorName, std::move(sensorThresholds), *interfacePath,
Konstantin Aladyshevc7a1ae62021-04-30 08:50:43 +0000876 readState, findSensorUnit->second, factor,
877 psuProperty->maxReading, psuProperty->minReading,
878 psuProperty->sensorOffset, labelHead, thresholdConfSize,
879 pollRate);
Yong Libf8b1da2020-04-15 16:32:50 +0800880 sensors[sensorName]->setupRead();
Josh Lehan74d9bd92019-10-31 08:51:58 -0700881 ++numCreated;
Ed Tanous8a57ec02020-10-09 12:46:52 -0700882 if constexpr (debug)
Josh Lehan74d9bd92019-10-31 08:51:58 -0700883 {
884 std::cerr << "Created " << numCreated << " sensors so far\n";
885 }
Cheng C Yang209ec562019-03-12 16:37:44 +0800886 }
Cheng C Yang58b2b532019-05-31 00:19:45 +0800887
888 // OperationalStatus event
Cheng C Yang92498eb2019-09-26 21:59:25 +0800889 combineEvents[*psuName + "OperationalStatus"] = nullptr;
Cheng C Yang58b2b532019-05-31 00:19:45 +0800890 combineEvents[*psuName + "OperationalStatus"] =
Konstantin Aladyshevc7a1ae62021-04-30 08:50:43 +0000891 std::make_unique<PSUCombineEvent>(objectServer, dbusConnection, io,
892 *psuName, readState,
893 eventPathList, groupEventPathList,
894 "OperationalStatus", pollRate);
Cheng C Yang209ec562019-03-12 16:37:44 +0800895 }
Josh Lehan49cfba92019-10-08 16:50:42 -0700896
Ed Tanous8a57ec02020-10-09 12:46:52 -0700897 if constexpr (debug)
Josh Lehan49cfba92019-10-08 16:50:42 -0700898 {
899 std::cerr << "Created total of " << numCreated << " sensors\n";
900 }
Cheng C Yang209ec562019-03-12 16:37:44 +0800901 return;
902}
903
Zhikui Ren23c96e72020-11-05 22:32:28 -0800904void createSensors(
905 boost::asio::io_service& io, sdbusplus::asio::object_server& objectServer,
906 std::shared_ptr<sdbusplus::asio::connection>& dbusConnection,
907 const std::shared_ptr<boost::container::flat_set<std::string>>&
908 sensorsChanged)
909{
910 auto getter = std::make_shared<GetSensorConfiguration>(
911 dbusConnection, [&io, &objectServer, &dbusConnection, sensorsChanged](
912 const ManagedObjectType& sensorConfigs) {
913 createSensorsCallback(io, objectServer, dbusConnection,
914 sensorConfigs, sensorsChanged);
915 });
916 getter->getConfiguration(
917 std::vector<std::string>(sensorTypes.begin(), sensorTypes.end()));
918}
919
Cheng C Yang916360b2019-05-07 18:47:16 +0800920void propertyInitialize(void)
Cheng C Yang209ec562019-03-12 16:37:44 +0800921{
Zev Weiss6b6891c2021-04-22 02:46:21 -0500922 sensorTable = {{"power", sensor_paths::unitWatts},
923 {"curr", sensor_paths::unitAmperes},
924 {"temp", sensor_paths::unitDegreesC},
925 {"in", sensor_paths::unitVolts},
926 {"fan", sensor_paths::unitRPMs}};
Cheng C Yange50345b2019-04-02 17:26:15 +0800927
Jeff Line41d52f2021-04-07 19:38:51 +0800928 labelMatch = {
929 {"pin", PSUProperty("Input Power", 3000, 0, 6, 0)},
930 {"pout1", PSUProperty("Output Power", 3000, 0, 6, 0)},
931 {"pout2", PSUProperty("Output Power", 3000, 0, 6, 0)},
932 {"pout3", PSUProperty("Output Power", 3000, 0, 6, 0)},
933 {"power1", PSUProperty("Output Power", 3000, 0, 6, 0)},
934 {"maxpin", PSUProperty("Max Input Power", 3000, 0, 6, 0)},
935 {"vin", PSUProperty("Input Voltage", 300, 0, 3, 0)},
936 {"maxvin", PSUProperty("Max Input Voltage", 300, 0, 3, 0)},
937 {"vout1", PSUProperty("Output Voltage", 255, 0, 3, 0)},
938 {"vout2", PSUProperty("Output Voltage", 255, 0, 3, 0)},
939 {"vout3", PSUProperty("Output Voltage", 255, 0, 3, 0)},
940 {"vout4", PSUProperty("Output Voltage", 255, 0, 3, 0)},
941 {"vout5", PSUProperty("Output Voltage", 255, 0, 3, 0)},
942 {"vout6", PSUProperty("Output Voltage", 255, 0, 3, 0)},
943 {"vout7", PSUProperty("Output Voltage", 255, 0, 3, 0)},
944 {"vout8", PSUProperty("Output Voltage", 255, 0, 3, 0)},
945 {"vout9", PSUProperty("Output Voltage", 255, 0, 3, 0)},
946 {"vout10", PSUProperty("Output Voltage", 255, 0, 3, 0)},
947 {"vout11", PSUProperty("Output Voltage", 255, 0, 3, 0)},
948 {"vout12", PSUProperty("Output Voltage", 255, 0, 3, 0)},
949 {"vout13", PSUProperty("Output Voltage", 255, 0, 3, 0)},
950 {"vout14", PSUProperty("Output Voltage", 255, 0, 3, 0)},
951 {"vout15", PSUProperty("Output Voltage", 255, 0, 3, 0)},
952 {"vout16", PSUProperty("Output Voltage", 255, 0, 3, 0)},
953 {"vout17", PSUProperty("Output Voltage", 255, 0, 3, 0)},
954 {"vout18", PSUProperty("Output Voltage", 255, 0, 3, 0)},
955 {"vout19", PSUProperty("Output Voltage", 255, 0, 3, 0)},
956 {"vout20", PSUProperty("Output Voltage", 255, 0, 3, 0)},
957 {"vout21", PSUProperty("Output Voltage", 255, 0, 3, 0)},
958 {"vout22", PSUProperty("Output Voltage", 255, 0, 3, 0)},
959 {"vout23", PSUProperty("Output Voltage", 255, 0, 3, 0)},
960 {"vout24", PSUProperty("Output Voltage", 255, 0, 3, 0)},
961 {"vout25", PSUProperty("Output Voltage", 255, 0, 3, 0)},
962 {"vout26", PSUProperty("Output Voltage", 255, 0, 3, 0)},
963 {"vout27", PSUProperty("Output Voltage", 255, 0, 3, 0)},
964 {"vout28", PSUProperty("Output Voltage", 255, 0, 3, 0)},
965 {"vout29", PSUProperty("Output Voltage", 255, 0, 3, 0)},
966 {"vout30", PSUProperty("Output Voltage", 255, 0, 3, 0)},
967 {"vout31", PSUProperty("Output Voltage", 255, 0, 3, 0)},
968 {"vout32", PSUProperty("Output Voltage", 255, 0, 3, 0)},
969 {"vmon", PSUProperty("Auxiliary Input Voltage", 255, 0, 3, 0)},
970 {"in1", PSUProperty("Output Voltage", 255, 0, 3, 0)},
971 {"iin", PSUProperty("Input Current", 20, 0, 3, 0)},
972 {"iout1", PSUProperty("Output Current", 255, 0, 3, 0)},
973 {"iout2", PSUProperty("Output Current", 255, 0, 3, 0)},
974 {"iout3", PSUProperty("Output Current", 255, 0, 3, 0)},
975 {"iout4", PSUProperty("Output Current", 255, 0, 3, 0)},
976 {"iout5", PSUProperty("Output Current", 255, 0, 3, 0)},
977 {"iout6", PSUProperty("Output Current", 255, 0, 3, 0)},
978 {"iout7", PSUProperty("Output Current", 255, 0, 3, 0)},
979 {"iout8", PSUProperty("Output Current", 255, 0, 3, 0)},
980 {"iout9", PSUProperty("Output Current", 255, 0, 3, 0)},
981 {"iout10", PSUProperty("Output Current", 255, 0, 3, 0)},
982 {"iout11", PSUProperty("Output Current", 255, 0, 3, 0)},
983 {"iout12", PSUProperty("Output Current", 255, 0, 3, 0)},
984 {"iout13", PSUProperty("Output Current", 255, 0, 3, 0)},
985 {"iout14", PSUProperty("Output Current", 255, 0, 3, 0)},
986 {"curr1", PSUProperty("Output Current", 255, 0, 3, 0)},
987 {"maxiout1", PSUProperty("Max Output Current", 255, 0, 3, 0)},
988 {"temp1", PSUProperty("Temperature", 127, -128, 3, 0)},
989 {"temp2", PSUProperty("Temperature", 127, -128, 3, 0)},
990 {"temp3", PSUProperty("Temperature", 127, -128, 3, 0)},
991 {"temp4", PSUProperty("Temperature", 127, -128, 3, 0)},
992 {"temp5", PSUProperty("Temperature", 127, -128, 3, 0)},
993 {"temp6", PSUProperty("Temperature", 127, -128, 3, 0)},
994 {"maxtemp1", PSUProperty("Max Temperature", 127, -128, 3, 0)},
995 {"fan1", PSUProperty("Fan Speed 1", 30000, 0, 0, 0)},
996 {"fan2", PSUProperty("Fan Speed 2", 30000, 0, 0, 0)}};
Cheng C Yang916360b2019-05-07 18:47:16 +0800997
998 pwmTable = {{"fan1", "Fan_1"}, {"fan2", "Fan_2"}};
Cheng C Yang58b2b532019-05-31 00:19:45 +0800999
1000 limitEventMatch = {{"PredictiveFailure", {"max_alarm", "min_alarm"}},
1001 {"Failure", {"crit_alarm", "lcrit_alarm"}}};
1002
Cheng C Yang202a1ff2020-01-09 09:34:22 +08001003 eventMatch = {{"PredictiveFailure", {"power1_alarm"}},
1004 {"Failure", {"in2_alarm"}},
1005 {"ACLost", {"in1_beep"}},
1006 {"ConfigureError", {"in1_fault"}}};
1007
1008 groupEventMatch = {{"FanFault",
1009 {{"fan1", {"fan1_alarm", "fan1_fault"}},
1010 {"fan2", {"fan2_alarm", "fan2_fault"}}}}};
Cheng C Yang209ec562019-03-12 16:37:44 +08001011}
1012
James Feistb6c0b912019-07-09 12:21:44 -07001013int main()
Cheng C Yang209ec562019-03-12 16:37:44 +08001014{
1015 boost::asio::io_service io;
1016 auto systemBus = std::make_shared<sdbusplus::asio::connection>(io);
1017
1018 systemBus->request_name("xyz.openbmc_project.PSUSensor");
1019 sdbusplus::asio::object_server objectServer(systemBus);
Cheng C Yang209ec562019-03-12 16:37:44 +08001020 std::vector<std::unique_ptr<sdbusplus::bus::match::match>> matches;
Zhikui Ren23c96e72020-11-05 22:32:28 -08001021 auto sensorsChanged =
1022 std::make_shared<boost::container::flat_set<std::string>>();
Cheng C Yang209ec562019-03-12 16:37:44 +08001023
Cheng C Yang916360b2019-05-07 18:47:16 +08001024 propertyInitialize();
Cheng C Yang209ec562019-03-12 16:37:44 +08001025
Zhikui Ren23c96e72020-11-05 22:32:28 -08001026 io.post([&]() { createSensors(io, objectServer, systemBus, nullptr); });
Cheng C Yang209ec562019-03-12 16:37:44 +08001027 boost::asio::deadline_timer filterTimer(io);
1028 std::function<void(sdbusplus::message::message&)> eventHandler =
1029 [&](sdbusplus::message::message& message) {
1030 if (message.is_method_error())
1031 {
1032 std::cerr << "callback method error\n";
1033 return;
1034 }
Zhikui Ren23c96e72020-11-05 22:32:28 -08001035 sensorsChanged->insert(message.get_path());
Cheng C Yanga97f1342020-02-11 15:10:41 +08001036 filterTimer.expires_from_now(boost::posix_time::seconds(3));
Cheng C Yang209ec562019-03-12 16:37:44 +08001037 filterTimer.async_wait([&](const boost::system::error_code& ec) {
1038 if (ec == boost::asio::error::operation_aborted)
1039 {
1040 return;
1041 }
Ed Tanous8a57ec02020-10-09 12:46:52 -07001042 if (ec)
Cheng C Yang209ec562019-03-12 16:37:44 +08001043 {
1044 std::cerr << "timer error\n";
1045 }
Zhikui Ren23c96e72020-11-05 22:32:28 -08001046 createSensors(io, objectServer, systemBus, sensorsChanged);
Cheng C Yang209ec562019-03-12 16:37:44 +08001047 });
1048 };
1049
1050 for (const char* type : sensorTypes)
1051 {
1052 auto match = std::make_unique<sdbusplus::bus::match::match>(
1053 static_cast<sdbusplus::bus::bus&>(*systemBus),
1054 "type='signal',member='PropertiesChanged',path_namespace='" +
1055 std::string(inventoryPath) + "',arg0namespace='" + type + "'",
1056 eventHandler);
1057 matches.emplace_back(std::move(match));
1058 }
Bruce Lee1263c3d2021-06-04 15:16:33 +08001059
1060 setupManufacturingModeMatch(*systemBus);
Cheng C Yang209ec562019-03-12 16:37:44 +08001061 io.run();
1062}