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" 21de90fb4dSMatthew Barth #include "fan.hpp" 22d9cb63b6SMatthew Barth #include "group.hpp" 23a227a16dSMatthew Barth #include "json_config.hpp" 2406764946SMatthew Barth #include "profile.hpp" 25acd737cdSMatthew Barth #include "zone.hpp" 26a227a16dSMatthew Barth 27acd737cdSMatthew Barth #include <nlohmann/json.hpp> 28a227a16dSMatthew Barth #include <sdbusplus/bus.hpp> 29acd737cdSMatthew Barth #include <sdeventplus/event.hpp> 30d9cb63b6SMatthew Barth #include <sdeventplus/utility/timer.hpp> 31a227a16dSMatthew Barth 32de90fb4dSMatthew Barth #include <algorithm> 33d9cb63b6SMatthew Barth #include <chrono> 34a227a16dSMatthew Barth #include <filesystem> 35d9cb63b6SMatthew Barth #include <functional> 36d9cb63b6SMatthew Barth #include <map> 37d9cb63b6SMatthew Barth #include <memory> 38d9cb63b6SMatthew Barth #include <tuple> 39d9cb63b6SMatthew Barth #include <utility> 4006764946SMatthew Barth #include <vector> 41a227a16dSMatthew Barth 42a227a16dSMatthew Barth namespace phosphor::fan::control::json 43a227a16dSMatthew Barth { 44a227a16dSMatthew Barth 45acd737cdSMatthew Barth using json = nlohmann::json; 46acd737cdSMatthew Barth 47acd737cdSMatthew Barth std::vector<std::string> Manager::_activeProfiles; 4812cb125aSMatthew Barth std::map<std::string, 4912cb125aSMatthew Barth std::map<std::pair<std::string, bool>, std::vector<std::string>>> 5012cb125aSMatthew Barth Manager::_servTree; 5107fecfc6SMatthew Barth std::map<std::string, 5207fecfc6SMatthew Barth std::map<std::string, std::map<std::string, PropertyVariantType>>> 5307fecfc6SMatthew Barth Manager::_objects; 54acd737cdSMatthew Barth 5506764946SMatthew Barth Manager::Manager(sdbusplus::bus::bus& bus, const sdeventplus::Event& event) : 56acd737cdSMatthew Barth _bus(bus), _event(event) 57a227a16dSMatthew Barth { 58a227a16dSMatthew Barth // Manager JSON config file is optional 59a227a16dSMatthew Barth auto confFile = 60a227a16dSMatthew Barth fan::JsonConfig::getConfFile(bus, confAppName, confFileName, true); 61a227a16dSMatthew Barth if (!confFile.empty()) 62a227a16dSMatthew Barth { 63a227a16dSMatthew Barth _jsonObj = fan::JsonConfig::load(confFile); 64a227a16dSMatthew Barth } 6506764946SMatthew Barth 66acd737cdSMatthew Barth // Parse and set the available profiles and which are active 67acd737cdSMatthew Barth setProfiles(); 68acd737cdSMatthew Barth 69acd737cdSMatthew Barth // Load the zone configurations 70*603ef164SMatthew Barth _zones = getConfig<Zone>(false, bus, bus, event, this); 71de90fb4dSMatthew Barth 72de90fb4dSMatthew Barth // Load the fan configurations and move each fan into its zone 73*603ef164SMatthew Barth auto fans = getConfig<Fan>(false, bus, bus); 74de90fb4dSMatthew Barth for (auto& fan : fans) 75de90fb4dSMatthew Barth { 76de90fb4dSMatthew Barth auto itZone = 77de90fb4dSMatthew Barth std::find_if(_zones.begin(), _zones.end(), 78de90fb4dSMatthew Barth [&fanZone = fan.second->getZone()](const auto& zone) { 79de90fb4dSMatthew Barth return fanZone == zone.second->getName(); 80de90fb4dSMatthew Barth }); 81de90fb4dSMatthew Barth if (itZone != _zones.end()) 82de90fb4dSMatthew Barth { 83de90fb4dSMatthew Barth itZone->second->addFan(std::move(fan.second)); 84de90fb4dSMatthew Barth } 85de90fb4dSMatthew Barth } 86b584d818SMatthew Barth 87b584d818SMatthew Barth bus.request_name(CONTROL_BUSNAME); 8806764946SMatthew Barth } 89acd737cdSMatthew Barth 90acd737cdSMatthew Barth const std::vector<std::string>& Manager::getActiveProfiles() 91acd737cdSMatthew Barth { 92acd737cdSMatthew Barth return _activeProfiles; 93a227a16dSMatthew Barth } 94a227a16dSMatthew Barth 9512cb125aSMatthew Barth bool Manager::hasOwner(const std::string& path, const std::string& intf) 9612cb125aSMatthew Barth { 9712cb125aSMatthew Barth auto itServ = _servTree.find(path); 9812cb125aSMatthew Barth if (itServ == _servTree.end()) 9912cb125aSMatthew Barth { 10012cb125aSMatthew Barth // Path not found in cache, therefore owner missing 10112cb125aSMatthew Barth return false; 10212cb125aSMatthew Barth } 10312cb125aSMatthew Barth for (const auto& serv : itServ->second) 10412cb125aSMatthew Barth { 10512cb125aSMatthew Barth auto itIntf = std::find_if( 10612cb125aSMatthew Barth serv.second.begin(), serv.second.end(), 10712cb125aSMatthew Barth [&intf](const auto& interface) { return intf == interface; }); 10812cb125aSMatthew Barth if (itIntf != std::end(serv.second)) 10912cb125aSMatthew Barth { 11012cb125aSMatthew Barth // Service found, return owner state 11112cb125aSMatthew Barth return serv.first.second; 11212cb125aSMatthew Barth } 11312cb125aSMatthew Barth } 11412cb125aSMatthew Barth // Interface not found in cache, therefore owner missing 11512cb125aSMatthew Barth return false; 11612cb125aSMatthew Barth } 11712cb125aSMatthew Barth 118d9cb63b6SMatthew Barth void Manager::addTimer(const TimerType type, 119d9cb63b6SMatthew Barth const std::chrono::microseconds interval, 120d9cb63b6SMatthew Barth std::unique_ptr<TimerPkg> pkg) 121d9cb63b6SMatthew Barth { 122d9cb63b6SMatthew Barth auto dataPtr = 123d9cb63b6SMatthew Barth std::make_unique<TimerData>(std::make_pair(type, std::move(*pkg))); 124d9cb63b6SMatthew Barth Timer timer(_event, 125d9cb63b6SMatthew Barth std::bind(&Manager::timerExpired, this, std::ref(*dataPtr))); 126d9cb63b6SMatthew Barth if (type == TimerType::repeating) 127d9cb63b6SMatthew Barth { 128d9cb63b6SMatthew Barth timer.restart(interval); 129d9cb63b6SMatthew Barth } 130d9cb63b6SMatthew Barth else if (type == TimerType::oneshot) 131d9cb63b6SMatthew Barth { 132d9cb63b6SMatthew Barth timer.restartOnce(interval); 133d9cb63b6SMatthew Barth } 134d9cb63b6SMatthew Barth else 135d9cb63b6SMatthew Barth { 136d9cb63b6SMatthew Barth throw std::invalid_argument("Invalid Timer Type"); 137d9cb63b6SMatthew Barth } 138d9cb63b6SMatthew Barth _timers.emplace_back(std::move(dataPtr), std::move(timer)); 139d9cb63b6SMatthew Barth } 140d9cb63b6SMatthew Barth 141d9cb63b6SMatthew Barth void Manager::timerExpired(TimerData& data) 142d9cb63b6SMatthew Barth { 143d9cb63b6SMatthew Barth auto& actions = 144d9cb63b6SMatthew Barth std::get<std::vector<std::unique_ptr<ActionBase>>&>(data.second); 145d9cb63b6SMatthew Barth // Perform the actions in the timer data 146d9cb63b6SMatthew Barth std::for_each(actions.begin(), actions.end(), 147d9cb63b6SMatthew Barth [zone = std::ref(std::get<Zone&>(data.second)), 148d9cb63b6SMatthew Barth group = std::cref(std::get<const Group&>(data.second))]( 149d9cb63b6SMatthew Barth auto& action) { action->run(zone, group); }); 150d9cb63b6SMatthew Barth 151d9cb63b6SMatthew Barth // Remove oneshot timers after they expired 152d9cb63b6SMatthew Barth if (data.first == TimerType::oneshot) 153d9cb63b6SMatthew Barth { 154d9cb63b6SMatthew Barth auto itTimer = std::find_if( 155d9cb63b6SMatthew Barth _timers.begin(), _timers.end(), [&data](const auto& timer) { 156d9cb63b6SMatthew Barth return (data.first == timer.first->first && 157d9cb63b6SMatthew Barth (std::get<std::string>(data.second) == 158d9cb63b6SMatthew Barth std::get<std::string>(timer.first->second))); 159d9cb63b6SMatthew Barth }); 160d9cb63b6SMatthew Barth if (itTimer != std::end(_timers)) 161d9cb63b6SMatthew Barth { 162d9cb63b6SMatthew Barth _timers.erase(itTimer); 163d9cb63b6SMatthew Barth } 164d9cb63b6SMatthew Barth } 165d9cb63b6SMatthew Barth } 166d9cb63b6SMatthew Barth 167a227a16dSMatthew Barth unsigned int Manager::getPowerOnDelay() 168a227a16dSMatthew Barth { 169a227a16dSMatthew Barth auto powerOnDelay = 0; 170a227a16dSMatthew Barth 171a227a16dSMatthew Barth // Parse optional "power_on_delay" from JSON object 172a227a16dSMatthew Barth if (!_jsonObj.empty() && _jsonObj.contains("power_on_delay")) 173a227a16dSMatthew Barth { 174a227a16dSMatthew Barth powerOnDelay = _jsonObj["power_on_delay"].get<unsigned int>(); 175a227a16dSMatthew Barth } 176a227a16dSMatthew Barth 177a227a16dSMatthew Barth return powerOnDelay; 178a227a16dSMatthew Barth } 179a227a16dSMatthew Barth 180acd737cdSMatthew Barth void Manager::setProfiles() 181acd737cdSMatthew Barth { 182acd737cdSMatthew Barth // Profiles JSON config file is optional 183acd737cdSMatthew Barth auto confFile = fan::JsonConfig::getConfFile(_bus, confAppName, 184acd737cdSMatthew Barth Profile::confFileName, true); 185acd737cdSMatthew Barth if (!confFile.empty()) 186acd737cdSMatthew Barth { 187acd737cdSMatthew Barth for (const auto& entry : fan::JsonConfig::load(confFile)) 188acd737cdSMatthew Barth { 189acd737cdSMatthew Barth auto obj = std::make_unique<Profile>(entry); 190acd737cdSMatthew Barth _profiles.emplace( 191acd737cdSMatthew Barth std::make_pair(obj->getName(), obj->getProfiles()), 192acd737cdSMatthew Barth std::move(obj)); 193acd737cdSMatthew Barth } 194acd737cdSMatthew Barth } 195acd737cdSMatthew Barth // Ensure all configurations use the same set of active profiles 196acd737cdSMatthew Barth // (In case a profile's active state changes during configuration) 197acd737cdSMatthew Barth for (const auto& profile : _profiles) 198acd737cdSMatthew Barth { 199acd737cdSMatthew Barth if (profile.second->isActive()) 200acd737cdSMatthew Barth { 201acd737cdSMatthew Barth _activeProfiles.emplace_back(profile.first.first); 202acd737cdSMatthew Barth } 203acd737cdSMatthew Barth } 204acd737cdSMatthew Barth } 205acd737cdSMatthew Barth 206a227a16dSMatthew Barth } // namespace phosphor::fan::control::json 207