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