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 
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 
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 
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 
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 
124 std::string getMatch(const std::string& path)
125 {
126     return sdbusplus::bus::match::rules::propertiesChangedNamespace(
127         path, "xyz.openbmc_project");
128 }
129 
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 
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