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