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 */ 16a227a16dSMatthew Barth #include "manager.hpp" 17a227a16dSMatthew Barth 18de90fb4dSMatthew Barth #include "fan.hpp" 19a227a16dSMatthew Barth #include "json_config.hpp" 2006764946SMatthew Barth #include "profile.hpp" 21acd737cdSMatthew Barth #include "zone.hpp" 22a227a16dSMatthew Barth 23acd737cdSMatthew Barth #include <nlohmann/json.hpp> 24a227a16dSMatthew Barth #include <sdbusplus/bus.hpp> 25acd737cdSMatthew Barth #include <sdeventplus/event.hpp> 26a227a16dSMatthew Barth 27de90fb4dSMatthew Barth #include <algorithm> 28a227a16dSMatthew Barth #include <filesystem> 2906764946SMatthew Barth #include <vector> 30a227a16dSMatthew Barth 31a227a16dSMatthew Barth namespace phosphor::fan::control::json 32a227a16dSMatthew Barth { 33a227a16dSMatthew Barth 34acd737cdSMatthew Barth using json = nlohmann::json; 35acd737cdSMatthew Barth 36acd737cdSMatthew Barth std::vector<std::string> Manager::_activeProfiles; 37*12cb125aSMatthew Barth std::map<std::string, 38*12cb125aSMatthew Barth std::map<std::pair<std::string, bool>, std::vector<std::string>>> 39*12cb125aSMatthew Barth Manager::_servTree; 40acd737cdSMatthew Barth 4106764946SMatthew Barth Manager::Manager(sdbusplus::bus::bus& bus, const sdeventplus::Event& event) : 42acd737cdSMatthew Barth _bus(bus), _event(event) 43a227a16dSMatthew Barth { 44a227a16dSMatthew Barth // Manager JSON config file is optional 45a227a16dSMatthew Barth auto confFile = 46a227a16dSMatthew Barth fan::JsonConfig::getConfFile(bus, confAppName, confFileName, true); 47a227a16dSMatthew Barth if (!confFile.empty()) 48a227a16dSMatthew Barth { 49a227a16dSMatthew Barth _jsonObj = fan::JsonConfig::load(confFile); 50a227a16dSMatthew Barth } 5106764946SMatthew Barth 52acd737cdSMatthew Barth // Parse and set the available profiles and which are active 53acd737cdSMatthew Barth setProfiles(); 54acd737cdSMatthew Barth 55acd737cdSMatthew Barth // Load the zone configurations 56acd737cdSMatthew Barth _zones = getConfig<Zone>(bus); 57de90fb4dSMatthew Barth 58de90fb4dSMatthew Barth // Load the fan configurations and move each fan into its zone 59de90fb4dSMatthew Barth auto fans = getConfig<Fan>(bus); 60de90fb4dSMatthew Barth for (auto& fan : fans) 61de90fb4dSMatthew Barth { 62de90fb4dSMatthew Barth auto itZone = 63de90fb4dSMatthew Barth std::find_if(_zones.begin(), _zones.end(), 64de90fb4dSMatthew Barth [&fanZone = fan.second->getZone()](const auto& zone) { 65de90fb4dSMatthew Barth return fanZone == zone.second->getName(); 66de90fb4dSMatthew Barth }); 67de90fb4dSMatthew Barth if (itZone != _zones.end()) 68de90fb4dSMatthew Barth { 69de90fb4dSMatthew Barth itZone->second->addFan(std::move(fan.second)); 70de90fb4dSMatthew Barth } 71de90fb4dSMatthew Barth } 7206764946SMatthew Barth } 73acd737cdSMatthew Barth 74acd737cdSMatthew Barth const std::vector<std::string>& Manager::getActiveProfiles() 75acd737cdSMatthew Barth { 76acd737cdSMatthew Barth return _activeProfiles; 77a227a16dSMatthew Barth } 78a227a16dSMatthew Barth 79*12cb125aSMatthew Barth bool Manager::hasOwner(const std::string& path, const std::string& intf) 80*12cb125aSMatthew Barth { 81*12cb125aSMatthew Barth auto itServ = _servTree.find(path); 82*12cb125aSMatthew Barth if (itServ == _servTree.end()) 83*12cb125aSMatthew Barth { 84*12cb125aSMatthew Barth // Path not found in cache, therefore owner missing 85*12cb125aSMatthew Barth return false; 86*12cb125aSMatthew Barth } 87*12cb125aSMatthew Barth for (const auto& serv : itServ->second) 88*12cb125aSMatthew Barth { 89*12cb125aSMatthew Barth auto itIntf = std::find_if( 90*12cb125aSMatthew Barth serv.second.begin(), serv.second.end(), 91*12cb125aSMatthew Barth [&intf](const auto& interface) { return intf == interface; }); 92*12cb125aSMatthew Barth if (itIntf != std::end(serv.second)) 93*12cb125aSMatthew Barth { 94*12cb125aSMatthew Barth // Service found, return owner state 95*12cb125aSMatthew Barth return serv.first.second; 96*12cb125aSMatthew Barth } 97*12cb125aSMatthew Barth } 98*12cb125aSMatthew Barth // Interface not found in cache, therefore owner missing 99*12cb125aSMatthew Barth return false; 100*12cb125aSMatthew Barth } 101*12cb125aSMatthew Barth 102a227a16dSMatthew Barth unsigned int Manager::getPowerOnDelay() 103a227a16dSMatthew Barth { 104a227a16dSMatthew Barth auto powerOnDelay = 0; 105a227a16dSMatthew Barth 106a227a16dSMatthew Barth // Parse optional "power_on_delay" from JSON object 107a227a16dSMatthew Barth if (!_jsonObj.empty() && _jsonObj.contains("power_on_delay")) 108a227a16dSMatthew Barth { 109a227a16dSMatthew Barth powerOnDelay = _jsonObj["power_on_delay"].get<unsigned int>(); 110a227a16dSMatthew Barth } 111a227a16dSMatthew Barth 112a227a16dSMatthew Barth return powerOnDelay; 113a227a16dSMatthew Barth } 114a227a16dSMatthew Barth 115acd737cdSMatthew Barth void Manager::setProfiles() 116acd737cdSMatthew Barth { 117acd737cdSMatthew Barth // Profiles JSON config file is optional 118acd737cdSMatthew Barth auto confFile = fan::JsonConfig::getConfFile(_bus, confAppName, 119acd737cdSMatthew Barth Profile::confFileName, true); 120acd737cdSMatthew Barth if (!confFile.empty()) 121acd737cdSMatthew Barth { 122acd737cdSMatthew Barth for (const auto& entry : fan::JsonConfig::load(confFile)) 123acd737cdSMatthew Barth { 124acd737cdSMatthew Barth auto obj = std::make_unique<Profile>(entry); 125acd737cdSMatthew Barth _profiles.emplace( 126acd737cdSMatthew Barth std::make_pair(obj->getName(), obj->getProfiles()), 127acd737cdSMatthew Barth std::move(obj)); 128acd737cdSMatthew Barth } 129acd737cdSMatthew Barth } 130acd737cdSMatthew Barth // Ensure all configurations use the same set of active profiles 131acd737cdSMatthew Barth // (In case a profile's active state changes during configuration) 132acd737cdSMatthew Barth for (const auto& profile : _profiles) 133acd737cdSMatthew Barth { 134acd737cdSMatthew Barth if (profile.second->isActive()) 135acd737cdSMatthew Barth { 136acd737cdSMatthew Barth _activeProfiles.emplace_back(profile.first.first); 137acd737cdSMatthew Barth } 138acd737cdSMatthew Barth } 139acd737cdSMatthew Barth } 140acd737cdSMatthew Barth 141a227a16dSMatthew Barth } // namespace phosphor::fan::control::json 142