1 #include "util.hpp"
2 
3 #include <cmath>
4 #include <cstdint>
5 #include <iostream>
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 
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 
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 
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.push_back(sensor);
86         }
87     }
88     return matches.size() > 0;
89 }
90 
91 std::string getSensorPath(const std::string& type, const std::string& id)
92 {
93     std::string layer;
94     if (type == "fan")
95     {
96         layer = "fan_tach";
97     }
98     else if (type == "temp")
99     {
100         layer = "temperature";
101     }
102     else if (type == "margin")
103     {
104         layer = "temperature";
105     }
106     else if (type == "power")
107     {
108         layer = "power";
109     }
110     else if (type == "powersum")
111     {
112         layer = "power";
113     }
114     else
115     {
116         layer = "unknown"; // TODO(venture): Need to handle.
117     }
118 
119     return std::string("/xyz/openbmc_project/sensors/" + layer + "/" + id);
120 }
121 
122 std::string getMatch(const std::string& path)
123 {
124     return std::string("type='signal',"
125                        "interface='org.freedesktop.DBus.Properties',"
126                        "member='PropertiesChanged',"
127                        "path='" +
128                        path + "'");
129 }
130 
131 bool validType(const std::string& type)
132 {
133     static std::set<std::string> valid = {"fan", "temp", "margin", "power",
134                                           "powersum"};
135     return (valid.find(type) != valid.end());
136 }
137 
138 void scaleSensorReading(const double min, const double max, double& value)
139 {
140     if (max <= 0 || max <= min)
141     {
142         return;
143     }
144     value -= min;
145     value /= (max - min);
146 }
147 
148 } // namespace pid_control
149