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 <format>
21
22 namespace phosphor::fan::control::json
23 {
24
25 using json = nlohmann::json;
26 using namespace phosphor::logging;
27
SetParameterFromGroupMax(const json & jsonObj,const std::vector<Group> & groups)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
run(Zone &)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>(std::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 std::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
setParameterName(const json & jsonObj)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
setModifier(const json & jsonObj)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