1
2 #include <sdbusplus/bus/match.hpp>
3
4 #include <cmath>
5 #include <cstdint>
6 #include <map>
7 #include <regex>
8 #include <set>
9 #include <string>
10 #include <unordered_map>
11 #include <utility>
12 #include <variant>
13 #include <vector>
14
15 using Property = std::string;
16 using Value = std::variant<int64_t, double, std::string, bool>;
17 using PropertyMap = std::map<Property, Value>;
18
19 namespace pid_control
20 {
21
setZoneIndex(const std::string & name,std::map<std::string,int64_t> & zones,int64_t index)22 int64_t setZoneIndex(const std::string& name,
23 std::map<std::string, int64_t>& zones, int64_t index)
24 {
25 auto it = zones.find(name);
26 if (it != zones.end())
27 {
28 // Name already allocated, make no change, return existing
29 return it->second;
30 }
31
32 // The zone name is known not to exist yet
33 for (;;)
34 {
35 bool usedIndex = false;
36
37 // See if desired index number is free
38 for (const auto& zi : zones)
39 {
40 if (index == zi.second)
41 {
42 usedIndex = true;
43 break;
44 }
45 }
46
47 // Increment until a free index number is found
48 if (usedIndex)
49 {
50 ++index;
51 continue;
52 }
53
54 break;
55 }
56
57 // Allocate and return new zone index number for this name
58 zones[name] = index;
59 return index;
60 }
61
getZoneIndex(const std::string & name,std::map<std::string,int64_t> & zones)62 int64_t getZoneIndex(const std::string& name,
63 std::map<std::string, int64_t>& zones)
64 {
65 auto it = zones.find(name);
66 if (it != zones.end())
67 {
68 return it->second;
69 }
70
71 // Auto-assign next unused zone number, using 0-based numbering
72 return setZoneIndex(name, zones, 0);
73 }
74
findSensors(const std::unordered_map<std::string,std::string> & sensors,const std::string & search,std::vector<std::pair<std::string,std::string>> & matches)75 bool findSensors(const std::unordered_map<std::string, std::string>& sensors,
76 const std::string& search,
77 std::vector<std::pair<std::string, std::string>>& matches)
78 {
79 std::smatch match;
80 std::regex reg('/' + search + '$');
81 for (const auto& sensor : sensors)
82 {
83 if (std::regex_search(sensor.first, match, reg))
84 {
85 matches.emplace_back(sensor);
86 }
87 }
88 return matches.size() > 0;
89 }
90
getSensorUnit(const std::string & type)91 std::string getSensorUnit(const std::string& type)
92 {
93 std::string unit;
94 if (type == "fan")
95 {
96 unit = "xyz.openbmc_project.Sensor.Value.Unit.RPMS";
97 }
98 else if (type == "temp" || type == "margin")
99 {
100 unit = "xyz.openbmc_project.Sensor.Value.Unit.DegreesC";
101 }
102 else if (type == "power" || type == "powersum")
103 {
104 unit = "xyz.openbmc_project.Sensor.Value.Unit.Watts";
105 }
106 else
107 {
108 unit = "unknown";
109 }
110 return unit;
111 }
112
getSensorPath(const std::string & type,const std::string & id)113 std::string getSensorPath(const std::string& type, const std::string& id)
114 {
115 std::string layer;
116 if (type == "fan")
117 {
118 layer = "fan_tach";
119 }
120 else if (type == "temp")
121 {
122 layer = "temperature";
123 }
124 else if (type == "margin")
125 {
126 layer = "temperature";
127 }
128 else if (type == "power")
129 {
130 layer = "power";
131 }
132 else if (type == "powersum")
133 {
134 layer = "power";
135 }
136 else
137 {
138 layer = "unknown"; // TODO(venture): Need to handle.
139 }
140
141 return std::string("/xyz/openbmc_project/sensors/" + layer + "/" + id);
142 }
143
getMatch(const std::string & path)144 std::string getMatch(const std::string& path)
145 {
146 return sdbusplus::bus::match::rules::propertiesChangedNamespace(
147 path, "xyz.openbmc_project");
148 }
149
validType(const std::string & type)150 bool validType(const std::string& type)
151 {
152 static std::set<std::string> valid = {"fan", "temp", "margin", "power",
153 "powersum"};
154 return (valid.find(type) != valid.end());
155 }
156
scaleSensorReading(const double min,const double max,double & value)157 void scaleSensorReading(const double min, const double max, double& value)
158 {
159 if (max <= 0 || max <= min)
160 {
161 return;
162 }
163 value -= min;
164 value /= (max - min);
165 }
166
167 } // namespace pid_control
168