xref: /openbmc/dbus-sensors/src/FanMain.cpp (revision 7b18b1e0)
16714a25aSJames Feist /*
26714a25aSJames Feist // Copyright (c) 2017 Intel Corporation
36714a25aSJames Feist //
46714a25aSJames Feist // Licensed under the Apache License, Version 2.0 (the "License");
56714a25aSJames Feist // you may not use this file except in compliance with the License.
66714a25aSJames Feist // You may obtain a copy of the License at
76714a25aSJames Feist //
86714a25aSJames Feist //      http://www.apache.org/licenses/LICENSE-2.0
96714a25aSJames Feist //
106714a25aSJames Feist // Unless required by applicable law or agreed to in writing, software
116714a25aSJames Feist // distributed under the License is distributed on an "AS IS" BASIS,
126714a25aSJames Feist // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
136714a25aSJames Feist // See the License for the specific language governing permissions and
146714a25aSJames Feist // limitations under the License.
156714a25aSJames Feist */
166714a25aSJames Feist 
176714a25aSJames Feist #include <PwmSensor.hpp>
186714a25aSJames Feist #include <TachSensor.hpp>
196714a25aSJames Feist #include <Utils.hpp>
206714a25aSJames Feist #include <VariantVisitors.hpp>
216714a25aSJames Feist #include <boost/algorithm/string/predicate.hpp>
226714a25aSJames Feist #include <boost/algorithm/string/replace.hpp>
236714a25aSJames Feist #include <boost/container/flat_set.hpp>
246714a25aSJames Feist #include <boost/lexical_cast.hpp>
2524f02f24SJames Feist #include <filesystem>
266714a25aSJames Feist #include <fstream>
276714a25aSJames Feist #include <regex>
286714a25aSJames Feist #include <sdbusplus/asio/connection.hpp>
296714a25aSJames Feist #include <sdbusplus/asio/object_server.hpp>
306714a25aSJames Feist 
316714a25aSJames Feist static constexpr bool DEBUG = false;
326714a25aSJames Feist 
33cf3bce6eSJames Feist namespace fs = std::filesystem;
343eb82629SJames Feist 
3595b079b7SJames Feist static constexpr std::array<const char*, 2> sensorTypes = {
3695b079b7SJames Feist     "xyz.openbmc_project.Configuration.AspeedFan",
3795b079b7SJames Feist     "xyz.openbmc_project.Configuration.I2CFan"};
38dc6c55f3SJames Feist constexpr const char* redundancyConfiguration =
39dc6c55f3SJames Feist     "xyz.openbmc_project.Configuration.FanRedundancy";
409ced0a38SJae Hyun Yoo static std::regex inputRegex(R"(fan(\d+)_input)");
416714a25aSJames Feist 
4295b079b7SJames Feist enum class FanTypes
4395b079b7SJames Feist {
4495b079b7SJames Feist     aspeed,
4595b079b7SJames Feist     i2c
4695b079b7SJames Feist };
4795b079b7SJames Feist 
48dc6c55f3SJames Feist // todo: power supply fan redundancy
49*7b18b1e0SJames Feist std::optional<RedundancySensor> systemRedundancy;
5095b079b7SJames Feist 
5195b079b7SJames Feist FanTypes getFanType(const fs::path& parentPath)
5295b079b7SJames Feist {
5395b079b7SJames Feist     fs::path linkPath = parentPath / "device";
5495b079b7SJames Feist     std::string canonical = fs::read_symlink(linkPath);
5595b079b7SJames Feist     if (boost::ends_with(canonical, "1e786000.pwm-tacho-controller"))
5695b079b7SJames Feist     {
5795b079b7SJames Feist         return FanTypes::aspeed;
5895b079b7SJames Feist     }
5995b079b7SJames Feist     // todo: will we need to support other types?
6095b079b7SJames Feist     return FanTypes::i2c;
6195b079b7SJames Feist }
62dc6c55f3SJames Feist 
636714a25aSJames Feist void createSensors(
646714a25aSJames Feist     boost::asio::io_service& io, sdbusplus::asio::object_server& objectServer,
656714a25aSJames Feist     boost::container::flat_map<std::string, std::unique_ptr<TachSensor>>&
666714a25aSJames Feist         tachSensors,
676714a25aSJames Feist     boost::container::flat_map<std::string, std::unique_ptr<PwmSensor>>&
686714a25aSJames Feist         pwmSensors,
696714a25aSJames Feist     std::shared_ptr<sdbusplus::asio::connection>& dbusConnection,
706714a25aSJames Feist     const std::unique_ptr<boost::container::flat_set<std::string>>&
716714a25aSJames Feist         sensorsChanged)
726714a25aSJames Feist {
736714a25aSJames Feist     bool firstScan = sensorsChanged == nullptr;
746714a25aSJames Feist     // use new data the first time, then refresh
756714a25aSJames Feist     ManagedObjectType sensorConfigurations;
766714a25aSJames Feist     bool useCache = false;
779ced0a38SJae Hyun Yoo     for (const char* type : sensorTypes)
786714a25aSJames Feist     {
796714a25aSJames Feist         if (!getSensorConfiguration(type, dbusConnection, sensorConfigurations,
806714a25aSJames Feist                                     useCache))
816714a25aSJames Feist         {
826714a25aSJames Feist             std::cerr << "error communicating to entity manager\n";
836714a25aSJames Feist             return;
846714a25aSJames Feist         }
856714a25aSJames Feist         useCache = true;
866714a25aSJames Feist     }
876714a25aSJames Feist     std::vector<fs::path> paths;
889ced0a38SJae Hyun Yoo     if (!findFiles(fs::path("/sys/class/hwmon"), R"(fan\d+_input)", paths))
896714a25aSJames Feist     {
906714a25aSJames Feist         std::cerr << "No temperature sensors in system\n";
916714a25aSJames Feist         return;
926714a25aSJames Feist     }
936714a25aSJames Feist 
9482bac4c7SJames Feist     std::vector<std::pair<uint8_t, std::string>> pwmNumbers;
958e94c204SJames Feist 
966714a25aSJames Feist     // iterate through all found fan sensors, and try to match them with
976714a25aSJames Feist     // configuration
9895b079b7SJames Feist     for (const auto& path : paths)
996714a25aSJames Feist     {
1006714a25aSJames Feist         std::smatch match;
1016714a25aSJames Feist         std::string pathStr = path.string();
1026714a25aSJames Feist 
1039ced0a38SJae Hyun Yoo         std::regex_search(pathStr, match, inputRegex);
1046714a25aSJames Feist         std::string indexStr = *(match.begin() + 1);
1056714a25aSJames Feist 
1066714a25aSJames Feist         auto directory = path.parent_path();
10795b079b7SJames Feist         FanTypes fanType = getFanType(directory);
10895b079b7SJames Feist         size_t bus = 0;
10995b079b7SJames Feist         size_t address = 0;
11095b079b7SJames Feist         if (fanType == FanTypes::i2c)
11195b079b7SJames Feist         {
11295b079b7SJames Feist             std::string link =
11395b079b7SJames Feist                 fs::read_symlink(directory / "device").filename();
11495b079b7SJames Feist 
11595b079b7SJames Feist             size_t findDash = link.find("-");
11695b079b7SJames Feist             if (findDash == std::string::npos || link.size() <= findDash + 1)
11795b079b7SJames Feist             {
11895b079b7SJames Feist                 std::cerr << "Error finding device from symlink";
11995b079b7SJames Feist             }
12095b079b7SJames Feist             bus = std::stoi(link.substr(0, findDash));
12195b079b7SJames Feist             address = std::stoi(link.substr(findDash + 1), nullptr, 16);
12295b079b7SJames Feist         }
1236714a25aSJames Feist         // convert to 0 based
1246714a25aSJames Feist         size_t index = std::stoul(indexStr) - 1;
1256714a25aSJames Feist 
1266714a25aSJames Feist         const char* baseType;
1276714a25aSJames Feist         const SensorData* sensorData = nullptr;
1286714a25aSJames Feist         const std::string* interfacePath = nullptr;
12987d713abSJames Feist         const SensorBaseConfiguration* baseConfiguration = nullptr;
1306714a25aSJames Feist         for (const std::pair<sdbusplus::message::object_path, SensorData>&
1316714a25aSJames Feist                  sensor : sensorConfigurations)
1326714a25aSJames Feist         {
1336714a25aSJames Feist             // find the base of the configuration to see if indexes match
1349ced0a38SJae Hyun Yoo             for (const char* type : sensorTypes)
1356714a25aSJames Feist             {
1366714a25aSJames Feist                 auto sensorBaseFind = sensor.second.find(type);
1376714a25aSJames Feist                 if (sensorBaseFind != sensor.second.end())
1386714a25aSJames Feist                 {
1396714a25aSJames Feist                     baseConfiguration = &(*sensorBaseFind);
1406714a25aSJames Feist                     interfacePath = &(sensor.first.str);
1416714a25aSJames Feist                     baseType = type;
1426714a25aSJames Feist                     break;
1436714a25aSJames Feist                 }
1446714a25aSJames Feist             }
1456714a25aSJames Feist             if (baseConfiguration == nullptr)
1466714a25aSJames Feist             {
1476714a25aSJames Feist                 continue;
1486714a25aSJames Feist             }
1496714a25aSJames Feist             auto findIndex = baseConfiguration->second.find("Index");
1506714a25aSJames Feist             if (findIndex == baseConfiguration->second.end())
1516714a25aSJames Feist             {
1526714a25aSJames Feist                 std::cerr << baseConfiguration->first << " missing index\n";
1536714a25aSJames Feist                 continue;
1546714a25aSJames Feist             }
1553eb82629SJames Feist             unsigned int configIndex =
1563eb82629SJames Feist                 std::visit(VariantToUnsignedIntVisitor(), findIndex->second);
1576714a25aSJames Feist             if (configIndex != index)
1586714a25aSJames Feist             {
1596714a25aSJames Feist                 continue;
1606714a25aSJames Feist             }
16195b079b7SJames Feist             if (fanType == FanTypes::aspeed)
1626714a25aSJames Feist             {
16395b079b7SJames Feist                 // there will be only 1 aspeed sensor object in sysfs, we found
16495b079b7SJames Feist                 // the fan
16595b079b7SJames Feist                 sensorData = &(sensor.second);
16695b079b7SJames Feist                 break;
16795b079b7SJames Feist             }
16895b079b7SJames Feist             else if (baseType == "xyz.openbmc_project.Configuration.I2CFan")
16995b079b7SJames Feist             {
17095b079b7SJames Feist                 auto findBus = baseConfiguration->second.find("Bus");
17195b079b7SJames Feist                 auto findAddress = baseConfiguration->second.find("Address");
17295b079b7SJames Feist                 if (findBus == baseConfiguration->second.end() ||
17395b079b7SJames Feist                     findAddress == baseConfiguration->second.end())
17495b079b7SJames Feist                 {
17595b079b7SJames Feist                     std::cerr << baseConfiguration->first
17695b079b7SJames Feist                               << " missing bus or address\n";
1776714a25aSJames Feist                     continue;
1786714a25aSJames Feist                 }
1793eb82629SJames Feist                 unsigned int configBus =
1803eb82629SJames Feist                     std::visit(VariantToUnsignedIntVisitor(), findBus->second);
1813eb82629SJames Feist                 unsigned int configAddress = std::visit(
18295b079b7SJames Feist                     VariantToUnsignedIntVisitor(), findAddress->second);
18395b079b7SJames Feist 
18484e9e662SJae Hyun Yoo                 if (configBus == bus && configAddress == address)
1856714a25aSJames Feist                 {
1866714a25aSJames Feist                     sensorData = &(sensor.second);
1876714a25aSJames Feist                     break;
1886714a25aSJames Feist                 }
1896714a25aSJames Feist             }
19095b079b7SJames Feist         }
1916714a25aSJames Feist         if (sensorData == nullptr)
1926714a25aSJames Feist         {
1936714a25aSJames Feist             std::cerr << "failed to find match for " << path.string() << "\n";
1946714a25aSJames Feist             continue;
1956714a25aSJames Feist         }
1966714a25aSJames Feist 
1976714a25aSJames Feist         auto findSensorName = baseConfiguration->second.find("Name");
1986714a25aSJames Feist         if (findSensorName == baseConfiguration->second.end())
1996714a25aSJames Feist         {
2006714a25aSJames Feist             std::cerr << "could not determine configuration name for "
2016714a25aSJames Feist                       << path.string() << "\n";
2026714a25aSJames Feist             continue;
2036714a25aSJames Feist         }
2043eb82629SJames Feist         std::string sensorName = std::get<std::string>(findSensorName->second);
2056714a25aSJames Feist         // on rescans, only update sensors we were signaled by
2066714a25aSJames Feist         auto findSensor = tachSensors.find(sensorName);
2076714a25aSJames Feist         if (!firstScan && findSensor != tachSensors.end())
2086714a25aSJames Feist         {
2096714a25aSJames Feist             bool found = false;
2106714a25aSJames Feist             for (auto it = sensorsChanged->begin(); it != sensorsChanged->end();
2116714a25aSJames Feist                  it++)
2126714a25aSJames Feist             {
2136714a25aSJames Feist                 if (boost::ends_with(*it, findSensor->second->name))
2146714a25aSJames Feist                 {
2156714a25aSJames Feist                     sensorsChanged->erase(it);
2166714a25aSJames Feist                     findSensor->second = nullptr;
2176714a25aSJames Feist                     found = true;
2186714a25aSJames Feist                     break;
2196714a25aSJames Feist                 }
2206714a25aSJames Feist             }
2216714a25aSJames Feist             if (!found)
2226714a25aSJames Feist             {
2236714a25aSJames Feist                 continue;
2246714a25aSJames Feist             }
2256714a25aSJames Feist         }
2266714a25aSJames Feist         std::vector<thresholds::Threshold> sensorThresholds;
2279ced0a38SJae Hyun Yoo         if (!parseThresholdsFromConfig(*sensorData, sensorThresholds))
2286714a25aSJames Feist         {
2296714a25aSJames Feist             std::cerr << "error populating thresholds for " << sensorName
2306714a25aSJames Feist                       << "\n";
2316714a25aSJames Feist         }
2326714a25aSJames Feist 
2337bc2bab2SJames Feist         auto presenceConfig =
2347bc2bab2SJames Feist             sensorData->find(baseType + std::string(".Presence"));
2357bc2bab2SJames Feist 
2367bc2bab2SJames Feist         std::unique_ptr<PresenceSensor> presenceSensor(nullptr);
2377bc2bab2SJames Feist 
2387bc2bab2SJames Feist         // presence sensors are optional
2397bc2bab2SJames Feist         if (presenceConfig != sensorData->end())
2407bc2bab2SJames Feist         {
2417bc2bab2SJames Feist             auto findIndex = presenceConfig->second.find("Index");
2427bc2bab2SJames Feist             auto findPolarity = presenceConfig->second.find("Polarity");
2437bc2bab2SJames Feist 
2447bc2bab2SJames Feist             if (findIndex == presenceConfig->second.end() ||
2457bc2bab2SJames Feist                 findPolarity == presenceConfig->second.end())
2467bc2bab2SJames Feist             {
2477bc2bab2SJames Feist                 std::cerr << "Malformed Presence Configuration\n";
2487bc2bab2SJames Feist             }
2497bc2bab2SJames Feist             else
2507bc2bab2SJames Feist             {
2513eb82629SJames Feist                 size_t index = std::get<uint64_t>(findIndex->second);
2527bc2bab2SJames Feist                 bool inverted =
2533eb82629SJames Feist                     std::get<std::string>(findPolarity->second) == "Low";
254*7b18b1e0SJames Feist                 presenceSensor = std::make_unique<PresenceSensor>(
255*7b18b1e0SJames Feist                     index, inverted, io, sensorName);
2567bc2bab2SJames Feist             }
2577bc2bab2SJames Feist         }
258*7b18b1e0SJames Feist         std::optional<RedundancySensor>* redundancy = nullptr;
25995b079b7SJames Feist         if (fanType == FanTypes::aspeed)
26095b079b7SJames Feist         {
261*7b18b1e0SJames Feist             redundancy = &systemRedundancy;
26295b079b7SJames Feist         }
2637bc2bab2SJames Feist 
26487d713abSJames Feist         constexpr double defaultMaxReading = 25000;
26587d713abSJames Feist         constexpr double defaultMinReading = 0;
26687d713abSJames Feist         auto limits = std::make_pair(defaultMinReading, defaultMaxReading);
26787d713abSJames Feist 
26887d713abSJames Feist         findLimits(limits, baseConfiguration);
2696714a25aSJames Feist         tachSensors[sensorName] = std::make_unique<TachSensor>(
270ce3fca41SJames Feist             path.string(), baseType, objectServer, dbusConnection,
27195b079b7SJames Feist             std::move(presenceSensor), redundancy, io, sensorName,
27287d713abSJames Feist             std::move(sensorThresholds), *interfacePath, limits);
2738e94c204SJames Feist 
2748e94c204SJames Feist         auto connector = sensorData->find(baseType + std::string(".Connector"));
2758e94c204SJames Feist         if (connector != sensorData->end())
2768e94c204SJames Feist         {
2778e94c204SJames Feist             auto findPwm = connector->second.find("Pwm");
2788e94c204SJames Feist             if (findPwm == connector->second.end())
2798e94c204SJames Feist             {
2808e94c204SJames Feist                 std::cerr << "Connector Missing PWM!\n";
2818e94c204SJames Feist                 continue;
2828e94c204SJames Feist             }
2838e94c204SJames Feist 
2848e94c204SJames Feist             size_t pwm =
2858e94c204SJames Feist                 std::visit(VariantToUnsignedIntVisitor(), findPwm->second);
28682bac4c7SJames Feist             pwmNumbers.emplace_back(pwm, *interfacePath);
2878e94c204SJames Feist         }
2886714a25aSJames Feist     }
2896714a25aSJames Feist     std::vector<fs::path> pwms;
2908e94c204SJames Feist     if (!findFiles(fs::path("/sys/class/hwmon"), R"(pwm\d+$)", pwms))
2916714a25aSJames Feist     {
2926714a25aSJames Feist         std::cerr << "No pwm in system\n";
2936714a25aSJames Feist         return;
2946714a25aSJames Feist     }
2956714a25aSJames Feist     for (const fs::path& pwm : pwms)
2966714a25aSJames Feist     {
29795b079b7SJames Feist         if (pwmSensors.find(pwm) != pwmSensors.end())
29895b079b7SJames Feist         {
29995b079b7SJames Feist             continue;
30095b079b7SJames Feist         }
30182bac4c7SJames Feist         const std::string* path = nullptr;
30282bac4c7SJames Feist         for (const auto& [index, configPath] : pwmNumbers)
3038e94c204SJames Feist         {
3048e94c204SJames Feist             if (boost::ends_with(pwm.string(), std::to_string(index + 1)))
3058e94c204SJames Feist             {
30682bac4c7SJames Feist                 path = &configPath;
3078e94c204SJames Feist                 break;
3088e94c204SJames Feist             }
3098e94c204SJames Feist         }
3108e94c204SJames Feist 
31182bac4c7SJames Feist         if (path == nullptr)
3128e94c204SJames Feist         {
3138e94c204SJames Feist             continue;
3148e94c204SJames Feist         }
3158e94c204SJames Feist 
3166714a25aSJames Feist         // only add new elements
317916360b8SCheng C Yang         const std::string& sysPath = pwm.string();
318916360b8SCheng C Yang         const std::string& pwmName =
319916360b8SCheng C Yang             "Pwm_" + sysPath.substr(sysPath.find_last_of("pwm") + 1);
3206714a25aSJames Feist         pwmSensors.insert(std::pair<std::string, std::unique_ptr<PwmSensor>>(
321916360b8SCheng C Yang             sysPath, std::make_unique<PwmSensor>(pwmName, sysPath, objectServer,
322916360b8SCheng C Yang                                                  *path)));
3236714a25aSJames Feist     }
3246714a25aSJames Feist }
3256714a25aSJames Feist 
326dc6c55f3SJames Feist void createRedundancySensor(
327dc6c55f3SJames Feist     const boost::container::flat_map<std::string, std::unique_ptr<TachSensor>>&
328dc6c55f3SJames Feist         sensors,
329dc6c55f3SJames Feist     std::shared_ptr<sdbusplus::asio::connection> conn,
330dc6c55f3SJames Feist     sdbusplus::asio::object_server& objectServer)
331dc6c55f3SJames Feist {
332dc6c55f3SJames Feist 
333dc6c55f3SJames Feist     conn->async_method_call(
334dc6c55f3SJames Feist         [&objectServer, &sensors](boost::system::error_code& ec,
335dc6c55f3SJames Feist                                   const ManagedObjectType managedObj) {
336dc6c55f3SJames Feist             if (ec)
337dc6c55f3SJames Feist             {
338dc6c55f3SJames Feist                 std::cerr << "Error calling entity manager \n";
339dc6c55f3SJames Feist                 return;
340dc6c55f3SJames Feist             }
341dc6c55f3SJames Feist             for (const auto& pathPair : managedObj)
342dc6c55f3SJames Feist             {
343dc6c55f3SJames Feist                 for (const auto& interfacePair : pathPair.second)
344dc6c55f3SJames Feist                 {
345dc6c55f3SJames Feist                     if (interfacePair.first == redundancyConfiguration)
346dc6c55f3SJames Feist                     {
347dc6c55f3SJames Feist                         // currently only support one
348dc6c55f3SJames Feist                         auto findCount =
349dc6c55f3SJames Feist                             interfacePair.second.find("AllowedFailures");
350dc6c55f3SJames Feist                         if (findCount == interfacePair.second.end())
351dc6c55f3SJames Feist                         {
352dc6c55f3SJames Feist                             std::cerr << "Malformed redundancy record \n";
353dc6c55f3SJames Feist                             return;
354dc6c55f3SJames Feist                         }
355dc6c55f3SJames Feist                         std::vector<std::string> sensorList;
356dc6c55f3SJames Feist 
357dc6c55f3SJames Feist                         for (const auto& sensor : sensors)
358dc6c55f3SJames Feist                         {
359dc6c55f3SJames Feist                             sensorList.push_back(
360dc6c55f3SJames Feist                                 "/xyz/openbmc_project/sensors/fan_tach/" +
361dc6c55f3SJames Feist                                 sensor.second->name);
362dc6c55f3SJames Feist                         }
363*7b18b1e0SJames Feist                         systemRedundancy.reset();
364*7b18b1e0SJames Feist                         systemRedundancy.emplace(RedundancySensor(
3653eb82629SJames Feist                             std::get<uint64_t>(findCount->second), sensorList,
366*7b18b1e0SJames Feist                             objectServer, pathPair.first));
367dc6c55f3SJames Feist 
368dc6c55f3SJames Feist                         return;
369dc6c55f3SJames Feist                     }
370dc6c55f3SJames Feist                 }
371dc6c55f3SJames Feist             }
372dc6c55f3SJames Feist         },
373dc6c55f3SJames Feist         "xyz.openbmc_project.EntityManager", "/",
374dc6c55f3SJames Feist         "org.freedesktop.DBus.ObjectManager", "GetManagedObjects");
375dc6c55f3SJames Feist }
376dc6c55f3SJames Feist 
3776714a25aSJames Feist int main(int argc, char** argv)
3786714a25aSJames Feist {
3796714a25aSJames Feist     boost::asio::io_service io;
3806714a25aSJames Feist     auto systemBus = std::make_shared<sdbusplus::asio::connection>(io);
3816714a25aSJames Feist     systemBus->request_name("xyz.openbmc_project.FanSensor");
3826714a25aSJames Feist     sdbusplus::asio::object_server objectServer(systemBus);
3836714a25aSJames Feist     boost::container::flat_map<std::string, std::unique_ptr<TachSensor>>
3846714a25aSJames Feist         tachSensors;
3856714a25aSJames Feist     boost::container::flat_map<std::string, std::unique_ptr<PwmSensor>>
3866714a25aSJames Feist         pwmSensors;
3876714a25aSJames Feist     std::vector<std::unique_ptr<sdbusplus::bus::match::match>> matches;
3886714a25aSJames Feist     std::unique_ptr<boost::container::flat_set<std::string>> sensorsChanged =
3896714a25aSJames Feist         std::make_unique<boost::container::flat_set<std::string>>();
3906714a25aSJames Feist 
3916714a25aSJames Feist     io.post([&]() {
3926714a25aSJames Feist         createSensors(io, objectServer, tachSensors, pwmSensors, systemBus,
3936714a25aSJames Feist                       nullptr);
394dc6c55f3SJames Feist         createRedundancySensor(tachSensors, systemBus, objectServer);
3956714a25aSJames Feist     });
3966714a25aSJames Feist 
3976714a25aSJames Feist     boost::asio::deadline_timer filterTimer(io);
3986714a25aSJames Feist     std::function<void(sdbusplus::message::message&)> eventHandler =
3996714a25aSJames Feist         [&](sdbusplus::message::message& message) {
4006714a25aSJames Feist             if (message.is_method_error())
4016714a25aSJames Feist             {
4026714a25aSJames Feist                 std::cerr << "callback method error\n";
4036714a25aSJames Feist                 return;
4046714a25aSJames Feist             }
4056714a25aSJames Feist             sensorsChanged->insert(message.get_path());
4066714a25aSJames Feist             // this implicitly cancels the timer
4076714a25aSJames Feist             filterTimer.expires_from_now(boost::posix_time::seconds(1));
4086714a25aSJames Feist 
4096714a25aSJames Feist             filterTimer.async_wait([&](const boost::system::error_code& ec) {
4106714a25aSJames Feist                 if (ec == boost::asio::error::operation_aborted)
4116714a25aSJames Feist                 {
4126714a25aSJames Feist                     /* we were canceled*/
4136714a25aSJames Feist                     return;
4146714a25aSJames Feist                 }
4156714a25aSJames Feist                 else if (ec)
4166714a25aSJames Feist                 {
4176714a25aSJames Feist                     std::cerr << "timer error\n";
4186714a25aSJames Feist                     return;
4196714a25aSJames Feist                 }
4206714a25aSJames Feist                 createSensors(io, objectServer, tachSensors, pwmSensors,
4216714a25aSJames Feist                               systemBus, sensorsChanged);
4226714a25aSJames Feist             });
4236714a25aSJames Feist         };
4246714a25aSJames Feist 
4259ced0a38SJae Hyun Yoo     for (const char* type : sensorTypes)
4266714a25aSJames Feist     {
4276714a25aSJames Feist         auto match = std::make_unique<sdbusplus::bus::match::match>(
4286714a25aSJames Feist             static_cast<sdbusplus::bus::bus&>(*systemBus),
4296714a25aSJames Feist             "type='signal',member='PropertiesChanged',path_namespace='" +
4309ced0a38SJae Hyun Yoo                 std::string(inventoryPath) + "',arg0namespace='" + type + "'",
4316714a25aSJames Feist             eventHandler);
4326714a25aSJames Feist         matches.emplace_back(std::move(match));
4336714a25aSJames Feist     }
4346714a25aSJames Feist 
435dc6c55f3SJames Feist     // redundancy sensor
436dc6c55f3SJames Feist     std::function<void(sdbusplus::message::message&)> redundancyHandler =
437dc6c55f3SJames Feist         [&tachSensors, &systemBus,
438dc6c55f3SJames Feist          &objectServer](sdbusplus::message::message& message) {
439dc6c55f3SJames Feist             createRedundancySensor(tachSensors, systemBus, objectServer);
440dc6c55f3SJames Feist         };
441dc6c55f3SJames Feist     auto match = std::make_unique<sdbusplus::bus::match::match>(
442dc6c55f3SJames Feist         static_cast<sdbusplus::bus::bus&>(*systemBus),
443dc6c55f3SJames Feist         "type='signal',member='PropertiesChanged',path_namespace='" +
444dc6c55f3SJames Feist             std::string(inventoryPath) + "',arg0namespace='" +
445dc6c55f3SJames Feist             redundancyConfiguration + "'",
446dc6c55f3SJames Feist         redundancyHandler);
447dc6c55f3SJames Feist     matches.emplace_back(std::move(match));
448dc6c55f3SJames Feist 
4496714a25aSJames Feist     io.run();
4506714a25aSJames Feist }
451