1a227a16dSMatthew Barth /** 2a227a16dSMatthew Barth * Copyright © 2020 IBM Corporation 3a227a16dSMatthew Barth * 4a227a16dSMatthew Barth * Licensed under the Apache License, Version 2.0 (the "License"); 5a227a16dSMatthew Barth * you may not use this file except in compliance with the License. 6a227a16dSMatthew Barth * You may obtain a copy of the License at 7a227a16dSMatthew Barth * 8a227a16dSMatthew Barth * http://www.apache.org/licenses/LICENSE-2.0 9a227a16dSMatthew Barth * 10a227a16dSMatthew Barth * Unless required by applicable law or agreed to in writing, software 11a227a16dSMatthew Barth * distributed under the License is distributed on an "AS IS" BASIS, 12a227a16dSMatthew Barth * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13a227a16dSMatthew Barth * See the License for the specific language governing permissions and 14a227a16dSMatthew Barth * limitations under the License. 15a227a16dSMatthew Barth */ 16b584d818SMatthew Barth #include "config.h" 17b584d818SMatthew Barth 18a227a16dSMatthew Barth #include "manager.hpp" 19a227a16dSMatthew Barth 20d9cb63b6SMatthew Barth #include "action.hpp" 2144ab7693SMatthew Barth #include "event.hpp" 22de90fb4dSMatthew Barth #include "fan.hpp" 23d9cb63b6SMatthew Barth #include "group.hpp" 24a227a16dSMatthew Barth #include "json_config.hpp" 2506764946SMatthew Barth #include "profile.hpp" 269403a217SMatthew Barth #include "sdbusplus.hpp" 27acd737cdSMatthew Barth #include "zone.hpp" 28a227a16dSMatthew Barth 29acd737cdSMatthew Barth #include <nlohmann/json.hpp> 30a227a16dSMatthew Barth #include <sdbusplus/bus.hpp> 31acd737cdSMatthew Barth #include <sdeventplus/event.hpp> 32d9cb63b6SMatthew Barth #include <sdeventplus/utility/timer.hpp> 33a227a16dSMatthew Barth 34de90fb4dSMatthew Barth #include <algorithm> 35d9cb63b6SMatthew Barth #include <chrono> 36a227a16dSMatthew Barth #include <filesystem> 37d9cb63b6SMatthew Barth #include <functional> 38d9cb63b6SMatthew Barth #include <map> 39d9cb63b6SMatthew Barth #include <memory> 40d9cb63b6SMatthew Barth #include <tuple> 41d9cb63b6SMatthew Barth #include <utility> 4206764946SMatthew Barth #include <vector> 43a227a16dSMatthew Barth 44a227a16dSMatthew Barth namespace phosphor::fan::control::json 45a227a16dSMatthew Barth { 46a227a16dSMatthew Barth 47acd737cdSMatthew Barth using json = nlohmann::json; 48acd737cdSMatthew Barth 49acd737cdSMatthew Barth std::vector<std::string> Manager::_activeProfiles; 5012cb125aSMatthew Barth std::map<std::string, 514ca87faeSMatthew Barth std::map<std::string, std::pair<bool, std::vector<std::string>>>> 5212cb125aSMatthew Barth Manager::_servTree; 5307fecfc6SMatthew Barth std::map<std::string, 5407fecfc6SMatthew Barth std::map<std::string, std::map<std::string, PropertyVariantType>>> 5507fecfc6SMatthew Barth Manager::_objects; 56acd737cdSMatthew Barth 579403a217SMatthew Barth Manager::Manager(const sdeventplus::Event& event) : 589403a217SMatthew Barth _bus(util::SDBusPlus::getBus()), _event(event) 59a227a16dSMatthew Barth { 60a227a16dSMatthew Barth // Manager JSON config file is optional 61a227a16dSMatthew Barth auto confFile = 629403a217SMatthew Barth fan::JsonConfig::getConfFile(_bus, confAppName, confFileName, true); 63a227a16dSMatthew Barth if (!confFile.empty()) 64a227a16dSMatthew Barth { 65a227a16dSMatthew Barth _jsonObj = fan::JsonConfig::load(confFile); 66a227a16dSMatthew Barth } 6706764946SMatthew Barth 68acd737cdSMatthew Barth // Parse and set the available profiles and which are active 69acd737cdSMatthew Barth setProfiles(); 70acd737cdSMatthew Barth 71acd737cdSMatthew Barth // Load the zone configurations 729403a217SMatthew Barth _zones = getConfig<Zone>(false, event, this); 73de90fb4dSMatthew Barth 74de90fb4dSMatthew Barth // Load the fan configurations and move each fan into its zone 759403a217SMatthew Barth auto fans = getConfig<Fan>(false); 76de90fb4dSMatthew Barth for (auto& fan : fans) 77de90fb4dSMatthew Barth { 780206c728SMatthew Barth configKey fanProfile = 790206c728SMatthew Barth std::make_pair(fan.second->getZone(), fan.first.second); 800206c728SMatthew Barth auto itZone = std::find_if( 810206c728SMatthew Barth _zones.begin(), _zones.end(), [&fanProfile](const auto& zone) { 820206c728SMatthew Barth return Manager::inConfig(fanProfile, zone.first); 83de90fb4dSMatthew Barth }); 84de90fb4dSMatthew Barth if (itZone != _zones.end()) 85de90fb4dSMatthew Barth { 866f787309SMatthew Barth if (itZone->second->getTarget() != fan.second->getTarget() && 876f787309SMatthew Barth fan.second->getTarget() != 0) 886f787309SMatthew Barth { 896f787309SMatthew Barth // Update zone target to current target of the fan in the zone 906f787309SMatthew Barth itZone->second->setTarget(fan.second->getTarget()); 916f787309SMatthew Barth } 92de90fb4dSMatthew Barth itZone->second->addFan(std::move(fan.second)); 93de90fb4dSMatthew Barth } 94de90fb4dSMatthew Barth } 95b584d818SMatthew Barth 9644ab7693SMatthew Barth // Load the configured groups that are copied into events where they're used 979403a217SMatthew Barth auto groups = getConfig<Group>(true); 9844ab7693SMatthew Barth 9944ab7693SMatthew Barth // Load any events configured 1009403a217SMatthew Barth _events = getConfig<Event>(true, this, groups, _zones); 10144ab7693SMatthew Barth 1029403a217SMatthew Barth _bus.request_name(CONTROL_BUSNAME); 10306764946SMatthew Barth } 104acd737cdSMatthew Barth 105acd737cdSMatthew Barth const std::vector<std::string>& Manager::getActiveProfiles() 106acd737cdSMatthew Barth { 107acd737cdSMatthew Barth return _activeProfiles; 108a227a16dSMatthew Barth } 109a227a16dSMatthew Barth 1100206c728SMatthew Barth bool Manager::inConfig(const configKey& input, const configKey& comp) 1110206c728SMatthew Barth { 1120206c728SMatthew Barth // Config names dont match, do not include in config 1130206c728SMatthew Barth if (input.first != comp.first) 1140206c728SMatthew Barth { 1150206c728SMatthew Barth return false; 1160206c728SMatthew Barth } 1170206c728SMatthew Barth // No profiles specified by input config, can be used in any config 1180206c728SMatthew Barth if (input.second.empty()) 1190206c728SMatthew Barth { 1200206c728SMatthew Barth return true; 1210206c728SMatthew Barth } 1220206c728SMatthew Barth else 1230206c728SMatthew Barth { 1240206c728SMatthew Barth // Profiles must have one match in the other's profiles(and they must be 1250206c728SMatthew Barth // an active profile) to be used in the config 1260206c728SMatthew Barth return std::any_of( 1270206c728SMatthew Barth input.second.begin(), input.second.end(), 1280206c728SMatthew Barth [&comp](const auto& lProfile) { 1290206c728SMatthew Barth return std::any_of( 1300206c728SMatthew Barth comp.second.begin(), comp.second.end(), 1310206c728SMatthew Barth [&lProfile](const auto& rProfile) { 1320206c728SMatthew Barth if (lProfile != rProfile) 1330206c728SMatthew Barth { 1340206c728SMatthew Barth return false; 1350206c728SMatthew Barth } 1360206c728SMatthew Barth auto activeProfs = getActiveProfiles(); 1370206c728SMatthew Barth return std::find(activeProfs.begin(), activeProfs.end(), 1380206c728SMatthew Barth lProfile) != activeProfs.end(); 1390206c728SMatthew Barth }); 1400206c728SMatthew Barth }); 1410206c728SMatthew Barth } 1420206c728SMatthew Barth } 1430206c728SMatthew Barth 14412cb125aSMatthew Barth bool Manager::hasOwner(const std::string& path, const std::string& intf) 14512cb125aSMatthew Barth { 14612cb125aSMatthew Barth auto itServ = _servTree.find(path); 14712cb125aSMatthew Barth if (itServ == _servTree.end()) 14812cb125aSMatthew Barth { 14912cb125aSMatthew Barth // Path not found in cache, therefore owner missing 15012cb125aSMatthew Barth return false; 15112cb125aSMatthew Barth } 1524ca87faeSMatthew Barth for (const auto& service : itServ->second) 15312cb125aSMatthew Barth { 15412cb125aSMatthew Barth auto itIntf = std::find_if( 1554ca87faeSMatthew Barth service.second.second.begin(), service.second.second.end(), 15612cb125aSMatthew Barth [&intf](const auto& interface) { return intf == interface; }); 1574ca87faeSMatthew Barth if (itIntf != std::end(service.second.second)) 15812cb125aSMatthew Barth { 15912cb125aSMatthew Barth // Service found, return owner state 1604ca87faeSMatthew Barth return service.second.first; 16112cb125aSMatthew Barth } 16212cb125aSMatthew Barth } 16312cb125aSMatthew Barth // Interface not found in cache, therefore owner missing 16412cb125aSMatthew Barth return false; 16512cb125aSMatthew Barth } 16612cb125aSMatthew Barth 1674ca87faeSMatthew Barth void Manager::setOwner(const std::string& path, const std::string& serv, 1684ca87faeSMatthew Barth const std::string& intf, bool isOwned) 1694ca87faeSMatthew Barth { 170*2a9e7b2eSMatthew Barth // Set owner state for specific object given 171*2a9e7b2eSMatthew Barth auto& ownIntf = _servTree[path][serv]; 172*2a9e7b2eSMatthew Barth ownIntf.first = isOwned; 1734ca87faeSMatthew Barth auto itIntf = std::find_if( 174*2a9e7b2eSMatthew Barth ownIntf.second.begin(), ownIntf.second.end(), 1754ca87faeSMatthew Barth [&intf](const auto& interface) { return intf == interface; }); 176*2a9e7b2eSMatthew Barth if (itIntf == std::end(ownIntf.second)) 1774ca87faeSMatthew Barth { 178*2a9e7b2eSMatthew Barth ownIntf.second.emplace_back(intf); 179*2a9e7b2eSMatthew Barth } 180*2a9e7b2eSMatthew Barth 181*2a9e7b2eSMatthew Barth // Update owner state on all entries of the same `serv` & `intf` 182*2a9e7b2eSMatthew Barth for (auto& itPath : _servTree) 1834ca87faeSMatthew Barth { 184*2a9e7b2eSMatthew Barth if (itPath.first == path) 185*2a9e7b2eSMatthew Barth { 186*2a9e7b2eSMatthew Barth // Already set/updated owner on this path for `serv` & `intf` 187*2a9e7b2eSMatthew Barth continue; 188*2a9e7b2eSMatthew Barth } 189*2a9e7b2eSMatthew Barth for (auto& itServ : itPath.second) 190*2a9e7b2eSMatthew Barth { 191*2a9e7b2eSMatthew Barth if (itServ.first != serv) 192*2a9e7b2eSMatthew Barth { 193*2a9e7b2eSMatthew Barth continue; 194*2a9e7b2eSMatthew Barth } 195*2a9e7b2eSMatthew Barth auto itIntf = std::find_if( 196*2a9e7b2eSMatthew Barth itServ.second.second.begin(), itServ.second.second.end(), 197*2a9e7b2eSMatthew Barth [&intf](const auto& interface) { return intf == interface; }); 198*2a9e7b2eSMatthew Barth if (itIntf != std::end(itServ.second.second)) 199*2a9e7b2eSMatthew Barth { 200*2a9e7b2eSMatthew Barth itServ.second.first = isOwned; 2014ca87faeSMatthew Barth } 2024ca87faeSMatthew Barth } 2034ca87faeSMatthew Barth } 2044ca87faeSMatthew Barth } 2054ca87faeSMatthew Barth 2064ca87faeSMatthew Barth const std::string& Manager::findService(const std::string& path, 2074ca87faeSMatthew Barth const std::string& intf) 2084ca87faeSMatthew Barth { 2094ca87faeSMatthew Barth static const std::string empty = ""; 2104ca87faeSMatthew Barth 2114ca87faeSMatthew Barth auto itServ = _servTree.find(path); 2124ca87faeSMatthew Barth if (itServ != _servTree.end()) 2134ca87faeSMatthew Barth { 2144ca87faeSMatthew Barth for (const auto& service : itServ->second) 2154ca87faeSMatthew Barth { 2164ca87faeSMatthew Barth auto itIntf = std::find_if( 2174ca87faeSMatthew Barth service.second.second.begin(), service.second.second.end(), 2184ca87faeSMatthew Barth [&intf](const auto& interface) { return intf == interface; }); 2194ca87faeSMatthew Barth if (itIntf != std::end(service.second.second)) 2204ca87faeSMatthew Barth { 2214ca87faeSMatthew Barth // Service found, return service name 2224ca87faeSMatthew Barth return service.first; 2234ca87faeSMatthew Barth } 2244ca87faeSMatthew Barth } 2254ca87faeSMatthew Barth } 2264ca87faeSMatthew Barth 2274ca87faeSMatthew Barth return empty; 2284ca87faeSMatthew Barth } 2294ca87faeSMatthew Barth 23098f6fc17SMatthew Barth void Manager::addServices(const std::string& intf, int32_t depth) 2314ca87faeSMatthew Barth { 2324ca87faeSMatthew Barth // Get all subtree objects for the given interface 2334ca87faeSMatthew Barth auto objects = util::SDBusPlus::getSubTree(util::SDBusPlus::getBus(), "/", 2344ca87faeSMatthew Barth intf, depth); 2354ca87faeSMatthew Barth // Add what's returned to the cache of path->services 2364ca87faeSMatthew Barth for (auto& itPath : objects) 2374ca87faeSMatthew Barth { 2384ca87faeSMatthew Barth auto pathIter = _servTree.find(itPath.first); 2394ca87faeSMatthew Barth if (pathIter != _servTree.end()) 2404ca87faeSMatthew Barth { 2414ca87faeSMatthew Barth // Path found in cache 2424ca87faeSMatthew Barth for (auto& itServ : itPath.second) 2434ca87faeSMatthew Barth { 2444ca87faeSMatthew Barth auto servIter = pathIter->second.find(itServ.first); 2454ca87faeSMatthew Barth if (servIter != pathIter->second.end()) 2464ca87faeSMatthew Barth { 2474ca87faeSMatthew Barth // Service found in cache 2484ca87faeSMatthew Barth for (auto& itIntf : itServ.second) 2494ca87faeSMatthew Barth { 2504ca87faeSMatthew Barth if (std::find(servIter->second.second.begin(), 2514ca87faeSMatthew Barth servIter->second.second.end(), 2524ca87faeSMatthew Barth itIntf) == servIter->second.second.end()) 2534ca87faeSMatthew Barth { 2544ca87faeSMatthew Barth // Add interface to cache 2554ca87faeSMatthew Barth servIter->second.second.emplace_back(itIntf); 2564ca87faeSMatthew Barth } 2574ca87faeSMatthew Barth } 2584ca87faeSMatthew Barth } 2594ca87faeSMatthew Barth else 2604ca87faeSMatthew Barth { 2614ca87faeSMatthew Barth // Service not found in cache 2624ca87faeSMatthew Barth auto intfs = {intf}; 2634ca87faeSMatthew Barth pathIter->second[itServ.first] = 2644ca87faeSMatthew Barth std::make_pair(true, intfs); 2654ca87faeSMatthew Barth } 2664ca87faeSMatthew Barth } 2674ca87faeSMatthew Barth } 2684ca87faeSMatthew Barth else 2694ca87faeSMatthew Barth { 2704ca87faeSMatthew Barth // Path not found in cache 2714ca87faeSMatthew Barth auto intfs = {intf}; 2724ca87faeSMatthew Barth _servTree[itPath.first] = { 2734ca87faeSMatthew Barth {itPath.second.begin()->first, std::make_pair(true, intfs)}}; 2744ca87faeSMatthew Barth } 2754ca87faeSMatthew Barth } 2764ca87faeSMatthew Barth } 2774ca87faeSMatthew Barth 2784ca87faeSMatthew Barth const std::string& Manager::getService(const std::string& path, 2794ca87faeSMatthew Barth const std::string& intf) 2804ca87faeSMatthew Barth { 2814ca87faeSMatthew Barth // Retrieve service from cache 2824ca87faeSMatthew Barth const auto& serviceName = findService(path, intf); 2834ca87faeSMatthew Barth if (serviceName.empty()) 2844ca87faeSMatthew Barth { 28598f6fc17SMatthew Barth addServices(intf, 0); 2864ca87faeSMatthew Barth return findService(path, intf); 2874ca87faeSMatthew Barth } 2884ca87faeSMatthew Barth 2894ca87faeSMatthew Barth return serviceName; 2904ca87faeSMatthew Barth } 2914ca87faeSMatthew Barth 292f41e947bSMatthew Barth std::vector<std::string> Manager::findPaths(const std::string& serv, 293f41e947bSMatthew Barth const std::string& intf) 294f41e947bSMatthew Barth { 295f41e947bSMatthew Barth std::vector<std::string> paths; 296f41e947bSMatthew Barth 297f41e947bSMatthew Barth for (const auto& path : _servTree) 298f41e947bSMatthew Barth { 299f41e947bSMatthew Barth auto itServ = path.second.find(serv); 300f41e947bSMatthew Barth if (itServ != path.second.end()) 301f41e947bSMatthew Barth { 302f41e947bSMatthew Barth if (std::find(itServ->second.second.begin(), 303f41e947bSMatthew Barth itServ->second.second.end(), 304f41e947bSMatthew Barth intf) != itServ->second.second.end()) 305f41e947bSMatthew Barth { 306f41e947bSMatthew Barth if (std::find(paths.begin(), paths.end(), path.first) == 307f41e947bSMatthew Barth paths.end()) 308f41e947bSMatthew Barth { 309f41e947bSMatthew Barth paths.push_back(path.first); 310f41e947bSMatthew Barth } 311f41e947bSMatthew Barth } 312f41e947bSMatthew Barth } 313f41e947bSMatthew Barth } 314f41e947bSMatthew Barth 315f41e947bSMatthew Barth return paths; 316f41e947bSMatthew Barth } 317f41e947bSMatthew Barth 318f41e947bSMatthew Barth std::vector<std::string> Manager::getPaths(const std::string& serv, 319f41e947bSMatthew Barth const std::string& intf) 320f41e947bSMatthew Barth { 321f41e947bSMatthew Barth auto paths = findPaths(serv, intf); 322f41e947bSMatthew Barth if (paths.empty()) 323f41e947bSMatthew Barth { 324f41e947bSMatthew Barth addServices(intf, 0); 325f41e947bSMatthew Barth return findPaths(serv, intf); 326f41e947bSMatthew Barth } 327f41e947bSMatthew Barth 328f41e947bSMatthew Barth return paths; 329f41e947bSMatthew Barth } 330f41e947bSMatthew Barth 331f41e947bSMatthew Barth void Manager::addObjects(const std::string& path, const std::string& intf, 332f41e947bSMatthew Barth const std::string& prop) 333f41e947bSMatthew Barth { 334f41e947bSMatthew Barth auto service = getService(path, intf); 335f41e947bSMatthew Barth if (service.empty()) 336f41e947bSMatthew Barth { 337f41e947bSMatthew Barth // Log service not found for object 338f41e947bSMatthew Barth log<level::ERR>( 339f41e947bSMatthew Barth fmt::format("Unable to get service name for path {}, interface {}", 340f41e947bSMatthew Barth path, intf) 341f41e947bSMatthew Barth .c_str()); 342f41e947bSMatthew Barth return; 343f41e947bSMatthew Barth } 344f41e947bSMatthew Barth 345f41e947bSMatthew Barth auto objMgrPaths = getPaths(service, "org.freedesktop.DBus.ObjectManager"); 346f41e947bSMatthew Barth if (objMgrPaths.empty()) 347f41e947bSMatthew Barth { 348f41e947bSMatthew Barth // No object manager interface provided by service? 349f41e947bSMatthew Barth // Attempt to retrieve property directly 350f41e947bSMatthew Barth auto variant = util::SDBusPlus::getPropertyVariant<PropertyVariantType>( 351f41e947bSMatthew Barth _bus, service, path, intf, prop); 352f41e947bSMatthew Barth _objects[path][intf][prop] = variant; 353f41e947bSMatthew Barth return; 354f41e947bSMatthew Barth } 355f41e947bSMatthew Barth 356f41e947bSMatthew Barth for (const auto& objMgrPath : objMgrPaths) 357f41e947bSMatthew Barth { 358f41e947bSMatthew Barth // Get all managed objects of service 359f41e947bSMatthew Barth auto objects = util::SDBusPlus::getManagedObjects<PropertyVariantType>( 360f41e947bSMatthew Barth _bus, service, objMgrPath); 361f41e947bSMatthew Barth 362f41e947bSMatthew Barth // Add what's returned to the cache of objects 363f41e947bSMatthew Barth for (auto& object : objects) 364f41e947bSMatthew Barth { 365f41e947bSMatthew Barth auto itPath = _objects.find(object.first); 366f41e947bSMatthew Barth if (itPath != _objects.end()) 367f41e947bSMatthew Barth { 368f41e947bSMatthew Barth // Path found in cache 369f41e947bSMatthew Barth for (auto& interface : itPath->second) 370f41e947bSMatthew Barth { 371f41e947bSMatthew Barth auto itIntf = itPath->second.find(interface.first); 372f41e947bSMatthew Barth if (itIntf != itPath->second.end()) 373f41e947bSMatthew Barth { 374f41e947bSMatthew Barth // Interface found in cache 375f41e947bSMatthew Barth for (auto& property : itIntf->second) 376f41e947bSMatthew Barth { 377f41e947bSMatthew Barth auto itProp = itIntf->second.find(property.first); 378f41e947bSMatthew Barth if (itProp != itIntf->second.end()) 379f41e947bSMatthew Barth { 380f41e947bSMatthew Barth // Property found, update value 381f41e947bSMatthew Barth itProp->second = property.second; 382f41e947bSMatthew Barth } 383f41e947bSMatthew Barth else 384f41e947bSMatthew Barth { 385f41e947bSMatthew Barth itIntf->second.insert(property); 386f41e947bSMatthew Barth } 387f41e947bSMatthew Barth } 388f41e947bSMatthew Barth } 389f41e947bSMatthew Barth else 390f41e947bSMatthew Barth { 391f41e947bSMatthew Barth // Interface not found in cache 392f41e947bSMatthew Barth itPath->second.insert(interface); 393f41e947bSMatthew Barth } 394f41e947bSMatthew Barth } 395f41e947bSMatthew Barth } 396f41e947bSMatthew Barth else 397f41e947bSMatthew Barth { 398f41e947bSMatthew Barth // Path not found in cache 399f41e947bSMatthew Barth _objects.insert(object); 400f41e947bSMatthew Barth } 401f41e947bSMatthew Barth } 402f41e947bSMatthew Barth } 403f41e947bSMatthew Barth } 404f41e947bSMatthew Barth 405f41e947bSMatthew Barth const std::optional<PropertyVariantType> 406f41e947bSMatthew Barth Manager::getProperty(const std::string& path, const std::string& intf, 407f41e947bSMatthew Barth const std::string& prop) 408f41e947bSMatthew Barth { 409f41e947bSMatthew Barth // TODO Objects hosted by fan control (i.e. ThermalMode) are required to 410f41e947bSMatthew Barth // update the cache upon being set/updated 411f41e947bSMatthew Barth auto itPath = _objects.find(path); 412f41e947bSMatthew Barth if (itPath != _objects.end()) 413f41e947bSMatthew Barth { 414f41e947bSMatthew Barth auto itIntf = itPath->second.find(intf); 415f41e947bSMatthew Barth if (itIntf != itPath->second.end()) 416f41e947bSMatthew Barth { 417f41e947bSMatthew Barth auto itProp = itIntf->second.find(prop); 418f41e947bSMatthew Barth if (itProp != itIntf->second.end()) 419f41e947bSMatthew Barth { 420f41e947bSMatthew Barth return itProp->second; 421f41e947bSMatthew Barth } 422f41e947bSMatthew Barth } 423f41e947bSMatthew Barth } 424f41e947bSMatthew Barth 425f41e947bSMatthew Barth return std::nullopt; 426f41e947bSMatthew Barth } 427f41e947bSMatthew Barth 428d9cb63b6SMatthew Barth void Manager::addTimer(const TimerType type, 429d9cb63b6SMatthew Barth const std::chrono::microseconds interval, 430d9cb63b6SMatthew Barth std::unique_ptr<TimerPkg> pkg) 431d9cb63b6SMatthew Barth { 432d9cb63b6SMatthew Barth auto dataPtr = 433d9cb63b6SMatthew Barth std::make_unique<TimerData>(std::make_pair(type, std::move(*pkg))); 434d9cb63b6SMatthew Barth Timer timer(_event, 435d9cb63b6SMatthew Barth std::bind(&Manager::timerExpired, this, std::ref(*dataPtr))); 436d9cb63b6SMatthew Barth if (type == TimerType::repeating) 437d9cb63b6SMatthew Barth { 438d9cb63b6SMatthew Barth timer.restart(interval); 439d9cb63b6SMatthew Barth } 440d9cb63b6SMatthew Barth else if (type == TimerType::oneshot) 441d9cb63b6SMatthew Barth { 442d9cb63b6SMatthew Barth timer.restartOnce(interval); 443d9cb63b6SMatthew Barth } 444d9cb63b6SMatthew Barth else 445d9cb63b6SMatthew Barth { 446d9cb63b6SMatthew Barth throw std::invalid_argument("Invalid Timer Type"); 447d9cb63b6SMatthew Barth } 448d9cb63b6SMatthew Barth _timers.emplace_back(std::move(dataPtr), std::move(timer)); 449d9cb63b6SMatthew Barth } 450d9cb63b6SMatthew Barth 451d9cb63b6SMatthew Barth void Manager::timerExpired(TimerData& data) 452d9cb63b6SMatthew Barth { 453d9cb63b6SMatthew Barth auto& actions = 454d9cb63b6SMatthew Barth std::get<std::vector<std::unique_ptr<ActionBase>>&>(data.second); 455d9cb63b6SMatthew Barth // Perform the actions in the timer data 456d9cb63b6SMatthew Barth std::for_each(actions.begin(), actions.end(), 45700f6aa09SMatthew Barth [](auto& action) { action->run(); }); 458d9cb63b6SMatthew Barth 459d9cb63b6SMatthew Barth // Remove oneshot timers after they expired 460d9cb63b6SMatthew Barth if (data.first == TimerType::oneshot) 461d9cb63b6SMatthew Barth { 462d9cb63b6SMatthew Barth auto itTimer = std::find_if( 463d9cb63b6SMatthew Barth _timers.begin(), _timers.end(), [&data](const auto& timer) { 464d9cb63b6SMatthew Barth return (data.first == timer.first->first && 465d9cb63b6SMatthew Barth (std::get<std::string>(data.second) == 466d9cb63b6SMatthew Barth std::get<std::string>(timer.first->second))); 467d9cb63b6SMatthew Barth }); 468d9cb63b6SMatthew Barth if (itTimer != std::end(_timers)) 469d9cb63b6SMatthew Barth { 470d9cb63b6SMatthew Barth _timers.erase(itTimer); 471d9cb63b6SMatthew Barth } 472d9cb63b6SMatthew Barth } 473d9cb63b6SMatthew Barth } 474d9cb63b6SMatthew Barth 475ebabc040SMatthew Barth void Manager::handleSignal(sdbusplus::message::message& msg, 476ebabc040SMatthew Barth const std::vector<SignalPkg>* pkgs) 477ebabc040SMatthew Barth { 478ebabc040SMatthew Barth for (auto& pkg : *pkgs) 479ebabc040SMatthew Barth { 480ebabc040SMatthew Barth // Handle the signal callback and only run the actions if the handler 481ebabc040SMatthew Barth // updated the cache for the given SignalObject 482ebabc040SMatthew Barth if (std::get<SignalHandler>(pkg)(msg, std::get<SignalObject>(pkg), 483ebabc040SMatthew Barth *this)) 484ebabc040SMatthew Barth { 485ebabc040SMatthew Barth // Perform the actions in the handler package 486ebabc040SMatthew Barth auto& actions = std::get<SignalActions>(pkg); 487ebabc040SMatthew Barth std::for_each(actions.begin(), actions.end(), 488ebabc040SMatthew Barth [](auto& action) { action.get()->run(); }); 489ebabc040SMatthew Barth } 490ebabc040SMatthew Barth } 491ebabc040SMatthew Barth } 492ebabc040SMatthew Barth 493a227a16dSMatthew Barth unsigned int Manager::getPowerOnDelay() 494a227a16dSMatthew Barth { 495a227a16dSMatthew Barth auto powerOnDelay = 0; 496a227a16dSMatthew Barth 497a227a16dSMatthew Barth // Parse optional "power_on_delay" from JSON object 498a227a16dSMatthew Barth if (!_jsonObj.empty() && _jsonObj.contains("power_on_delay")) 499a227a16dSMatthew Barth { 500a227a16dSMatthew Barth powerOnDelay = _jsonObj["power_on_delay"].get<unsigned int>(); 501a227a16dSMatthew Barth } 502a227a16dSMatthew Barth 503a227a16dSMatthew Barth return powerOnDelay; 504a227a16dSMatthew Barth } 505a227a16dSMatthew Barth 506acd737cdSMatthew Barth void Manager::setProfiles() 507acd737cdSMatthew Barth { 508acd737cdSMatthew Barth // Profiles JSON config file is optional 509acd737cdSMatthew Barth auto confFile = fan::JsonConfig::getConfFile(_bus, confAppName, 510acd737cdSMatthew Barth Profile::confFileName, true); 511acd737cdSMatthew Barth if (!confFile.empty()) 512acd737cdSMatthew Barth { 513acd737cdSMatthew Barth for (const auto& entry : fan::JsonConfig::load(confFile)) 514acd737cdSMatthew Barth { 515acd737cdSMatthew Barth auto obj = std::make_unique<Profile>(entry); 516acd737cdSMatthew Barth _profiles.emplace( 517acd737cdSMatthew Barth std::make_pair(obj->getName(), obj->getProfiles()), 518acd737cdSMatthew Barth std::move(obj)); 519acd737cdSMatthew Barth } 520acd737cdSMatthew Barth } 521acd737cdSMatthew Barth // Ensure all configurations use the same set of active profiles 522acd737cdSMatthew Barth // (In case a profile's active state changes during configuration) 523acd737cdSMatthew Barth for (const auto& profile : _profiles) 524acd737cdSMatthew Barth { 525acd737cdSMatthew Barth if (profile.second->isActive()) 526acd737cdSMatthew Barth { 527acd737cdSMatthew Barth _activeProfiles.emplace_back(profile.first.first); 528acd737cdSMatthew Barth } 529acd737cdSMatthew Barth } 530acd737cdSMatthew Barth } 531acd737cdSMatthew Barth 532a227a16dSMatthew Barth } // namespace phosphor::fan::control::json 533