1 /** 2 * Copyright © 2021 IBM Corporation 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 #include "set_parameter_from_group_max.hpp" 17 18 #include "../manager.hpp" 19 20 #include <fmt/format.h> 21 22 namespace phosphor::fan::control::json 23 { 24 25 using json = nlohmann::json; 26 using namespace phosphor::logging; 27 28 SetParameterFromGroupMax::SetParameterFromGroupMax( 29 const json& jsonObj, const std::vector<Group>& groups) : 30 ActionBase(jsonObj, groups) 31 { 32 setParameterName(jsonObj); 33 setModifier(jsonObj); 34 } 35 36 void SetParameterFromGroupMax::run(Zone& /*zone*/) 37 { 38 std::optional<PropertyVariantType> max; 39 40 // Find the maximum value of all group member properties, possibly modify 41 // it, and then write it to the Manager as a parameter. 42 43 for (const auto& group : _groups) 44 { 45 const auto& members = group.getMembers(); 46 for (const auto& member : members) 47 { 48 PropertyVariantType value; 49 try 50 { 51 value = Manager::getObjValueVariant( 52 member, group.getInterface(), group.getProperty()); 53 } 54 catch (const std::out_of_range&) 55 { 56 continue; 57 } 58 59 // Only allow a group to have multiple members if it's 60 // numeric. Unlike with std::is_arithmetic, bools are not 61 // considered numeric here. 62 if (members.size() > 1) 63 { 64 bool invalid = false; 65 std::visit( 66 [&group, &invalid, this](auto&& val) { 67 using V = std::decay_t<decltype(val)>; 68 if constexpr (!std::is_same_v<double, V> && 69 !std::is_same_v<int32_t, V> && 70 !std::is_same_v<int64_t, V>) 71 { 72 log<level::ERR>(fmt::format("{}: Group {} has more " 73 "than one member but " 74 "isn't numeric", 75 ActionBase::getName(), 76 group.getName()) 77 .c_str()); 78 invalid = true; 79 } 80 }, 81 value); 82 if (invalid) 83 { 84 continue; 85 } 86 } 87 88 if (max && (value > max)) 89 { 90 max = value; 91 } 92 else if (!max) 93 { 94 max = value; 95 } 96 } 97 } 98 99 if (_modifier && max) 100 { 101 try 102 { 103 *max = _modifier->doOp(*max); 104 } 105 catch (const std::exception& e) 106 { 107 log<level::ERR>( 108 fmt::format("{}: Could not perform modifier operation: {}", 109 ActionBase::getName(), e.what()) 110 .c_str()); 111 return; 112 } 113 } 114 115 Manager::setParameter(_name, max); 116 } 117 118 void SetParameterFromGroupMax::setParameterName(const json& jsonObj) 119 { 120 if (!jsonObj.contains("parameter_name")) 121 { 122 throw ActionParseError{ActionBase::getName(), 123 "Missing required parameter_name value"}; 124 } 125 126 _name = jsonObj["parameter_name"].get<std::string>(); 127 } 128 129 void SetParameterFromGroupMax::setModifier(const json& jsonObj) 130 { 131 if (jsonObj.contains("modifier")) 132 { 133 try 134 { 135 _modifier = std::make_unique<Modifier>(jsonObj.at("modifier")); 136 } 137 catch (const std::invalid_argument& e) 138 { 139 throw ActionParseError{ActionBase::getName(), e.what()}; 140 } 141 } 142 } 143 144 }; // namespace phosphor::fan::control::json 145