181bc880dSMatt Spinler /**
281bc880dSMatt Spinler * Copyright © 2021 IBM Corporation
381bc880dSMatt Spinler *
481bc880dSMatt Spinler * Licensed under the Apache License, Version 2.0 (the "License");
581bc880dSMatt Spinler * you may not use this file except in compliance with the License.
681bc880dSMatt Spinler * You may obtain a copy of the License at
781bc880dSMatt Spinler *
881bc880dSMatt Spinler * http://www.apache.org/licenses/LICENSE-2.0
981bc880dSMatt Spinler *
1081bc880dSMatt Spinler * Unless required by applicable law or agreed to in writing, software
1181bc880dSMatt Spinler * distributed under the License is distributed on an "AS IS" BASIS,
1281bc880dSMatt Spinler * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1381bc880dSMatt Spinler * See the License for the specific language governing permissions and
1481bc880dSMatt Spinler * limitations under the License.
1581bc880dSMatt Spinler */
1681bc880dSMatt Spinler #include "set_parameter_from_group_max.hpp"
1781bc880dSMatt Spinler
1881bc880dSMatt Spinler #include "../manager.hpp"
1981bc880dSMatt Spinler
20*fbf4703fSPatrick Williams #include <format>
2181bc880dSMatt Spinler
2281bc880dSMatt Spinler namespace phosphor::fan::control::json
2381bc880dSMatt Spinler {
2481bc880dSMatt Spinler
2581bc880dSMatt Spinler using json = nlohmann::json;
2681bc880dSMatt Spinler using namespace phosphor::logging;
2781bc880dSMatt Spinler
SetParameterFromGroupMax(const json & jsonObj,const std::vector<Group> & groups)2881bc880dSMatt Spinler SetParameterFromGroupMax::SetParameterFromGroupMax(
2981bc880dSMatt Spinler const json& jsonObj, const std::vector<Group>& groups) :
3081bc880dSMatt Spinler ActionBase(jsonObj, groups)
3181bc880dSMatt Spinler {
3281bc880dSMatt Spinler setParameterName(jsonObj);
3381bc880dSMatt Spinler setModifier(jsonObj);
3481bc880dSMatt Spinler }
3581bc880dSMatt Spinler
run(Zone &)36b2e9a4fcSMike Capps void SetParameterFromGroupMax::run(Zone& /*zone*/)
3781bc880dSMatt Spinler {
3881bc880dSMatt Spinler std::optional<PropertyVariantType> max;
3981bc880dSMatt Spinler
4081bc880dSMatt Spinler // Find the maximum value of all group member properties, possibly modify
4181bc880dSMatt Spinler // it, and then write it to the Manager as a parameter.
4281bc880dSMatt Spinler
4381bc880dSMatt Spinler for (const auto& group : _groups)
4481bc880dSMatt Spinler {
4581bc880dSMatt Spinler const auto& members = group.getMembers();
4681bc880dSMatt Spinler for (const auto& member : members)
4781bc880dSMatt Spinler {
4881bc880dSMatt Spinler PropertyVariantType value;
4981bc880dSMatt Spinler try
5081bc880dSMatt Spinler {
5181bc880dSMatt Spinler value = Manager::getObjValueVariant(
5281bc880dSMatt Spinler member, group.getInterface(), group.getProperty());
5381bc880dSMatt Spinler }
5481bc880dSMatt Spinler catch (const std::out_of_range&)
5581bc880dSMatt Spinler {
5681bc880dSMatt Spinler continue;
5781bc880dSMatt Spinler }
5881bc880dSMatt Spinler
5981bc880dSMatt Spinler // Only allow a group to have multiple members if it's
6081bc880dSMatt Spinler // numeric. Unlike with std::is_arithmetic, bools are not
6181bc880dSMatt Spinler // considered numeric here.
6281bc880dSMatt Spinler if (members.size() > 1)
6381bc880dSMatt Spinler {
6481bc880dSMatt Spinler bool invalid = false;
6581bc880dSMatt Spinler std::visit(
6681bc880dSMatt Spinler [&group, &invalid, this](auto&& val) {
6781bc880dSMatt Spinler using V = std::decay_t<decltype(val)>;
6881bc880dSMatt Spinler if constexpr (!std::is_same_v<double, V> &&
6981bc880dSMatt Spinler !std::is_same_v<int32_t, V> &&
7081bc880dSMatt Spinler !std::is_same_v<int64_t, V>)
7181bc880dSMatt Spinler {
72*fbf4703fSPatrick Williams log<level::ERR>(std::format("{}: Group {} has more "
7381bc880dSMatt Spinler "than one member but "
7481bc880dSMatt Spinler "isn't numeric",
7581bc880dSMatt Spinler ActionBase::getName(),
7681bc880dSMatt Spinler group.getName())
7781bc880dSMatt Spinler .c_str());
7881bc880dSMatt Spinler invalid = true;
7981bc880dSMatt Spinler }
8081bc880dSMatt Spinler },
8181bc880dSMatt Spinler value);
8281bc880dSMatt Spinler if (invalid)
8381bc880dSMatt Spinler {
8481bc880dSMatt Spinler continue;
8581bc880dSMatt Spinler }
8681bc880dSMatt Spinler }
8781bc880dSMatt Spinler
8881bc880dSMatt Spinler if (max && (value > max))
8981bc880dSMatt Spinler {
9081bc880dSMatt Spinler max = value;
9181bc880dSMatt Spinler }
9281bc880dSMatt Spinler else if (!max)
9381bc880dSMatt Spinler {
9481bc880dSMatt Spinler max = value;
9581bc880dSMatt Spinler }
9681bc880dSMatt Spinler }
9781bc880dSMatt Spinler }
9881bc880dSMatt Spinler
9968a025f8SMatt Spinler if (_modifier && max)
10081bc880dSMatt Spinler {
10181bc880dSMatt Spinler try
10281bc880dSMatt Spinler {
10381bc880dSMatt Spinler *max = _modifier->doOp(*max);
10481bc880dSMatt Spinler }
10581bc880dSMatt Spinler catch (const std::exception& e)
10681bc880dSMatt Spinler {
10781bc880dSMatt Spinler log<level::ERR>(
108*fbf4703fSPatrick Williams std::format("{}: Could not perform modifier operation: {}",
10981bc880dSMatt Spinler ActionBase::getName(), e.what())
11081bc880dSMatt Spinler .c_str());
11181bc880dSMatt Spinler return;
11281bc880dSMatt Spinler }
11381bc880dSMatt Spinler }
11481bc880dSMatt Spinler
11572c4af43SMatt Spinler Manager::setParameter(_name, max);
11668a025f8SMatt Spinler }
11781bc880dSMatt Spinler
setParameterName(const json & jsonObj)11881bc880dSMatt Spinler void SetParameterFromGroupMax::setParameterName(const json& jsonObj)
11981bc880dSMatt Spinler {
12081bc880dSMatt Spinler if (!jsonObj.contains("parameter_name"))
12181bc880dSMatt Spinler {
12281bc880dSMatt Spinler throw ActionParseError{ActionBase::getName(),
12381bc880dSMatt Spinler "Missing required parameter_name value"};
12481bc880dSMatt Spinler }
12581bc880dSMatt Spinler
12681bc880dSMatt Spinler _name = jsonObj["parameter_name"].get<std::string>();
12781bc880dSMatt Spinler }
12881bc880dSMatt Spinler
setModifier(const json & jsonObj)12981bc880dSMatt Spinler void SetParameterFromGroupMax::setModifier(const json& jsonObj)
13081bc880dSMatt Spinler {
13181bc880dSMatt Spinler if (jsonObj.contains("modifier"))
13281bc880dSMatt Spinler {
13381bc880dSMatt Spinler try
13481bc880dSMatt Spinler {
13581bc880dSMatt Spinler _modifier = std::make_unique<Modifier>(jsonObj.at("modifier"));
13681bc880dSMatt Spinler }
13781bc880dSMatt Spinler catch (const std::invalid_argument& e)
13881bc880dSMatt Spinler {
13981bc880dSMatt Spinler throw ActionParseError{ActionBase::getName(), e.what()};
14081bc880dSMatt Spinler }
14181bc880dSMatt Spinler }
14281bc880dSMatt Spinler }
14381bc880dSMatt Spinler
14481bc880dSMatt Spinler }; // namespace phosphor::fan::control::json
145