/** * 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 "zone.hpp" #include "../zone.hpp" #include "functor.hpp" #include "handlers.hpp" #include "types.hpp" #include #include #include #include #include #include #include #include namespace phosphor::fan::control::json { using json = nlohmann::json; using namespace phosphor::logging; const std::map> Zone::_intfPropHandlers = {{thermModeIntf, {{supportedProp, zone::property::supported}, {currentProp, zone::property::current}}}}; Zone::Zone(sdbusplus::bus::bus& bus, const json& jsonObj) : ConfigBase(jsonObj), _incDelay(0) { if (jsonObj.contains("profiles")) { for (const auto& profile : jsonObj["profiles"]) { _profiles.emplace_back(profile.get()); } } // Speed increase delay is optional, defaults to 0 if (jsonObj.contains("increase_delay")) { _incDelay = jsonObj["increase_delay"].get(); } setFullSpeed(jsonObj); setDefaultFloor(jsonObj); setDecInterval(jsonObj); // Setting properties on interfaces to be served are optional if (jsonObj.contains("interfaces")) { setInterfaces(jsonObj); } } void Zone::setFullSpeed(const json& jsonObj) { if (!jsonObj.contains("full_speed")) { log("Missing required zone's full speed", entry("JSON=%s", jsonObj.dump().c_str())); throw std::runtime_error("Missing required zone's full speed"); } _fullSpeed = jsonObj["full_speed"].get(); } void Zone::setDefaultFloor(const json& jsonObj) { if (!jsonObj.contains("default_floor")) { log("Missing required zone's default floor speed", entry("JSON=%s", jsonObj.dump().c_str())); throw std::runtime_error("Missing required zone's default floor speed"); } _defaultFloor = jsonObj["default_floor"].get(); } void Zone::setDecInterval(const json& jsonObj) { if (!jsonObj.contains("decrease_interval")) { log("Missing required zone's decrease interval", entry("JSON=%s", jsonObj.dump().c_str())); throw std::runtime_error("Missing required zone's decrease interval"); } _decInterval = jsonObj["decrease_interval"].get(); } void Zone::setInterfaces(const json& jsonObj) { for (const auto& interface : jsonObj["interfaces"]) { if (!interface.contains("name") || !interface.contains("properties")) { log("Missing required zone interface attributes", entry("JSON=%s", interface.dump().c_str())); throw std::runtime_error( "Missing required zone interface attributes"); } auto propFuncs = _intfPropHandlers.find(interface["name"].get()); if (propFuncs == _intfPropHandlers.end()) { // Construct list of available configurable interfaces auto intfs = std::accumulate( std::next(_intfPropHandlers.begin()), _intfPropHandlers.end(), _intfPropHandlers.begin()->first, [](auto list, auto intf) { return std::move(list) + ", " + intf.first; }); log("Configured interface not available", entry("JSON=%s", interface.dump().c_str()), entry("AVAILABLE_INTFS=%s", intfs.c_str())); throw std::runtime_error("Configured interface not available"); } for (const auto& property : interface["properties"]) { if (!property.contains("name")) { log( "Missing required interface property attributes", entry("JSON=%s", property.dump().c_str())); throw std::runtime_error( "Missing required interface property attributes"); } // Attribute "persist" is optional, defaults to `false` auto persist = false; if (property.contains("persist")) { persist = property["persist"].get(); } // Property name from JSON must exactly match supported // index names to functions in property namespace auto propFunc = propFuncs->second.find(property["name"].get()); if (propFunc == propFuncs->second.end()) { // Construct list of available configurable properties auto props = std::accumulate( std::next(propFuncs->second.begin()), propFuncs->second.end(), propFuncs->second.begin()->first, [](auto list, auto prop) { return std::move(list) + ", " + prop.first; }); log("Configured property not available", entry("JSON=%s", property.dump().c_str()), entry("AVAILABLE_PROPS=%s", props.c_str())); throw std::runtime_error( "Configured property function not available"); } auto zHandler = propFunc->second(property, persist); // Only add non-null zone handler functions if (zHandler) { _zoneHandlers.emplace_back(zHandler); } } } } /** * Properties of interfaces supported by the zone configuration that return * a ZoneHandler function that sets the zone's property value(s). */ namespace zone::property { // Get a zone handler function for the configured values of the "Supported" // property ZoneHandler supported(const json& jsonObj, bool persist) { std::vector values; if (!jsonObj.contains("values")) { log( "No 'values' found for \"Supported\" property, using an empty list", entry("JSON=%s", jsonObj.dump().c_str())); } else { for (const auto& value : jsonObj["values"]) { if (!value.contains("value")) { log("No 'value' found for \"Supported\" property " "entry, skipping", entry("JSON=%s", value.dump().c_str())); } else { values.emplace_back(value["value"].get()); } } } return make_zoneHandler(handler::setZoneProperty>( Zone::thermModeIntf, Zone::supportedProp, &control::Zone::supported, std::move(values), persist)); } // Get a zone handler function for a configured value of the "Current" // property ZoneHandler current(const json& jsonObj, bool persist) { // Use default value for "Current" property if no "value" entry given if (!jsonObj.contains("value")) { log("No 'value' found for \"Current\" property, " "using default", entry("JSON=%s", jsonObj.dump().c_str())); return {}; } return make_zoneHandler(handler::setZoneProperty( Zone::thermModeIntf, Zone::currentProp, &control::Zone::current, jsonObj["value"].get(), persist)); } } // namespace zone::property } // namespace phosphor::fan::control::json