xref: /openbmc/phosphor-pid-control/util.cpp (revision 3f0f7bc3)
1 /*
2 // Copyright (c) 2018 Intel 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 "util.hpp"
17 
18 #include "conf.hpp"
19 
20 #include <cstdint>
21 #include <iostream>
22 #include <map>
23 #include <string>
24 
25 namespace pid_control
26 {
27 
debugPrint(const std::map<std::string,conf::SensorConfig> & sensorConfig,const std::map<int64_t,conf::PIDConf> & zoneConfig,const std::map<int64_t,conf::ZoneConfig> & zoneDetailsConfig)28 void debugPrint(const std::map<std::string, conf::SensorConfig>& sensorConfig,
29                 const std::map<int64_t, conf::PIDConf>& zoneConfig,
30                 const std::map<int64_t, conf::ZoneConfig>& zoneDetailsConfig)
31 {
32     if constexpr (!conf::DEBUG)
33     {
34         return;
35     }
36     // print sensor config
37     std::cout << "sensor config:\n";
38     std::cout << "{\n";
39     for (const auto& pair : sensorConfig)
40     {
41         std::cout << "\t{" << pair.first << ",\n\t\t{";
42         std::cout << pair.second.type << ", ";
43         std::cout << pair.second.readPath << ", ";
44         std::cout << pair.second.writePath << ", ";
45         std::cout << pair.second.min << ", ";
46         std::cout << pair.second.max << ", ";
47         std::cout << pair.second.timeout << ", ";
48         std::cout << pair.second.unavailableAsFailed << "},\n\t},\n";
49     }
50     std::cout << "}\n\n";
51     std::cout << "ZoneDetailsConfig\n";
52     std::cout << "{\n";
53     for (const auto& zone : zoneDetailsConfig)
54     {
55         std::cout << "\t{" << zone.first << ",\n";
56         std::cout << "\t\t{" << zone.second.minThermalOutput << ", ";
57         std::cout << zone.second.failsafePercent << "}\n\t},\n";
58     }
59     std::cout << "}\n\n";
60     std::cout << "ZoneConfig\n";
61     std::cout << "{\n";
62     for (const auto& zone : zoneConfig)
63     {
64         std::cout << "\t{" << zone.first << "\n";
65         for (const auto& pidconf : zone.second)
66         {
67             std::cout << "\t\t{" << pidconf.first << ",\n";
68             std::cout << "\t\t\t{" << pidconf.second.type << ",\n";
69             std::cout << "\t\t\t{";
70             for (const auto& input : pidconf.second.inputs)
71             {
72                 std::cout << "\n\t\t\t" << input.name;
73                 if (input.convertTempToMargin)
74                 {
75                     std::cout << "[" << input.convertMarginZero << "]";
76                 }
77                 std::cout << ",\n";
78             }
79             std::cout << "\t\t\t}\n";
80             std::cout << "\t\t\t" << pidconf.second.setpoint << ",\n";
81             std::cout << "\t\t\t{" << pidconf.second.pidInfo.ts << ",\n";
82             std::cout << "\t\t\t" << pidconf.second.pidInfo.proportionalCoeff
83                       << ",\n";
84             std::cout << "\t\t\t" << pidconf.second.pidInfo.integralCoeff
85                       << ",\n";
86             std::cout << "\t\t\t" << pidconf.second.pidInfo.feedFwdOffset
87                       << ",\n";
88             std::cout << "\t\t\t" << pidconf.second.pidInfo.feedFwdGain
89                       << ",\n";
90             std::cout << "\t\t\t{" << pidconf.second.pidInfo.integralLimit.min
91                       << "," << pidconf.second.pidInfo.integralLimit.max
92                       << "},\n";
93             std::cout << "\t\t\t{" << pidconf.second.pidInfo.outLim.min << ","
94                       << pidconf.second.pidInfo.outLim.max << "},\n";
95             std::cout << "\t\t\t" << pidconf.second.pidInfo.slewNeg << ",\n";
96             std::cout << "\t\t\t" << pidconf.second.pidInfo.slewPos << ",\n";
97             std::cout << "\t\t\t}\n\t\t}\n";
98         }
99         std::cout << "\t},\n";
100     }
101     std::cout << "}\n\n";
102 }
103 
104 std::vector<conf::SensorInput>
spliceInputs(const std::vector<std::string> & inputNames,const std::vector<double> & inputTempToMargin,const std::vector<std::string> & missingAcceptableNames)105     spliceInputs(const std::vector<std::string>& inputNames,
106                  const std::vector<double>& inputTempToMargin,
107                  const std::vector<std::string>& missingAcceptableNames)
108 {
109     std::vector<conf::SensorInput> results;
110 
111     // Default to TempToMargin and MissingIsAcceptable disabled
112     for (const auto& inputName : inputNames)
113     {
114         conf::SensorInput newInput{
115             inputName, std::numeric_limits<double>::quiet_NaN(), false, false};
116 
117         results.emplace_back(newInput);
118     }
119 
120     size_t resultSize = results.size();
121     size_t marginSize = inputTempToMargin.size();
122 
123     for (size_t index = 0; index < resultSize; ++index)
124     {
125         // If fewer doubles than strings, and vice versa, ignore remainder
126         if (index >= marginSize)
127         {
128             break;
129         }
130 
131         // Both vectors have this index, combine both into SensorInput
132         results[index].convertMarginZero = inputTempToMargin[index];
133         results[index].convertTempToMargin = true;
134     }
135 
136     std::set<std::string> acceptableSet;
137 
138     // Copy vector to set, to avoid O(n^2) runtime below
139     for (const auto& name : missingAcceptableNames)
140     {
141         acceptableSet.emplace(name);
142     }
143 
144     // Flag missingIsAcceptable true if name found in that set
145     for (auto& result : results)
146     {
147         if (acceptableSet.find(result.name) != acceptableSet.end())
148         {
149             result.missingIsAcceptable = true;
150         }
151     }
152 
153     return results;
154 }
155 
156 std::vector<std::string>
splitNames(const std::vector<conf::SensorInput> & sensorInputs)157     splitNames(const std::vector<conf::SensorInput>& sensorInputs)
158 {
159     std::vector<std::string> results;
160 
161     for (const auto& sensorInput : sensorInputs)
162     {
163         results.emplace_back(sensorInput.name);
164     }
165 
166     return results;
167 }
168 
169 } // namespace pid_control
170