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 = type; 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 107 { 108 layer = "unknown"; // TODO(venture): Need to handle. 109 } 110 111 return std::string("/xyz/openbmc_project/sensors/" + layer + "/" + id); 112 } 113 114 std::string getMatch(const std::string& type, const std::string& id) 115 { 116 return std::string("type='signal'," 117 "interface='org.freedesktop.DBus.Properties'," 118 "member='PropertiesChanged'," 119 "path='" + 120 getSensorPath(type, id) + "'"); 121 } 122 123 bool validType(const std::string& type) 124 { 125 static std::set<std::string> valid = {"fan", "temp", "margin"}; 126 return (valid.find(type) != valid.end()); 127 } 128 129 void scaleSensorReading(const double min, const double max, double& value) 130 { 131 if (max <= 0 || max <= min) 132 { 133 return; 134 } 135 value -= min; 136 value /= (max - min); 137 } 138 139 } // namespace pid_control 140