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 getSensorUnit(const std::string& type) 94 { 95 std::string unit; 96 if (type == "fan") 97 { 98 unit = "xyz.openbmc_project.Sensor.Value.Unit.RPMS"; 99 } 100 else if (type == "temp" || type == "margin") 101 { 102 unit = "xyz.openbmc_project.Sensor.Value.Unit.DegreesC"; 103 } 104 else if (type == "power" || type == "powersum") 105 { 106 unit = "xyz.openbmc_project.Sensor.Value.Unit.Watts"; 107 } 108 else 109 { 110 unit = "unknown"; 111 } 112 return unit; 113 } 114 115 std::string getSensorPath(const std::string& type, const std::string& id) 116 { 117 std::string layer; 118 if (type == "fan") 119 { 120 layer = "fan_tach"; 121 } 122 else if (type == "temp") 123 { 124 layer = "temperature"; 125 } 126 else if (type == "margin") 127 { 128 layer = "temperature"; 129 } 130 else if (type == "power") 131 { 132 layer = "power"; 133 } 134 else if (type == "powersum") 135 { 136 layer = "power"; 137 } 138 else 139 { 140 layer = "unknown"; // TODO(venture): Need to handle. 141 } 142 143 return std::string("/xyz/openbmc_project/sensors/" + layer + "/" + id); 144 } 145 146 std::string getMatch(const std::string& path) 147 { 148 return sdbusplus::bus::match::rules::propertiesChangedNamespace( 149 path, "xyz.openbmc_project"); 150 } 151 152 bool validType(const std::string& type) 153 { 154 static std::set<std::string> valid = {"fan", "temp", "margin", "power", 155 "powersum"}; 156 return (valid.find(type) != valid.end()); 157 } 158 159 void scaleSensorReading(const double min, const double max, double& value) 160 { 161 if (max <= 0 || max <= min) 162 { 163 return; 164 } 165 value -= min; 166 value /= (max - min); 167 } 168 169 } // namespace pid_control 170