blob: 12c2c99620cb857642e3074144867cf18e10e9f6 [file] [log] [blame]
/**
* Copyright © 2020 IBM Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "json_parser.hpp"
#include "json/event.hpp"
#include "json/fan.hpp"
#include "json/group.hpp"
#include "json/manager.hpp"
#include "json/profile.hpp"
#include "json/zone.hpp"
#include "types.hpp"
#include <sdbusplus/bus.hpp>
#include <algorithm>
#include <cstdlib>
#include <string>
#include <tuple>
#include <vector>
namespace phosphor::fan::control
{
bool checkEntry(const std::vector<std::string>& activeProfiles,
const std::vector<std::string>& entryProfiles)
{
// Include entry if its list of profiles to be included in is empty
if (entryProfiles.empty())
{
// Entry always to be included
return true;
}
else
{
for (const auto& profile : activeProfiles)
{
auto iter =
std::find(entryProfiles.begin(), entryProfiles.end(), profile);
if (iter != entryProfiles.end())
{
// Entry configured to be included in active profile
return true;
}
}
}
return false;
}
const std::vector<ZoneGroup> getZoneGroups(sdbusplus::bus::bus& bus)
{
std::vector<ZoneGroup> zoneGrps;
// Profiles are optional
auto profiles = getConfig<json::Profile>(true);
// Fans to be controlled
auto fans = getConfig<json::Fan>(bus);
// Zones within the system
auto zones = getConfig<json::Zone>(bus);
// Fan control events are optional
auto events = getConfig<json::Event>(bus, true);
// Ensure all configurations use the same set of active profiles
// (In case a profile's active state changes during configuration)
std::vector<std::string> activeProfiles;
for (const auto& profile : profiles)
{
if (profile.second->isActive())
{
activeProfiles.emplace_back(profile.first.first);
}
}
// Conditions list empty for JSON based configurations
// TODO Remove conditions after YAML based configuration removed
std::vector<Condition> conditions;
std::vector<ZoneDefinition> zoneDefs;
for (const auto& zone : zones)
{
// Check zone profiles against active profiles
if (checkEntry(activeProfiles, zone.second->getProfiles()))
{
auto zoneName = zone.second->getName();
// Create FanDefinition list for zone
std::vector<FanDefinition> fanDefs;
for (const auto& fan : fans)
{
// Check fan profiles against active profiles and
// if the fan is included in the zone
if (checkEntry(activeProfiles, fan.second->getProfiles()) &&
fan.second->getZone() == zoneName)
{
// Adjust fan object sensor list to be included in the
// YAML fan definitions structure
std::vector<std::string> fanSensorList;
for (const auto& sensorMap : fan.second->getSensors())
{
auto sensor = sensorMap.first;
sensor.erase(0, 38);
fanSensorList.emplace_back(sensor);
}
fanDefs.emplace_back(
std::make_tuple(fan.second->getName(), fanSensorList,
fan.second->getInterface()));
}
}
// Create SetSpeedEvents list for zone
std::vector<SetSpeedEvent> speedEvents;
// TODO Populate SetSpeedEvents list with configured events
// YAML zone name was an integer, JSON is a string
// Design direction is for it to be a string and this can be
// removed after YAML based configurations are removed.
char* zoneName_end;
auto zoneNum = std::strtol(zoneName.c_str(), &zoneName_end, 10);
if (*zoneName_end)
{
throw std::runtime_error(
"Zone names must be a string representation of a number");
}
zoneDefs.emplace_back(std::make_tuple(
zoneNum, zone.second->getDefaultCeiling(),
zone.second->getDefaultFloor(), zone.second->getIncDelay(),
zone.second->getDecInterval(), std::vector<ZoneHandler>{},
std::move(fanDefs), std::move(speedEvents)));
}
}
// TODO Should only result in a single entry but YAML based configurations
// produce a list of zone groups. Change to single zone group after YAML
// based configuartions are removed.
zoneGrps.emplace_back(std::make_tuple(conditions, zoneDefs));
return zoneGrps;
}
const unsigned int getPowerOnDelay(sdbusplus::bus::bus& bus,
const sdeventplus::Event& event)
{
json::Manager mgr{bus, event};
return mgr.getPowerOnDelay();
}
} // namespace phosphor::fan::control