blob: 2cb4df8d5197249811a8b168c92c71790376bad4 [file] [log] [blame]
Cheng C Yang209ec562019-03-12 16:37:44 +08001/*
2// Copyright (c) 2019 Intel Corporation
3//
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7//
8// http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15*/
Josh Lehan0830c7b2019-10-08 16:35:09 -070016
Ed Tanous8a57ec02020-10-09 12:46:52 -070017#include <PSUEvent.hpp>
18#include <PSUSensor.hpp>
19#include <Utils.hpp>
Cheng C Yang209ec562019-03-12 16:37:44 +080020#include <boost/algorithm/string/predicate.hpp>
21#include <boost/algorithm/string/replace.hpp>
Patrick Venture96e97db2019-10-31 13:44:38 -070022#include <boost/container/flat_map.hpp>
Cheng C Yang209ec562019-03-12 16:37:44 +080023#include <boost/container/flat_set.hpp>
James Feist38fb5982020-05-28 10:09:54 -070024#include <sdbusplus/asio/connection.hpp>
25#include <sdbusplus/asio/object_server.hpp>
26#include <sdbusplus/bus/match.hpp>
27
28#include <array>
Josh Lehan74d9bd92019-10-31 08:51:58 -070029#include <cmath>
James Feist24f02f22019-04-15 11:05:39 -070030#include <filesystem>
Cheng C Yang209ec562019-03-12 16:37:44 +080031#include <fstream>
Patrick Venture96e97db2019-10-31 13:44:38 -070032#include <functional>
Cheng C Yang58b2b532019-05-31 00:19:45 +080033#include <iostream>
Cheng C Yang209ec562019-03-12 16:37:44 +080034#include <regex>
Patrick Venture96e97db2019-10-31 13:44:38 -070035#include <string>
Lei YUa2c7cea2020-12-23 14:07:28 +080036#include <string_view>
Patrick Venture96e97db2019-10-31 13:44:38 -070037#include <utility>
38#include <variant>
39#include <vector>
Cheng C Yang209ec562019-03-12 16:37:44 +080040
Ed Tanous8a57ec02020-10-09 12:46:52 -070041static constexpr bool debug = false;
Josh Lehan49cfba92019-10-08 16:50:42 -070042
Avenash Asai Thambif1ace502021-08-02 16:10:19 -050043static constexpr std::array<const char*, 26> sensorTypes = {
44 "xyz.openbmc_project.Configuration.ADM1266",
Josh Lehan62084c82020-06-22 15:27:12 -070045 "xyz.openbmc_project.Configuration.ADM1272",
Paul Fertser678f53b2021-04-06 07:06:28 +000046 "xyz.openbmc_project.Configuration.ADM1275",
Josh Lehan62084c82020-06-22 15:27:12 -070047 "xyz.openbmc_project.Configuration.ADM1278",
Jeff Lina0683a82021-02-22 13:56:55 +080048 "xyz.openbmc_project.Configuration.DPS800",
Josh Lehan62084c82020-06-22 15:27:12 -070049 "xyz.openbmc_project.Configuration.INA219",
Devjit Gopalpurde65ef72019-10-30 04:47:35 -070050 "xyz.openbmc_project.Configuration.INA230",
Lei YU8e0eccd2021-04-23 11:01:59 +080051 "xyz.openbmc_project.Configuration.IPSPS",
Alex Qiu6690d8f2020-01-22 17:56:33 -080052 "xyz.openbmc_project.Configuration.ISL68137",
Jason Lingdfad1ff2020-07-29 15:43:11 -070053 "xyz.openbmc_project.Configuration.ISL68220",
Gaurav Gandhi49585582020-12-22 01:01:24 +000054 "xyz.openbmc_project.Configuration.ISL68223",
55 "xyz.openbmc_project.Configuration.ISL69243",
Jeff Lina0683a82021-02-22 13:56:55 +080056 "xyz.openbmc_project.Configuration.ISL69260",
Zev Weisseb0b84d2021-04-22 15:03:38 -050057 "xyz.openbmc_project.Configuration.LM25066",
Alex Qiuf5709b42020-01-29 13:29:50 -080058 "xyz.openbmc_project.Configuration.MAX16601",
Gaurav Gandhi49585582020-12-22 01:01:24 +000059 "xyz.openbmc_project.Configuration.MAX20710",
Alex Qiu6690d8f2020-01-22 17:56:33 -080060 "xyz.openbmc_project.Configuration.MAX20730",
61 "xyz.openbmc_project.Configuration.MAX20734",
62 "xyz.openbmc_project.Configuration.MAX20796",
63 "xyz.openbmc_project.Configuration.MAX34451",
Josh Lehan62084c82020-06-22 15:27:12 -070064 "xyz.openbmc_project.Configuration.pmbus",
65 "xyz.openbmc_project.Configuration.PXE1610",
Jeff Lina0683a82021-02-22 13:56:55 +080066 "xyz.openbmc_project.Configuration.RAA228000",
67 "xyz.openbmc_project.Configuration.RAA228228",
68 "xyz.openbmc_project.Configuration.RAA229004",
69 "xyz.openbmc_project.Configuration.TPS546D24"};
Cheng C Yang209ec562019-03-12 16:37:44 +080070
Alex Qiu6690d8f2020-01-22 17:56:33 -080071static std::vector<std::string> pmbusNames = {
Avenash Asai Thambif1ace502021-08-02 16:10:19 -050072 "adm1266", "adm1272", "adm1275", "adm1278", "dps800", "ina219",
73 "ina230", "ipsps1", "isl68137", "isl68220", "isl68223", "isl69243",
74 "isl69260", "lm25066", "max16601", "max20710", "max20730", "max20734",
75 "max20796", "max34451", "pmbus", "pxe1610", "raa228000", "raa228228",
76 "raa229004", "tps546d24"};
Josh Lehan0830c7b2019-10-08 16:35:09 -070077
Cheng C Yang209ec562019-03-12 16:37:44 +080078namespace fs = std::filesystem;
79
Yong Libf8b1da2020-04-15 16:32:50 +080080static boost::container::flat_map<std::string, std::shared_ptr<PSUSensor>>
Cheng C Yang916360b2019-05-07 18:47:16 +080081 sensors;
Cheng C Yang58b2b532019-05-31 00:19:45 +080082static boost::container::flat_map<std::string, std::unique_ptr<PSUCombineEvent>>
83 combineEvents;
Cheng C Yang916360b2019-05-07 18:47:16 +080084static boost::container::flat_map<std::string, std::unique_ptr<PwmSensor>>
85 pwmSensors;
86static boost::container::flat_map<std::string, std::string> sensorTable;
87static boost::container::flat_map<std::string, PSUProperty> labelMatch;
88static boost::container::flat_map<std::string, std::string> pwmTable;
Cheng C Yang58b2b532019-05-31 00:19:45 +080089static boost::container::flat_map<std::string, std::vector<std::string>>
90 eventMatch;
Cheng C Yang202a1ff2020-01-09 09:34:22 +080091static boost::container::flat_map<
92 std::string,
93 boost::container::flat_map<std::string, std::vector<std::string>>>
94 groupEventMatch;
Cheng C Yang58b2b532019-05-31 00:19:45 +080095static boost::container::flat_map<std::string, std::vector<std::string>>
96 limitEventMatch;
97
Josh Lehan74d9bd92019-10-31 08:51:58 -070098static std::vector<PSUProperty> psuProperties;
99
Cheng C Yang58b2b532019-05-31 00:19:45 +0800100// Function CheckEvent will check each attribute from eventMatch table in the
101// sysfs. If the attributes exists in sysfs, then store the complete path
102// of the attribute into eventPathList.
103void checkEvent(
104 const std::string& directory,
105 const boost::container::flat_map<std::string, std::vector<std::string>>&
106 eventMatch,
107 boost::container::flat_map<std::string, std::vector<std::string>>&
108 eventPathList)
109{
110 for (const auto& match : eventMatch)
111 {
112 const std::vector<std::string>& eventAttrs = match.second;
113 const std::string& eventName = match.first;
114 for (const auto& eventAttr : eventAttrs)
115 {
Ed Tanous8a57ec02020-10-09 12:46:52 -0700116 std::string eventPath = directory;
117 eventPath += "/";
118 eventPath += eventAttr;
Cheng C Yang58b2b532019-05-31 00:19:45 +0800119
120 std::ifstream eventFile(eventPath);
121 if (!eventFile.good())
122 {
123 continue;
124 }
125
126 eventPathList[eventName].push_back(eventPath);
127 }
128 }
129}
130
Cheng C Yang202a1ff2020-01-09 09:34:22 +0800131// Check Group Events which contains more than one targets in each combine
132// events.
133void checkGroupEvent(
134 const std::string& directory,
135 const boost::container::flat_map<
136 std::string,
137 boost::container::flat_map<std::string, std::vector<std::string>>>&
138 groupEventMatch,
139 boost::container::flat_map<
140 std::string,
141 boost::container::flat_map<std::string, std::vector<std::string>>>&
142 groupEventPathList)
143{
144 for (const auto& match : groupEventMatch)
145 {
146 const std::string& groupEventName = match.first;
147 const boost::container::flat_map<std::string, std::vector<std::string>>
148 events = match.second;
149 boost::container::flat_map<std::string, std::vector<std::string>>
150 pathList;
151 for (const auto& match : events)
152 {
153 const std::string& eventName = match.first;
154 const std::vector<std::string>& eventAttrs = match.second;
155 for (const auto& eventAttr : eventAttrs)
156 {
Ed Tanous8a57ec02020-10-09 12:46:52 -0700157 std::string eventPath = directory;
158 eventPath += "/";
159 eventPath += eventAttr;
Cheng C Yang202a1ff2020-01-09 09:34:22 +0800160 std::ifstream eventFile(eventPath);
161 if (!eventFile.good())
162 {
163 continue;
164 }
165
166 pathList[eventName].push_back(eventPath);
167 }
168 }
169 groupEventPathList[groupEventName] = pathList;
170 }
171}
172
Cheng C Yang58b2b532019-05-31 00:19:45 +0800173// Function checkEventLimits will check all the psu related xxx_input attributes
174// in sysfs to see if xxx_crit_alarm xxx_lcrit_alarm xxx_max_alarm
175// xxx_min_alarm exist, then store the existing paths of the alarm attributes
176// to eventPathList.
177void checkEventLimits(
178 const std::string& sensorPathStr,
179 const boost::container::flat_map<std::string, std::vector<std::string>>&
180 limitEventMatch,
181 boost::container::flat_map<std::string, std::vector<std::string>>&
182 eventPathList)
183{
Lei YUa2c7cea2020-12-23 14:07:28 +0800184 auto attributePartPos = sensorPathStr.find_last_of('_');
185 if (attributePartPos == std::string::npos)
186 {
187 // There is no '_' in the string, skip it
188 return;
189 }
190 auto attributePart =
191 std::string_view(sensorPathStr).substr(attributePartPos + 1);
192 if (attributePart != "input")
193 {
194 // If the sensor is not xxx_input, skip it
195 return;
196 }
197
198 auto prefixPart = sensorPathStr.substr(0, attributePartPos + 1);
Cheng C Yang58b2b532019-05-31 00:19:45 +0800199 for (const auto& limitMatch : limitEventMatch)
200 {
201 const std::vector<std::string>& limitEventAttrs = limitMatch.second;
202 const std::string& eventName = limitMatch.first;
203 for (const auto& limitEventAttr : limitEventAttrs)
204 {
Lei YUa2c7cea2020-12-23 14:07:28 +0800205 auto limitEventPath = prefixPart + limitEventAttr;
Cheng C Yang58b2b532019-05-31 00:19:45 +0800206 std::ifstream eventFile(limitEventPath);
207 if (!eventFile.good())
208 {
209 continue;
210 }
211 eventPathList[eventName].push_back(limitEventPath);
212 }
213 }
214}
Cheng C Yang916360b2019-05-07 18:47:16 +0800215
AppaRao Pulid9d8caf2020-02-27 20:56:59 +0530216static void
217 checkPWMSensor(const fs::path& sensorPath, std::string& labelHead,
218 const std::string& interfacePath,
219 std::shared_ptr<sdbusplus::asio::connection>& dbusConnection,
220 sdbusplus::asio::object_server& objectServer,
221 const std::string& psuName)
Cheng C Yang916360b2019-05-07 18:47:16 +0800222{
223 for (const auto& pwmName : pwmTable)
224 {
225 if (pwmName.first != labelHead)
226 {
227 continue;
228 }
229
230 const std::string& sensorPathStr = sensorPath.string();
231 const std::string& pwmPathStr =
232 boost::replace_all_copy(sensorPathStr, "input", "target");
233 std::ifstream pwmFile(pwmPathStr);
234 if (!pwmFile.good())
235 {
236 continue;
237 }
238
239 auto findPWMSensor = pwmSensors.find(psuName + labelHead);
240 if (findPWMSensor != pwmSensors.end())
241 {
242 continue;
243 }
244
245 pwmSensors[psuName + labelHead] = std::make_unique<PwmSensor>(
AppaRao Pulid9d8caf2020-02-27 20:56:59 +0530246 "Pwm_" + psuName + "_" + pwmName.second, pwmPathStr, dbusConnection,
247 objectServer, interfacePath + "_" + pwmName.second, "PSU");
Cheng C Yang916360b2019-05-07 18:47:16 +0800248 }
249}
250
Zhikui Ren23c96e72020-11-05 22:32:28 -0800251static void createSensorsCallback(
252 boost::asio::io_service& io, sdbusplus::asio::object_server& objectServer,
253 std::shared_ptr<sdbusplus::asio::connection>& dbusConnection,
254 const ManagedObjectType& sensorConfigs,
255 const std::shared_ptr<boost::container::flat_set<std::string>>&
256 sensorsChanged)
Cheng C Yang209ec562019-03-12 16:37:44 +0800257{
Josh Lehan49cfba92019-10-08 16:50:42 -0700258 int numCreated = 0;
Zhikui Ren23c96e72020-11-05 22:32:28 -0800259 bool firstScan = sensorsChanged == nullptr;
Cheng C Yang209ec562019-03-12 16:37:44 +0800260
261 std::vector<fs::path> pmbusPaths;
262 if (!findFiles(fs::path("/sys/class/hwmon"), "name", pmbusPaths))
263 {
264 std::cerr << "No PSU sensors in system\n";
265 return;
266 }
267
268 boost::container::flat_set<std::string> directories;
269 for (const auto& pmbusPath : pmbusPaths)
270 {
Cheng C Yang58b2b532019-05-31 00:19:45 +0800271 boost::container::flat_map<std::string, std::vector<std::string>>
272 eventPathList;
Cheng C Yang202a1ff2020-01-09 09:34:22 +0800273 boost::container::flat_map<
274 std::string,
275 boost::container::flat_map<std::string, std::vector<std::string>>>
276 groupEventPathList;
Cheng C Yang58b2b532019-05-31 00:19:45 +0800277
278 std::ifstream nameFile(pmbusPath);
279 if (!nameFile.good())
280 {
Josh Lehan49cfba92019-10-08 16:50:42 -0700281 std::cerr << "Failure finding pmbus path " << pmbusPath << "\n";
Cheng C Yang58b2b532019-05-31 00:19:45 +0800282 continue;
283 }
284
285 std::string pmbusName;
286 std::getline(nameFile, pmbusName);
287 nameFile.close();
Vijay Khemka996bad12019-05-28 15:15:16 -0700288
289 if (std::find(pmbusNames.begin(), pmbusNames.end(), pmbusName) ==
290 pmbusNames.end())
Cheng C Yang58b2b532019-05-31 00:19:45 +0800291 {
Josh Lehan49cfba92019-10-08 16:50:42 -0700292 // To avoid this error message, add your driver name to
293 // the pmbusNames vector at the top of this file.
294 std::cerr << "Driver name " << pmbusName
295 << " not found in sensor whitelist\n";
Cheng C Yang58b2b532019-05-31 00:19:45 +0800296 continue;
297 }
298
299 const std::string* psuName;
Cheng C Yang209ec562019-03-12 16:37:44 +0800300 auto directory = pmbusPath.parent_path();
301
302 auto ret = directories.insert(directory.string());
303 if (!ret.second)
304 {
Josh Lehan49cfba92019-10-08 16:50:42 -0700305 std::cerr << "Duplicate path " << directory.string() << "\n";
Cheng C Yang58b2b532019-05-31 00:19:45 +0800306 continue; // check if path has already been searched
Cheng C Yang209ec562019-03-12 16:37:44 +0800307 }
308
James Feistb6c0b912019-07-09 12:21:44 -0700309 fs::path device = directory / "device";
Cheng C Yang209ec562019-03-12 16:37:44 +0800310 std::string deviceName = fs::canonical(device).stem();
Ed Tanous8a57ec02020-10-09 12:46:52 -0700311 auto findHyphen = deviceName.find('-');
Cheng C Yang209ec562019-03-12 16:37:44 +0800312 if (findHyphen == std::string::npos)
313 {
314 std::cerr << "found bad device" << deviceName << "\n";
315 continue;
316 }
317 std::string busStr = deviceName.substr(0, findHyphen);
318 std::string addrStr = deviceName.substr(findHyphen + 1);
319
320 size_t bus = 0;
321 size_t addr = 0;
322
323 try
324 {
325 bus = std::stoi(busStr);
Ed Tanous8a57ec02020-10-09 12:46:52 -0700326 addr = std::stoi(addrStr, nullptr, 16);
Cheng C Yang209ec562019-03-12 16:37:44 +0800327 }
James Feistb6c0b912019-07-09 12:21:44 -0700328 catch (std::invalid_argument&)
Cheng C Yang209ec562019-03-12 16:37:44 +0800329 {
Josh Lehan49cfba92019-10-08 16:50:42 -0700330 std::cerr << "Error parsing bus " << busStr << " addr " << addrStr
331 << "\n";
Cheng C Yang209ec562019-03-12 16:37:44 +0800332 continue;
333 }
334
Cheng C Yang209ec562019-03-12 16:37:44 +0800335 const std::pair<std::string, boost::container::flat_map<
336 std::string, BasicVariantType>>*
337 baseConfig = nullptr;
338 const SensorData* sensorData = nullptr;
339 const std::string* interfacePath = nullptr;
340 const char* sensorType = nullptr;
Cheng C Yang6b1247a2020-03-09 23:48:39 +0800341 size_t thresholdConfSize = 0;
Cheng C Yang209ec562019-03-12 16:37:44 +0800342
343 for (const std::pair<sdbusplus::message::object_path, SensorData>&
344 sensor : sensorConfigs)
345 {
346 sensorData = &(sensor.second);
347 for (const char* type : sensorTypes)
348 {
349 auto sensorBase = sensorData->find(type);
350 if (sensorBase != sensorData->end())
351 {
352 baseConfig = &(*sensorBase);
353 sensorType = type;
354 break;
355 }
356 }
357 if (baseConfig == nullptr)
358 {
359 std::cerr << "error finding base configuration for "
360 << deviceName << "\n";
361 continue;
362 }
363
364 auto configBus = baseConfig->second.find("Bus");
365 auto configAddress = baseConfig->second.find("Address");
366
367 if (configBus == baseConfig->second.end() ||
368 configAddress == baseConfig->second.end())
369 {
Cheng C Yang58b2b532019-05-31 00:19:45 +0800370 std::cerr << "error finding necessary entry in configuration\n";
Cheng C Yang209ec562019-03-12 16:37:44 +0800371 continue;
372 }
373
Cheng C Yang58b2b532019-05-31 00:19:45 +0800374 const uint64_t* confBus;
375 const uint64_t* confAddr;
376 if (!(confBus = std::get_if<uint64_t>(&(configBus->second))) ||
377 !(confAddr = std::get_if<uint64_t>(&(configAddress->second))))
378 {
379 std::cerr
Josh Lehan49cfba92019-10-08 16:50:42 -0700380 << "Cannot get bus or address, invalid configuration\n";
Cheng C Yang58b2b532019-05-31 00:19:45 +0800381 continue;
382 }
383
384 if ((*confBus != bus) || (*confAddr != addr))
Cheng C Yang209ec562019-03-12 16:37:44 +0800385 {
Josh Lehan432d1ed2019-10-16 12:23:31 -0700386 std::cerr << "Configuration skipping " << *confBus << "-"
387 << *confAddr << " because not " << bus << "-" << addr
388 << "\n";
Cheng C Yang209ec562019-03-12 16:37:44 +0800389 continue;
390 }
391
Cheng C Yang6b1247a2020-03-09 23:48:39 +0800392 std::vector<thresholds::Threshold> confThresholds;
393 if (!parseThresholdsFromConfig(*sensorData, confThresholds))
394 {
395 std::cerr << "error populating totoal thresholds\n";
396 }
397 thresholdConfSize = confThresholds.size();
398
Cheng C Yang209ec562019-03-12 16:37:44 +0800399 interfacePath = &(sensor.first.str);
400 break;
401 }
402 if (interfacePath == nullptr)
403 {
Josh Lehan49cfba92019-10-08 16:50:42 -0700404 // To avoid this error message, add your export map entry,
405 // from Entity Manager, to sensorTypes at the top of this file.
Cheng C Yang209ec562019-03-12 16:37:44 +0800406 std::cerr << "failed to find match for " << deviceName << "\n";
407 continue;
408 }
409
Cheng C Yange50345b2019-04-02 17:26:15 +0800410 auto findPSUName = baseConfig->second.find("Name");
411 if (findPSUName == baseConfig->second.end())
Cheng C Yang209ec562019-03-12 16:37:44 +0800412 {
413 std::cerr << "could not determine configuration name for "
414 << deviceName << "\n";
415 continue;
416 }
417
Cheng C Yang58b2b532019-05-31 00:19:45 +0800418 if (!(psuName = std::get_if<std::string>(&(findPSUName->second))))
419 {
420 std::cerr << "Cannot find psu name, invalid configuration\n";
421 continue;
422 }
Zhikui Ren23c96e72020-11-05 22:32:28 -0800423
424 // on rescans, only update sensors we were signaled by
425 if (!firstScan)
426 {
427 std::string psuNameStr = "/" + *psuName;
428 auto it =
429 std::find_if(sensorsChanged->begin(), sensorsChanged->end(),
430 [psuNameStr](std::string& s) {
431 return boost::ends_with(s, psuNameStr);
432 });
433
434 if (it == sensorsChanged->end())
435 {
436 continue;
437 }
438 sensorsChanged->erase(it);
439 }
Cheng C Yang58b2b532019-05-31 00:19:45 +0800440 checkEvent(directory.string(), eventMatch, eventPathList);
Cheng C Yang202a1ff2020-01-09 09:34:22 +0800441 checkGroupEvent(directory.string(), groupEventMatch,
442 groupEventPathList);
Cheng C Yang58b2b532019-05-31 00:19:45 +0800443
Vijay Khemka996bad12019-05-28 15:15:16 -0700444 /* Check if there are more sensors in the same interface */
445 int i = 1;
446 std::vector<std::string> psuNames;
447 do
448 {
Josh Lehan49cfba92019-10-08 16:50:42 -0700449 // Individual string fields: Name, Name1, Name2, Name3, ...
Vijay Khemka996bad12019-05-28 15:15:16 -0700450 psuNames.push_back(std::get<std::string>(findPSUName->second));
451 findPSUName = baseConfig->second.find("Name" + std::to_string(i++));
452 } while (findPSUName != baseConfig->second.end());
453
Cheng C Yange50345b2019-04-02 17:26:15 +0800454 std::vector<fs::path> sensorPaths;
James Feistb6c0b912019-07-09 12:21:44 -0700455 if (!findFiles(directory, R"(\w\d+_input$)", sensorPaths, 0))
Cheng C Yang209ec562019-03-12 16:37:44 +0800456 {
Cheng C Yange50345b2019-04-02 17:26:15 +0800457 std::cerr << "No PSU non-label sensor in PSU\n";
Cheng C Yang209ec562019-03-12 16:37:44 +0800458 continue;
459 }
460
Manikandan Elumalaic7e95622020-06-03 20:22:01 +0530461 /* read max value in sysfs for in, curr, power, temp, ... */
462 if (!findFiles(directory, R"(\w\d+_max$)", sensorPaths, 0))
463 {
Ed Tanous8a57ec02020-10-09 12:46:52 -0700464 if constexpr (debug)
Manikandan Elumalaic7e95622020-06-03 20:22:01 +0530465 {
466 std::cerr << "No max name in PSU \n";
467 }
468 }
469
Lei YU7170a232021-02-04 16:19:27 +0800470 /* The poll rate for the sensors */
471 double pollRate = 0.0;
472 auto pollRateObj = baseConfig->second.find("PollRate");
473
474 if (pollRateObj != baseConfig->second.end())
475 {
476 pollRate =
477 std::visit(VariantToDoubleVisitor(), pollRateObj->second);
478 if (pollRate <= 0.0)
479 {
480 pollRate = PSUSensor::defaultSensorPoll;
481 }
482 }
483
Vijay Khemka996bad12019-05-28 15:15:16 -0700484 /* Find array of labels to be exposed if it is defined in config */
485 std::vector<std::string> findLabels;
486 auto findLabelObj = baseConfig->second.find("Labels");
487 if (findLabelObj != baseConfig->second.end())
488 {
489 findLabels =
490 std::get<std::vector<std::string>>(findLabelObj->second);
491 }
492
Jason Ling5747fab2019-10-02 16:46:23 -0700493 std::regex sensorNameRegEx("([A-Za-z]+)[0-9]*_");
494 std::smatch matches;
495
Cheng C Yange50345b2019-04-02 17:26:15 +0800496 for (const auto& sensorPath : sensorPaths)
Cheng C Yang209ec562019-03-12 16:37:44 +0800497 {
Manikandan Elumalaic7e95622020-06-03 20:22:01 +0530498 bool maxLabel = false;
Cheng C Yange50345b2019-04-02 17:26:15 +0800499 std::string labelHead;
500 std::string sensorPathStr = sensorPath.string();
501 std::string sensorNameStr = sensorPath.filename();
Jason Ling5747fab2019-10-02 16:46:23 -0700502 std::string sensorNameSubStr{""};
503 if (std::regex_search(sensorNameStr, matches, sensorNameRegEx))
504 {
Josh Lehan06494452019-10-31 09:49:16 -0700505 // hwmon *_input filename without number:
506 // in, curr, power, temp, ...
Jason Ling5747fab2019-10-02 16:46:23 -0700507 sensorNameSubStr = matches[1];
508 }
509 else
510 {
Josh Lehan06494452019-10-31 09:49:16 -0700511 std::cerr << "Could not extract the alpha prefix from "
Jason Ling5747fab2019-10-02 16:46:23 -0700512 << sensorNameStr;
513 continue;
514 }
Cheng C Yange50345b2019-04-02 17:26:15 +0800515
Manikandan Elumalaic7e95622020-06-03 20:22:01 +0530516 std::string labelPath;
517
518 /* find and differentiate _max and _input to replace "label" */
Ed Tanous8a57ec02020-10-09 12:46:52 -0700519 size_t pos = sensorPathStr.find('_');
Manikandan Elumalaic7e95622020-06-03 20:22:01 +0530520 if (pos != std::string::npos)
521 {
522
523 std::string sensorPathStrMax = sensorPathStr.substr(pos);
524 if (sensorPathStrMax.compare("_max") == 0)
525 {
526 labelPath =
527 boost::replace_all_copy(sensorPathStr, "max", "label");
528 maxLabel = true;
529 }
530 else
531 {
532 labelPath = boost::replace_all_copy(sensorPathStr, "input",
533 "label");
534 maxLabel = false;
535 }
536 }
537 else
538 {
539 continue;
540 }
541
Cheng C Yangecba9de2019-09-12 23:41:50 +0800542 std::ifstream labelFile(labelPath);
543 if (!labelFile.good())
Cheng C Yang209ec562019-03-12 16:37:44 +0800544 {
Ed Tanous8a57ec02020-10-09 12:46:52 -0700545 if constexpr (debug)
Cheng C Yang6b1247a2020-03-09 23:48:39 +0800546 {
547 std::cerr << "Input file " << sensorPath
548 << " has no corresponding label file\n";
549 }
Josh Lehan06494452019-10-31 09:49:16 -0700550 // hwmon *_input filename with number:
551 // temp1, temp2, temp3, ...
Ed Tanous8a57ec02020-10-09 12:46:52 -0700552 labelHead = sensorNameStr.substr(0, sensorNameStr.find('_'));
Cheng C Yang209ec562019-03-12 16:37:44 +0800553 }
554 else
555 {
Cheng C Yange50345b2019-04-02 17:26:15 +0800556 std::string label;
557 std::getline(labelFile, label);
558 labelFile.close();
Cheng C Yange50345b2019-04-02 17:26:15 +0800559 auto findSensor = sensors.find(label);
560 if (findSensor != sensors.end())
561 {
562 continue;
563 }
564
Josh Lehan06494452019-10-31 09:49:16 -0700565 // hwmon corresponding *_label file contents:
566 // vin1, vout1, ...
Ed Tanous8a57ec02020-10-09 12:46:52 -0700567 labelHead = label.substr(0, label.find(' '));
Cheng C Yange50345b2019-04-02 17:26:15 +0800568 }
569
Manikandan Elumalaic7e95622020-06-03 20:22:01 +0530570 /* append "max" for labelMatch */
571 if (maxLabel)
572 {
Ed Tanous8a57ec02020-10-09 12:46:52 -0700573 labelHead.insert(0, "max");
Manikandan Elumalaic7e95622020-06-03 20:22:01 +0530574 }
575
Ed Tanous8a57ec02020-10-09 12:46:52 -0700576 if constexpr (debug)
Josh Lehan74d9bd92019-10-31 08:51:58 -0700577 {
578 std::cerr << "Sensor type=\"" << sensorNameSubStr
579 << "\" label=\"" << labelHead << "\"\n";
580 }
581
AppaRao Pulid9d8caf2020-02-27 20:56:59 +0530582 checkPWMSensor(sensorPath, labelHead, *interfacePath,
583 dbusConnection, objectServer, psuNames[0]);
Cheng C Yang916360b2019-05-07 18:47:16 +0800584
Vijay Khemka996bad12019-05-28 15:15:16 -0700585 if (!findLabels.empty())
586 {
587 /* Check if this labelHead is enabled in config file */
588 if (std::find(findLabels.begin(), findLabels.end(),
589 labelHead) == findLabels.end())
590 {
Ed Tanous8a57ec02020-10-09 12:46:52 -0700591 if constexpr (debug)
Cheng C Yang6b1247a2020-03-09 23:48:39 +0800592 {
593 std::cerr << "could not find " << labelHead
594 << " in the Labels list\n";
595 }
Vijay Khemka996bad12019-05-28 15:15:16 -0700596 continue;
597 }
598 }
Cheng C Yange50345b2019-04-02 17:26:15 +0800599
Cheng C Yange50345b2019-04-02 17:26:15 +0800600 auto findProperty = labelMatch.find(labelHead);
601 if (findProperty == labelMatch.end())
Cheng C Yang209ec562019-03-12 16:37:44 +0800602 {
Ed Tanous8a57ec02020-10-09 12:46:52 -0700603 if constexpr (debug)
Josh Lehan74d9bd92019-10-31 08:51:58 -0700604 {
605 std::cerr << "Could not find matching default property for "
606 << labelHead << "\n";
607 }
Cheng C Yang209ec562019-03-12 16:37:44 +0800608 continue;
609 }
610
Josh Lehan74d9bd92019-10-31 08:51:58 -0700611 // Protect the hardcoded labelMatch list from changes,
612 // by making a copy and modifying that instead.
613 // Avoid bleedthrough of one device's customizations to
614 // the next device, as each should be independently customizable.
615 psuProperties.push_back(findProperty->second);
616 auto psuProperty = psuProperties.rbegin();
617
618 // Use label head as prefix for reading from config file,
619 // example if temp1: temp1_Name, temp1_Scale, temp1_Min, ...
620 std::string keyName = labelHead + "_Name";
621 std::string keyScale = labelHead + "_Scale";
622 std::string keyMin = labelHead + "_Min";
623 std::string keyMax = labelHead + "_Max";
Jeff Line41d52f2021-04-07 19:38:51 +0800624 std::string keyOffset = labelHead + "_Offset";
Josh Lehan74d9bd92019-10-31 08:51:58 -0700625
626 bool customizedName = false;
627 auto findCustomName = baseConfig->second.find(keyName);
628 if (findCustomName != baseConfig->second.end())
Josh Lehan432d1ed2019-10-16 12:23:31 -0700629 {
Josh Lehan74d9bd92019-10-31 08:51:58 -0700630 try
631 {
632 psuProperty->labelTypeName = std::visit(
633 VariantToStringVisitor(), findCustomName->second);
634 }
635 catch (std::invalid_argument&)
636 {
637 std::cerr << "Unable to parse " << keyName << "\n";
638 continue;
639 }
640
641 // All strings are valid, including empty string
642 customizedName = true;
643 }
644
645 bool customizedScale = false;
646 auto findCustomScale = baseConfig->second.find(keyScale);
647 if (findCustomScale != baseConfig->second.end())
648 {
649 try
650 {
651 psuProperty->sensorScaleFactor = std::visit(
652 VariantToUnsignedIntVisitor(), findCustomScale->second);
653 }
654 catch (std::invalid_argument&)
655 {
656 std::cerr << "Unable to parse " << keyScale << "\n";
657 continue;
658 }
659
660 // Avoid later division by zero
661 if (psuProperty->sensorScaleFactor > 0)
662 {
663 customizedScale = true;
664 }
665 else
666 {
667 std::cerr << "Unable to accept " << keyScale << "\n";
668 continue;
669 }
670 }
671
672 auto findCustomMin = baseConfig->second.find(keyMin);
673 if (findCustomMin != baseConfig->second.end())
674 {
675 try
676 {
677 psuProperty->minReading = std::visit(
678 VariantToDoubleVisitor(), findCustomMin->second);
679 }
680 catch (std::invalid_argument&)
681 {
682 std::cerr << "Unable to parse " << keyMin << "\n";
683 continue;
684 }
685 }
686
687 auto findCustomMax = baseConfig->second.find(keyMax);
688 if (findCustomMax != baseConfig->second.end())
689 {
690 try
691 {
692 psuProperty->maxReading = std::visit(
693 VariantToDoubleVisitor(), findCustomMax->second);
694 }
695 catch (std::invalid_argument&)
696 {
697 std::cerr << "Unable to parse " << keyMax << "\n";
698 continue;
699 }
700 }
701
Jeff Line41d52f2021-04-07 19:38:51 +0800702 auto findCustomOffset = baseConfig->second.find(keyOffset);
703 if (findCustomOffset != baseConfig->second.end())
704 {
705 try
706 {
707 psuProperty->sensorOffset = std::visit(
708 VariantToDoubleVisitor(), findCustomOffset->second);
709 }
710 catch (std::invalid_argument&)
711 {
712 std::cerr << "Unable to parse " << keyOffset << "\n";
713 continue;
714 }
715 }
716
Josh Lehan74d9bd92019-10-31 08:51:58 -0700717 if (!(psuProperty->minReading < psuProperty->maxReading))
718 {
719 std::cerr << "Min must be less than Max\n";
720 continue;
721 }
722
723 // If the sensor name is being customized by config file,
724 // then prefix/suffix composition becomes not necessary,
725 // and in fact not wanted, because it gets in the way.
726 std::string psuNameFromIndex;
727 if (!customizedName)
728 {
729 /* Find out sensor name index for this label */
730 std::regex rgx("[A-Za-z]+([0-9]+)");
Brad Bishopfbb44ad2019-11-08 09:42:37 -0500731 size_t nameIndex{0};
Josh Lehan74d9bd92019-10-31 08:51:58 -0700732 if (std::regex_search(labelHead, matches, rgx))
733 {
734 nameIndex = std::stoi(matches[1]);
735
736 // Decrement to preserve alignment, because hwmon
737 // human-readable filenames and labels use 1-based
738 // numbering, but the "Name", "Name1", "Name2", etc. naming
739 // convention (the psuNames vector) uses 0-based numbering.
740 if (nameIndex > 0)
741 {
742 --nameIndex;
743 }
744 }
745 else
746 {
747 nameIndex = 0;
748 }
749
750 if (psuNames.size() <= nameIndex)
751 {
752 std::cerr << "Could not pair " << labelHead
753 << " with a Name field\n";
754 continue;
755 }
756
757 psuNameFromIndex = psuNames[nameIndex];
758
Ed Tanous8a57ec02020-10-09 12:46:52 -0700759 if constexpr (debug)
Josh Lehan74d9bd92019-10-31 08:51:58 -0700760 {
761 std::cerr << "Sensor label head " << labelHead
762 << " paired with " << psuNameFromIndex
763 << " at index " << nameIndex << "\n";
764 }
Josh Lehan432d1ed2019-10-16 12:23:31 -0700765 }
766
Cheng C Yang58b2b532019-05-31 00:19:45 +0800767 checkEventLimits(sensorPathStr, limitEventMatch, eventPathList);
768
Josh Lehan74d9bd92019-10-31 08:51:58 -0700769 // Similarly, if sensor scaling factor is being customized,
770 // then the below power-of-10 constraint becomes unnecessary,
771 // as config should be able to specify an arbitrary divisor.
772 unsigned int factor = psuProperty->sensorScaleFactor;
773 if (!customizedScale)
Vijay Khemka53ca4442019-07-23 11:03:55 -0700774 {
Josh Lehan74d9bd92019-10-31 08:51:58 -0700775 // Preserve existing usage of hardcoded labelMatch table below
776 factor = std::pow(10.0, factor);
Vijay Khemka53ca4442019-07-23 11:03:55 -0700777
Josh Lehan74d9bd92019-10-31 08:51:58 -0700778 /* Change first char of substring to uppercase */
Ed Tanous8a57ec02020-10-09 12:46:52 -0700779 char firstChar =
780 static_cast<char>(std::toupper(sensorNameSubStr[0]));
Josh Lehan74d9bd92019-10-31 08:51:58 -0700781 std::string strScaleFactor =
782 firstChar + sensorNameSubStr.substr(1) + "ScaleFactor";
783
784 // Preserve existing configs by accepting earlier syntax,
785 // example CurrScaleFactor, PowerScaleFactor, ...
786 auto findScaleFactor = baseConfig->second.find(strScaleFactor);
787 if (findScaleFactor != baseConfig->second.end())
788 {
789 factor = std::visit(VariantToIntVisitor(),
790 findScaleFactor->second);
791 }
792
Ed Tanous8a57ec02020-10-09 12:46:52 -0700793 if constexpr (debug)
Josh Lehan74d9bd92019-10-31 08:51:58 -0700794 {
795 std::cerr << "Sensor scaling factor " << factor
796 << " string " << strScaleFactor << "\n";
797 }
Josh Lehan49cfba92019-10-08 16:50:42 -0700798 }
799
Vijay Khemka996bad12019-05-28 15:15:16 -0700800 std::vector<thresholds::Threshold> sensorThresholds;
Joshi, Mansi14f0ad82019-11-21 10:52:30 +0530801 if (!parseThresholdsFromConfig(*sensorData, sensorThresholds,
802 &labelHead))
Cheng C Yange50345b2019-04-02 17:26:15 +0800803 {
James Feist17ab6e02019-06-25 12:28:13 -0700804 std::cerr << "error populating thresholds for "
805 << sensorNameSubStr << "\n";
Cheng C Yange50345b2019-04-02 17:26:15 +0800806 }
807
Zev Weiss6b6891c2021-04-22 02:46:21 -0500808 auto findSensorUnit = sensorTable.find(sensorNameSubStr);
809 if (findSensorUnit == sensorTable.end())
Cheng C Yange50345b2019-04-02 17:26:15 +0800810 {
Jason Ling5747fab2019-10-02 16:46:23 -0700811 std::cerr << sensorNameSubStr
Josh Lehan06494452019-10-31 09:49:16 -0700812 << " is not a recognized sensor type\n";
Cheng C Yange50345b2019-04-02 17:26:15 +0800813 continue;
814 }
815
Ed Tanous8a57ec02020-10-09 12:46:52 -0700816 if constexpr (debug)
Josh Lehan49cfba92019-10-08 16:50:42 -0700817 {
Josh Lehan74d9bd92019-10-31 08:51:58 -0700818 std::cerr << "Sensor properties: Name \""
819 << psuProperty->labelTypeName << "\" Scale "
820 << psuProperty->sensorScaleFactor << " Min "
821 << psuProperty->minReading << " Max "
Jeff Line41d52f2021-04-07 19:38:51 +0800822 << psuProperty->maxReading << " Offset "
823 << psuProperty->sensorOffset << "\n";
Josh Lehan74d9bd92019-10-31 08:51:58 -0700824 }
825
826 std::string sensorName = psuProperty->labelTypeName;
827 if (customizedName)
828 {
829 if (sensorName.empty())
830 {
831 // Allow selective disabling of an individual sensor,
832 // by customizing its name to an empty string.
833 std::cerr << "Sensor disabled, empty string\n";
834 continue;
835 }
836 }
837 else
838 {
839 // Sensor name not customized, do prefix/suffix composition,
840 // preserving default behavior by using psuNameFromIndex.
841 sensorName =
842 psuNameFromIndex + " " + psuProperty->labelTypeName;
843 }
844
Ed Tanous8a57ec02020-10-09 12:46:52 -0700845 if constexpr (debug)
Josh Lehan74d9bd92019-10-31 08:51:58 -0700846 {
847 std::cerr << "Sensor name \"" << sensorName << "\" path \""
848 << sensorPathStr << "\" type \"" << sensorType
849 << "\"\n";
Josh Lehan49cfba92019-10-08 16:50:42 -0700850 }
Zhikui Ren23c96e72020-11-05 22:32:28 -0800851 // destruct existing one first if already created
852 sensors[sensorName] = nullptr;
Yong Libf8b1da2020-04-15 16:32:50 +0800853 sensors[sensorName] = std::make_shared<PSUSensor>(
Cheng C Yange50345b2019-04-02 17:26:15 +0800854 sensorPathStr, sensorType, objectServer, dbusConnection, io,
Cheng C Yang209ec562019-03-12 16:37:44 +0800855 sensorName, std::move(sensorThresholds), *interfacePath,
Zev Weiss6b6891c2021-04-22 02:46:21 -0500856 findSensorUnit->second, factor, psuProperty->maxReading,
Jeff Line41d52f2021-04-07 19:38:51 +0800857 psuProperty->minReading, psuProperty->sensorOffset, labelHead,
858 thresholdConfSize, pollRate);
Yong Libf8b1da2020-04-15 16:32:50 +0800859 sensors[sensorName]->setupRead();
Josh Lehan74d9bd92019-10-31 08:51:58 -0700860 ++numCreated;
Ed Tanous8a57ec02020-10-09 12:46:52 -0700861 if constexpr (debug)
Josh Lehan74d9bd92019-10-31 08:51:58 -0700862 {
863 std::cerr << "Created " << numCreated << " sensors so far\n";
864 }
Cheng C Yang209ec562019-03-12 16:37:44 +0800865 }
Cheng C Yang58b2b532019-05-31 00:19:45 +0800866
867 // OperationalStatus event
Cheng C Yang92498eb2019-09-26 21:59:25 +0800868 combineEvents[*psuName + "OperationalStatus"] = nullptr;
Cheng C Yang58b2b532019-05-31 00:19:45 +0800869 combineEvents[*psuName + "OperationalStatus"] =
Yong Li3046a022020-04-03 13:01:02 +0800870 std::make_unique<PSUCombineEvent>(
871 objectServer, dbusConnection, io, *psuName, eventPathList,
Lei YU7170a232021-02-04 16:19:27 +0800872 groupEventPathList, "OperationalStatus", pollRate);
Cheng C Yang209ec562019-03-12 16:37:44 +0800873 }
Josh Lehan49cfba92019-10-08 16:50:42 -0700874
Ed Tanous8a57ec02020-10-09 12:46:52 -0700875 if constexpr (debug)
Josh Lehan49cfba92019-10-08 16:50:42 -0700876 {
877 std::cerr << "Created total of " << numCreated << " sensors\n";
878 }
Cheng C Yang209ec562019-03-12 16:37:44 +0800879 return;
880}
881
Zhikui Ren23c96e72020-11-05 22:32:28 -0800882void createSensors(
883 boost::asio::io_service& io, sdbusplus::asio::object_server& objectServer,
884 std::shared_ptr<sdbusplus::asio::connection>& dbusConnection,
885 const std::shared_ptr<boost::container::flat_set<std::string>>&
886 sensorsChanged)
887{
888 auto getter = std::make_shared<GetSensorConfiguration>(
889 dbusConnection, [&io, &objectServer, &dbusConnection, sensorsChanged](
890 const ManagedObjectType& sensorConfigs) {
891 createSensorsCallback(io, objectServer, dbusConnection,
892 sensorConfigs, sensorsChanged);
893 });
894 getter->getConfiguration(
895 std::vector<std::string>(sensorTypes.begin(), sensorTypes.end()));
896}
897
Cheng C Yang916360b2019-05-07 18:47:16 +0800898void propertyInitialize(void)
Cheng C Yang209ec562019-03-12 16:37:44 +0800899{
Zev Weiss6b6891c2021-04-22 02:46:21 -0500900 sensorTable = {{"power", sensor_paths::unitWatts},
901 {"curr", sensor_paths::unitAmperes},
902 {"temp", sensor_paths::unitDegreesC},
903 {"in", sensor_paths::unitVolts},
904 {"fan", sensor_paths::unitRPMs}};
Cheng C Yange50345b2019-04-02 17:26:15 +0800905
Jeff Line41d52f2021-04-07 19:38:51 +0800906 labelMatch = {
907 {"pin", PSUProperty("Input Power", 3000, 0, 6, 0)},
908 {"pout1", PSUProperty("Output Power", 3000, 0, 6, 0)},
909 {"pout2", PSUProperty("Output Power", 3000, 0, 6, 0)},
910 {"pout3", PSUProperty("Output Power", 3000, 0, 6, 0)},
911 {"power1", PSUProperty("Output Power", 3000, 0, 6, 0)},
912 {"maxpin", PSUProperty("Max Input Power", 3000, 0, 6, 0)},
913 {"vin", PSUProperty("Input Voltage", 300, 0, 3, 0)},
914 {"maxvin", PSUProperty("Max Input Voltage", 300, 0, 3, 0)},
915 {"vout1", PSUProperty("Output Voltage", 255, 0, 3, 0)},
916 {"vout2", PSUProperty("Output Voltage", 255, 0, 3, 0)},
917 {"vout3", PSUProperty("Output Voltage", 255, 0, 3, 0)},
918 {"vout4", PSUProperty("Output Voltage", 255, 0, 3, 0)},
919 {"vout5", PSUProperty("Output Voltage", 255, 0, 3, 0)},
920 {"vout6", PSUProperty("Output Voltage", 255, 0, 3, 0)},
921 {"vout7", PSUProperty("Output Voltage", 255, 0, 3, 0)},
922 {"vout8", PSUProperty("Output Voltage", 255, 0, 3, 0)},
923 {"vout9", PSUProperty("Output Voltage", 255, 0, 3, 0)},
924 {"vout10", PSUProperty("Output Voltage", 255, 0, 3, 0)},
925 {"vout11", PSUProperty("Output Voltage", 255, 0, 3, 0)},
926 {"vout12", PSUProperty("Output Voltage", 255, 0, 3, 0)},
927 {"vout13", PSUProperty("Output Voltage", 255, 0, 3, 0)},
928 {"vout14", PSUProperty("Output Voltage", 255, 0, 3, 0)},
929 {"vout15", PSUProperty("Output Voltage", 255, 0, 3, 0)},
930 {"vout16", PSUProperty("Output Voltage", 255, 0, 3, 0)},
931 {"vout17", PSUProperty("Output Voltage", 255, 0, 3, 0)},
932 {"vout18", PSUProperty("Output Voltage", 255, 0, 3, 0)},
933 {"vout19", PSUProperty("Output Voltage", 255, 0, 3, 0)},
934 {"vout20", PSUProperty("Output Voltage", 255, 0, 3, 0)},
935 {"vout21", PSUProperty("Output Voltage", 255, 0, 3, 0)},
936 {"vout22", PSUProperty("Output Voltage", 255, 0, 3, 0)},
937 {"vout23", PSUProperty("Output Voltage", 255, 0, 3, 0)},
938 {"vout24", PSUProperty("Output Voltage", 255, 0, 3, 0)},
939 {"vout25", PSUProperty("Output Voltage", 255, 0, 3, 0)},
940 {"vout26", PSUProperty("Output Voltage", 255, 0, 3, 0)},
941 {"vout27", PSUProperty("Output Voltage", 255, 0, 3, 0)},
942 {"vout28", PSUProperty("Output Voltage", 255, 0, 3, 0)},
943 {"vout29", PSUProperty("Output Voltage", 255, 0, 3, 0)},
944 {"vout30", PSUProperty("Output Voltage", 255, 0, 3, 0)},
945 {"vout31", PSUProperty("Output Voltage", 255, 0, 3, 0)},
946 {"vout32", PSUProperty("Output Voltage", 255, 0, 3, 0)},
947 {"vmon", PSUProperty("Auxiliary Input Voltage", 255, 0, 3, 0)},
948 {"in1", PSUProperty("Output Voltage", 255, 0, 3, 0)},
949 {"iin", PSUProperty("Input Current", 20, 0, 3, 0)},
950 {"iout1", PSUProperty("Output Current", 255, 0, 3, 0)},
951 {"iout2", PSUProperty("Output Current", 255, 0, 3, 0)},
952 {"iout3", PSUProperty("Output Current", 255, 0, 3, 0)},
953 {"iout4", PSUProperty("Output Current", 255, 0, 3, 0)},
954 {"iout5", PSUProperty("Output Current", 255, 0, 3, 0)},
955 {"iout6", PSUProperty("Output Current", 255, 0, 3, 0)},
956 {"iout7", PSUProperty("Output Current", 255, 0, 3, 0)},
957 {"iout8", PSUProperty("Output Current", 255, 0, 3, 0)},
958 {"iout9", PSUProperty("Output Current", 255, 0, 3, 0)},
959 {"iout10", PSUProperty("Output Current", 255, 0, 3, 0)},
960 {"iout11", PSUProperty("Output Current", 255, 0, 3, 0)},
961 {"iout12", PSUProperty("Output Current", 255, 0, 3, 0)},
962 {"iout13", PSUProperty("Output Current", 255, 0, 3, 0)},
963 {"iout14", PSUProperty("Output Current", 255, 0, 3, 0)},
964 {"curr1", PSUProperty("Output Current", 255, 0, 3, 0)},
965 {"maxiout1", PSUProperty("Max Output Current", 255, 0, 3, 0)},
966 {"temp1", PSUProperty("Temperature", 127, -128, 3, 0)},
967 {"temp2", PSUProperty("Temperature", 127, -128, 3, 0)},
968 {"temp3", PSUProperty("Temperature", 127, -128, 3, 0)},
969 {"temp4", PSUProperty("Temperature", 127, -128, 3, 0)},
970 {"temp5", PSUProperty("Temperature", 127, -128, 3, 0)},
971 {"temp6", PSUProperty("Temperature", 127, -128, 3, 0)},
972 {"maxtemp1", PSUProperty("Max Temperature", 127, -128, 3, 0)},
973 {"fan1", PSUProperty("Fan Speed 1", 30000, 0, 0, 0)},
974 {"fan2", PSUProperty("Fan Speed 2", 30000, 0, 0, 0)}};
Cheng C Yang916360b2019-05-07 18:47:16 +0800975
976 pwmTable = {{"fan1", "Fan_1"}, {"fan2", "Fan_2"}};
Cheng C Yang58b2b532019-05-31 00:19:45 +0800977
978 limitEventMatch = {{"PredictiveFailure", {"max_alarm", "min_alarm"}},
979 {"Failure", {"crit_alarm", "lcrit_alarm"}}};
980
Cheng C Yang202a1ff2020-01-09 09:34:22 +0800981 eventMatch = {{"PredictiveFailure", {"power1_alarm"}},
982 {"Failure", {"in2_alarm"}},
983 {"ACLost", {"in1_beep"}},
984 {"ConfigureError", {"in1_fault"}}};
985
986 groupEventMatch = {{"FanFault",
987 {{"fan1", {"fan1_alarm", "fan1_fault"}},
988 {"fan2", {"fan2_alarm", "fan2_fault"}}}}};
Cheng C Yang209ec562019-03-12 16:37:44 +0800989}
990
James Feistb6c0b912019-07-09 12:21:44 -0700991int main()
Cheng C Yang209ec562019-03-12 16:37:44 +0800992{
993 boost::asio::io_service io;
994 auto systemBus = std::make_shared<sdbusplus::asio::connection>(io);
995
996 systemBus->request_name("xyz.openbmc_project.PSUSensor");
997 sdbusplus::asio::object_server objectServer(systemBus);
Cheng C Yang209ec562019-03-12 16:37:44 +0800998 std::vector<std::unique_ptr<sdbusplus::bus::match::match>> matches;
Zhikui Ren23c96e72020-11-05 22:32:28 -0800999 auto sensorsChanged =
1000 std::make_shared<boost::container::flat_set<std::string>>();
Cheng C Yang209ec562019-03-12 16:37:44 +08001001
Cheng C Yang916360b2019-05-07 18:47:16 +08001002 propertyInitialize();
Cheng C Yang209ec562019-03-12 16:37:44 +08001003
Zhikui Ren23c96e72020-11-05 22:32:28 -08001004 io.post([&]() { createSensors(io, objectServer, systemBus, nullptr); });
Cheng C Yang209ec562019-03-12 16:37:44 +08001005 boost::asio::deadline_timer filterTimer(io);
1006 std::function<void(sdbusplus::message::message&)> eventHandler =
1007 [&](sdbusplus::message::message& message) {
1008 if (message.is_method_error())
1009 {
1010 std::cerr << "callback method error\n";
1011 return;
1012 }
Zhikui Ren23c96e72020-11-05 22:32:28 -08001013 sensorsChanged->insert(message.get_path());
Cheng C Yanga97f1342020-02-11 15:10:41 +08001014 filterTimer.expires_from_now(boost::posix_time::seconds(3));
Cheng C Yang209ec562019-03-12 16:37:44 +08001015 filterTimer.async_wait([&](const boost::system::error_code& ec) {
1016 if (ec == boost::asio::error::operation_aborted)
1017 {
1018 return;
1019 }
Ed Tanous8a57ec02020-10-09 12:46:52 -07001020 if (ec)
Cheng C Yang209ec562019-03-12 16:37:44 +08001021 {
1022 std::cerr << "timer error\n";
1023 }
Zhikui Ren23c96e72020-11-05 22:32:28 -08001024 createSensors(io, objectServer, systemBus, sensorsChanged);
Cheng C Yang209ec562019-03-12 16:37:44 +08001025 });
1026 };
1027
1028 for (const char* type : sensorTypes)
1029 {
1030 auto match = std::make_unique<sdbusplus::bus::match::match>(
1031 static_cast<sdbusplus::bus::bus&>(*systemBus),
1032 "type='signal',member='PropertiesChanged',path_namespace='" +
1033 std::string(inventoryPath) + "',arg0namespace='" + type + "'",
1034 eventHandler);
1035 matches.emplace_back(std::move(match));
1036 }
Bruce Lee1263c3d2021-06-04 15:16:33 +08001037
1038 setupManufacturingModeMatch(*systemBus);
Cheng C Yang209ec562019-03-12 16:37:44 +08001039 io.run();
1040}