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