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