blob: 4f7eb06c61b736b42986eebdcf4cb424d889a506 [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";
Josh Lehan74d9bd92019-10-31 08:51:58 -0700636
637 bool customizedName = false;
638 auto findCustomName = baseConfig->second.find(keyName);
639 if (findCustomName != baseConfig->second.end())
Josh Lehan432d1ed2019-10-16 12:23:31 -0700640 {
Josh Lehan74d9bd92019-10-31 08:51:58 -0700641 try
642 {
643 psuProperty->labelTypeName = std::visit(
644 VariantToStringVisitor(), findCustomName->second);
645 }
Patrick Williams26601e82021-10-06 12:43:25 -0500646 catch (const std::invalid_argument&)
Josh Lehan74d9bd92019-10-31 08:51:58 -0700647 {
648 std::cerr << "Unable to parse " << keyName << "\n";
649 continue;
650 }
651
652 // All strings are valid, including empty string
653 customizedName = true;
654 }
655
656 bool customizedScale = false;
657 auto findCustomScale = baseConfig->second.find(keyScale);
658 if (findCustomScale != baseConfig->second.end())
659 {
660 try
661 {
662 psuProperty->sensorScaleFactor = std::visit(
663 VariantToUnsignedIntVisitor(), findCustomScale->second);
664 }
Patrick Williams26601e82021-10-06 12:43:25 -0500665 catch (const std::invalid_argument&)
Josh Lehan74d9bd92019-10-31 08:51:58 -0700666 {
667 std::cerr << "Unable to parse " << keyScale << "\n";
668 continue;
669 }
670
671 // Avoid later division by zero
672 if (psuProperty->sensorScaleFactor > 0)
673 {
674 customizedScale = true;
675 }
676 else
677 {
678 std::cerr << "Unable to accept " << keyScale << "\n";
679 continue;
680 }
681 }
682
683 auto findCustomMin = baseConfig->second.find(keyMin);
684 if (findCustomMin != baseConfig->second.end())
685 {
686 try
687 {
688 psuProperty->minReading = std::visit(
689 VariantToDoubleVisitor(), findCustomMin->second);
690 }
Patrick Williams26601e82021-10-06 12:43:25 -0500691 catch (const std::invalid_argument&)
Josh Lehan74d9bd92019-10-31 08:51:58 -0700692 {
693 std::cerr << "Unable to parse " << keyMin << "\n";
694 continue;
695 }
696 }
697
698 auto findCustomMax = baseConfig->second.find(keyMax);
699 if (findCustomMax != baseConfig->second.end())
700 {
701 try
702 {
703 psuProperty->maxReading = std::visit(
704 VariantToDoubleVisitor(), findCustomMax->second);
705 }
Patrick Williams26601e82021-10-06 12:43:25 -0500706 catch (const std::invalid_argument&)
Josh Lehan74d9bd92019-10-31 08:51:58 -0700707 {
708 std::cerr << "Unable to parse " << keyMax << "\n";
709 continue;
710 }
711 }
712
Jeff Line41d52f2021-04-07 19:38:51 +0800713 auto findCustomOffset = baseConfig->second.find(keyOffset);
714 if (findCustomOffset != baseConfig->second.end())
715 {
716 try
717 {
718 psuProperty->sensorOffset = std::visit(
719 VariantToDoubleVisitor(), findCustomOffset->second);
720 }
Patrick Williams26601e82021-10-06 12:43:25 -0500721 catch (const std::invalid_argument&)
Jeff Line41d52f2021-04-07 19:38:51 +0800722 {
723 std::cerr << "Unable to parse " << keyOffset << "\n";
724 continue;
725 }
726 }
727
Josh Lehan74d9bd92019-10-31 08:51:58 -0700728 if (!(psuProperty->minReading < psuProperty->maxReading))
729 {
730 std::cerr << "Min must be less than Max\n";
731 continue;
732 }
733
734 // If the sensor name is being customized by config file,
735 // then prefix/suffix composition becomes not necessary,
736 // and in fact not wanted, because it gets in the way.
737 std::string psuNameFromIndex;
738 if (!customizedName)
739 {
740 /* Find out sensor name index for this label */
741 std::regex rgx("[A-Za-z]+([0-9]+)");
Brad Bishopfbb44ad2019-11-08 09:42:37 -0500742 size_t nameIndex{0};
Josh Lehan74d9bd92019-10-31 08:51:58 -0700743 if (std::regex_search(labelHead, matches, rgx))
744 {
745 nameIndex = std::stoi(matches[1]);
746
747 // Decrement to preserve alignment, because hwmon
748 // human-readable filenames and labels use 1-based
749 // numbering, but the "Name", "Name1", "Name2", etc. naming
750 // convention (the psuNames vector) uses 0-based numbering.
751 if (nameIndex > 0)
752 {
753 --nameIndex;
754 }
755 }
756 else
757 {
758 nameIndex = 0;
759 }
760
761 if (psuNames.size() <= nameIndex)
762 {
763 std::cerr << "Could not pair " << labelHead
764 << " with a Name field\n";
765 continue;
766 }
767
768 psuNameFromIndex = psuNames[nameIndex];
769
Ed Tanous8a57ec02020-10-09 12:46:52 -0700770 if constexpr (debug)
Josh Lehan74d9bd92019-10-31 08:51:58 -0700771 {
772 std::cerr << "Sensor label head " << labelHead
773 << " paired with " << psuNameFromIndex
774 << " at index " << nameIndex << "\n";
775 }
Josh Lehan432d1ed2019-10-16 12:23:31 -0700776 }
777
Cheng C Yang58b2b532019-05-31 00:19:45 +0800778 checkEventLimits(sensorPathStr, limitEventMatch, eventPathList);
779
Josh Lehan74d9bd92019-10-31 08:51:58 -0700780 // Similarly, if sensor scaling factor is being customized,
781 // then the below power-of-10 constraint becomes unnecessary,
782 // as config should be able to specify an arbitrary divisor.
783 unsigned int factor = psuProperty->sensorScaleFactor;
784 if (!customizedScale)
Vijay Khemka53ca4442019-07-23 11:03:55 -0700785 {
Josh Lehan74d9bd92019-10-31 08:51:58 -0700786 // Preserve existing usage of hardcoded labelMatch table below
787 factor = std::pow(10.0, factor);
Vijay Khemka53ca4442019-07-23 11:03:55 -0700788
Josh Lehan74d9bd92019-10-31 08:51:58 -0700789 /* Change first char of substring to uppercase */
Ed Tanous8a57ec02020-10-09 12:46:52 -0700790 char firstChar =
791 static_cast<char>(std::toupper(sensorNameSubStr[0]));
Josh Lehan74d9bd92019-10-31 08:51:58 -0700792 std::string strScaleFactor =
793 firstChar + sensorNameSubStr.substr(1) + "ScaleFactor";
794
795 // Preserve existing configs by accepting earlier syntax,
796 // example CurrScaleFactor, PowerScaleFactor, ...
797 auto findScaleFactor = baseConfig->second.find(strScaleFactor);
798 if (findScaleFactor != baseConfig->second.end())
799 {
800 factor = std::visit(VariantToIntVisitor(),
801 findScaleFactor->second);
802 }
803
Ed Tanous8a57ec02020-10-09 12:46:52 -0700804 if constexpr (debug)
Josh Lehan74d9bd92019-10-31 08:51:58 -0700805 {
806 std::cerr << "Sensor scaling factor " << factor
807 << " string " << strScaleFactor << "\n";
808 }
Josh Lehan49cfba92019-10-08 16:50:42 -0700809 }
810
Vijay Khemka996bad12019-05-28 15:15:16 -0700811 std::vector<thresholds::Threshold> sensorThresholds;
Joshi, Mansi14f0ad82019-11-21 10:52:30 +0530812 if (!parseThresholdsFromConfig(*sensorData, sensorThresholds,
813 &labelHead))
Cheng C Yange50345b2019-04-02 17:26:15 +0800814 {
James Feist17ab6e02019-06-25 12:28:13 -0700815 std::cerr << "error populating thresholds for "
816 << sensorNameSubStr << "\n";
Cheng C Yange50345b2019-04-02 17:26:15 +0800817 }
818
Zev Weiss6b6891c2021-04-22 02:46:21 -0500819 auto findSensorUnit = sensorTable.find(sensorNameSubStr);
820 if (findSensorUnit == sensorTable.end())
Cheng C Yange50345b2019-04-02 17:26:15 +0800821 {
Jason Ling5747fab2019-10-02 16:46:23 -0700822 std::cerr << sensorNameSubStr
Josh Lehan06494452019-10-31 09:49:16 -0700823 << " is not a recognized sensor type\n";
Cheng C Yange50345b2019-04-02 17:26:15 +0800824 continue;
825 }
826
Ed Tanous8a57ec02020-10-09 12:46:52 -0700827 if constexpr (debug)
Josh Lehan49cfba92019-10-08 16:50:42 -0700828 {
Josh Lehan74d9bd92019-10-31 08:51:58 -0700829 std::cerr << "Sensor properties: Name \""
830 << psuProperty->labelTypeName << "\" Scale "
831 << psuProperty->sensorScaleFactor << " Min "
832 << psuProperty->minReading << " Max "
Jeff Line41d52f2021-04-07 19:38:51 +0800833 << psuProperty->maxReading << " Offset "
834 << psuProperty->sensorOffset << "\n";
Josh Lehan74d9bd92019-10-31 08:51:58 -0700835 }
836
837 std::string sensorName = psuProperty->labelTypeName;
838 if (customizedName)
839 {
840 if (sensorName.empty())
841 {
842 // Allow selective disabling of an individual sensor,
843 // by customizing its name to an empty string.
844 std::cerr << "Sensor disabled, empty string\n";
845 continue;
846 }
847 }
848 else
849 {
850 // Sensor name not customized, do prefix/suffix composition,
851 // preserving default behavior by using psuNameFromIndex.
852 sensorName =
853 psuNameFromIndex + " " + psuProperty->labelTypeName;
854 }
855
Ed Tanous8a57ec02020-10-09 12:46:52 -0700856 if constexpr (debug)
Josh Lehan74d9bd92019-10-31 08:51:58 -0700857 {
858 std::cerr << "Sensor name \"" << sensorName << "\" path \""
859 << sensorPathStr << "\" type \"" << sensorType
860 << "\"\n";
Josh Lehan49cfba92019-10-08 16:50:42 -0700861 }
Zhikui Ren23c96e72020-11-05 22:32:28 -0800862 // destruct existing one first if already created
863 sensors[sensorName] = nullptr;
Yong Libf8b1da2020-04-15 16:32:50 +0800864 sensors[sensorName] = std::make_shared<PSUSensor>(
Cheng C Yange50345b2019-04-02 17:26:15 +0800865 sensorPathStr, sensorType, objectServer, dbusConnection, io,
Cheng C Yang209ec562019-03-12 16:37:44 +0800866 sensorName, std::move(sensorThresholds), *interfacePath,
Konstantin Aladyshevc7a1ae62021-04-30 08:50:43 +0000867 readState, findSensorUnit->second, factor,
868 psuProperty->maxReading, psuProperty->minReading,
869 psuProperty->sensorOffset, labelHead, thresholdConfSize,
870 pollRate);
Yong Libf8b1da2020-04-15 16:32:50 +0800871 sensors[sensorName]->setupRead();
Josh Lehan74d9bd92019-10-31 08:51:58 -0700872 ++numCreated;
Ed Tanous8a57ec02020-10-09 12:46:52 -0700873 if constexpr (debug)
Josh Lehan74d9bd92019-10-31 08:51:58 -0700874 {
875 std::cerr << "Created " << numCreated << " sensors so far\n";
876 }
Cheng C Yang209ec562019-03-12 16:37:44 +0800877 }
Cheng C Yang58b2b532019-05-31 00:19:45 +0800878
879 // OperationalStatus event
Cheng C Yang92498eb2019-09-26 21:59:25 +0800880 combineEvents[*psuName + "OperationalStatus"] = nullptr;
Cheng C Yang58b2b532019-05-31 00:19:45 +0800881 combineEvents[*psuName + "OperationalStatus"] =
Konstantin Aladyshevc7a1ae62021-04-30 08:50:43 +0000882 std::make_unique<PSUCombineEvent>(objectServer, dbusConnection, io,
883 *psuName, readState,
884 eventPathList, groupEventPathList,
885 "OperationalStatus", pollRate);
Cheng C Yang209ec562019-03-12 16:37:44 +0800886 }
Josh Lehan49cfba92019-10-08 16:50:42 -0700887
Ed Tanous8a57ec02020-10-09 12:46:52 -0700888 if constexpr (debug)
Josh Lehan49cfba92019-10-08 16:50:42 -0700889 {
890 std::cerr << "Created total of " << numCreated << " sensors\n";
891 }
Cheng C Yang209ec562019-03-12 16:37:44 +0800892 return;
893}
894
Zhikui Ren23c96e72020-11-05 22:32:28 -0800895void createSensors(
896 boost::asio::io_service& io, sdbusplus::asio::object_server& objectServer,
897 std::shared_ptr<sdbusplus::asio::connection>& dbusConnection,
898 const std::shared_ptr<boost::container::flat_set<std::string>>&
899 sensorsChanged)
900{
901 auto getter = std::make_shared<GetSensorConfiguration>(
902 dbusConnection, [&io, &objectServer, &dbusConnection, sensorsChanged](
903 const ManagedObjectType& sensorConfigs) {
904 createSensorsCallback(io, objectServer, dbusConnection,
905 sensorConfigs, sensorsChanged);
906 });
907 getter->getConfiguration(
908 std::vector<std::string>(sensorTypes.begin(), sensorTypes.end()));
909}
910
Cheng C Yang916360b2019-05-07 18:47:16 +0800911void propertyInitialize(void)
Cheng C Yang209ec562019-03-12 16:37:44 +0800912{
Zev Weiss6b6891c2021-04-22 02:46:21 -0500913 sensorTable = {{"power", sensor_paths::unitWatts},
914 {"curr", sensor_paths::unitAmperes},
915 {"temp", sensor_paths::unitDegreesC},
916 {"in", sensor_paths::unitVolts},
917 {"fan", sensor_paths::unitRPMs}};
Cheng C Yange50345b2019-04-02 17:26:15 +0800918
Jeff Line41d52f2021-04-07 19:38:51 +0800919 labelMatch = {
920 {"pin", PSUProperty("Input Power", 3000, 0, 6, 0)},
921 {"pout1", PSUProperty("Output Power", 3000, 0, 6, 0)},
922 {"pout2", PSUProperty("Output Power", 3000, 0, 6, 0)},
923 {"pout3", PSUProperty("Output Power", 3000, 0, 6, 0)},
924 {"power1", PSUProperty("Output Power", 3000, 0, 6, 0)},
925 {"maxpin", PSUProperty("Max Input Power", 3000, 0, 6, 0)},
926 {"vin", PSUProperty("Input Voltage", 300, 0, 3, 0)},
927 {"maxvin", PSUProperty("Max Input Voltage", 300, 0, 3, 0)},
928 {"vout1", PSUProperty("Output Voltage", 255, 0, 3, 0)},
929 {"vout2", PSUProperty("Output Voltage", 255, 0, 3, 0)},
930 {"vout3", PSUProperty("Output Voltage", 255, 0, 3, 0)},
931 {"vout4", PSUProperty("Output Voltage", 255, 0, 3, 0)},
932 {"vout5", PSUProperty("Output Voltage", 255, 0, 3, 0)},
933 {"vout6", PSUProperty("Output Voltage", 255, 0, 3, 0)},
934 {"vout7", PSUProperty("Output Voltage", 255, 0, 3, 0)},
935 {"vout8", PSUProperty("Output Voltage", 255, 0, 3, 0)},
936 {"vout9", PSUProperty("Output Voltage", 255, 0, 3, 0)},
937 {"vout10", PSUProperty("Output Voltage", 255, 0, 3, 0)},
938 {"vout11", PSUProperty("Output Voltage", 255, 0, 3, 0)},
939 {"vout12", PSUProperty("Output Voltage", 255, 0, 3, 0)},
940 {"vout13", PSUProperty("Output Voltage", 255, 0, 3, 0)},
941 {"vout14", PSUProperty("Output Voltage", 255, 0, 3, 0)},
942 {"vout15", PSUProperty("Output Voltage", 255, 0, 3, 0)},
943 {"vout16", PSUProperty("Output Voltage", 255, 0, 3, 0)},
944 {"vout17", PSUProperty("Output Voltage", 255, 0, 3, 0)},
945 {"vout18", PSUProperty("Output Voltage", 255, 0, 3, 0)},
946 {"vout19", PSUProperty("Output Voltage", 255, 0, 3, 0)},
947 {"vout20", PSUProperty("Output Voltage", 255, 0, 3, 0)},
948 {"vout21", PSUProperty("Output Voltage", 255, 0, 3, 0)},
949 {"vout22", PSUProperty("Output Voltage", 255, 0, 3, 0)},
950 {"vout23", PSUProperty("Output Voltage", 255, 0, 3, 0)},
951 {"vout24", PSUProperty("Output Voltage", 255, 0, 3, 0)},
952 {"vout25", PSUProperty("Output Voltage", 255, 0, 3, 0)},
953 {"vout26", PSUProperty("Output Voltage", 255, 0, 3, 0)},
954 {"vout27", PSUProperty("Output Voltage", 255, 0, 3, 0)},
955 {"vout28", PSUProperty("Output Voltage", 255, 0, 3, 0)},
956 {"vout29", PSUProperty("Output Voltage", 255, 0, 3, 0)},
957 {"vout30", PSUProperty("Output Voltage", 255, 0, 3, 0)},
958 {"vout31", PSUProperty("Output Voltage", 255, 0, 3, 0)},
959 {"vout32", PSUProperty("Output Voltage", 255, 0, 3, 0)},
960 {"vmon", PSUProperty("Auxiliary Input Voltage", 255, 0, 3, 0)},
961 {"in1", PSUProperty("Output Voltage", 255, 0, 3, 0)},
962 {"iin", PSUProperty("Input Current", 20, 0, 3, 0)},
963 {"iout1", PSUProperty("Output Current", 255, 0, 3, 0)},
964 {"iout2", PSUProperty("Output Current", 255, 0, 3, 0)},
965 {"iout3", PSUProperty("Output Current", 255, 0, 3, 0)},
966 {"iout4", PSUProperty("Output Current", 255, 0, 3, 0)},
967 {"iout5", PSUProperty("Output Current", 255, 0, 3, 0)},
968 {"iout6", PSUProperty("Output Current", 255, 0, 3, 0)},
969 {"iout7", PSUProperty("Output Current", 255, 0, 3, 0)},
970 {"iout8", PSUProperty("Output Current", 255, 0, 3, 0)},
971 {"iout9", PSUProperty("Output Current", 255, 0, 3, 0)},
972 {"iout10", PSUProperty("Output Current", 255, 0, 3, 0)},
973 {"iout11", PSUProperty("Output Current", 255, 0, 3, 0)},
974 {"iout12", PSUProperty("Output Current", 255, 0, 3, 0)},
975 {"iout13", PSUProperty("Output Current", 255, 0, 3, 0)},
976 {"iout14", PSUProperty("Output Current", 255, 0, 3, 0)},
977 {"curr1", PSUProperty("Output Current", 255, 0, 3, 0)},
978 {"maxiout1", PSUProperty("Max Output Current", 255, 0, 3, 0)},
979 {"temp1", PSUProperty("Temperature", 127, -128, 3, 0)},
980 {"temp2", PSUProperty("Temperature", 127, -128, 3, 0)},
981 {"temp3", PSUProperty("Temperature", 127, -128, 3, 0)},
982 {"temp4", PSUProperty("Temperature", 127, -128, 3, 0)},
983 {"temp5", PSUProperty("Temperature", 127, -128, 3, 0)},
984 {"temp6", PSUProperty("Temperature", 127, -128, 3, 0)},
985 {"maxtemp1", PSUProperty("Max Temperature", 127, -128, 3, 0)},
986 {"fan1", PSUProperty("Fan Speed 1", 30000, 0, 0, 0)},
987 {"fan2", PSUProperty("Fan Speed 2", 30000, 0, 0, 0)}};
Cheng C Yang916360b2019-05-07 18:47:16 +0800988
989 pwmTable = {{"fan1", "Fan_1"}, {"fan2", "Fan_2"}};
Cheng C Yang58b2b532019-05-31 00:19:45 +0800990
991 limitEventMatch = {{"PredictiveFailure", {"max_alarm", "min_alarm"}},
992 {"Failure", {"crit_alarm", "lcrit_alarm"}}};
993
Cheng C Yang202a1ff2020-01-09 09:34:22 +0800994 eventMatch = {{"PredictiveFailure", {"power1_alarm"}},
995 {"Failure", {"in2_alarm"}},
996 {"ACLost", {"in1_beep"}},
997 {"ConfigureError", {"in1_fault"}}};
998
999 groupEventMatch = {{"FanFault",
1000 {{"fan1", {"fan1_alarm", "fan1_fault"}},
1001 {"fan2", {"fan2_alarm", "fan2_fault"}}}}};
Cheng C Yang209ec562019-03-12 16:37:44 +08001002}
1003
James Feistb6c0b912019-07-09 12:21:44 -07001004int main()
Cheng C Yang209ec562019-03-12 16:37:44 +08001005{
1006 boost::asio::io_service io;
1007 auto systemBus = std::make_shared<sdbusplus::asio::connection>(io);
1008
1009 systemBus->request_name("xyz.openbmc_project.PSUSensor");
1010 sdbusplus::asio::object_server objectServer(systemBus);
Cheng C Yang209ec562019-03-12 16:37:44 +08001011 std::vector<std::unique_ptr<sdbusplus::bus::match::match>> matches;
Zhikui Ren23c96e72020-11-05 22:32:28 -08001012 auto sensorsChanged =
1013 std::make_shared<boost::container::flat_set<std::string>>();
Cheng C Yang209ec562019-03-12 16:37:44 +08001014
Cheng C Yang916360b2019-05-07 18:47:16 +08001015 propertyInitialize();
Cheng C Yang209ec562019-03-12 16:37:44 +08001016
Zhikui Ren23c96e72020-11-05 22:32:28 -08001017 io.post([&]() { createSensors(io, objectServer, systemBus, nullptr); });
Cheng C Yang209ec562019-03-12 16:37:44 +08001018 boost::asio::deadline_timer filterTimer(io);
1019 std::function<void(sdbusplus::message::message&)> eventHandler =
1020 [&](sdbusplus::message::message& message) {
1021 if (message.is_method_error())
1022 {
1023 std::cerr << "callback method error\n";
1024 return;
1025 }
Zhikui Ren23c96e72020-11-05 22:32:28 -08001026 sensorsChanged->insert(message.get_path());
Cheng C Yanga97f1342020-02-11 15:10:41 +08001027 filterTimer.expires_from_now(boost::posix_time::seconds(3));
Cheng C Yang209ec562019-03-12 16:37:44 +08001028 filterTimer.async_wait([&](const boost::system::error_code& ec) {
1029 if (ec == boost::asio::error::operation_aborted)
1030 {
1031 return;
1032 }
Ed Tanous8a57ec02020-10-09 12:46:52 -07001033 if (ec)
Cheng C Yang209ec562019-03-12 16:37:44 +08001034 {
1035 std::cerr << "timer error\n";
1036 }
Zhikui Ren23c96e72020-11-05 22:32:28 -08001037 createSensors(io, objectServer, systemBus, sensorsChanged);
Cheng C Yang209ec562019-03-12 16:37:44 +08001038 });
1039 };
1040
1041 for (const char* type : sensorTypes)
1042 {
1043 auto match = std::make_unique<sdbusplus::bus::match::match>(
1044 static_cast<sdbusplus::bus::bus&>(*systemBus),
1045 "type='signal',member='PropertiesChanged',path_namespace='" +
1046 std::string(inventoryPath) + "',arg0namespace='" + type + "'",
1047 eventHandler);
1048 matches.emplace_back(std::move(match));
1049 }
Bruce Lee1263c3d2021-06-04 15:16:33 +08001050
1051 setupManufacturingModeMatch(*systemBus);
Cheng C Yang209ec562019-03-12 16:37:44 +08001052 io.run();
1053}