blob: a464458c123568531f6d5c4568f8721e51b64e58 [file] [log] [blame]
James Feist0c8223b2019-05-08 15:33:33 -07001#include "util.hpp"
Patrick Ventureda4a5dd2018-08-31 09:42:48 -07002
Patrick Venturea83a3ec2020-08-04 09:52:05 -07003#include <phosphor-logging/log.hpp>
4
James Feist36b7d8e2018-10-05 15:39:01 -07005#include <cmath>
Patrick Venture863b9242018-03-08 08:29:23 -08006#include <iostream>
Patrick Venture0ef1faf2018-06-13 12:50:53 -07007#include <set>
James Feist1f802f52019-02-08 13:51:43 -08008#include <variant>
Patrick Venture863b9242018-03-08 08:29:23 -08009
Patrick Venture863b9242018-03-08 08:29:23 -080010using Property = std::string;
James Feist1f802f52019-02-08 13:51:43 -080011using Value = std::variant<int64_t, double, std::string, bool>;
Patrick Venture863b9242018-03-08 08:29:23 -080012using PropertyMap = std::map<Property, Value>;
13
Patrick Venturea0764872020-08-08 07:48:43 -070014namespace pid_control
15{
16
Patrick Venture34ddc902018-10-30 11:05:17 -070017using namespace phosphor::logging;
18
Patrick Venture863b9242018-03-08 08:29:23 -080019/* TODO(venture): Basically all phosphor apps need this, maybe it should be a
20 * part of sdbusplus. There is an old version in libmapper.
21 */
Patrick Venture563a3562018-10-30 09:31:26 -070022std::string DbusHelper::getService(sdbusplus::bus::bus& bus,
Patrick Venture0df7c0f2018-06-13 09:02:13 -070023 const std::string& intf,
24 const std::string& path)
Patrick Venture863b9242018-03-08 08:29:23 -080025{
Patrick Ventureda4a5dd2018-08-31 09:42:48 -070026 auto mapper =
27 bus.new_method_call("xyz.openbmc_project.ObjectMapper",
28 "/xyz/openbmc_project/object_mapper",
29 "xyz.openbmc_project.ObjectMapper", "GetObject");
Patrick Venture863b9242018-03-08 08:29:23 -080030
31 mapper.append(path);
32 mapper.append(std::vector<std::string>({intf}));
33
Patrick Venture863b9242018-03-08 08:29:23 -080034 std::map<std::string, std::vector<std::string>> response;
Patrick Venture34ddc902018-10-30 11:05:17 -070035
36 try
37 {
38 auto responseMsg = bus.call(mapper);
39
40 responseMsg.read(response);
41 }
42 catch (const sdbusplus::exception::SdBusError& ex)
43 {
44 log<level::ERR>("ObjectMapper call failure",
45 entry("WHAT=%s", ex.what()));
46 throw;
47 }
Patrick Venture863b9242018-03-08 08:29:23 -080048
49 if (response.begin() == response.end())
50 {
51 throw std::runtime_error("Unable to find Object: " + path);
52 }
53
54 return response.begin()->first;
55}
56
Patrick Venture563a3562018-10-30 09:31:26 -070057void DbusHelper::getProperties(sdbusplus::bus::bus& bus,
Patrick Venture0df7c0f2018-06-13 09:02:13 -070058 const std::string& service,
59 const std::string& path,
60 struct SensorProperties* prop)
Patrick Venture863b9242018-03-08 08:29:23 -080061{
Patrick Ventureda4a5dd2018-08-31 09:42:48 -070062 auto pimMsg = bus.new_method_call(service.c_str(), path.c_str(),
63 propertiesintf.c_str(), "GetAll");
Patrick Venture863b9242018-03-08 08:29:23 -080064
65 pimMsg.append(sensorintf);
Patrick Venture863b9242018-03-08 08:29:23 -080066
Patrick Venture7dbc5172018-10-30 12:18:45 -070067 PropertyMap propMap;
68
69 try
Patrick Venture863b9242018-03-08 08:29:23 -080070 {
Patrick Venture7dbc5172018-10-30 12:18:45 -070071 auto valueResponseMsg = bus.call(pimMsg);
72 valueResponseMsg.read(propMap);
73 }
74 catch (const sdbusplus::exception::SdBusError& ex)
75 {
76 log<level::ERR>("GetAll Properties Failed",
77 entry("WHAT=%s", ex.what()));
78 throw;
Patrick Venture863b9242018-03-08 08:29:23 -080079 }
80
81 // The PropertyMap returned will look like this because it's always
82 // reading a Sensor.Value interface.
83 // a{sv} 3:
84 // "Value" x 24875
85 // "Unit" s "xyz.openbmc_project.Sensor.Value.Unit.DegreesC"
86 // "Scale" x -3
Patrick Venture863b9242018-03-08 08:29:23 -080087
Patrick Venture0d73b102018-05-09 10:29:42 -070088 // If no error was set, the values should all be there.
James Feistc065cf12018-07-05 10:23:11 -070089 auto findUnit = propMap.find("Unit");
90 if (findUnit != propMap.end())
91 {
James Feist1f802f52019-02-08 13:51:43 -080092 prop->unit = std::get<std::string>(findUnit->second);
James Feistc065cf12018-07-05 10:23:11 -070093 }
94 auto findScale = propMap.find("Scale");
James Feist75eb7692019-02-25 12:50:02 -080095 auto findMax = propMap.find("MaxValue");
96 auto findMin = propMap.find("MinValue");
97
98 prop->min = 0;
99 prop->max = 0;
100 prop->scale = 0;
James Feistc065cf12018-07-05 10:23:11 -0700101 if (findScale != propMap.end())
102 {
James Feist1f802f52019-02-08 13:51:43 -0800103 prop->scale = std::get<int64_t>(findScale->second);
James Feistc065cf12018-07-05 10:23:11 -0700104 }
James Feist75eb7692019-02-25 12:50:02 -0800105 if (findMax != propMap.end())
James Feistc065cf12018-07-05 10:23:11 -0700106 {
James Feist75eb7692019-02-25 12:50:02 -0800107 prop->max = std::visit(VariantToDoubleVisitor(), findMax->second);
108 }
109 if (findMin != propMap.end())
110 {
111 prop->min = std::visit(VariantToDoubleVisitor(), findMin->second);
James Feistc065cf12018-07-05 10:23:11 -0700112 }
113
James Feist1f802f52019-02-08 13:51:43 -0800114 prop->value = std::visit(VariantToDoubleVisitor(), propMap["Value"]);
Patrick Venture863b9242018-03-08 08:29:23 -0800115
116 return;
117}
118
Patrick Venture563a3562018-10-30 09:31:26 -0700119bool DbusHelper::thresholdsAsserted(sdbusplus::bus::bus& bus,
James Feist36b7d8e2018-10-05 15:39:01 -0700120 const std::string& service,
121 const std::string& path)
122{
123
124 auto critical = bus.new_method_call(service.c_str(), path.c_str(),
125 propertiesintf.c_str(), "GetAll");
126 critical.append(criticalThreshInf);
127 PropertyMap criticalMap;
128
129 try
130 {
131 auto msg = bus.call(critical);
Patrick Venture4fd8cff2018-10-31 14:24:12 -0700132 msg.read(criticalMap);
James Feist36b7d8e2018-10-05 15:39:01 -0700133 }
134 catch (sdbusplus::exception_t&)
135 {
136 // do nothing, sensors don't have to expose critical thresholds
137 return false;
138 }
139
140 auto findCriticalLow = criticalMap.find("CriticalAlarmLow");
141 auto findCriticalHigh = criticalMap.find("CriticalAlarmHigh");
142
143 bool asserted = false;
144 if (findCriticalLow != criticalMap.end())
145 {
James Feist1f802f52019-02-08 13:51:43 -0800146 asserted = std::get<bool>(findCriticalLow->second);
James Feist36b7d8e2018-10-05 15:39:01 -0700147 }
148
149 // as we are catching properties changed, a sensor could theoretically jump
150 // from one threshold to the other in one event, so check both thresholds
151 if (!asserted && findCriticalHigh != criticalMap.end())
152 {
James Feist1f802f52019-02-08 13:51:43 -0800153 asserted = std::get<bool>(findCriticalHigh->second);
James Feist36b7d8e2018-10-05 15:39:01 -0700154 }
155 return asserted;
156}
157
Patrick Venture7af157b2018-10-30 11:24:40 -0700158std::string getSensorPath(const std::string& type, const std::string& id)
Patrick Venture863b9242018-03-08 08:29:23 -0800159{
160 std::string layer = type;
161 if (type == "fan")
162 {
163 layer = "fan_tach";
164 }
165 else if (type == "temp")
166 {
167 layer = "temperature";
168 }
169 else
170 {
171 layer = "unknown"; // TODO(venture): Need to handle.
172 }
173
174 return std::string("/xyz/openbmc_project/sensors/" + layer + "/" + id);
175}
176
Patrick Venture7af157b2018-10-30 11:24:40 -0700177std::string getMatch(const std::string& type, const std::string& id)
Patrick Venture863b9242018-03-08 08:29:23 -0800178{
179 return std::string("type='signal',"
180 "interface='org.freedesktop.DBus.Properties',"
181 "member='PropertiesChanged',"
Patrick Ventureda4a5dd2018-08-31 09:42:48 -0700182 "path='" +
Patrick Venture7af157b2018-10-30 11:24:40 -0700183 getSensorPath(type, id) + "'");
Patrick Venture863b9242018-03-08 08:29:23 -0800184}
185
Patrick Venture7af157b2018-10-30 11:24:40 -0700186bool validType(const std::string& type)
Patrick Venture0ef1faf2018-06-13 12:50:53 -0700187{
188 static std::set<std::string> valid = {"fan", "temp"};
189 return (valid.find(type) != valid.end());
190}
James Feist75eb7692019-02-25 12:50:02 -0800191
192void scaleSensorReading(const double min, const double max, double& value)
193{
Kun Yi6aae76f2019-07-10 21:58:32 -0700194 if (max <= 0 || max <= min)
James Feist75eb7692019-02-25 12:50:02 -0800195 {
196 return;
197 }
198 value /= (max - min);
James Feist0c8223b2019-05-08 15:33:33 -0700199}
Patrick Venturea0764872020-08-08 07:48:43 -0700200
201} // namespace pid_control