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 178a57ec09SEd Tanous #include <PwmSensor.hpp> 188a57ec09SEd Tanous #include <TachSensor.hpp> 198a57ec09SEd Tanous #include <Utils.hpp> 208a57ec09SEd Tanous #include <VariantVisitors.hpp> 216714a25aSJames Feist #include <boost/algorithm/string/predicate.hpp> 226714a25aSJames Feist #include <boost/algorithm/string/replace.hpp> 2396e97db7SPatrick Venture #include <boost/container/flat_map.hpp> 246714a25aSJames Feist #include <boost/container/flat_set.hpp> 256714a25aSJames Feist #include <boost/lexical_cast.hpp> 2638fb5983SJames Feist #include <sdbusplus/asio/connection.hpp> 2738fb5983SJames Feist #include <sdbusplus/asio/object_server.hpp> 2838fb5983SJames Feist #include <sdbusplus/bus/match.hpp> 2938fb5983SJames Feist 3038fb5983SJames Feist #include <array> 3124f02f24SJames Feist #include <filesystem> 326714a25aSJames Feist #include <fstream> 3396e97db7SPatrick Venture #include <functional> 3496e97db7SPatrick Venture #include <memory> 3596e97db7SPatrick Venture #include <optional> 366714a25aSJames Feist #include <regex> 3796e97db7SPatrick Venture #include <string> 3896e97db7SPatrick Venture #include <utility> 3996e97db7SPatrick Venture #include <variant> 4096e97db7SPatrick Venture #include <vector> 416714a25aSJames Feist 428a57ec09SEd Tanous static constexpr bool debug = false; 436714a25aSJames Feist 44cf3bce6eSJames Feist namespace fs = std::filesystem; 453eb82629SJames Feist 46a3e8f2a3SYong Zhao // The following two structures need to be consistent 478843b627SPeter Lundgren static constexpr std::array<const char*, 3> sensorTypes = { 4895b079b7SJames Feist "xyz.openbmc_project.Configuration.AspeedFan", 498843b627SPeter Lundgren "xyz.openbmc_project.Configuration.I2CFan", 508843b627SPeter Lundgren "xyz.openbmc_project.Configuration.NuvotonFan"}; 51a3e8f2a3SYong Zhao 52a3e8f2a3SYong Zhao enum FanTypes 53a3e8f2a3SYong Zhao { 54a3e8f2a3SYong Zhao aspeed = 0, 55a3e8f2a3SYong Zhao i2c, 56a3e8f2a3SYong Zhao nuvoton, 57a3e8f2a3SYong Zhao max, 58a3e8f2a3SYong Zhao }; 59a3e8f2a3SYong Zhao 60a3e8f2a3SYong Zhao static_assert(std::tuple_size<decltype(sensorTypes)>::value == FanTypes::max, 61a3e8f2a3SYong Zhao "sensorTypes element number is not equal to FanTypes number"); 62a3e8f2a3SYong Zhao 63dc6c55f3SJames Feist constexpr const char* redundancyConfiguration = 64dc6c55f3SJames Feist "xyz.openbmc_project.Configuration.FanRedundancy"; 659ced0a38SJae Hyun Yoo static std::regex inputRegex(R"(fan(\d+)_input)"); 666714a25aSJames Feist 67dc6c55f3SJames Feist // todo: power supply fan redundancy 687b18b1e0SJames Feist std::optional<RedundancySensor> systemRedundancy; 6995b079b7SJames Feist 7095b079b7SJames Feist FanTypes getFanType(const fs::path& parentPath) 7195b079b7SJames Feist { 7295b079b7SJames Feist fs::path linkPath = parentPath / "device"; 7395b079b7SJames Feist std::string canonical = fs::read_symlink(linkPath); 74241356e3SJae Hyun Yoo if (boost::ends_with(canonical, "1e786000.pwm-tacho-controller") || 75241356e3SJae Hyun Yoo boost::ends_with(canonical, "1e610000.pwm-tacho-controller")) 7695b079b7SJames Feist { 7795b079b7SJames Feist return FanTypes::aspeed; 7895b079b7SJames Feist } 798a57ec09SEd Tanous if (boost::ends_with(canonical, "f0103000.pwm-fan-controller")) 808843b627SPeter Lundgren { 818843b627SPeter Lundgren return FanTypes::nuvoton; 828843b627SPeter Lundgren } 8395b079b7SJames Feist // todo: will we need to support other types? 8495b079b7SJames Feist return FanTypes::i2c; 8595b079b7SJames Feist } 86dc6c55f3SJames Feist 87d540741eSKuiying Wang void createRedundancySensor( 88d540741eSKuiying Wang const boost::container::flat_map<std::string, std::unique_ptr<TachSensor>>& 89d540741eSKuiying Wang sensors, 908a57ec09SEd Tanous const std::shared_ptr<sdbusplus::asio::connection>& conn, 91d540741eSKuiying Wang sdbusplus::asio::object_server& objectServer) 92d540741eSKuiying Wang { 93d540741eSKuiying Wang 94d540741eSKuiying Wang conn->async_method_call( 95d540741eSKuiying Wang [&objectServer, &sensors](boost::system::error_code& ec, 968a57ec09SEd Tanous const ManagedObjectType& managedObj) { 97d540741eSKuiying Wang if (ec) 98d540741eSKuiying Wang { 99d540741eSKuiying Wang std::cerr << "Error calling entity manager \n"; 100d540741eSKuiying Wang return; 101d540741eSKuiying Wang } 102d540741eSKuiying Wang for (const auto& pathPair : managedObj) 103d540741eSKuiying Wang { 104d540741eSKuiying Wang for (const auto& interfacePair : pathPair.second) 105d540741eSKuiying Wang { 106d540741eSKuiying Wang if (interfacePair.first == redundancyConfiguration) 107d540741eSKuiying Wang { 108d540741eSKuiying Wang // currently only support one 109d540741eSKuiying Wang auto findCount = 110d540741eSKuiying Wang interfacePair.second.find("AllowedFailures"); 111d540741eSKuiying Wang if (findCount == interfacePair.second.end()) 112d540741eSKuiying Wang { 113d540741eSKuiying Wang std::cerr << "Malformed redundancy record \n"; 114d540741eSKuiying Wang return; 115d540741eSKuiying Wang } 116d540741eSKuiying Wang std::vector<std::string> sensorList; 117d540741eSKuiying Wang 118d540741eSKuiying Wang for (const auto& sensor : sensors) 119d540741eSKuiying Wang { 120d540741eSKuiying Wang sensorList.push_back( 121d540741eSKuiying Wang "/xyz/openbmc_project/sensors/fan_tach/" + 122d540741eSKuiying Wang sensor.second->name); 123d540741eSKuiying Wang } 124d540741eSKuiying Wang systemRedundancy.reset(); 125d540741eSKuiying Wang systemRedundancy.emplace(RedundancySensor( 126d540741eSKuiying Wang std::get<uint64_t>(findCount->second), sensorList, 127d540741eSKuiying Wang objectServer, pathPair.first)); 128d540741eSKuiying Wang 129d540741eSKuiying Wang return; 130d540741eSKuiying Wang } 131d540741eSKuiying Wang } 132d540741eSKuiying Wang } 133d540741eSKuiying Wang }, 134d540741eSKuiying Wang "xyz.openbmc_project.EntityManager", "/", 135d540741eSKuiying Wang "org.freedesktop.DBus.ObjectManager", "GetManagedObjects"); 136d540741eSKuiying Wang } 137d540741eSKuiying Wang 1386714a25aSJames Feist void createSensors( 1396714a25aSJames Feist boost::asio::io_service& io, sdbusplus::asio::object_server& objectServer, 1406714a25aSJames Feist boost::container::flat_map<std::string, std::unique_ptr<TachSensor>>& 1416714a25aSJames Feist tachSensors, 1426714a25aSJames Feist boost::container::flat_map<std::string, std::unique_ptr<PwmSensor>>& 1436714a25aSJames Feist pwmSensors, 1446714a25aSJames Feist std::shared_ptr<sdbusplus::asio::connection>& dbusConnection, 1455591cf08SJames Feist const std::shared_ptr<boost::container::flat_set<std::string>>& 146f27a55c7SJames Feist sensorsChanged, 147f27a55c7SJames Feist size_t retries = 0) 1486714a25aSJames Feist { 149de5e9705SJames Feist auto getter = std::make_shared<GetSensorConfiguration>( 150de5e9705SJames Feist dbusConnection, 151de5e9705SJames Feist std::move([&io, &objectServer, &tachSensors, &pwmSensors, 1525591cf08SJames Feist &dbusConnection, sensorsChanged]( 153de5e9705SJames Feist const ManagedObjectType& sensorConfigurations) { 1546714a25aSJames Feist bool firstScan = sensorsChanged == nullptr; 1556714a25aSJames Feist std::vector<fs::path> paths; 156de5e9705SJames Feist if (!findFiles(fs::path("/sys/class/hwmon"), R"(fan\d+_input)", 157de5e9705SJames Feist paths)) 1586714a25aSJames Feist { 15977b3add2SYong Zhao std::cerr << "No fan sensors in system\n"; 1606714a25aSJames Feist return; 1616714a25aSJames Feist } 1626714a25aSJames Feist 1636714a25aSJames Feist // iterate through all found fan sensors, and try to match them with 1646714a25aSJames Feist // configuration 16595b079b7SJames Feist for (const auto& path : paths) 1666714a25aSJames Feist { 1676714a25aSJames Feist std::smatch match; 1686714a25aSJames Feist std::string pathStr = path.string(); 1696714a25aSJames Feist 1709ced0a38SJae Hyun Yoo std::regex_search(pathStr, match, inputRegex); 1716714a25aSJames Feist std::string indexStr = *(match.begin() + 1); 1726714a25aSJames Feist 17377b3add2SYong Zhao fs::path directory = path.parent_path(); 17495b079b7SJames Feist FanTypes fanType = getFanType(directory); 17577b3add2SYong Zhao 1766714a25aSJames Feist // convert to 0 based 1776714a25aSJames Feist size_t index = std::stoul(indexStr) - 1; 1786714a25aSJames Feist 1796714a25aSJames Feist const char* baseType; 1806714a25aSJames Feist const SensorData* sensorData = nullptr; 1816714a25aSJames Feist const std::string* interfacePath = nullptr; 18287d713abSJames Feist const SensorBaseConfiguration* baseConfiguration = nullptr; 183de5e9705SJames Feist for (const std::pair<sdbusplus::message::object_path, 184de5e9705SJames Feist SensorData>& sensor : sensorConfigurations) 1856714a25aSJames Feist { 186de5e9705SJames Feist // find the base of the configuration to see if indexes 187de5e9705SJames Feist // match 188a3e8f2a3SYong Zhao auto sensorBaseFind = 189a3e8f2a3SYong Zhao sensor.second.find(sensorTypes[fanType]); 190a3e8f2a3SYong Zhao if (sensorBaseFind == sensor.second.end()) 1916714a25aSJames Feist { 1926714a25aSJames Feist continue; 1936714a25aSJames Feist } 194347dd4e7SZhikui Ren 195a3e8f2a3SYong Zhao baseConfiguration = &(*sensorBaseFind); 196a3e8f2a3SYong Zhao interfacePath = &(sensor.first.str); 197a3e8f2a3SYong Zhao baseType = sensorTypes[fanType]; 198a3e8f2a3SYong Zhao 1996714a25aSJames Feist auto findIndex = baseConfiguration->second.find("Index"); 2006714a25aSJames Feist if (findIndex == baseConfiguration->second.end()) 2016714a25aSJames Feist { 202de5e9705SJames Feist std::cerr << baseConfiguration->first 203de5e9705SJames Feist << " missing index\n"; 2046714a25aSJames Feist continue; 2056714a25aSJames Feist } 206de5e9705SJames Feist unsigned int configIndex = std::visit( 207de5e9705SJames Feist VariantToUnsignedIntVisitor(), findIndex->second); 2086714a25aSJames Feist if (configIndex != index) 2096714a25aSJames Feist { 2106714a25aSJames Feist continue; 2116714a25aSJames Feist } 212de5e9705SJames Feist if (fanType == FanTypes::aspeed || 213de5e9705SJames Feist fanType == FanTypes::nuvoton) 2146714a25aSJames Feist { 215de5e9705SJames Feist // there will be only 1 aspeed or nuvoton sensor object 216de5e9705SJames Feist // in sysfs, we found the fan 21795b079b7SJames Feist sensorData = &(sensor.second); 21895b079b7SJames Feist break; 21995b079b7SJames Feist } 2208a57ec09SEd Tanous if (fanType == FanTypes::i2c) 22195b079b7SJames Feist { 222*add46820SYong Zhao size_t bus = 0; 223*add46820SYong Zhao size_t address = 0; 224*add46820SYong Zhao 225*add46820SYong Zhao std::string link = 226*add46820SYong Zhao fs::read_symlink(directory / "device").filename(); 227*add46820SYong Zhao 228*add46820SYong Zhao size_t findDash = link.find('-'); 229*add46820SYong Zhao if (findDash == std::string::npos || 230*add46820SYong Zhao link.size() <= findDash + 1) 231*add46820SYong Zhao { 232*add46820SYong Zhao std::cerr << "Error finding device from symlink"; 233*add46820SYong Zhao } 234*add46820SYong Zhao bus = std::stoi(link.substr(0, findDash)); 235*add46820SYong Zhao address = 236*add46820SYong Zhao std::stoi(link.substr(findDash + 1), nullptr, 16); 237*add46820SYong Zhao 23895b079b7SJames Feist auto findBus = baseConfiguration->second.find("Bus"); 239de5e9705SJames Feist auto findAddress = 240de5e9705SJames Feist baseConfiguration->second.find("Address"); 24195b079b7SJames Feist if (findBus == baseConfiguration->second.end() || 24295b079b7SJames Feist findAddress == baseConfiguration->second.end()) 24395b079b7SJames Feist { 24495b079b7SJames Feist std::cerr << baseConfiguration->first 24595b079b7SJames Feist << " missing bus or address\n"; 2466714a25aSJames Feist continue; 2476714a25aSJames Feist } 248de5e9705SJames Feist unsigned int configBus = std::visit( 249de5e9705SJames Feist VariantToUnsignedIntVisitor(), findBus->second); 2503eb82629SJames Feist unsigned int configAddress = std::visit( 25195b079b7SJames Feist VariantToUnsignedIntVisitor(), findAddress->second); 25295b079b7SJames Feist 25384e9e662SJae Hyun Yoo if (configBus == bus && configAddress == address) 2546714a25aSJames Feist { 2556714a25aSJames Feist sensorData = &(sensor.second); 2566714a25aSJames Feist break; 2576714a25aSJames Feist } 2586714a25aSJames Feist } 25995b079b7SJames Feist } 2606714a25aSJames Feist if (sensorData == nullptr) 2616714a25aSJames Feist { 262de5e9705SJames Feist std::cerr << "failed to find match for " << path.string() 263de5e9705SJames Feist << "\n"; 2646714a25aSJames Feist continue; 2656714a25aSJames Feist } 2666714a25aSJames Feist 2676714a25aSJames Feist auto findSensorName = baseConfiguration->second.find("Name"); 268347dd4e7SZhikui Ren 2696714a25aSJames Feist if (findSensorName == baseConfiguration->second.end()) 2706714a25aSJames Feist { 2716714a25aSJames Feist std::cerr << "could not determine configuration name for " 2726714a25aSJames Feist << path.string() << "\n"; 2736714a25aSJames Feist continue; 2746714a25aSJames Feist } 275de5e9705SJames Feist std::string sensorName = 276de5e9705SJames Feist std::get<std::string>(findSensorName->second); 277347dd4e7SZhikui Ren 2786714a25aSJames Feist // on rescans, only update sensors we were signaled by 2796714a25aSJames Feist auto findSensor = tachSensors.find(sensorName); 2806714a25aSJames Feist if (!firstScan && findSensor != tachSensors.end()) 2816714a25aSJames Feist { 2826714a25aSJames Feist bool found = false; 283de5e9705SJames Feist for (auto it = sensorsChanged->begin(); 284de5e9705SJames Feist it != sensorsChanged->end(); it++) 2856714a25aSJames Feist { 2866714a25aSJames Feist if (boost::ends_with(*it, findSensor->second->name)) 2876714a25aSJames Feist { 2886714a25aSJames Feist sensorsChanged->erase(it); 2896714a25aSJames Feist findSensor->second = nullptr; 2906714a25aSJames Feist found = true; 2916714a25aSJames Feist break; 2926714a25aSJames Feist } 2936714a25aSJames Feist } 2946714a25aSJames Feist if (!found) 2956714a25aSJames Feist { 2966714a25aSJames Feist continue; 2976714a25aSJames Feist } 2986714a25aSJames Feist } 2996714a25aSJames Feist std::vector<thresholds::Threshold> sensorThresholds; 3009ced0a38SJae Hyun Yoo if (!parseThresholdsFromConfig(*sensorData, sensorThresholds)) 3016714a25aSJames Feist { 302de5e9705SJames Feist std::cerr << "error populating thresholds for " 303de5e9705SJames Feist << sensorName << "\n"; 3046714a25aSJames Feist } 3056714a25aSJames Feist 3067bc2bab2SJames Feist auto presenceConfig = 3077bc2bab2SJames Feist sensorData->find(baseType + std::string(".Presence")); 3087bc2bab2SJames Feist 3097bc2bab2SJames Feist std::unique_ptr<PresenceSensor> presenceSensor(nullptr); 3107bc2bab2SJames Feist 3117bc2bab2SJames Feist // presence sensors are optional 3127bc2bab2SJames Feist if (presenceConfig != sensorData->end()) 3137bc2bab2SJames Feist { 3147bc2bab2SJames Feist auto findPolarity = presenceConfig->second.find("Polarity"); 315347dd4e7SZhikui Ren auto findPinName = presenceConfig->second.find("PinName"); 3167bc2bab2SJames Feist 317347dd4e7SZhikui Ren if (findPinName == presenceConfig->second.end() || 3187bc2bab2SJames Feist findPolarity == presenceConfig->second.end()) 3197bc2bab2SJames Feist { 3207bc2bab2SJames Feist std::cerr << "Malformed Presence Configuration\n"; 3217bc2bab2SJames Feist } 3227bc2bab2SJames Feist else 3237bc2bab2SJames Feist { 324de5e9705SJames Feist bool inverted = std::get<std::string>( 325de5e9705SJames Feist findPolarity->second) == "Low"; 326347dd4e7SZhikui Ren if (auto pinName = 327347dd4e7SZhikui Ren std::get_if<std::string>(&findPinName->second)) 328347dd4e7SZhikui Ren { 3297b18b1e0SJames Feist presenceSensor = std::make_unique<PresenceSensor>( 330347dd4e7SZhikui Ren *pinName, inverted, io, sensorName); 331347dd4e7SZhikui Ren } 332347dd4e7SZhikui Ren else 333347dd4e7SZhikui Ren { 334347dd4e7SZhikui Ren std::cerr 335347dd4e7SZhikui Ren << "Malformed Presence pinName for sensor " 336347dd4e7SZhikui Ren << sensorName << " \n"; 337347dd4e7SZhikui Ren } 3387bc2bab2SJames Feist } 3397bc2bab2SJames Feist } 3407b18b1e0SJames Feist std::optional<RedundancySensor>* redundancy = nullptr; 34195b079b7SJames Feist if (fanType == FanTypes::aspeed) 34295b079b7SJames Feist { 3437b18b1e0SJames Feist redundancy = &systemRedundancy; 34495b079b7SJames Feist } 3457bc2bab2SJames Feist 346f920e09cSJosh Lehan PowerState powerState = PowerState::on; 347f920e09cSJosh Lehan auto findPower = baseConfiguration->second.find("PowerState"); 348f920e09cSJosh Lehan if (findPower != baseConfiguration->second.end()) 349f920e09cSJosh Lehan { 350f920e09cSJosh Lehan auto ptrPower = 351f920e09cSJosh Lehan std::get_if<std::string>(&(findPower->second)); 352f920e09cSJosh Lehan if (ptrPower) 353f920e09cSJosh Lehan { 354f920e09cSJosh Lehan setReadState(*ptrPower, powerState); 355f920e09cSJosh Lehan } 356f920e09cSJosh Lehan } 357f920e09cSJosh Lehan 35887d713abSJames Feist constexpr double defaultMaxReading = 25000; 35987d713abSJames Feist constexpr double defaultMinReading = 0; 360de5e9705SJames Feist auto limits = 361de5e9705SJames Feist std::make_pair(defaultMinReading, defaultMaxReading); 36287d713abSJames Feist 363de5e9705SJames Feist auto connector = 364de5e9705SJames Feist sensorData->find(baseType + std::string(".Connector")); 36549a8ccd6SJames Feist 36649a8ccd6SJames Feist std::optional<std::string> led; 36777b3add2SYong Zhao std::string pwmName; 368d05867c0SZhikui Ren fs::path pwmPath; 36949a8ccd6SJames Feist 3708e94c204SJames Feist if (connector != sensorData->end()) 3718e94c204SJames Feist { 3728e94c204SJames Feist auto findPwm = connector->second.find("Pwm"); 37349a8ccd6SJames Feist if (findPwm != connector->second.end()) 3748e94c204SJames Feist { 37549a8ccd6SJames Feist 376de5e9705SJames Feist size_t pwm = std::visit(VariantToUnsignedIntVisitor(), 377de5e9705SJames Feist findPwm->second); 378d05867c0SZhikui Ren pwmPath = directory / ("pwm" + std::to_string(pwm + 1)); 37949a8ccd6SJames Feist /* use pwm name override if found in configuration else 38049a8ccd6SJames Feist * use default */ 381d320a2e1SJason Ling auto findOverride = connector->second.find("PwmName"); 382d320a2e1SJason Ling if (findOverride != connector->second.end()) 383d320a2e1SJason Ling { 384d320a2e1SJason Ling pwmName = std::visit(VariantToStringVisitor(), 385d320a2e1SJason Ling findOverride->second); 386d320a2e1SJason Ling } 387d320a2e1SJason Ling else 388d320a2e1SJason Ling { 389d320a2e1SJason Ling pwmName = "Pwm_" + std::to_string(pwm + 1); 390d320a2e1SJason Ling } 3918e94c204SJames Feist } 39249a8ccd6SJames Feist else 39349a8ccd6SJames Feist { 39449a8ccd6SJames Feist std::cerr << "Connector for " << sensorName 39549a8ccd6SJames Feist << " missing pwm!\n"; 39649a8ccd6SJames Feist } 39749a8ccd6SJames Feist 39849a8ccd6SJames Feist auto findLED = connector->second.find("LED"); 39949a8ccd6SJames Feist if (findLED != connector->second.end()) 40049a8ccd6SJames Feist { 40149a8ccd6SJames Feist auto ledName = 40249a8ccd6SJames Feist std::get_if<std::string>(&(findLED->second)); 40349a8ccd6SJames Feist if (ledName == nullptr) 40449a8ccd6SJames Feist { 40549a8ccd6SJames Feist std::cerr << "Wrong format for LED of " 40649a8ccd6SJames Feist << sensorName << "\n"; 40749a8ccd6SJames Feist } 40849a8ccd6SJames Feist else 40949a8ccd6SJames Feist { 41049a8ccd6SJames Feist led = *ledName; 41149a8ccd6SJames Feist } 41249a8ccd6SJames Feist } 41349a8ccd6SJames Feist } 41449a8ccd6SJames Feist 41549a8ccd6SJames Feist findLimits(limits, baseConfiguration); 41649a8ccd6SJames Feist tachSensors[sensorName] = std::make_unique<TachSensor>( 41749a8ccd6SJames Feist path.string(), baseType, objectServer, dbusConnection, 41849a8ccd6SJames Feist std::move(presenceSensor), redundancy, io, sensorName, 41949a8ccd6SJames Feist std::move(sensorThresholds), *interfacePath, limits, 42049a8ccd6SJames Feist powerState, led); 42177b3add2SYong Zhao 422d05867c0SZhikui Ren if (!pwmPath.empty() && fs::exists(pwmPath) && 423d05867c0SZhikui Ren !pwmSensors.count(pwmPath)) 42477b3add2SYong Zhao { 42577b3add2SYong Zhao pwmSensors[pwmPath] = std::make_unique<PwmSensor>( 42677b3add2SYong Zhao pwmName, pwmPath, dbusConnection, objectServer, 42777b3add2SYong Zhao *interfacePath, "Fan"); 4286714a25aSJames Feist } 42977b3add2SYong Zhao } 43077b3add2SYong Zhao 431d540741eSKuiying Wang createRedundancySensor(tachSensors, dbusConnection, objectServer); 432de5e9705SJames Feist })); 433de5e9705SJames Feist getter->getConfiguration( 434f27a55c7SJames Feist std::vector<std::string>{sensorTypes.begin(), sensorTypes.end()}, 435f27a55c7SJames Feist retries); 4366714a25aSJames Feist } 4376714a25aSJames Feist 438b6c0b914SJames Feist int main() 4396714a25aSJames Feist { 4406714a25aSJames Feist boost::asio::io_service io; 4416714a25aSJames Feist auto systemBus = std::make_shared<sdbusplus::asio::connection>(io); 4426714a25aSJames Feist systemBus->request_name("xyz.openbmc_project.FanSensor"); 4436714a25aSJames Feist sdbusplus::asio::object_server objectServer(systemBus); 4446714a25aSJames Feist boost::container::flat_map<std::string, std::unique_ptr<TachSensor>> 4456714a25aSJames Feist tachSensors; 4466714a25aSJames Feist boost::container::flat_map<std::string, std::unique_ptr<PwmSensor>> 4476714a25aSJames Feist pwmSensors; 4486714a25aSJames Feist std::vector<std::unique_ptr<sdbusplus::bus::match::match>> matches; 4495591cf08SJames Feist auto sensorsChanged = 4505591cf08SJames Feist std::make_shared<boost::container::flat_set<std::string>>(); 4516714a25aSJames Feist 4526714a25aSJames Feist io.post([&]() { 4536714a25aSJames Feist createSensors(io, objectServer, tachSensors, pwmSensors, systemBus, 4546714a25aSJames Feist nullptr); 4556714a25aSJames Feist }); 4566714a25aSJames Feist 4576714a25aSJames Feist boost::asio::deadline_timer filterTimer(io); 4586714a25aSJames Feist std::function<void(sdbusplus::message::message&)> eventHandler = 4596714a25aSJames Feist [&](sdbusplus::message::message& message) { 4606714a25aSJames Feist if (message.is_method_error()) 4616714a25aSJames Feist { 4626714a25aSJames Feist std::cerr << "callback method error\n"; 4636714a25aSJames Feist return; 4646714a25aSJames Feist } 4656714a25aSJames Feist sensorsChanged->insert(message.get_path()); 4666714a25aSJames Feist // this implicitly cancels the timer 4676714a25aSJames Feist filterTimer.expires_from_now(boost::posix_time::seconds(1)); 4686714a25aSJames Feist 4696714a25aSJames Feist filterTimer.async_wait([&](const boost::system::error_code& ec) { 4706714a25aSJames Feist if (ec == boost::asio::error::operation_aborted) 4716714a25aSJames Feist { 4726714a25aSJames Feist /* we were canceled*/ 4736714a25aSJames Feist return; 4746714a25aSJames Feist } 4758a57ec09SEd Tanous if (ec) 4766714a25aSJames Feist { 4776714a25aSJames Feist std::cerr << "timer error\n"; 4786714a25aSJames Feist return; 4796714a25aSJames Feist } 4806714a25aSJames Feist createSensors(io, objectServer, tachSensors, pwmSensors, 481f27a55c7SJames Feist systemBus, sensorsChanged, 5); 4826714a25aSJames Feist }); 4836714a25aSJames Feist }; 4846714a25aSJames Feist 4859ced0a38SJae Hyun Yoo for (const char* type : sensorTypes) 4866714a25aSJames Feist { 4876714a25aSJames Feist auto match = std::make_unique<sdbusplus::bus::match::match>( 4886714a25aSJames Feist static_cast<sdbusplus::bus::bus&>(*systemBus), 4896714a25aSJames Feist "type='signal',member='PropertiesChanged',path_namespace='" + 4909ced0a38SJae Hyun Yoo std::string(inventoryPath) + "',arg0namespace='" + type + "'", 4916714a25aSJames Feist eventHandler); 4926714a25aSJames Feist matches.emplace_back(std::move(match)); 4936714a25aSJames Feist } 4946714a25aSJames Feist 495dc6c55f3SJames Feist // redundancy sensor 496dc6c55f3SJames Feist std::function<void(sdbusplus::message::message&)> redundancyHandler = 497dc6c55f3SJames Feist [&tachSensors, &systemBus, 498b6c0b914SJames Feist &objectServer](sdbusplus::message::message&) { 499dc6c55f3SJames Feist createRedundancySensor(tachSensors, systemBus, objectServer); 500dc6c55f3SJames Feist }; 501dc6c55f3SJames Feist auto match = std::make_unique<sdbusplus::bus::match::match>( 502dc6c55f3SJames Feist static_cast<sdbusplus::bus::bus&>(*systemBus), 503dc6c55f3SJames Feist "type='signal',member='PropertiesChanged',path_namespace='" + 504dc6c55f3SJames Feist std::string(inventoryPath) + "',arg0namespace='" + 505dc6c55f3SJames Feist redundancyConfiguration + "'", 506b6c0b914SJames Feist std::move(redundancyHandler)); 507dc6c55f3SJames Feist matches.emplace_back(std::move(match)); 508dc6c55f3SJames Feist 5096714a25aSJames Feist io.run(); 5106714a25aSJames Feist } 511