blob: f7c6f1083e3f675dc9cdcca2e7af3357ac2a03c9 [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
Zev Weisseb0b84d2021-04-22 15:03:38 -050043static constexpr std::array<const char*, 24> sensorTypes = {
Josh Lehan62084c82020-06-22 15:27:12 -070044 "xyz.openbmc_project.Configuration.ADM1272",
Paul Fertser678f53b2021-04-06 07:06:28 +000045 "xyz.openbmc_project.Configuration.ADM1275",
Josh Lehan62084c82020-06-22 15:27:12 -070046 "xyz.openbmc_project.Configuration.ADM1278",
Jeff Lina0683a82021-02-22 13:56:55 +080047 "xyz.openbmc_project.Configuration.DPS800",
Josh Lehan62084c82020-06-22 15:27:12 -070048 "xyz.openbmc_project.Configuration.INA219",
Devjit Gopalpurde65ef72019-10-30 04:47:35 -070049 "xyz.openbmc_project.Configuration.INA230",
Alex Qiu6690d8f2020-01-22 17:56:33 -080050 "xyz.openbmc_project.Configuration.ISL68137",
Jason Lingdfad1ff2020-07-29 15:43:11 -070051 "xyz.openbmc_project.Configuration.ISL68220",
Gaurav Gandhi49585582020-12-22 01:01:24 +000052 "xyz.openbmc_project.Configuration.ISL68223",
53 "xyz.openbmc_project.Configuration.ISL69243",
Jeff Lina0683a82021-02-22 13:56:55 +080054 "xyz.openbmc_project.Configuration.ISL69260",
Zev Weisseb0b84d2021-04-22 15:03:38 -050055 "xyz.openbmc_project.Configuration.LM25066",
Alex Qiuf5709b42020-01-29 13:29:50 -080056 "xyz.openbmc_project.Configuration.MAX16601",
Gaurav Gandhi49585582020-12-22 01:01:24 +000057 "xyz.openbmc_project.Configuration.MAX20710",
Alex Qiu6690d8f2020-01-22 17:56:33 -080058 "xyz.openbmc_project.Configuration.MAX20730",
59 "xyz.openbmc_project.Configuration.MAX20734",
60 "xyz.openbmc_project.Configuration.MAX20796",
61 "xyz.openbmc_project.Configuration.MAX34451",
Josh Lehan62084c82020-06-22 15:27:12 -070062 "xyz.openbmc_project.Configuration.pmbus",
63 "xyz.openbmc_project.Configuration.PXE1610",
Jeff Lina0683a82021-02-22 13:56:55 +080064 "xyz.openbmc_project.Configuration.RAA228000",
65 "xyz.openbmc_project.Configuration.RAA228228",
66 "xyz.openbmc_project.Configuration.RAA229004",
67 "xyz.openbmc_project.Configuration.TPS546D24"};
Cheng C Yang209ec562019-03-12 16:37:44 +080068
Alex Qiu6690d8f2020-01-22 17:56:33 -080069static std::vector<std::string> pmbusNames = {
Zev Weisseb0b84d2021-04-22 15:03:38 -050070 "adm1272", "adm1275", "adm1278", "dps800", "ina219", "ina230",
71 "isl68137", "isl68220", "isl68223", "isl69243", "isl69260", "lm25066",
72 "max16601", "max20710", "max20730", "max20734", "max20796", "max34451",
73 "pmbus", "pxe1610", "raa228000", "raa228228", "raa229004", "tps546d24"};
Josh Lehan0830c7b2019-10-08 16:35:09 -070074
Cheng C Yang209ec562019-03-12 16:37:44 +080075namespace fs = std::filesystem;
76
Yong Libf8b1da2020-04-15 16:32:50 +080077static boost::container::flat_map<std::string, std::shared_ptr<PSUSensor>>
Cheng C Yang916360b2019-05-07 18:47:16 +080078 sensors;
Cheng C Yang58b2b532019-05-31 00:19:45 +080079static boost::container::flat_map<std::string, std::unique_ptr<PSUCombineEvent>>
80 combineEvents;
Cheng C Yang916360b2019-05-07 18:47:16 +080081static boost::container::flat_map<std::string, std::unique_ptr<PwmSensor>>
82 pwmSensors;
83static boost::container::flat_map<std::string, std::string> sensorTable;
84static boost::container::flat_map<std::string, PSUProperty> labelMatch;
85static boost::container::flat_map<std::string, std::string> pwmTable;
Cheng C Yang58b2b532019-05-31 00:19:45 +080086static boost::container::flat_map<std::string, std::vector<std::string>>
87 eventMatch;
Cheng C Yang202a1ff2020-01-09 09:34:22 +080088static boost::container::flat_map<
89 std::string,
90 boost::container::flat_map<std::string, std::vector<std::string>>>
91 groupEventMatch;
Cheng C Yang58b2b532019-05-31 00:19:45 +080092static boost::container::flat_map<std::string, std::vector<std::string>>
93 limitEventMatch;
94
Josh Lehan74d9bd92019-10-31 08:51:58 -070095static std::vector<PSUProperty> psuProperties;
96
Cheng C Yang58b2b532019-05-31 00:19:45 +080097// Function CheckEvent will check each attribute from eventMatch table in the
98// sysfs. If the attributes exists in sysfs, then store the complete path
99// of the attribute into eventPathList.
100void checkEvent(
101 const std::string& directory,
102 const boost::container::flat_map<std::string, std::vector<std::string>>&
103 eventMatch,
104 boost::container::flat_map<std::string, std::vector<std::string>>&
105 eventPathList)
106{
107 for (const auto& match : eventMatch)
108 {
109 const std::vector<std::string>& eventAttrs = match.second;
110 const std::string& eventName = match.first;
111 for (const auto& eventAttr : eventAttrs)
112 {
Ed Tanous8a57ec02020-10-09 12:46:52 -0700113 std::string eventPath = directory;
114 eventPath += "/";
115 eventPath += eventAttr;
Cheng C Yang58b2b532019-05-31 00:19:45 +0800116
117 std::ifstream eventFile(eventPath);
118 if (!eventFile.good())
119 {
120 continue;
121 }
122
123 eventPathList[eventName].push_back(eventPath);
124 }
125 }
126}
127
Cheng C Yang202a1ff2020-01-09 09:34:22 +0800128// Check Group Events which contains more than one targets in each combine
129// events.
130void checkGroupEvent(
131 const std::string& directory,
132 const boost::container::flat_map<
133 std::string,
134 boost::container::flat_map<std::string, std::vector<std::string>>>&
135 groupEventMatch,
136 boost::container::flat_map<
137 std::string,
138 boost::container::flat_map<std::string, std::vector<std::string>>>&
139 groupEventPathList)
140{
141 for (const auto& match : groupEventMatch)
142 {
143 const std::string& groupEventName = match.first;
144 const boost::container::flat_map<std::string, std::vector<std::string>>
145 events = match.second;
146 boost::container::flat_map<std::string, std::vector<std::string>>
147 pathList;
148 for (const auto& match : events)
149 {
150 const std::string& eventName = match.first;
151 const std::vector<std::string>& eventAttrs = match.second;
152 for (const auto& eventAttr : eventAttrs)
153 {
Ed Tanous8a57ec02020-10-09 12:46:52 -0700154 std::string eventPath = directory;
155 eventPath += "/";
156 eventPath += eventAttr;
Cheng C Yang202a1ff2020-01-09 09:34:22 +0800157 std::ifstream eventFile(eventPath);
158 if (!eventFile.good())
159 {
160 continue;
161 }
162
163 pathList[eventName].push_back(eventPath);
164 }
165 }
166 groupEventPathList[groupEventName] = pathList;
167 }
168}
169
Cheng C Yang58b2b532019-05-31 00:19:45 +0800170// Function checkEventLimits will check all the psu related xxx_input attributes
171// in sysfs to see if xxx_crit_alarm xxx_lcrit_alarm xxx_max_alarm
172// xxx_min_alarm exist, then store the existing paths of the alarm attributes
173// to eventPathList.
174void checkEventLimits(
175 const std::string& sensorPathStr,
176 const boost::container::flat_map<std::string, std::vector<std::string>>&
177 limitEventMatch,
178 boost::container::flat_map<std::string, std::vector<std::string>>&
179 eventPathList)
180{
Lei YUa2c7cea2020-12-23 14:07:28 +0800181 auto attributePartPos = sensorPathStr.find_last_of('_');
182 if (attributePartPos == std::string::npos)
183 {
184 // There is no '_' in the string, skip it
185 return;
186 }
187 auto attributePart =
188 std::string_view(sensorPathStr).substr(attributePartPos + 1);
189 if (attributePart != "input")
190 {
191 // If the sensor is not xxx_input, skip it
192 return;
193 }
194
195 auto prefixPart = sensorPathStr.substr(0, attributePartPos + 1);
Cheng C Yang58b2b532019-05-31 00:19:45 +0800196 for (const auto& limitMatch : limitEventMatch)
197 {
198 const std::vector<std::string>& limitEventAttrs = limitMatch.second;
199 const std::string& eventName = limitMatch.first;
200 for (const auto& limitEventAttr : limitEventAttrs)
201 {
Lei YUa2c7cea2020-12-23 14:07:28 +0800202 auto limitEventPath = prefixPart + limitEventAttr;
Cheng C Yang58b2b532019-05-31 00:19:45 +0800203 std::ifstream eventFile(limitEventPath);
204 if (!eventFile.good())
205 {
206 continue;
207 }
208 eventPathList[eventName].push_back(limitEventPath);
209 }
210 }
211}
Cheng C Yang916360b2019-05-07 18:47:16 +0800212
AppaRao Pulid9d8caf2020-02-27 20:56:59 +0530213static void
214 checkPWMSensor(const fs::path& sensorPath, std::string& labelHead,
215 const std::string& interfacePath,
216 std::shared_ptr<sdbusplus::asio::connection>& dbusConnection,
217 sdbusplus::asio::object_server& objectServer,
218 const std::string& psuName)
Cheng C Yang916360b2019-05-07 18:47:16 +0800219{
220 for (const auto& pwmName : pwmTable)
221 {
222 if (pwmName.first != labelHead)
223 {
224 continue;
225 }
226
227 const std::string& sensorPathStr = sensorPath.string();
228 const std::string& pwmPathStr =
229 boost::replace_all_copy(sensorPathStr, "input", "target");
230 std::ifstream pwmFile(pwmPathStr);
231 if (!pwmFile.good())
232 {
233 continue;
234 }
235
236 auto findPWMSensor = pwmSensors.find(psuName + labelHead);
237 if (findPWMSensor != pwmSensors.end())
238 {
239 continue;
240 }
241
242 pwmSensors[psuName + labelHead] = std::make_unique<PwmSensor>(
AppaRao Pulid9d8caf2020-02-27 20:56:59 +0530243 "Pwm_" + psuName + "_" + pwmName.second, pwmPathStr, dbusConnection,
244 objectServer, interfacePath + "_" + pwmName.second, "PSU");
Cheng C Yang916360b2019-05-07 18:47:16 +0800245 }
246}
247
Zhikui Ren23c96e72020-11-05 22:32:28 -0800248static void createSensorsCallback(
249 boost::asio::io_service& io, sdbusplus::asio::object_server& objectServer,
250 std::shared_ptr<sdbusplus::asio::connection>& dbusConnection,
251 const ManagedObjectType& sensorConfigs,
252 const std::shared_ptr<boost::container::flat_set<std::string>>&
253 sensorsChanged)
Cheng C Yang209ec562019-03-12 16:37:44 +0800254{
Josh Lehan49cfba92019-10-08 16:50:42 -0700255 int numCreated = 0;
Zhikui Ren23c96e72020-11-05 22:32:28 -0800256 bool firstScan = sensorsChanged == nullptr;
Cheng C Yang209ec562019-03-12 16:37:44 +0800257
258 std::vector<fs::path> pmbusPaths;
259 if (!findFiles(fs::path("/sys/class/hwmon"), "name", pmbusPaths))
260 {
261 std::cerr << "No PSU sensors in system\n";
262 return;
263 }
264
265 boost::container::flat_set<std::string> directories;
266 for (const auto& pmbusPath : pmbusPaths)
267 {
Cheng C Yang58b2b532019-05-31 00:19:45 +0800268 boost::container::flat_map<std::string, std::vector<std::string>>
269 eventPathList;
Cheng C Yang202a1ff2020-01-09 09:34:22 +0800270 boost::container::flat_map<
271 std::string,
272 boost::container::flat_map<std::string, std::vector<std::string>>>
273 groupEventPathList;
Cheng C Yang58b2b532019-05-31 00:19:45 +0800274
275 std::ifstream nameFile(pmbusPath);
276 if (!nameFile.good())
277 {
Josh Lehan49cfba92019-10-08 16:50:42 -0700278 std::cerr << "Failure finding pmbus path " << pmbusPath << "\n";
Cheng C Yang58b2b532019-05-31 00:19:45 +0800279 continue;
280 }
281
282 std::string pmbusName;
283 std::getline(nameFile, pmbusName);
284 nameFile.close();
Vijay Khemka996bad12019-05-28 15:15:16 -0700285
286 if (std::find(pmbusNames.begin(), pmbusNames.end(), pmbusName) ==
287 pmbusNames.end())
Cheng C Yang58b2b532019-05-31 00:19:45 +0800288 {
Josh Lehan49cfba92019-10-08 16:50:42 -0700289 // To avoid this error message, add your driver name to
290 // the pmbusNames vector at the top of this file.
291 std::cerr << "Driver name " << pmbusName
292 << " not found in sensor whitelist\n";
Cheng C Yang58b2b532019-05-31 00:19:45 +0800293 continue;
294 }
295
296 const std::string* psuName;
Cheng C Yang209ec562019-03-12 16:37:44 +0800297 auto directory = pmbusPath.parent_path();
298
299 auto ret = directories.insert(directory.string());
300 if (!ret.second)
301 {
Josh Lehan49cfba92019-10-08 16:50:42 -0700302 std::cerr << "Duplicate path " << directory.string() << "\n";
Cheng C Yang58b2b532019-05-31 00:19:45 +0800303 continue; // check if path has already been searched
Cheng C Yang209ec562019-03-12 16:37:44 +0800304 }
305
James Feistb6c0b912019-07-09 12:21:44 -0700306 fs::path device = directory / "device";
Cheng C Yang209ec562019-03-12 16:37:44 +0800307 std::string deviceName = fs::canonical(device).stem();
Ed Tanous8a57ec02020-10-09 12:46:52 -0700308 auto findHyphen = deviceName.find('-');
Cheng C Yang209ec562019-03-12 16:37:44 +0800309 if (findHyphen == std::string::npos)
310 {
311 std::cerr << "found bad device" << deviceName << "\n";
312 continue;
313 }
314 std::string busStr = deviceName.substr(0, findHyphen);
315 std::string addrStr = deviceName.substr(findHyphen + 1);
316
317 size_t bus = 0;
318 size_t addr = 0;
319
320 try
321 {
322 bus = std::stoi(busStr);
Ed Tanous8a57ec02020-10-09 12:46:52 -0700323 addr = std::stoi(addrStr, nullptr, 16);
Cheng C Yang209ec562019-03-12 16:37:44 +0800324 }
James Feistb6c0b912019-07-09 12:21:44 -0700325 catch (std::invalid_argument&)
Cheng C Yang209ec562019-03-12 16:37:44 +0800326 {
Josh Lehan49cfba92019-10-08 16:50:42 -0700327 std::cerr << "Error parsing bus " << busStr << " addr " << addrStr
328 << "\n";
Cheng C Yang209ec562019-03-12 16:37:44 +0800329 continue;
330 }
331
Cheng C Yang209ec562019-03-12 16:37:44 +0800332 const std::pair<std::string, boost::container::flat_map<
333 std::string, BasicVariantType>>*
334 baseConfig = nullptr;
335 const SensorData* sensorData = nullptr;
336 const std::string* interfacePath = nullptr;
337 const char* sensorType = nullptr;
Cheng C Yang6b1247a2020-03-09 23:48:39 +0800338 size_t thresholdConfSize = 0;
Cheng C Yang209ec562019-03-12 16:37:44 +0800339
340 for (const std::pair<sdbusplus::message::object_path, SensorData>&
341 sensor : sensorConfigs)
342 {
343 sensorData = &(sensor.second);
344 for (const char* type : sensorTypes)
345 {
346 auto sensorBase = sensorData->find(type);
347 if (sensorBase != sensorData->end())
348 {
349 baseConfig = &(*sensorBase);
350 sensorType = type;
351 break;
352 }
353 }
354 if (baseConfig == nullptr)
355 {
356 std::cerr << "error finding base configuration for "
357 << deviceName << "\n";
358 continue;
359 }
360
361 auto configBus = baseConfig->second.find("Bus");
362 auto configAddress = baseConfig->second.find("Address");
363
364 if (configBus == baseConfig->second.end() ||
365 configAddress == baseConfig->second.end())
366 {
Cheng C Yang58b2b532019-05-31 00:19:45 +0800367 std::cerr << "error finding necessary entry in configuration\n";
Cheng C Yang209ec562019-03-12 16:37:44 +0800368 continue;
369 }
370
Cheng C Yang58b2b532019-05-31 00:19:45 +0800371 const uint64_t* confBus;
372 const uint64_t* confAddr;
373 if (!(confBus = std::get_if<uint64_t>(&(configBus->second))) ||
374 !(confAddr = std::get_if<uint64_t>(&(configAddress->second))))
375 {
376 std::cerr
Josh Lehan49cfba92019-10-08 16:50:42 -0700377 << "Cannot get bus or address, invalid configuration\n";
Cheng C Yang58b2b532019-05-31 00:19:45 +0800378 continue;
379 }
380
381 if ((*confBus != bus) || (*confAddr != addr))
Cheng C Yang209ec562019-03-12 16:37:44 +0800382 {
Josh Lehan432d1ed2019-10-16 12:23:31 -0700383 std::cerr << "Configuration skipping " << *confBus << "-"
384 << *confAddr << " because not " << bus << "-" << addr
385 << "\n";
Cheng C Yang209ec562019-03-12 16:37:44 +0800386 continue;
387 }
388
Cheng C Yang6b1247a2020-03-09 23:48:39 +0800389 std::vector<thresholds::Threshold> confThresholds;
390 if (!parseThresholdsFromConfig(*sensorData, confThresholds))
391 {
392 std::cerr << "error populating totoal thresholds\n";
393 }
394 thresholdConfSize = confThresholds.size();
395
Cheng C Yang209ec562019-03-12 16:37:44 +0800396 interfacePath = &(sensor.first.str);
397 break;
398 }
399 if (interfacePath == nullptr)
400 {
Josh Lehan49cfba92019-10-08 16:50:42 -0700401 // To avoid this error message, add your export map entry,
402 // from Entity Manager, to sensorTypes at the top of this file.
Cheng C Yang209ec562019-03-12 16:37:44 +0800403 std::cerr << "failed to find match for " << deviceName << "\n";
404 continue;
405 }
406
Cheng C Yange50345b2019-04-02 17:26:15 +0800407 auto findPSUName = baseConfig->second.find("Name");
408 if (findPSUName == baseConfig->second.end())
Cheng C Yang209ec562019-03-12 16:37:44 +0800409 {
410 std::cerr << "could not determine configuration name for "
411 << deviceName << "\n";
412 continue;
413 }
414
Cheng C Yang58b2b532019-05-31 00:19:45 +0800415 if (!(psuName = std::get_if<std::string>(&(findPSUName->second))))
416 {
417 std::cerr << "Cannot find psu name, invalid configuration\n";
418 continue;
419 }
Zhikui Ren23c96e72020-11-05 22:32:28 -0800420
421 // on rescans, only update sensors we were signaled by
422 if (!firstScan)
423 {
424 std::string psuNameStr = "/" + *psuName;
425 auto it =
426 std::find_if(sensorsChanged->begin(), sensorsChanged->end(),
427 [psuNameStr](std::string& s) {
428 return boost::ends_with(s, psuNameStr);
429 });
430
431 if (it == sensorsChanged->end())
432 {
433 continue;
434 }
435 sensorsChanged->erase(it);
436 }
Cheng C Yang58b2b532019-05-31 00:19:45 +0800437 checkEvent(directory.string(), eventMatch, eventPathList);
Cheng C Yang202a1ff2020-01-09 09:34:22 +0800438 checkGroupEvent(directory.string(), groupEventMatch,
439 groupEventPathList);
Cheng C Yang58b2b532019-05-31 00:19:45 +0800440
Vijay Khemka996bad12019-05-28 15:15:16 -0700441 /* Check if there are more sensors in the same interface */
442 int i = 1;
443 std::vector<std::string> psuNames;
444 do
445 {
Josh Lehan49cfba92019-10-08 16:50:42 -0700446 // Individual string fields: Name, Name1, Name2, Name3, ...
Vijay Khemka996bad12019-05-28 15:15:16 -0700447 psuNames.push_back(std::get<std::string>(findPSUName->second));
448 findPSUName = baseConfig->second.find("Name" + std::to_string(i++));
449 } while (findPSUName != baseConfig->second.end());
450
Cheng C Yange50345b2019-04-02 17:26:15 +0800451 std::vector<fs::path> sensorPaths;
James Feistb6c0b912019-07-09 12:21:44 -0700452 if (!findFiles(directory, R"(\w\d+_input$)", sensorPaths, 0))
Cheng C Yang209ec562019-03-12 16:37:44 +0800453 {
Cheng C Yange50345b2019-04-02 17:26:15 +0800454 std::cerr << "No PSU non-label sensor in PSU\n";
Cheng C Yang209ec562019-03-12 16:37:44 +0800455 continue;
456 }
457
Manikandan Elumalaic7e95622020-06-03 20:22:01 +0530458 /* read max value in sysfs for in, curr, power, temp, ... */
459 if (!findFiles(directory, R"(\w\d+_max$)", sensorPaths, 0))
460 {
Ed Tanous8a57ec02020-10-09 12:46:52 -0700461 if constexpr (debug)
Manikandan Elumalaic7e95622020-06-03 20:22:01 +0530462 {
463 std::cerr << "No max name in PSU \n";
464 }
465 }
466
Vijay Khemka996bad12019-05-28 15:15:16 -0700467 /* Find array of labels to be exposed if it is defined in config */
468 std::vector<std::string> findLabels;
469 auto findLabelObj = baseConfig->second.find("Labels");
470 if (findLabelObj != baseConfig->second.end())
471 {
472 findLabels =
473 std::get<std::vector<std::string>>(findLabelObj->second);
474 }
475
Jason Ling5747fab2019-10-02 16:46:23 -0700476 std::regex sensorNameRegEx("([A-Za-z]+)[0-9]*_");
477 std::smatch matches;
478
Cheng C Yange50345b2019-04-02 17:26:15 +0800479 for (const auto& sensorPath : sensorPaths)
Cheng C Yang209ec562019-03-12 16:37:44 +0800480 {
Manikandan Elumalaic7e95622020-06-03 20:22:01 +0530481 bool maxLabel = false;
Cheng C Yange50345b2019-04-02 17:26:15 +0800482 std::string labelHead;
483 std::string sensorPathStr = sensorPath.string();
484 std::string sensorNameStr = sensorPath.filename();
Jason Ling5747fab2019-10-02 16:46:23 -0700485 std::string sensorNameSubStr{""};
486 if (std::regex_search(sensorNameStr, matches, sensorNameRegEx))
487 {
Josh Lehan06494452019-10-31 09:49:16 -0700488 // hwmon *_input filename without number:
489 // in, curr, power, temp, ...
Jason Ling5747fab2019-10-02 16:46:23 -0700490 sensorNameSubStr = matches[1];
491 }
492 else
493 {
Josh Lehan06494452019-10-31 09:49:16 -0700494 std::cerr << "Could not extract the alpha prefix from "
Jason Ling5747fab2019-10-02 16:46:23 -0700495 << sensorNameStr;
496 continue;
497 }
Cheng C Yange50345b2019-04-02 17:26:15 +0800498
Manikandan Elumalaic7e95622020-06-03 20:22:01 +0530499 std::string labelPath;
500
501 /* find and differentiate _max and _input to replace "label" */
Ed Tanous8a57ec02020-10-09 12:46:52 -0700502 size_t pos = sensorPathStr.find('_');
Manikandan Elumalaic7e95622020-06-03 20:22:01 +0530503 if (pos != std::string::npos)
504 {
505
506 std::string sensorPathStrMax = sensorPathStr.substr(pos);
507 if (sensorPathStrMax.compare("_max") == 0)
508 {
509 labelPath =
510 boost::replace_all_copy(sensorPathStr, "max", "label");
511 maxLabel = true;
512 }
513 else
514 {
515 labelPath = boost::replace_all_copy(sensorPathStr, "input",
516 "label");
517 maxLabel = false;
518 }
519 }
520 else
521 {
522 continue;
523 }
524
Cheng C Yangecba9de2019-09-12 23:41:50 +0800525 std::ifstream labelFile(labelPath);
526 if (!labelFile.good())
Cheng C Yang209ec562019-03-12 16:37:44 +0800527 {
Ed Tanous8a57ec02020-10-09 12:46:52 -0700528 if constexpr (debug)
Cheng C Yang6b1247a2020-03-09 23:48:39 +0800529 {
530 std::cerr << "Input file " << sensorPath
531 << " has no corresponding label file\n";
532 }
Josh Lehan06494452019-10-31 09:49:16 -0700533 // hwmon *_input filename with number:
534 // temp1, temp2, temp3, ...
Ed Tanous8a57ec02020-10-09 12:46:52 -0700535 labelHead = sensorNameStr.substr(0, sensorNameStr.find('_'));
Cheng C Yang209ec562019-03-12 16:37:44 +0800536 }
537 else
538 {
Cheng C Yange50345b2019-04-02 17:26:15 +0800539 std::string label;
540 std::getline(labelFile, label);
541 labelFile.close();
Cheng C Yange50345b2019-04-02 17:26:15 +0800542 auto findSensor = sensors.find(label);
543 if (findSensor != sensors.end())
544 {
545 continue;
546 }
547
Josh Lehan06494452019-10-31 09:49:16 -0700548 // hwmon corresponding *_label file contents:
549 // vin1, vout1, ...
Ed Tanous8a57ec02020-10-09 12:46:52 -0700550 labelHead = label.substr(0, label.find(' '));
Cheng C Yange50345b2019-04-02 17:26:15 +0800551 }
552
Manikandan Elumalaic7e95622020-06-03 20:22:01 +0530553 /* append "max" for labelMatch */
554 if (maxLabel)
555 {
Ed Tanous8a57ec02020-10-09 12:46:52 -0700556 labelHead.insert(0, "max");
Manikandan Elumalaic7e95622020-06-03 20:22:01 +0530557 }
558
Ed Tanous8a57ec02020-10-09 12:46:52 -0700559 if constexpr (debug)
Josh Lehan74d9bd92019-10-31 08:51:58 -0700560 {
561 std::cerr << "Sensor type=\"" << sensorNameSubStr
562 << "\" label=\"" << labelHead << "\"\n";
563 }
564
AppaRao Pulid9d8caf2020-02-27 20:56:59 +0530565 checkPWMSensor(sensorPath, labelHead, *interfacePath,
566 dbusConnection, objectServer, psuNames[0]);
Cheng C Yang916360b2019-05-07 18:47:16 +0800567
Vijay Khemka996bad12019-05-28 15:15:16 -0700568 if (!findLabels.empty())
569 {
570 /* Check if this labelHead is enabled in config file */
571 if (std::find(findLabels.begin(), findLabels.end(),
572 labelHead) == findLabels.end())
573 {
Ed Tanous8a57ec02020-10-09 12:46:52 -0700574 if constexpr (debug)
Cheng C Yang6b1247a2020-03-09 23:48:39 +0800575 {
576 std::cerr << "could not find " << labelHead
577 << " in the Labels list\n";
578 }
Vijay Khemka996bad12019-05-28 15:15:16 -0700579 continue;
580 }
581 }
Cheng C Yange50345b2019-04-02 17:26:15 +0800582
Cheng C Yange50345b2019-04-02 17:26:15 +0800583 auto findProperty = labelMatch.find(labelHead);
584 if (findProperty == labelMatch.end())
Cheng C Yang209ec562019-03-12 16:37:44 +0800585 {
Ed Tanous8a57ec02020-10-09 12:46:52 -0700586 if constexpr (debug)
Josh Lehan74d9bd92019-10-31 08:51:58 -0700587 {
588 std::cerr << "Could not find matching default property for "
589 << labelHead << "\n";
590 }
Cheng C Yang209ec562019-03-12 16:37:44 +0800591 continue;
592 }
593
Josh Lehan74d9bd92019-10-31 08:51:58 -0700594 // Protect the hardcoded labelMatch list from changes,
595 // by making a copy and modifying that instead.
596 // Avoid bleedthrough of one device's customizations to
597 // the next device, as each should be independently customizable.
598 psuProperties.push_back(findProperty->second);
599 auto psuProperty = psuProperties.rbegin();
600
601 // Use label head as prefix for reading from config file,
602 // example if temp1: temp1_Name, temp1_Scale, temp1_Min, ...
603 std::string keyName = labelHead + "_Name";
604 std::string keyScale = labelHead + "_Scale";
605 std::string keyMin = labelHead + "_Min";
606 std::string keyMax = labelHead + "_Max";
607
608 bool customizedName = false;
609 auto findCustomName = baseConfig->second.find(keyName);
610 if (findCustomName != baseConfig->second.end())
Josh Lehan432d1ed2019-10-16 12:23:31 -0700611 {
Josh Lehan74d9bd92019-10-31 08:51:58 -0700612 try
613 {
614 psuProperty->labelTypeName = std::visit(
615 VariantToStringVisitor(), findCustomName->second);
616 }
617 catch (std::invalid_argument&)
618 {
619 std::cerr << "Unable to parse " << keyName << "\n";
620 continue;
621 }
622
623 // All strings are valid, including empty string
624 customizedName = true;
625 }
626
627 bool customizedScale = false;
628 auto findCustomScale = baseConfig->second.find(keyScale);
629 if (findCustomScale != baseConfig->second.end())
630 {
631 try
632 {
633 psuProperty->sensorScaleFactor = std::visit(
634 VariantToUnsignedIntVisitor(), findCustomScale->second);
635 }
636 catch (std::invalid_argument&)
637 {
638 std::cerr << "Unable to parse " << keyScale << "\n";
639 continue;
640 }
641
642 // Avoid later division by zero
643 if (psuProperty->sensorScaleFactor > 0)
644 {
645 customizedScale = true;
646 }
647 else
648 {
649 std::cerr << "Unable to accept " << keyScale << "\n";
650 continue;
651 }
652 }
653
654 auto findCustomMin = baseConfig->second.find(keyMin);
655 if (findCustomMin != baseConfig->second.end())
656 {
657 try
658 {
659 psuProperty->minReading = std::visit(
660 VariantToDoubleVisitor(), findCustomMin->second);
661 }
662 catch (std::invalid_argument&)
663 {
664 std::cerr << "Unable to parse " << keyMin << "\n";
665 continue;
666 }
667 }
668
669 auto findCustomMax = baseConfig->second.find(keyMax);
670 if (findCustomMax != baseConfig->second.end())
671 {
672 try
673 {
674 psuProperty->maxReading = std::visit(
675 VariantToDoubleVisitor(), findCustomMax->second);
676 }
677 catch (std::invalid_argument&)
678 {
679 std::cerr << "Unable to parse " << keyMax << "\n";
680 continue;
681 }
682 }
683
684 if (!(psuProperty->minReading < psuProperty->maxReading))
685 {
686 std::cerr << "Min must be less than Max\n";
687 continue;
688 }
689
690 // If the sensor name is being customized by config file,
691 // then prefix/suffix composition becomes not necessary,
692 // and in fact not wanted, because it gets in the way.
693 std::string psuNameFromIndex;
694 if (!customizedName)
695 {
696 /* Find out sensor name index for this label */
697 std::regex rgx("[A-Za-z]+([0-9]+)");
Brad Bishopfbb44ad2019-11-08 09:42:37 -0500698 size_t nameIndex{0};
Josh Lehan74d9bd92019-10-31 08:51:58 -0700699 if (std::regex_search(labelHead, matches, rgx))
700 {
701 nameIndex = std::stoi(matches[1]);
702
703 // Decrement to preserve alignment, because hwmon
704 // human-readable filenames and labels use 1-based
705 // numbering, but the "Name", "Name1", "Name2", etc. naming
706 // convention (the psuNames vector) uses 0-based numbering.
707 if (nameIndex > 0)
708 {
709 --nameIndex;
710 }
711 }
712 else
713 {
714 nameIndex = 0;
715 }
716
717 if (psuNames.size() <= nameIndex)
718 {
719 std::cerr << "Could not pair " << labelHead
720 << " with a Name field\n";
721 continue;
722 }
723
724 psuNameFromIndex = psuNames[nameIndex];
725
Ed Tanous8a57ec02020-10-09 12:46:52 -0700726 if constexpr (debug)
Josh Lehan74d9bd92019-10-31 08:51:58 -0700727 {
728 std::cerr << "Sensor label head " << labelHead
729 << " paired with " << psuNameFromIndex
730 << " at index " << nameIndex << "\n";
731 }
Josh Lehan432d1ed2019-10-16 12:23:31 -0700732 }
733
Cheng C Yang58b2b532019-05-31 00:19:45 +0800734 checkEventLimits(sensorPathStr, limitEventMatch, eventPathList);
735
Josh Lehan74d9bd92019-10-31 08:51:58 -0700736 // Similarly, if sensor scaling factor is being customized,
737 // then the below power-of-10 constraint becomes unnecessary,
738 // as config should be able to specify an arbitrary divisor.
739 unsigned int factor = psuProperty->sensorScaleFactor;
740 if (!customizedScale)
Vijay Khemka53ca4442019-07-23 11:03:55 -0700741 {
Josh Lehan74d9bd92019-10-31 08:51:58 -0700742 // Preserve existing usage of hardcoded labelMatch table below
743 factor = std::pow(10.0, factor);
Vijay Khemka53ca4442019-07-23 11:03:55 -0700744
Josh Lehan74d9bd92019-10-31 08:51:58 -0700745 /* Change first char of substring to uppercase */
Ed Tanous8a57ec02020-10-09 12:46:52 -0700746 char firstChar =
747 static_cast<char>(std::toupper(sensorNameSubStr[0]));
Josh Lehan74d9bd92019-10-31 08:51:58 -0700748 std::string strScaleFactor =
749 firstChar + sensorNameSubStr.substr(1) + "ScaleFactor";
750
751 // Preserve existing configs by accepting earlier syntax,
752 // example CurrScaleFactor, PowerScaleFactor, ...
753 auto findScaleFactor = baseConfig->second.find(strScaleFactor);
754 if (findScaleFactor != baseConfig->second.end())
755 {
756 factor = std::visit(VariantToIntVisitor(),
757 findScaleFactor->second);
758 }
759
Ed Tanous8a57ec02020-10-09 12:46:52 -0700760 if constexpr (debug)
Josh Lehan74d9bd92019-10-31 08:51:58 -0700761 {
762 std::cerr << "Sensor scaling factor " << factor
763 << " string " << strScaleFactor << "\n";
764 }
Josh Lehan49cfba92019-10-08 16:50:42 -0700765 }
766
Vijay Khemka996bad12019-05-28 15:15:16 -0700767 std::vector<thresholds::Threshold> sensorThresholds;
Joshi, Mansi14f0ad82019-11-21 10:52:30 +0530768 if (!parseThresholdsFromConfig(*sensorData, sensorThresholds,
769 &labelHead))
Cheng C Yange50345b2019-04-02 17:26:15 +0800770 {
James Feist17ab6e02019-06-25 12:28:13 -0700771 std::cerr << "error populating thresholds for "
772 << sensorNameSubStr << "\n";
Cheng C Yange50345b2019-04-02 17:26:15 +0800773 }
774
775 auto findSensorType = sensorTable.find(sensorNameSubStr);
776 if (findSensorType == sensorTable.end())
777 {
Jason Ling5747fab2019-10-02 16:46:23 -0700778 std::cerr << sensorNameSubStr
Josh Lehan06494452019-10-31 09:49:16 -0700779 << " is not a recognized sensor type\n";
Cheng C Yange50345b2019-04-02 17:26:15 +0800780 continue;
781 }
782
Ed Tanous8a57ec02020-10-09 12:46:52 -0700783 if constexpr (debug)
Josh Lehan49cfba92019-10-08 16:50:42 -0700784 {
Josh Lehan74d9bd92019-10-31 08:51:58 -0700785 std::cerr << "Sensor properties: Name \""
786 << psuProperty->labelTypeName << "\" Scale "
787 << psuProperty->sensorScaleFactor << " Min "
788 << psuProperty->minReading << " Max "
789 << psuProperty->maxReading << "\n";
790 }
791
792 std::string sensorName = psuProperty->labelTypeName;
793 if (customizedName)
794 {
795 if (sensorName.empty())
796 {
797 // Allow selective disabling of an individual sensor,
798 // by customizing its name to an empty string.
799 std::cerr << "Sensor disabled, empty string\n";
800 continue;
801 }
802 }
803 else
804 {
805 // Sensor name not customized, do prefix/suffix composition,
806 // preserving default behavior by using psuNameFromIndex.
807 sensorName =
808 psuNameFromIndex + " " + psuProperty->labelTypeName;
809 }
810
Ed Tanous8a57ec02020-10-09 12:46:52 -0700811 if constexpr (debug)
Josh Lehan74d9bd92019-10-31 08:51:58 -0700812 {
813 std::cerr << "Sensor name \"" << sensorName << "\" path \""
814 << sensorPathStr << "\" type \"" << sensorType
815 << "\"\n";
Josh Lehan49cfba92019-10-08 16:50:42 -0700816 }
Zhikui Ren23c96e72020-11-05 22:32:28 -0800817 // destruct existing one first if already created
818 sensors[sensorName] = nullptr;
Yong Libf8b1da2020-04-15 16:32:50 +0800819 sensors[sensorName] = std::make_shared<PSUSensor>(
Cheng C Yange50345b2019-04-02 17:26:15 +0800820 sensorPathStr, sensorType, objectServer, dbusConnection, io,
Cheng C Yang209ec562019-03-12 16:37:44 +0800821 sensorName, std::move(sensorThresholds), *interfacePath,
Josh Lehan74d9bd92019-10-31 08:51:58 -0700822 findSensorType->second, factor, psuProperty->maxReading,
Cheng C Yang6b1247a2020-03-09 23:48:39 +0800823 psuProperty->minReading, labelHead, thresholdConfSize);
Yong Libf8b1da2020-04-15 16:32:50 +0800824 sensors[sensorName]->setupRead();
Josh Lehan74d9bd92019-10-31 08:51:58 -0700825 ++numCreated;
Ed Tanous8a57ec02020-10-09 12:46:52 -0700826 if constexpr (debug)
Josh Lehan74d9bd92019-10-31 08:51:58 -0700827 {
828 std::cerr << "Created " << numCreated << " sensors so far\n";
829 }
Cheng C Yang209ec562019-03-12 16:37:44 +0800830 }
Cheng C Yang58b2b532019-05-31 00:19:45 +0800831
832 // OperationalStatus event
Cheng C Yang92498eb2019-09-26 21:59:25 +0800833 combineEvents[*psuName + "OperationalStatus"] = nullptr;
Cheng C Yang58b2b532019-05-31 00:19:45 +0800834 combineEvents[*psuName + "OperationalStatus"] =
Yong Li3046a022020-04-03 13:01:02 +0800835 std::make_unique<PSUCombineEvent>(
836 objectServer, dbusConnection, io, *psuName, eventPathList,
837 groupEventPathList, "OperationalStatus");
Cheng C Yang209ec562019-03-12 16:37:44 +0800838 }
Josh Lehan49cfba92019-10-08 16:50:42 -0700839
Ed Tanous8a57ec02020-10-09 12:46:52 -0700840 if constexpr (debug)
Josh Lehan49cfba92019-10-08 16:50:42 -0700841 {
842 std::cerr << "Created total of " << numCreated << " sensors\n";
843 }
Cheng C Yang209ec562019-03-12 16:37:44 +0800844 return;
845}
846
Zhikui Ren23c96e72020-11-05 22:32:28 -0800847void createSensors(
848 boost::asio::io_service& io, sdbusplus::asio::object_server& objectServer,
849 std::shared_ptr<sdbusplus::asio::connection>& dbusConnection,
850 const std::shared_ptr<boost::container::flat_set<std::string>>&
851 sensorsChanged)
852{
853 auto getter = std::make_shared<GetSensorConfiguration>(
854 dbusConnection, [&io, &objectServer, &dbusConnection, sensorsChanged](
855 const ManagedObjectType& sensorConfigs) {
856 createSensorsCallback(io, objectServer, dbusConnection,
857 sensorConfigs, sensorsChanged);
858 });
859 getter->getConfiguration(
860 std::vector<std::string>(sensorTypes.begin(), sensorTypes.end()));
861}
862
Cheng C Yang916360b2019-05-07 18:47:16 +0800863void propertyInitialize(void)
Cheng C Yang209ec562019-03-12 16:37:44 +0800864{
Cheng C Yange50345b2019-04-02 17:26:15 +0800865 sensorTable = {{"power", "power/"},
866 {"curr", "current/"},
867 {"temp", "temperature/"},
868 {"in", "voltage/"},
869 {"fan", "fan_tach/"}};
870
871 labelMatch = {{"pin", PSUProperty("Input Power", 3000, 0, 6)},
872 {"pout1", PSUProperty("Output Power", 3000, 0, 6)},
Vijay Khemka996bad12019-05-28 15:15:16 -0700873 {"pout2", PSUProperty("Output Power", 3000, 0, 6)},
874 {"pout3", PSUProperty("Output Power", 3000, 0, 6)},
Vijay Khemkabe664412019-06-28 12:10:04 -0700875 {"power1", PSUProperty("Output Power", 3000, 0, 6)},
Manikandan Elumalaic7e95622020-06-03 20:22:01 +0530876 {"maxpin", PSUProperty("Max Input Power", 3000, 0, 6)},
Cheng C Yangbdbde962019-04-26 22:50:34 +0800877 {"vin", PSUProperty("Input Voltage", 300, 0, 3)},
Manikandan Elumalaic7e95622020-06-03 20:22:01 +0530878 {"maxvin", PSUProperty("Max Input Voltage", 300, 0, 3)},
Vijay Khemka996bad12019-05-28 15:15:16 -0700879 {"vout1", PSUProperty("Output Voltage", 255, 0, 3)},
880 {"vout2", PSUProperty("Output Voltage", 255, 0, 3)},
881 {"vout3", PSUProperty("Output Voltage", 255, 0, 3)},
Jason Ling5747fab2019-10-02 16:46:23 -0700882 {"vout4", PSUProperty("Output Voltage", 255, 0, 3)},
883 {"vout5", PSUProperty("Output Voltage", 255, 0, 3)},
884 {"vout6", PSUProperty("Output Voltage", 255, 0, 3)},
885 {"vout7", PSUProperty("Output Voltage", 255, 0, 3)},
886 {"vout8", PSUProperty("Output Voltage", 255, 0, 3)},
887 {"vout9", PSUProperty("Output Voltage", 255, 0, 3)},
888 {"vout10", PSUProperty("Output Voltage", 255, 0, 3)},
889 {"vout11", PSUProperty("Output Voltage", 255, 0, 3)},
890 {"vout12", PSUProperty("Output Voltage", 255, 0, 3)},
891 {"vout13", PSUProperty("Output Voltage", 255, 0, 3)},
892 {"vout14", PSUProperty("Output Voltage", 255, 0, 3)},
893 {"vout15", PSUProperty("Output Voltage", 255, 0, 3)},
894 {"vout16", PSUProperty("Output Voltage", 255, 0, 3)},
Jason Ling32047ef2020-09-30 15:43:32 -0700895 {"vout17", PSUProperty("Output Voltage", 255, 0, 3)},
896 {"vout18", PSUProperty("Output Voltage", 255, 0, 3)},
897 {"vout19", PSUProperty("Output Voltage", 255, 0, 3)},
898 {"vout20", PSUProperty("Output Voltage", 255, 0, 3)},
899 {"vout21", PSUProperty("Output Voltage", 255, 0, 3)},
900 {"vout22", PSUProperty("Output Voltage", 255, 0, 3)},
901 {"vout23", PSUProperty("Output Voltage", 255, 0, 3)},
902 {"vout24", PSUProperty("Output Voltage", 255, 0, 3)},
903 {"vout25", PSUProperty("Output Voltage", 255, 0, 3)},
904 {"vout26", PSUProperty("Output Voltage", 255, 0, 3)},
905 {"vout27", PSUProperty("Output Voltage", 255, 0, 3)},
906 {"vout28", PSUProperty("Output Voltage", 255, 0, 3)},
907 {"vout29", PSUProperty("Output Voltage", 255, 0, 3)},
908 {"vout30", PSUProperty("Output Voltage", 255, 0, 3)},
909 {"vout31", PSUProperty("Output Voltage", 255, 0, 3)},
910 {"vout32", PSUProperty("Output Voltage", 255, 0, 3)},
Zev Weisseb0b84d2021-04-22 15:03:38 -0500911 {"vmon", PSUProperty("Auxiliary Input Voltage", 255, 0, 3)},
Vijay Khemkabe664412019-06-28 12:10:04 -0700912 {"in1", PSUProperty("Output Voltage", 255, 0, 3)},
Cheng C Yange50345b2019-04-02 17:26:15 +0800913 {"iin", PSUProperty("Input Current", 20, 0, 3)},
914 {"iout1", PSUProperty("Output Current", 255, 0, 3)},
Vijay Khemka996bad12019-05-28 15:15:16 -0700915 {"iout2", PSUProperty("Output Current", 255, 0, 3)},
916 {"iout3", PSUProperty("Output Current", 255, 0, 3)},
Peter Lundgren48b44232020-01-30 16:02:11 -0800917 {"iout4", PSUProperty("Output Current", 255, 0, 3)},
918 {"iout5", PSUProperty("Output Current", 255, 0, 3)},
919 {"iout6", PSUProperty("Output Current", 255, 0, 3)},
920 {"iout7", PSUProperty("Output Current", 255, 0, 3)},
921 {"iout8", PSUProperty("Output Current", 255, 0, 3)},
922 {"iout9", PSUProperty("Output Current", 255, 0, 3)},
923 {"iout10", PSUProperty("Output Current", 255, 0, 3)},
924 {"iout11", PSUProperty("Output Current", 255, 0, 3)},
925 {"iout12", PSUProperty("Output Current", 255, 0, 3)},
926 {"iout13", PSUProperty("Output Current", 255, 0, 3)},
927 {"iout14", PSUProperty("Output Current", 255, 0, 3)},
Vijay Khemkabe664412019-06-28 12:10:04 -0700928 {"curr1", PSUProperty("Output Current", 255, 0, 3)},
Manikandan Elumalaic7e95622020-06-03 20:22:01 +0530929 {"maxiout1", PSUProperty("Max Output Current", 255, 0, 3)},
Cheng C Yange50345b2019-04-02 17:26:15 +0800930 {"temp1", PSUProperty("Temperature", 127, -128, 3)},
Vijay Khemka996bad12019-05-28 15:15:16 -0700931 {"temp2", PSUProperty("Temperature", 127, -128, 3)},
932 {"temp3", PSUProperty("Temperature", 127, -128, 3)},
Jason Ling5747fab2019-10-02 16:46:23 -0700933 {"temp4", PSUProperty("Temperature", 127, -128, 3)},
934 {"temp5", PSUProperty("Temperature", 127, -128, 3)},
Alex Qiuf5709b42020-01-29 13:29:50 -0800935 {"temp6", PSUProperty("Temperature", 127, -128, 3)},
Manikandan Elumalaic7e95622020-06-03 20:22:01 +0530936 {"maxtemp1", PSUProperty("Max Temperature", 127, -128, 3)},
Cheng C Yang8dbb3952019-05-23 00:03:12 +0800937 {"fan1", PSUProperty("Fan Speed 1", 30000, 0, 0)},
938 {"fan2", PSUProperty("Fan Speed 2", 30000, 0, 0)}};
Cheng C Yang916360b2019-05-07 18:47:16 +0800939
940 pwmTable = {{"fan1", "Fan_1"}, {"fan2", "Fan_2"}};
Cheng C Yang58b2b532019-05-31 00:19:45 +0800941
942 limitEventMatch = {{"PredictiveFailure", {"max_alarm", "min_alarm"}},
943 {"Failure", {"crit_alarm", "lcrit_alarm"}}};
944
Cheng C Yang202a1ff2020-01-09 09:34:22 +0800945 eventMatch = {{"PredictiveFailure", {"power1_alarm"}},
946 {"Failure", {"in2_alarm"}},
947 {"ACLost", {"in1_beep"}},
948 {"ConfigureError", {"in1_fault"}}};
949
950 groupEventMatch = {{"FanFault",
951 {{"fan1", {"fan1_alarm", "fan1_fault"}},
952 {"fan2", {"fan2_alarm", "fan2_fault"}}}}};
Cheng C Yang209ec562019-03-12 16:37:44 +0800953}
954
James Feistb6c0b912019-07-09 12:21:44 -0700955int main()
Cheng C Yang209ec562019-03-12 16:37:44 +0800956{
957 boost::asio::io_service io;
958 auto systemBus = std::make_shared<sdbusplus::asio::connection>(io);
959
960 systemBus->request_name("xyz.openbmc_project.PSUSensor");
961 sdbusplus::asio::object_server objectServer(systemBus);
Cheng C Yang209ec562019-03-12 16:37:44 +0800962 std::vector<std::unique_ptr<sdbusplus::bus::match::match>> matches;
Zhikui Ren23c96e72020-11-05 22:32:28 -0800963 auto sensorsChanged =
964 std::make_shared<boost::container::flat_set<std::string>>();
Cheng C Yang209ec562019-03-12 16:37:44 +0800965
Cheng C Yang916360b2019-05-07 18:47:16 +0800966 propertyInitialize();
Cheng C Yang209ec562019-03-12 16:37:44 +0800967
Zhikui Ren23c96e72020-11-05 22:32:28 -0800968 io.post([&]() { createSensors(io, objectServer, systemBus, nullptr); });
Cheng C Yang209ec562019-03-12 16:37:44 +0800969 boost::asio::deadline_timer filterTimer(io);
970 std::function<void(sdbusplus::message::message&)> eventHandler =
971 [&](sdbusplus::message::message& message) {
972 if (message.is_method_error())
973 {
974 std::cerr << "callback method error\n";
975 return;
976 }
Zhikui Ren23c96e72020-11-05 22:32:28 -0800977 sensorsChanged->insert(message.get_path());
Cheng C Yanga97f1342020-02-11 15:10:41 +0800978 filterTimer.expires_from_now(boost::posix_time::seconds(3));
Cheng C Yang209ec562019-03-12 16:37:44 +0800979 filterTimer.async_wait([&](const boost::system::error_code& ec) {
980 if (ec == boost::asio::error::operation_aborted)
981 {
982 return;
983 }
Ed Tanous8a57ec02020-10-09 12:46:52 -0700984 if (ec)
Cheng C Yang209ec562019-03-12 16:37:44 +0800985 {
986 std::cerr << "timer error\n";
987 }
Zhikui Ren23c96e72020-11-05 22:32:28 -0800988 createSensors(io, objectServer, systemBus, sensorsChanged);
Cheng C Yang209ec562019-03-12 16:37:44 +0800989 });
990 };
991
992 for (const char* type : sensorTypes)
993 {
994 auto match = std::make_unique<sdbusplus::bus::match::match>(
995 static_cast<sdbusplus::bus::bus&>(*systemBus),
996 "type='signal',member='PropertiesChanged',path_namespace='" +
997 std::string(inventoryPath) + "',arg0namespace='" + type + "'",
998 eventHandler);
999 matches.emplace_back(std::move(match));
1000 }
1001 io.run();
1002}