blob: 6732575c9d1bb5ac4763ace8d3bfdb5c054c303d [file] [log] [blame]
James Feist6714a252018-09-10 15:26:18 -07001/*
2// Copyright (c) 2017 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*/
16
Ed Tanous8a57ec02020-10-09 12:46:52 -070017#include <PwmSensor.hpp>
18#include <TachSensor.hpp>
19#include <Utils.hpp>
20#include <VariantVisitors.hpp>
James Feist6714a252018-09-10 15:26:18 -070021#include <boost/algorithm/string/replace.hpp>
Patrick Venture96e97db2019-10-31 13:44:38 -070022#include <boost/container/flat_map.hpp>
James Feist6714a252018-09-10 15:26:18 -070023#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>
James Feist24f02f22019-04-15 11:05:39 -070029#include <filesystem>
James Feist6714a252018-09-10 15:26:18 -070030#include <fstream>
Patrick Venture96e97db2019-10-31 13:44:38 -070031#include <functional>
32#include <memory>
33#include <optional>
James Feist6714a252018-09-10 15:26:18 -070034#include <regex>
Patrick Venture96e97db2019-10-31 13:44:38 -070035#include <string>
36#include <utility>
37#include <variant>
38#include <vector>
James Feist6714a252018-09-10 15:26:18 -070039
James Feistcf3bce62019-01-08 10:07:19 -080040namespace fs = std::filesystem;
James Feist3eb82622019-02-08 13:10:22 -080041
Yong Zhaoa3e8f2a2021-01-09 02:22:43 +000042// The following two structures need to be consistent
Brandon Kim66558232021-11-09 16:53:08 -080043static auto sensorTypes{std::to_array<const char*>(
44 {"xyz.openbmc_project.Configuration.AspeedFan",
45 "xyz.openbmc_project.Configuration.I2CFan",
46 "xyz.openbmc_project.Configuration.NuvotonFan"})};
Yong Zhaoa3e8f2a2021-01-09 02:22:43 +000047
48enum FanTypes
49{
50 aspeed = 0,
51 i2c,
52 nuvoton,
53 max,
54};
55
56static_assert(std::tuple_size<decltype(sensorTypes)>::value == FanTypes::max,
57 "sensorTypes element number is not equal to FanTypes number");
58
James Feistdc6c55f2018-10-31 12:53:20 -070059constexpr const char* redundancyConfiguration =
60 "xyz.openbmc_project.Configuration.FanRedundancy";
Jae Hyun Yoo9ced0a32018-10-25 10:42:39 -070061static std::regex inputRegex(R"(fan(\d+)_input)");
James Feist6714a252018-09-10 15:26:18 -070062
James Feistdc6c55f2018-10-31 12:53:20 -070063// todo: power supply fan redundancy
James Feist7b18b1e2019-05-14 13:42:09 -070064std::optional<RedundancySensor> systemRedundancy;
James Feist95b079b2018-11-21 09:28:00 -080065
66FanTypes getFanType(const fs::path& parentPath)
67{
68 fs::path linkPath = parentPath / "device";
69 std::string canonical = fs::read_symlink(linkPath);
Zev Weiss6c106d62022-08-17 20:50:00 -070070 if (canonical.ends_with("pwm-tacho-controller") ||
71 canonical.ends_with("pwm_tach:tach"))
James Feist95b079b2018-11-21 09:28:00 -080072 {
73 return FanTypes::aspeed;
74 }
Zev Weiss6c106d62022-08-17 20:50:00 -070075 if (canonical.ends_with("pwm-fan-controller"))
Peter Lundgren8843b622019-09-12 10:33:41 -070076 {
77 return FanTypes::nuvoton;
78 }
James Feist95b079b2018-11-21 09:28:00 -080079 // todo: will we need to support other types?
80 return FanTypes::i2c;
81}
Jeff Linabf91de2020-12-23 10:55:42 +080082void enablePwm(const fs::path& filePath)
83{
84 std::fstream enableFile(filePath, std::ios::in | std::ios::out);
85 if (!enableFile.good())
86 {
87 std::cerr << "Error read/write " << filePath << "\n";
88 return;
89 }
James Feistdc6c55f2018-10-31 12:53:20 -070090
Jeff Linabf91de2020-12-23 10:55:42 +080091 std::string regulateMode;
92 std::getline(enableFile, regulateMode);
93 if (regulateMode == "0")
94 {
95 enableFile << 1;
96 }
97}
Howard Chiuddf25d12021-12-02 15:14:44 +080098bool findPwmfanPath(unsigned int configPwmfanIndex, fs::path& pwmPath)
99{
100 /* Search PWM since pwm-fan had separated
101 * PWM from tach directory and 1 channel only*/
102 std::vector<fs::path> pwmfanPaths;
103 std::string pwnfanDevName("pwm-fan");
104
105 pwnfanDevName += std::to_string(configPwmfanIndex);
106
107 if (!findFiles(fs::path("/sys/class/hwmon"), R"(pwm\d+)", pwmfanPaths))
108 {
109 std::cerr << "No PWMs are found!\n";
110 return false;
111 }
112 for (const auto& path : pwmfanPaths)
113 {
114 std::error_code ec;
115 fs::path link = fs::read_symlink(path.parent_path() / "device", ec);
116
117 if (ec)
118 {
119 std::cerr << "read_symlink() failed: " << ec.message() << " ("
120 << ec.value() << ")\n";
121 continue;
122 }
123
124 if (link.filename().string() == pwnfanDevName)
125 {
126 pwmPath = path;
127 return true;
128 }
129 }
130 return false;
131}
132bool findPwmPath(const fs::path& directory, unsigned int pwm, fs::path& pwmPath)
133{
134 std::error_code ec;
135
136 /* Assuming PWM file is appeared in the same directory as fanX_input */
137 auto path = directory / ("pwm" + std::to_string(pwm + 1));
138 bool exists = fs::exists(path, ec);
139
140 if (ec || !exists)
141 {
142 /* PWM file not exist or error happened */
143 if (ec)
144 {
145 std::cerr << "exists() failed: " << ec.message() << " ("
146 << ec.value() << ")\n";
147 }
148 /* try search form pwm-fanX directory */
149 return findPwmfanPath(pwm, pwmPath);
150 }
151
152 pwmPath = path;
153 return true;
154}
Kuiying Wangd5407412020-09-09 16:06:56 +0800155void createRedundancySensor(
Josh Lehan5170fe62022-08-03 13:17:41 -0700156 const boost::container::flat_map<std::string, std::shared_ptr<TachSensor>>&
Kuiying Wangd5407412020-09-09 16:06:56 +0800157 sensors,
Ed Tanous8a57ec02020-10-09 12:46:52 -0700158 const std::shared_ptr<sdbusplus::asio::connection>& conn,
Kuiying Wangd5407412020-09-09 16:06:56 +0800159 sdbusplus::asio::object_server& objectServer)
160{
161
162 conn->async_method_call(
163 [&objectServer, &sensors](boost::system::error_code& ec,
Ed Tanous8a57ec02020-10-09 12:46:52 -0700164 const ManagedObjectType& managedObj) {
Ed Tanousbb679322022-05-16 16:10:00 -0700165 if (ec)
166 {
167 std::cerr << "Error calling entity manager \n";
168 return;
169 }
Zev Weiss77636ec2022-08-12 18:21:01 -0700170 for (const auto& [path, interfaces] : managedObj)
Ed Tanousbb679322022-05-16 16:10:00 -0700171 {
Zev Weiss77636ec2022-08-12 18:21:01 -0700172 for (const auto& [intf, cfg] : interfaces)
Kuiying Wangd5407412020-09-09 16:06:56 +0800173 {
Zev Weiss77636ec2022-08-12 18:21:01 -0700174 if (intf == redundancyConfiguration)
Kuiying Wangd5407412020-09-09 16:06:56 +0800175 {
Ed Tanousbb679322022-05-16 16:10:00 -0700176 // currently only support one
Zev Weiss77636ec2022-08-12 18:21:01 -0700177 auto findCount = cfg.find("AllowedFailures");
178 if (findCount == cfg.end())
Kuiying Wangd5407412020-09-09 16:06:56 +0800179 {
Ed Tanousbb679322022-05-16 16:10:00 -0700180 std::cerr << "Malformed redundancy record \n";
Kuiying Wangd5407412020-09-09 16:06:56 +0800181 return;
182 }
Ed Tanousbb679322022-05-16 16:10:00 -0700183 std::vector<std::string> sensorList;
184
Zev Weiss77636ec2022-08-12 18:21:01 -0700185 for (const auto& [name, sensor] : sensors)
Ed Tanousbb679322022-05-16 16:10:00 -0700186 {
187 sensorList.push_back(
188 "/xyz/openbmc_project/sensors/fan_tach/" +
Zev Weiss77636ec2022-08-12 18:21:01 -0700189 sensor->name);
Ed Tanousbb679322022-05-16 16:10:00 -0700190 }
191 systemRedundancy.reset();
Zev Weiss77636ec2022-08-12 18:21:01 -0700192 systemRedundancy.emplace(
193 RedundancySensor(std::get<uint64_t>(findCount->second),
194 sensorList, objectServer, path));
Ed Tanousbb679322022-05-16 16:10:00 -0700195
196 return;
Kuiying Wangd5407412020-09-09 16:06:56 +0800197 }
198 }
Ed Tanousbb679322022-05-16 16:10:00 -0700199 }
Kuiying Wangd5407412020-09-09 16:06:56 +0800200 },
201 "xyz.openbmc_project.EntityManager", "/",
202 "org.freedesktop.DBus.ObjectManager", "GetManagedObjects");
203}
204
James Feist6714a252018-09-10 15:26:18 -0700205void createSensors(
206 boost::asio::io_service& io, sdbusplus::asio::object_server& objectServer,
Josh Lehan5170fe62022-08-03 13:17:41 -0700207 boost::container::flat_map<std::string, std::shared_ptr<TachSensor>>&
James Feist6714a252018-09-10 15:26:18 -0700208 tachSensors,
209 boost::container::flat_map<std::string, std::unique_ptr<PwmSensor>>&
210 pwmSensors,
211 std::shared_ptr<sdbusplus::asio::connection>& dbusConnection,
James Feist5591cf082020-07-15 16:44:54 -0700212 const std::shared_ptr<boost::container::flat_set<std::string>>&
James Feistf27a55c2020-08-04 14:27:30 -0700213 sensorsChanged,
214 size_t retries = 0)
James Feist6714a252018-09-10 15:26:18 -0700215{
James Feistde5e9702019-09-18 16:13:02 -0700216 auto getter = std::make_shared<GetSensorConfiguration>(
217 dbusConnection,
Ed Tanous8a17c302021-09-02 15:07:11 -0700218 [&io, &objectServer, &tachSensors, &pwmSensors, &dbusConnection,
219 sensorsChanged](const ManagedObjectType& sensorConfigurations) {
Ed Tanousbb679322022-05-16 16:10:00 -0700220 bool firstScan = sensorsChanged == nullptr;
221 std::vector<fs::path> paths;
222 if (!findFiles(fs::path("/sys/class/hwmon"), R"(fan\d+_input)", paths))
223 {
224 std::cerr << "No fan sensors in system\n";
225 return;
226 }
227
228 // iterate through all found fan sensors, and try to match them with
229 // configuration
230 for (const auto& path : paths)
231 {
232 std::smatch match;
233 std::string pathStr = path.string();
234
235 std::regex_search(pathStr, match, inputRegex);
236 std::string indexStr = *(match.begin() + 1);
237
238 fs::path directory = path.parent_path();
239 FanTypes fanType = getFanType(directory);
240
241 // convert to 0 based
242 size_t index = std::stoul(indexStr) - 1;
243
244 const char* baseType = nullptr;
245 const SensorData* sensorData = nullptr;
246 const std::string* interfacePath = nullptr;
247 const SensorBaseConfiguration* baseConfiguration = nullptr;
Zev Weiss77636ec2022-08-12 18:21:01 -0700248 for (const auto& [path, cfgData] : sensorConfigurations)
James Feist95b079b2018-11-21 09:28:00 -0800249 {
Ed Tanousbb679322022-05-16 16:10:00 -0700250 // find the base of the configuration to see if indexes
251 // match
Zev Weiss77636ec2022-08-12 18:21:01 -0700252 auto sensorBaseFind = cfgData.find(sensorTypes[fanType]);
253 if (sensorBaseFind == cfgData.end())
James Feist95b079b2018-11-21 09:28:00 -0800254 {
Ed Tanousbb679322022-05-16 16:10:00 -0700255 continue;
256 }
257
258 baseConfiguration = &(*sensorBaseFind);
Zev Weiss77636ec2022-08-12 18:21:01 -0700259 interfacePath = &path.str;
Ed Tanousbb679322022-05-16 16:10:00 -0700260 baseType = sensorTypes[fanType];
261
262 auto findIndex = baseConfiguration->second.find("Index");
263 if (findIndex == baseConfiguration->second.end())
264 {
265 std::cerr << baseConfiguration->first << " missing index\n";
266 continue;
267 }
268 unsigned int configIndex = std::visit(
269 VariantToUnsignedIntVisitor(), findIndex->second);
270 if (configIndex != index)
271 {
272 continue;
273 }
274 if (fanType == FanTypes::aspeed || fanType == FanTypes::nuvoton)
275 {
276 // there will be only 1 aspeed or nuvoton sensor object
277 // in sysfs, we found the fan
Zev Weiss77636ec2022-08-12 18:21:01 -0700278 sensorData = &cfgData;
Ed Tanousbb679322022-05-16 16:10:00 -0700279 break;
280 }
281 if (fanType == FanTypes::i2c)
282 {
283 size_t bus = 0;
284 size_t address = 0;
285
286 std::string link =
287 fs::read_symlink(directory / "device").filename();
288
289 size_t findDash = link.find('-');
290 if (findDash == std::string::npos ||
291 link.size() <= findDash + 1)
James Feistde5e9702019-09-18 16:13:02 -0700292 {
Ed Tanousbb679322022-05-16 16:10:00 -0700293 std::cerr << "Error finding device from symlink";
James Feistde5e9702019-09-18 16:13:02 -0700294 }
Ed Tanousbb679322022-05-16 16:10:00 -0700295 bus = std::stoi(link.substr(0, findDash));
296 address = std::stoi(link.substr(findDash + 1), nullptr, 16);
Zhikui Ren347dd4e2019-12-12 13:39:50 -0800297
Ed Tanousbb679322022-05-16 16:10:00 -0700298 auto findBus = baseConfiguration->second.find("Bus");
299 auto findAddress =
300 baseConfiguration->second.find("Address");
301 if (findBus == baseConfiguration->second.end() ||
302 findAddress == baseConfiguration->second.end())
James Feistde5e9702019-09-18 16:13:02 -0700303 {
304 std::cerr << baseConfiguration->first
Ed Tanousbb679322022-05-16 16:10:00 -0700305 << " missing bus or address\n";
James Feistde5e9702019-09-18 16:13:02 -0700306 continue;
307 }
Ed Tanousbb679322022-05-16 16:10:00 -0700308 unsigned int configBus = std::visit(
309 VariantToUnsignedIntVisitor(), findBus->second);
310 unsigned int configAddress = std::visit(
311 VariantToUnsignedIntVisitor(), findAddress->second);
312
313 if (configBus == bus && configAddress == address)
James Feistde5e9702019-09-18 16:13:02 -0700314 {
Zev Weiss77636ec2022-08-12 18:21:01 -0700315 sensorData = &cfgData;
James Feistde5e9702019-09-18 16:13:02 -0700316 break;
317 }
Ed Tanousbb679322022-05-16 16:10:00 -0700318 }
319 }
320 if (sensorData == nullptr)
321 {
322 std::cerr << "failed to find match for " << path.string()
323 << "\n";
324 continue;
325 }
326
327 auto findSensorName = baseConfiguration->second.find("Name");
328
329 if (findSensorName == baseConfiguration->second.end())
330 {
331 std::cerr << "could not determine configuration name for "
332 << path.string() << "\n";
333 continue;
334 }
335 std::string sensorName =
336 std::get<std::string>(findSensorName->second);
337
338 // on rescans, only update sensors we were signaled by
339 auto findSensor = tachSensors.find(sensorName);
340 if (!firstScan && findSensor != tachSensors.end())
341 {
342 bool found = false;
343 for (auto it = sensorsChanged->begin();
344 it != sensorsChanged->end(); it++)
345 {
Zev Weiss6c106d62022-08-17 20:50:00 -0700346 if (it->ends_with(findSensor->second->name))
James Feistde5e9702019-09-18 16:13:02 -0700347 {
Ed Tanousbb679322022-05-16 16:10:00 -0700348 sensorsChanged->erase(it);
349 findSensor->second = nullptr;
350 found = true;
351 break;
James Feistde5e9702019-09-18 16:13:02 -0700352 }
353 }
Ed Tanousbb679322022-05-16 16:10:00 -0700354 if (!found)
James Feistde5e9702019-09-18 16:13:02 -0700355 {
James Feist95b079b2018-11-21 09:28:00 -0800356 continue;
357 }
Ed Tanousbb679322022-05-16 16:10:00 -0700358 }
359 std::vector<thresholds::Threshold> sensorThresholds;
360 if (!parseThresholdsFromConfig(*sensorData, sensorThresholds))
361 {
362 std::cerr << "error populating thresholds for " << sensorName
363 << "\n";
364 }
James Feist95b079b2018-11-21 09:28:00 -0800365
Ed Tanousbb679322022-05-16 16:10:00 -0700366 auto presenceConfig =
367 sensorData->find(baseType + std::string(".Presence"));
Zhikui Ren347dd4e2019-12-12 13:39:50 -0800368
Ed Tanousbb679322022-05-16 16:10:00 -0700369 std::unique_ptr<PresenceSensor> presenceSensor(nullptr);
370
371 // presence sensors are optional
372 if (presenceConfig != sensorData->end())
373 {
374 auto findPolarity = presenceConfig->second.find("Polarity");
375 auto findPinName = presenceConfig->second.find("PinName");
376
377 if (findPinName == presenceConfig->second.end() ||
378 findPolarity == presenceConfig->second.end())
James Feist95b079b2018-11-21 09:28:00 -0800379 {
Ed Tanousbb679322022-05-16 16:10:00 -0700380 std::cerr << "Malformed Presence Configuration\n";
James Feistde5e9702019-09-18 16:13:02 -0700381 }
Ed Tanousbb679322022-05-16 16:10:00 -0700382 else
James Feistde5e9702019-09-18 16:13:02 -0700383 {
Ed Tanousbb679322022-05-16 16:10:00 -0700384 bool inverted =
385 std::get<std::string>(findPolarity->second) == "Low";
Ed Tanous2049bd22022-07-09 07:20:26 -0700386 if (const auto* pinName =
Ed Tanousbb679322022-05-16 16:10:00 -0700387 std::get_if<std::string>(&findPinName->second))
James Feistde5e9702019-09-18 16:13:02 -0700388 {
Ed Tanousbb679322022-05-16 16:10:00 -0700389 presenceSensor = std::make_unique<PresenceSensor>(
390 *pinName, inverted, io, sensorName);
James Feistde5e9702019-09-18 16:13:02 -0700391 }
392 else
393 {
Ed Tanousbb679322022-05-16 16:10:00 -0700394 std::cerr << "Malformed Presence pinName for sensor "
395 << sensorName << " \n";
James Feistde5e9702019-09-18 16:13:02 -0700396 }
397 }
Ed Tanousbb679322022-05-16 16:10:00 -0700398 }
399 std::optional<RedundancySensor>* redundancy = nullptr;
400 if (fanType == FanTypes::aspeed)
401 {
402 redundancy = &systemRedundancy;
403 }
404
Zev Weissa4d27682022-07-19 15:30:36 -0700405 PowerState powerState = getPowerState(baseConfiguration->second);
Yong Zhao77b3add2021-01-09 04:25:18 +0000406
Ed Tanousbb679322022-05-16 16:10:00 -0700407 constexpr double defaultMaxReading = 25000;
408 constexpr double defaultMinReading = 0;
409 std::pair<double, double> limits =
410 std::make_pair(defaultMinReading, defaultMaxReading);
411
412 auto connector =
413 sensorData->find(baseType + std::string(".Connector"));
414
415 std::optional<std::string> led;
416 std::string pwmName;
417 fs::path pwmPath;
418
419 // The Mutable parameter is optional, defaulting to false
420 bool isValueMutable = false;
421 if (connector != sensorData->end())
422 {
423 auto findPwm = connector->second.find("Pwm");
424 if (findPwm != connector->second.end())
425 {
426 size_t pwm = std::visit(VariantToUnsignedIntVisitor(),
427 findPwm->second);
428 if (!findPwmPath(directory, pwm, pwmPath))
429 {
430 std::cerr << "Connector for " << sensorName
431 << " no pwm channel found!\n";
432 continue;
433 }
434
435 fs::path pwmEnableFile =
436 "pwm" + std::to_string(pwm + 1) + "_enable";
437 fs::path enablePath = pwmPath.parent_path() / pwmEnableFile;
438 enablePwm(enablePath);
439
440 /* use pwm name override if found in configuration else
441 * use default */
442 auto findOverride = connector->second.find("PwmName");
443 if (findOverride != connector->second.end())
444 {
445 pwmName = std::visit(VariantToStringVisitor(),
446 findOverride->second);
447 }
448 else
449 {
450 pwmName = "Pwm_" + std::to_string(pwm + 1);
451 }
452
453 // Check PWM sensor mutability
454 auto findMutable = connector->second.find("Mutable");
455 if (findMutable != connector->second.end())
456 {
Ed Tanous2049bd22022-07-09 07:20:26 -0700457 const auto* ptrMutable =
Ed Tanousbb679322022-05-16 16:10:00 -0700458 std::get_if<bool>(&(findMutable->second));
Ed Tanous2049bd22022-07-09 07:20:26 -0700459 if (ptrMutable != nullptr)
Ed Tanousbb679322022-05-16 16:10:00 -0700460 {
461 isValueMutable = *ptrMutable;
462 }
463 }
464 }
465 else
466 {
467 std::cerr << "Connector for " << sensorName
468 << " missing pwm!\n";
469 }
470
471 auto findLED = connector->second.find("LED");
472 if (findLED != connector->second.end())
473 {
Ed Tanous2049bd22022-07-09 07:20:26 -0700474 const auto* ledName =
475 std::get_if<std::string>(&(findLED->second));
Ed Tanousbb679322022-05-16 16:10:00 -0700476 if (ledName == nullptr)
477 {
478 std::cerr << "Wrong format for LED of " << sensorName
479 << "\n";
480 }
481 else
482 {
483 led = *ledName;
484 }
485 }
486 }
487
488 findLimits(limits, baseConfiguration);
Josh Lehan5170fe62022-08-03 13:17:41 -0700489
490 auto& tachSensor = tachSensors[sensorName];
491 tachSensor = nullptr;
492 tachSensor = std::make_shared<TachSensor>(
Ed Tanousbb679322022-05-16 16:10:00 -0700493 path.string(), baseType, objectServer, dbusConnection,
494 std::move(presenceSensor), redundancy, io, sensorName,
495 std::move(sensorThresholds), *interfacePath, limits, powerState,
496 led);
Josh Lehan5170fe62022-08-03 13:17:41 -0700497 tachSensor->setupRead();
Ed Tanousbb679322022-05-16 16:10:00 -0700498
499 if (!pwmPath.empty() && fs::exists(pwmPath) &&
Ed Tanous2049bd22022-07-09 07:20:26 -0700500 (pwmSensors.count(pwmPath) == 0U))
Ed Tanousbb679322022-05-16 16:10:00 -0700501 {
502 pwmSensors[pwmPath] = std::make_unique<PwmSensor>(
503 pwmName, pwmPath, dbusConnection, objectServer,
504 *interfacePath, "Fan", isValueMutable);
505 }
506 }
507
508 createRedundancySensor(tachSensors, dbusConnection, objectServer);
Ed Tanous8a17c302021-09-02 15:07:11 -0700509 });
James Feistde5e9702019-09-18 16:13:02 -0700510 getter->getConfiguration(
James Feistf27a55c2020-08-04 14:27:30 -0700511 std::vector<std::string>{sensorTypes.begin(), sensorTypes.end()},
512 retries);
James Feist6714a252018-09-10 15:26:18 -0700513}
514
James Feistb6c0b912019-07-09 12:21:44 -0700515int main()
James Feist6714a252018-09-10 15:26:18 -0700516{
517 boost::asio::io_service io;
518 auto systemBus = std::make_shared<sdbusplus::asio::connection>(io);
519 systemBus->request_name("xyz.openbmc_project.FanSensor");
520 sdbusplus::asio::object_server objectServer(systemBus);
Josh Lehan5170fe62022-08-03 13:17:41 -0700521 boost::container::flat_map<std::string, std::shared_ptr<TachSensor>>
James Feist6714a252018-09-10 15:26:18 -0700522 tachSensors;
523 boost::container::flat_map<std::string, std::unique_ptr<PwmSensor>>
524 pwmSensors;
James Feist5591cf082020-07-15 16:44:54 -0700525 auto sensorsChanged =
526 std::make_shared<boost::container::flat_set<std::string>>();
James Feist6714a252018-09-10 15:26:18 -0700527
528 io.post([&]() {
529 createSensors(io, objectServer, tachSensors, pwmSensors, systemBus,
530 nullptr);
531 });
532
533 boost::asio::deadline_timer filterTimer(io);
Patrick Williams92f8f512022-07-22 19:26:55 -0500534 std::function<void(sdbusplus::message_t&)> eventHandler =
535 [&](sdbusplus::message_t& message) {
Ed Tanousbb679322022-05-16 16:10:00 -0700536 if (message.is_method_error())
537 {
538 std::cerr << "callback method error\n";
539 return;
540 }
541 sensorsChanged->insert(message.get_path());
542 // this implicitly cancels the timer
543 filterTimer.expires_from_now(boost::posix_time::seconds(1));
544
545 filterTimer.async_wait([&](const boost::system::error_code& ec) {
546 if (ec == boost::asio::error::operation_aborted)
James Feist6714a252018-09-10 15:26:18 -0700547 {
Ed Tanousbb679322022-05-16 16:10:00 -0700548 /* we were canceled*/
James Feist6714a252018-09-10 15:26:18 -0700549 return;
550 }
Ed Tanousbb679322022-05-16 16:10:00 -0700551 if (ec)
552 {
553 std::cerr << "timer error\n";
554 return;
555 }
556 createSensors(io, objectServer, tachSensors, pwmSensors, systemBus,
557 sensorsChanged, 5);
558 });
559 };
James Feist6714a252018-09-10 15:26:18 -0700560
Zev Weiss214d9712022-08-12 12:54:31 -0700561 std::vector<std::unique_ptr<sdbusplus::bus::match_t>> matches =
562 setupPropertiesChangedMatches(*systemBus, sensorTypes, eventHandler);
James Feist6714a252018-09-10 15:26:18 -0700563
James Feistdc6c55f2018-10-31 12:53:20 -0700564 // redundancy sensor
Patrick Williams92f8f512022-07-22 19:26:55 -0500565 std::function<void(sdbusplus::message_t&)> redundancyHandler =
566 [&tachSensors, &systemBus, &objectServer](sdbusplus::message_t&) {
Ed Tanousbb679322022-05-16 16:10:00 -0700567 createRedundancySensor(tachSensors, systemBus, objectServer);
568 };
Patrick Williams92f8f512022-07-22 19:26:55 -0500569 auto match = std::make_unique<sdbusplus::bus::match_t>(
570 static_cast<sdbusplus::bus_t&>(*systemBus),
James Feistdc6c55f2018-10-31 12:53:20 -0700571 "type='signal',member='PropertiesChanged',path_namespace='" +
572 std::string(inventoryPath) + "',arg0namespace='" +
573 redundancyConfiguration + "'",
James Feistb6c0b912019-07-09 12:21:44 -0700574 std::move(redundancyHandler));
James Feistdc6c55f2018-10-31 12:53:20 -0700575 matches.emplace_back(std::move(match));
576
Bruce Lee1263c3d2021-06-04 15:16:33 +0800577 setupManufacturingModeMatch(*systemBus);
James Feist6714a252018-09-10 15:26:18 -0700578 io.run();
Zhikui Ren8685b172021-06-29 15:16:52 -0700579 return 0;
James Feist6714a252018-09-10 15:26:18 -0700580}