xref: /openbmc/phosphor-fan-presence/control/json/actions/set_parameter_from_group_max.cpp (revision 64b5ac203518568ec8b7569d0e785352278f2472)
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 <phosphor-logging/lg2.hpp>
21 
22 namespace phosphor::fan::control::json
23 {
24 
25 using json = nlohmann::json;
26 
SetParameterFromGroupMax(const json & jsonObj,const std::vector<Group> & groups)27 SetParameterFromGroupMax::SetParameterFromGroupMax(
28     const json& jsonObj, const std::vector<Group>& groups) :
29     ActionBase(jsonObj, groups)
30 {
31     setParameterName(jsonObj);
32     setModifier(jsonObj);
33 }
34 
run(Zone &)35 void SetParameterFromGroupMax::run(Zone& /*zone*/)
36 {
37     std::optional<PropertyVariantType> max;
38 
39     // Find the maximum value of all group member properties, possibly modify
40     // it, and then write it to the Manager as a parameter.
41 
42     for (const auto& group : _groups)
43     {
44         const auto& members = group.getMembers();
45         for (const auto& member : members)
46         {
47             PropertyVariantType value;
48             try
49             {
50                 value = Manager::getObjValueVariant(
51                     member, group.getInterface(), group.getProperty());
52             }
53             catch (const std::out_of_range&)
54             {
55                 continue;
56             }
57 
58             // Only allow a group to have multiple members if it's
59             // numeric. Unlike with std::is_arithmetic, bools are not
60             // considered numeric here.
61             if (members.size() > 1)
62             {
63                 bool invalid = false;
64                 std::visit(
65                     [&group, &invalid, this](auto&& val) {
66                         using V = std::decay_t<decltype(val)>;
67                         if constexpr (!std::is_same_v<double, V> &&
68                                       !std::is_same_v<int32_t, V> &&
69                                       !std::is_same_v<int64_t, V>)
70                         {
71                             lg2::error(
72                                 "{ACTION_NAME}: Group {GROUP_NAME} has more "
73                                 "than one member but "
74                                 "isn't numeric",
75                                 "ACTION_NAME", ActionBase::getName(),
76                                 "GROUP_NAME", group.getName());
77                             invalid = true;
78                         }
79                     },
80                     value);
81                 if (invalid)
82                 {
83                     continue;
84                 }
85             }
86 
87             if (max && (value > max))
88             {
89                 max = value;
90             }
91             else if (!max)
92             {
93                 max = value;
94             }
95         }
96     }
97 
98     if (_modifier && max)
99     {
100         try
101         {
102             *max = _modifier->doOp(*max);
103         }
104         catch (const std::exception& e)
105         {
106             lg2::error(
107                 "{ACTION_NAME}: Could not perform modifier operation: {ERROR}",
108                 "ACTION_NAME", ActionBase::getName(), "ERROR", e);
109             return;
110         }
111     }
112 
113     Manager::setParameter(_name, max);
114 }
115 
setParameterName(const json & jsonObj)116 void SetParameterFromGroupMax::setParameterName(const json& jsonObj)
117 {
118     if (!jsonObj.contains("parameter_name"))
119     {
120         throw ActionParseError{ActionBase::getName(),
121                                "Missing required parameter_name value"};
122     }
123 
124     _name = jsonObj["parameter_name"].get<std::string>();
125 }
126 
setModifier(const json & jsonObj)127 void SetParameterFromGroupMax::setModifier(const json& jsonObj)
128 {
129     if (jsonObj.contains("modifier"))
130     {
131         try
132         {
133             _modifier = std::make_unique<Modifier>(jsonObj.at("modifier"));
134         }
135         catch (const std::invalid_argument& e)
136         {
137             throw ActionParseError{ActionBase::getName(), e.what()};
138         }
139     }
140 }
141 
142 }; // namespace phosphor::fan::control::json
143