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 17cf3bce6eSJames Feist #include "filesystem.hpp" 18cf3bce6eSJames Feist 196714a25aSJames Feist #include <PwmSensor.hpp> 206714a25aSJames Feist #include <TachSensor.hpp> 216714a25aSJames Feist #include <Utils.hpp> 226714a25aSJames Feist #include <VariantVisitors.hpp> 236714a25aSJames Feist #include <boost/algorithm/string/predicate.hpp> 246714a25aSJames Feist #include <boost/algorithm/string/replace.hpp> 256714a25aSJames Feist #include <boost/container/flat_set.hpp> 266714a25aSJames Feist #include <boost/lexical_cast.hpp> 276714a25aSJames Feist #include <fstream> 286714a25aSJames Feist #include <regex> 296714a25aSJames Feist #include <sdbusplus/asio/connection.hpp> 306714a25aSJames Feist #include <sdbusplus/asio/object_server.hpp> 316714a25aSJames Feist 326714a25aSJames Feist static constexpr bool DEBUG = false; 336714a25aSJames Feist 34cf3bce6eSJames Feist namespace fs = std::filesystem; 353eb82629SJames Feist 3695b079b7SJames Feist static constexpr std::array<const char*, 2> sensorTypes = { 3795b079b7SJames Feist "xyz.openbmc_project.Configuration.AspeedFan", 3895b079b7SJames Feist "xyz.openbmc_project.Configuration.I2CFan"}; 39dc6c55f3SJames Feist constexpr const char* redundancyConfiguration = 40dc6c55f3SJames Feist "xyz.openbmc_project.Configuration.FanRedundancy"; 419ced0a38SJae Hyun Yoo static std::regex inputRegex(R"(fan(\d+)_input)"); 426714a25aSJames Feist 4395b079b7SJames Feist enum class FanTypes 4495b079b7SJames Feist { 4595b079b7SJames Feist aspeed, 4695b079b7SJames Feist i2c 4795b079b7SJames Feist }; 4895b079b7SJames Feist 49dc6c55f3SJames Feist // todo: power supply fan redundancy 5095b079b7SJames Feist std::shared_ptr<RedundancySensor> systemRedundancy = nullptr; 5195b079b7SJames Feist 5295b079b7SJames Feist FanTypes getFanType(const fs::path& parentPath) 5395b079b7SJames Feist { 5495b079b7SJames Feist fs::path linkPath = parentPath / "device"; 5595b079b7SJames Feist std::string canonical = fs::read_symlink(linkPath); 5695b079b7SJames Feist if (boost::ends_with(canonical, "1e786000.pwm-tacho-controller")) 5795b079b7SJames Feist { 5895b079b7SJames Feist return FanTypes::aspeed; 5995b079b7SJames Feist } 6095b079b7SJames Feist // todo: will we need to support other types? 6195b079b7SJames Feist return FanTypes::i2c; 6295b079b7SJames Feist } 63dc6c55f3SJames Feist 646714a25aSJames Feist void createSensors( 656714a25aSJames Feist boost::asio::io_service& io, sdbusplus::asio::object_server& objectServer, 666714a25aSJames Feist boost::container::flat_map<std::string, std::unique_ptr<TachSensor>>& 676714a25aSJames Feist tachSensors, 686714a25aSJames Feist boost::container::flat_map<std::string, std::unique_ptr<PwmSensor>>& 696714a25aSJames Feist pwmSensors, 706714a25aSJames Feist std::shared_ptr<sdbusplus::asio::connection>& dbusConnection, 716714a25aSJames Feist const std::unique_ptr<boost::container::flat_set<std::string>>& 726714a25aSJames Feist sensorsChanged) 736714a25aSJames Feist { 746714a25aSJames Feist bool firstScan = sensorsChanged == nullptr; 756714a25aSJames Feist // use new data the first time, then refresh 766714a25aSJames Feist ManagedObjectType sensorConfigurations; 776714a25aSJames Feist bool useCache = false; 789ced0a38SJae Hyun Yoo for (const char* type : sensorTypes) 796714a25aSJames Feist { 806714a25aSJames Feist if (!getSensorConfiguration(type, dbusConnection, sensorConfigurations, 816714a25aSJames Feist useCache)) 826714a25aSJames Feist { 836714a25aSJames Feist std::cerr << "error communicating to entity manager\n"; 846714a25aSJames Feist return; 856714a25aSJames Feist } 866714a25aSJames Feist useCache = true; 876714a25aSJames Feist } 886714a25aSJames Feist std::vector<fs::path> paths; 899ced0a38SJae Hyun Yoo if (!findFiles(fs::path("/sys/class/hwmon"), R"(fan\d+_input)", paths)) 906714a25aSJames Feist { 916714a25aSJames Feist std::cerr << "No temperature sensors in system\n"; 926714a25aSJames Feist return; 936714a25aSJames Feist } 946714a25aSJames Feist 95*82bac4c7SJames Feist std::vector<std::pair<uint8_t, std::string>> pwmNumbers; 968e94c204SJames Feist 976714a25aSJames Feist // iterate through all found fan sensors, and try to match them with 986714a25aSJames Feist // configuration 9995b079b7SJames Feist for (const auto& path : paths) 1006714a25aSJames Feist { 1016714a25aSJames Feist std::smatch match; 1026714a25aSJames Feist std::string pathStr = path.string(); 1036714a25aSJames Feist 1049ced0a38SJae Hyun Yoo std::regex_search(pathStr, match, inputRegex); 1056714a25aSJames Feist std::string indexStr = *(match.begin() + 1); 1066714a25aSJames Feist 1076714a25aSJames Feist auto directory = path.parent_path(); 10895b079b7SJames Feist FanTypes fanType = getFanType(directory); 10995b079b7SJames Feist size_t bus = 0; 11095b079b7SJames Feist size_t address = 0; 11195b079b7SJames Feist if (fanType == FanTypes::i2c) 11295b079b7SJames Feist { 11395b079b7SJames Feist std::string link = 11495b079b7SJames Feist fs::read_symlink(directory / "device").filename(); 11595b079b7SJames Feist 11695b079b7SJames Feist size_t findDash = link.find("-"); 11795b079b7SJames Feist if (findDash == std::string::npos || link.size() <= findDash + 1) 11895b079b7SJames Feist { 11995b079b7SJames Feist std::cerr << "Error finding device from symlink"; 12095b079b7SJames Feist } 12195b079b7SJames Feist bus = std::stoi(link.substr(0, findDash)); 12295b079b7SJames Feist address = std::stoi(link.substr(findDash + 1), nullptr, 16); 12395b079b7SJames Feist } 1246714a25aSJames Feist // convert to 0 based 1256714a25aSJames Feist size_t index = std::stoul(indexStr) - 1; 1266714a25aSJames Feist 1276714a25aSJames Feist const char* baseType; 1286714a25aSJames Feist const SensorData* sensorData = nullptr; 1296714a25aSJames Feist const std::string* interfacePath = nullptr; 13087d713abSJames Feist const SensorBaseConfiguration* baseConfiguration = nullptr; 1316714a25aSJames Feist for (const std::pair<sdbusplus::message::object_path, SensorData>& 1326714a25aSJames Feist sensor : sensorConfigurations) 1336714a25aSJames Feist { 1346714a25aSJames Feist // find the base of the configuration to see if indexes match 1359ced0a38SJae Hyun Yoo for (const char* type : sensorTypes) 1366714a25aSJames Feist { 1376714a25aSJames Feist auto sensorBaseFind = sensor.second.find(type); 1386714a25aSJames Feist if (sensorBaseFind != sensor.second.end()) 1396714a25aSJames Feist { 1406714a25aSJames Feist baseConfiguration = &(*sensorBaseFind); 1416714a25aSJames Feist interfacePath = &(sensor.first.str); 1426714a25aSJames Feist baseType = type; 1436714a25aSJames Feist break; 1446714a25aSJames Feist } 1456714a25aSJames Feist } 1466714a25aSJames Feist if (baseConfiguration == nullptr) 1476714a25aSJames Feist { 1486714a25aSJames Feist continue; 1496714a25aSJames Feist } 1506714a25aSJames Feist auto findIndex = baseConfiguration->second.find("Index"); 1516714a25aSJames Feist if (findIndex == baseConfiguration->second.end()) 1526714a25aSJames Feist { 1536714a25aSJames Feist std::cerr << baseConfiguration->first << " missing index\n"; 1546714a25aSJames Feist continue; 1556714a25aSJames Feist } 1563eb82629SJames Feist unsigned int configIndex = 1573eb82629SJames Feist std::visit(VariantToUnsignedIntVisitor(), findIndex->second); 1586714a25aSJames Feist if (configIndex != index) 1596714a25aSJames Feist { 1606714a25aSJames Feist continue; 1616714a25aSJames Feist } 16295b079b7SJames Feist if (fanType == FanTypes::aspeed) 1636714a25aSJames Feist { 16495b079b7SJames Feist // there will be only 1 aspeed sensor object in sysfs, we found 16595b079b7SJames Feist // the fan 16695b079b7SJames Feist sensorData = &(sensor.second); 16795b079b7SJames Feist break; 16895b079b7SJames Feist } 16995b079b7SJames Feist else if (baseType == "xyz.openbmc_project.Configuration.I2CFan") 17095b079b7SJames Feist { 17195b079b7SJames Feist auto findBus = baseConfiguration->second.find("Bus"); 17295b079b7SJames Feist auto findAddress = baseConfiguration->second.find("Address"); 17395b079b7SJames Feist if (findBus == baseConfiguration->second.end() || 17495b079b7SJames Feist findAddress == baseConfiguration->second.end()) 17595b079b7SJames Feist { 17695b079b7SJames Feist std::cerr << baseConfiguration->first 17795b079b7SJames Feist << " missing bus or address\n"; 1786714a25aSJames Feist continue; 1796714a25aSJames Feist } 1803eb82629SJames Feist unsigned int configBus = 1813eb82629SJames Feist std::visit(VariantToUnsignedIntVisitor(), findBus->second); 1823eb82629SJames Feist unsigned int configAddress = std::visit( 18395b079b7SJames Feist VariantToUnsignedIntVisitor(), findAddress->second); 18495b079b7SJames Feist 18595b079b7SJames Feist if (configBus == bus && configAddress == configAddress) 1866714a25aSJames Feist { 1876714a25aSJames Feist sensorData = &(sensor.second); 1886714a25aSJames Feist break; 1896714a25aSJames Feist } 1906714a25aSJames Feist } 19195b079b7SJames Feist } 1926714a25aSJames Feist if (sensorData == nullptr) 1936714a25aSJames Feist { 1946714a25aSJames Feist std::cerr << "failed to find match for " << path.string() << "\n"; 1956714a25aSJames Feist continue; 1966714a25aSJames Feist } 1976714a25aSJames Feist 1986714a25aSJames Feist auto findSensorName = baseConfiguration->second.find("Name"); 1996714a25aSJames Feist if (findSensorName == baseConfiguration->second.end()) 2006714a25aSJames Feist { 2016714a25aSJames Feist std::cerr << "could not determine configuration name for " 2026714a25aSJames Feist << path.string() << "\n"; 2036714a25aSJames Feist continue; 2046714a25aSJames Feist } 2053eb82629SJames Feist std::string sensorName = std::get<std::string>(findSensorName->second); 2066714a25aSJames Feist // on rescans, only update sensors we were signaled by 2076714a25aSJames Feist auto findSensor = tachSensors.find(sensorName); 2086714a25aSJames Feist if (!firstScan && findSensor != tachSensors.end()) 2096714a25aSJames Feist { 2106714a25aSJames Feist bool found = false; 2116714a25aSJames Feist for (auto it = sensorsChanged->begin(); it != sensorsChanged->end(); 2126714a25aSJames Feist it++) 2136714a25aSJames Feist { 2146714a25aSJames Feist if (boost::ends_with(*it, findSensor->second->name)) 2156714a25aSJames Feist { 2166714a25aSJames Feist sensorsChanged->erase(it); 2176714a25aSJames Feist findSensor->second = nullptr; 2186714a25aSJames Feist found = true; 2196714a25aSJames Feist break; 2206714a25aSJames Feist } 2216714a25aSJames Feist } 2226714a25aSJames Feist if (!found) 2236714a25aSJames Feist { 2246714a25aSJames Feist continue; 2256714a25aSJames Feist } 2266714a25aSJames Feist } 2276714a25aSJames Feist std::vector<thresholds::Threshold> sensorThresholds; 2289ced0a38SJae Hyun Yoo if (!parseThresholdsFromConfig(*sensorData, sensorThresholds)) 2296714a25aSJames Feist { 2306714a25aSJames Feist std::cerr << "error populating thresholds for " << sensorName 2316714a25aSJames Feist << "\n"; 2326714a25aSJames Feist } 2336714a25aSJames Feist 2347bc2bab2SJames Feist auto presenceConfig = 2357bc2bab2SJames Feist sensorData->find(baseType + std::string(".Presence")); 2367bc2bab2SJames Feist 2377bc2bab2SJames Feist std::unique_ptr<PresenceSensor> presenceSensor(nullptr); 2387bc2bab2SJames Feist 2397bc2bab2SJames Feist // presence sensors are optional 2407bc2bab2SJames Feist if (presenceConfig != sensorData->end()) 2417bc2bab2SJames Feist { 2427bc2bab2SJames Feist auto findIndex = presenceConfig->second.find("Index"); 2437bc2bab2SJames Feist auto findPolarity = presenceConfig->second.find("Polarity"); 2447bc2bab2SJames Feist 2457bc2bab2SJames Feist if (findIndex == presenceConfig->second.end() || 2467bc2bab2SJames Feist findPolarity == presenceConfig->second.end()) 2477bc2bab2SJames Feist { 2487bc2bab2SJames Feist std::cerr << "Malformed Presence Configuration\n"; 2497bc2bab2SJames Feist } 2507bc2bab2SJames Feist else 2517bc2bab2SJames Feist { 2523eb82629SJames Feist size_t index = std::get<uint64_t>(findIndex->second); 2537bc2bab2SJames Feist bool inverted = 2543eb82629SJames Feist std::get<std::string>(findPolarity->second) == "Low"; 2557bc2bab2SJames Feist presenceSensor = 2567bc2bab2SJames Feist std::make_unique<PresenceSensor>(index, inverted, io); 2577bc2bab2SJames Feist } 2587bc2bab2SJames Feist } 25995b079b7SJames Feist std::shared_ptr<RedundancySensor> redundancy; 26095b079b7SJames Feist if (fanType == FanTypes::aspeed) 26195b079b7SJames Feist { 26295b079b7SJames Feist redundancy = systemRedundancy; 26395b079b7SJames Feist } 2647bc2bab2SJames Feist 26587d713abSJames Feist constexpr double defaultMaxReading = 25000; 26687d713abSJames Feist constexpr double defaultMinReading = 0; 26787d713abSJames Feist auto limits = std::make_pair(defaultMinReading, defaultMaxReading); 26887d713abSJames Feist 26987d713abSJames Feist findLimits(limits, baseConfiguration); 2706714a25aSJames Feist tachSensors[sensorName] = std::make_unique<TachSensor>( 271ce3fca41SJames Feist path.string(), baseType, objectServer, dbusConnection, 27295b079b7SJames Feist std::move(presenceSensor), redundancy, io, sensorName, 27387d713abSJames Feist std::move(sensorThresholds), *interfacePath, limits); 2748e94c204SJames Feist 2758e94c204SJames Feist auto connector = sensorData->find(baseType + std::string(".Connector")); 2768e94c204SJames Feist if (connector != sensorData->end()) 2778e94c204SJames Feist { 2788e94c204SJames Feist auto findPwm = connector->second.find("Pwm"); 2798e94c204SJames Feist if (findPwm == connector->second.end()) 2808e94c204SJames Feist { 2818e94c204SJames Feist std::cerr << "Connector Missing PWM!\n"; 2828e94c204SJames Feist continue; 2838e94c204SJames Feist } 2848e94c204SJames Feist 2858e94c204SJames Feist size_t pwm = 2868e94c204SJames Feist std::visit(VariantToUnsignedIntVisitor(), findPwm->second); 287*82bac4c7SJames Feist pwmNumbers.emplace_back(pwm, *interfacePath); 2888e94c204SJames Feist } 2896714a25aSJames Feist } 2906714a25aSJames Feist std::vector<fs::path> pwms; 2918e94c204SJames Feist if (!findFiles(fs::path("/sys/class/hwmon"), R"(pwm\d+$)", pwms)) 2926714a25aSJames Feist { 2936714a25aSJames Feist std::cerr << "No pwm in system\n"; 2946714a25aSJames Feist return; 2956714a25aSJames Feist } 2966714a25aSJames Feist for (const fs::path& pwm : pwms) 2976714a25aSJames Feist { 29895b079b7SJames Feist if (pwmSensors.find(pwm) != pwmSensors.end()) 29995b079b7SJames Feist { 30095b079b7SJames Feist continue; 30195b079b7SJames Feist } 302*82bac4c7SJames Feist const std::string* path = nullptr; 303*82bac4c7SJames Feist for (const auto& [index, configPath] : pwmNumbers) 3048e94c204SJames Feist { 3058e94c204SJames Feist if (boost::ends_with(pwm.string(), std::to_string(index + 1))) 3068e94c204SJames Feist { 307*82bac4c7SJames Feist path = &configPath; 3088e94c204SJames Feist break; 3098e94c204SJames Feist } 3108e94c204SJames Feist } 3118e94c204SJames Feist 312*82bac4c7SJames Feist if (path == nullptr) 3138e94c204SJames Feist { 3148e94c204SJames Feist continue; 3158e94c204SJames Feist } 3168e94c204SJames Feist 3176714a25aSJames Feist // only add new elements 3186714a25aSJames Feist pwmSensors.insert(std::pair<std::string, std::unique_ptr<PwmSensor>>( 3196714a25aSJames Feist pwm.string(), 320*82bac4c7SJames Feist std::make_unique<PwmSensor>(pwm.string(), objectServer, *path))); 3216714a25aSJames Feist } 3226714a25aSJames Feist } 3236714a25aSJames Feist 324dc6c55f3SJames Feist void createRedundancySensor( 325dc6c55f3SJames Feist const boost::container::flat_map<std::string, std::unique_ptr<TachSensor>>& 326dc6c55f3SJames Feist sensors, 327dc6c55f3SJames Feist std::shared_ptr<sdbusplus::asio::connection> conn, 328dc6c55f3SJames Feist sdbusplus::asio::object_server& objectServer) 329dc6c55f3SJames Feist { 330dc6c55f3SJames Feist 331dc6c55f3SJames Feist conn->async_method_call( 332dc6c55f3SJames Feist [&objectServer, &sensors](boost::system::error_code& ec, 333dc6c55f3SJames Feist const ManagedObjectType managedObj) { 334dc6c55f3SJames Feist if (ec) 335dc6c55f3SJames Feist { 336dc6c55f3SJames Feist std::cerr << "Error calling entity manager \n"; 337dc6c55f3SJames Feist return; 338dc6c55f3SJames Feist } 339dc6c55f3SJames Feist for (const auto& pathPair : managedObj) 340dc6c55f3SJames Feist { 341dc6c55f3SJames Feist for (const auto& interfacePair : pathPair.second) 342dc6c55f3SJames Feist { 343dc6c55f3SJames Feist if (interfacePair.first == redundancyConfiguration) 344dc6c55f3SJames Feist { 345dc6c55f3SJames Feist // currently only support one 346dc6c55f3SJames Feist auto findCount = 347dc6c55f3SJames Feist interfacePair.second.find("AllowedFailures"); 348dc6c55f3SJames Feist if (findCount == interfacePair.second.end()) 349dc6c55f3SJames Feist { 350dc6c55f3SJames Feist std::cerr << "Malformed redundancy record \n"; 351dc6c55f3SJames Feist return; 352dc6c55f3SJames Feist } 353dc6c55f3SJames Feist std::vector<std::string> sensorList; 354dc6c55f3SJames Feist 355dc6c55f3SJames Feist for (const auto& sensor : sensors) 356dc6c55f3SJames Feist { 357dc6c55f3SJames Feist sensorList.push_back( 358dc6c55f3SJames Feist "/xyz/openbmc_project/sensors/fan_tach/" + 359dc6c55f3SJames Feist sensor.second->name); 360dc6c55f3SJames Feist } 3613a1807e0SJames Feist systemRedundancy = nullptr; 3623a1807e0SJames Feist systemRedundancy = std::make_shared<RedundancySensor>( 3633eb82629SJames Feist std::get<uint64_t>(findCount->second), sensorList, 3643eb82629SJames Feist objectServer); 365dc6c55f3SJames Feist 366dc6c55f3SJames Feist return; 367dc6c55f3SJames Feist } 368dc6c55f3SJames Feist } 369dc6c55f3SJames Feist } 370dc6c55f3SJames Feist }, 371dc6c55f3SJames Feist "xyz.openbmc_project.EntityManager", "/", 372dc6c55f3SJames Feist "org.freedesktop.DBus.ObjectManager", "GetManagedObjects"); 373dc6c55f3SJames Feist } 374dc6c55f3SJames Feist 3756714a25aSJames Feist int main(int argc, char** argv) 3766714a25aSJames Feist { 3776714a25aSJames Feist boost::asio::io_service io; 3786714a25aSJames Feist auto systemBus = std::make_shared<sdbusplus::asio::connection>(io); 3796714a25aSJames Feist systemBus->request_name("xyz.openbmc_project.FanSensor"); 3806714a25aSJames Feist sdbusplus::asio::object_server objectServer(systemBus); 3816714a25aSJames Feist boost::container::flat_map<std::string, std::unique_ptr<TachSensor>> 3826714a25aSJames Feist tachSensors; 3836714a25aSJames Feist boost::container::flat_map<std::string, std::unique_ptr<PwmSensor>> 3846714a25aSJames Feist pwmSensors; 3856714a25aSJames Feist std::vector<std::unique_ptr<sdbusplus::bus::match::match>> matches; 3866714a25aSJames Feist std::unique_ptr<boost::container::flat_set<std::string>> sensorsChanged = 3876714a25aSJames Feist std::make_unique<boost::container::flat_set<std::string>>(); 3886714a25aSJames Feist 3896714a25aSJames Feist io.post([&]() { 3906714a25aSJames Feist createSensors(io, objectServer, tachSensors, pwmSensors, systemBus, 3916714a25aSJames Feist nullptr); 392dc6c55f3SJames Feist createRedundancySensor(tachSensors, systemBus, objectServer); 3936714a25aSJames Feist }); 3946714a25aSJames Feist 3956714a25aSJames Feist boost::asio::deadline_timer filterTimer(io); 3966714a25aSJames Feist std::function<void(sdbusplus::message::message&)> eventHandler = 3976714a25aSJames Feist [&](sdbusplus::message::message& message) { 3986714a25aSJames Feist if (message.is_method_error()) 3996714a25aSJames Feist { 4006714a25aSJames Feist std::cerr << "callback method error\n"; 4016714a25aSJames Feist return; 4026714a25aSJames Feist } 4036714a25aSJames Feist sensorsChanged->insert(message.get_path()); 4046714a25aSJames Feist // this implicitly cancels the timer 4056714a25aSJames Feist filterTimer.expires_from_now(boost::posix_time::seconds(1)); 4066714a25aSJames Feist 4076714a25aSJames Feist filterTimer.async_wait([&](const boost::system::error_code& ec) { 4086714a25aSJames Feist if (ec == boost::asio::error::operation_aborted) 4096714a25aSJames Feist { 4106714a25aSJames Feist /* we were canceled*/ 4116714a25aSJames Feist return; 4126714a25aSJames Feist } 4136714a25aSJames Feist else if (ec) 4146714a25aSJames Feist { 4156714a25aSJames Feist std::cerr << "timer error\n"; 4166714a25aSJames Feist return; 4176714a25aSJames Feist } 4186714a25aSJames Feist createSensors(io, objectServer, tachSensors, pwmSensors, 4196714a25aSJames Feist systemBus, sensorsChanged); 4206714a25aSJames Feist }); 4216714a25aSJames Feist }; 4226714a25aSJames Feist 4239ced0a38SJae Hyun Yoo for (const char* type : sensorTypes) 4246714a25aSJames Feist { 4256714a25aSJames Feist auto match = std::make_unique<sdbusplus::bus::match::match>( 4266714a25aSJames Feist static_cast<sdbusplus::bus::bus&>(*systemBus), 4276714a25aSJames Feist "type='signal',member='PropertiesChanged',path_namespace='" + 4289ced0a38SJae Hyun Yoo std::string(inventoryPath) + "',arg0namespace='" + type + "'", 4296714a25aSJames Feist eventHandler); 4306714a25aSJames Feist matches.emplace_back(std::move(match)); 4316714a25aSJames Feist } 4326714a25aSJames Feist 433dc6c55f3SJames Feist // redundancy sensor 434dc6c55f3SJames Feist std::function<void(sdbusplus::message::message&)> redundancyHandler = 435dc6c55f3SJames Feist [&tachSensors, &systemBus, 436dc6c55f3SJames Feist &objectServer](sdbusplus::message::message& message) { 437dc6c55f3SJames Feist createRedundancySensor(tachSensors, systemBus, objectServer); 438dc6c55f3SJames Feist }; 439dc6c55f3SJames Feist auto match = std::make_unique<sdbusplus::bus::match::match>( 440dc6c55f3SJames Feist static_cast<sdbusplus::bus::bus&>(*systemBus), 441dc6c55f3SJames Feist "type='signal',member='PropertiesChanged',path_namespace='" + 442dc6c55f3SJames Feist std::string(inventoryPath) + "',arg0namespace='" + 443dc6c55f3SJames Feist redundancyConfiguration + "'", 444dc6c55f3SJames Feist redundancyHandler); 445dc6c55f3SJames Feist matches.emplace_back(std::move(match)); 446dc6c55f3SJames Feist 4476714a25aSJames Feist io.run(); 4486714a25aSJames Feist } 449