blob: b5b22f49f490d5c3cfe2e1f7a85f5d214811aef0 [file] [log] [blame]
Patrick Ventureda4a5dd2018-08-31 09:42:48 -07001#include "dbus/util.hpp"
2
James Feist36b7d8e2018-10-05 15:39:01 -07003#include <cmath>
Patrick Venture863b9242018-03-08 08:29:23 -08004#include <iostream>
Patrick Venture34ddc902018-10-30 11:05:17 -07005#include <phosphor-logging/log.hpp>
Patrick Venture0ef1faf2018-06-13 12:50:53 -07006#include <set>
James Feist1f802f52019-02-08 13:51:43 -08007#include <variant>
Patrick Venture863b9242018-03-08 08:29:23 -08008
Patrick Venture863b9242018-03-08 08:29:23 -08009using Property = std::string;
James Feist1f802f52019-02-08 13:51:43 -080010using Value = std::variant<int64_t, double, std::string, bool>;
Patrick Venture863b9242018-03-08 08:29:23 -080011using PropertyMap = std::map<Property, Value>;
12
Patrick Venture34ddc902018-10-30 11:05:17 -070013using namespace phosphor::logging;
14
Patrick Venture863b9242018-03-08 08:29:23 -080015/* TODO(venture): Basically all phosphor apps need this, maybe it should be a
16 * part of sdbusplus. There is an old version in libmapper.
17 */
Patrick Venture563a3562018-10-30 09:31:26 -070018std::string DbusHelper::getService(sdbusplus::bus::bus& bus,
Patrick Venture0df7c0f2018-06-13 09:02:13 -070019 const std::string& intf,
20 const std::string& path)
Patrick Venture863b9242018-03-08 08:29:23 -080021{
Patrick Ventureda4a5dd2018-08-31 09:42:48 -070022 auto mapper =
23 bus.new_method_call("xyz.openbmc_project.ObjectMapper",
24 "/xyz/openbmc_project/object_mapper",
25 "xyz.openbmc_project.ObjectMapper", "GetObject");
Patrick Venture863b9242018-03-08 08:29:23 -080026
27 mapper.append(path);
28 mapper.append(std::vector<std::string>({intf}));
29
Patrick Venture863b9242018-03-08 08:29:23 -080030 std::map<std::string, std::vector<std::string>> response;
Patrick Venture34ddc902018-10-30 11:05:17 -070031
32 try
33 {
34 auto responseMsg = bus.call(mapper);
35
36 responseMsg.read(response);
37 }
38 catch (const sdbusplus::exception::SdBusError& ex)
39 {
40 log<level::ERR>("ObjectMapper call failure",
41 entry("WHAT=%s", ex.what()));
42 throw;
43 }
Patrick Venture863b9242018-03-08 08:29:23 -080044
45 if (response.begin() == response.end())
46 {
47 throw std::runtime_error("Unable to find Object: " + path);
48 }
49
50 return response.begin()->first;
51}
52
Patrick Venture563a3562018-10-30 09:31:26 -070053void DbusHelper::getProperties(sdbusplus::bus::bus& bus,
Patrick Venture0df7c0f2018-06-13 09:02:13 -070054 const std::string& service,
55 const std::string& path,
56 struct SensorProperties* prop)
Patrick Venture863b9242018-03-08 08:29:23 -080057{
Patrick Ventureda4a5dd2018-08-31 09:42:48 -070058 auto pimMsg = bus.new_method_call(service.c_str(), path.c_str(),
59 propertiesintf.c_str(), "GetAll");
Patrick Venture863b9242018-03-08 08:29:23 -080060
61 pimMsg.append(sensorintf);
Patrick Venture863b9242018-03-08 08:29:23 -080062
Patrick Venture7dbc5172018-10-30 12:18:45 -070063 PropertyMap propMap;
64
65 try
Patrick Venture863b9242018-03-08 08:29:23 -080066 {
Patrick Venture7dbc5172018-10-30 12:18:45 -070067 auto valueResponseMsg = bus.call(pimMsg);
68 valueResponseMsg.read(propMap);
69 }
70 catch (const sdbusplus::exception::SdBusError& ex)
71 {
72 log<level::ERR>("GetAll Properties Failed",
73 entry("WHAT=%s", ex.what()));
74 throw;
Patrick Venture863b9242018-03-08 08:29:23 -080075 }
76
77 // The PropertyMap returned will look like this because it's always
78 // reading a Sensor.Value interface.
79 // a{sv} 3:
80 // "Value" x 24875
81 // "Unit" s "xyz.openbmc_project.Sensor.Value.Unit.DegreesC"
82 // "Scale" x -3
Patrick Venture863b9242018-03-08 08:29:23 -080083
Patrick Venture0d73b102018-05-09 10:29:42 -070084 // If no error was set, the values should all be there.
James Feistc065cf12018-07-05 10:23:11 -070085 auto findUnit = propMap.find("Unit");
86 if (findUnit != propMap.end())
87 {
James Feist1f802f52019-02-08 13:51:43 -080088 prop->unit = std::get<std::string>(findUnit->second);
James Feistc065cf12018-07-05 10:23:11 -070089 }
90 auto findScale = propMap.find("Scale");
James Feist75eb7692019-02-25 12:50:02 -080091 auto findMax = propMap.find("MaxValue");
92 auto findMin = propMap.find("MinValue");
93
94 prop->min = 0;
95 prop->max = 0;
96 prop->scale = 0;
James Feistc065cf12018-07-05 10:23:11 -070097 if (findScale != propMap.end())
98 {
James Feist1f802f52019-02-08 13:51:43 -080099 prop->scale = std::get<int64_t>(findScale->second);
James Feistc065cf12018-07-05 10:23:11 -0700100 }
James Feist75eb7692019-02-25 12:50:02 -0800101 if (findMax != propMap.end())
James Feistc065cf12018-07-05 10:23:11 -0700102 {
James Feist75eb7692019-02-25 12:50:02 -0800103 prop->max = std::visit(VariantToDoubleVisitor(), findMax->second);
104 }
105 if (findMin != propMap.end())
106 {
107 prop->min = std::visit(VariantToDoubleVisitor(), findMin->second);
James Feistc065cf12018-07-05 10:23:11 -0700108 }
109
James Feist1f802f52019-02-08 13:51:43 -0800110 prop->value = std::visit(VariantToDoubleVisitor(), propMap["Value"]);
Patrick Venture863b9242018-03-08 08:29:23 -0800111
112 return;
113}
114
Patrick Venture563a3562018-10-30 09:31:26 -0700115bool DbusHelper::thresholdsAsserted(sdbusplus::bus::bus& bus,
James Feist36b7d8e2018-10-05 15:39:01 -0700116 const std::string& service,
117 const std::string& path)
118{
119
120 auto critical = bus.new_method_call(service.c_str(), path.c_str(),
121 propertiesintf.c_str(), "GetAll");
122 critical.append(criticalThreshInf);
123 PropertyMap criticalMap;
124
125 try
126 {
127 auto msg = bus.call(critical);
Patrick Venture4fd8cff2018-10-31 14:24:12 -0700128 msg.read(criticalMap);
James Feist36b7d8e2018-10-05 15:39:01 -0700129 }
130 catch (sdbusplus::exception_t&)
131 {
132 // do nothing, sensors don't have to expose critical thresholds
133 return false;
134 }
135
136 auto findCriticalLow = criticalMap.find("CriticalAlarmLow");
137 auto findCriticalHigh = criticalMap.find("CriticalAlarmHigh");
138
139 bool asserted = false;
140 if (findCriticalLow != criticalMap.end())
141 {
James Feist1f802f52019-02-08 13:51:43 -0800142 asserted = std::get<bool>(findCriticalLow->second);
James Feist36b7d8e2018-10-05 15:39:01 -0700143 }
144
145 // as we are catching properties changed, a sensor could theoretically jump
146 // from one threshold to the other in one event, so check both thresholds
147 if (!asserted && findCriticalHigh != criticalMap.end())
148 {
James Feist1f802f52019-02-08 13:51:43 -0800149 asserted = std::get<bool>(findCriticalHigh->second);
James Feist36b7d8e2018-10-05 15:39:01 -0700150 }
151 return asserted;
152}
153
Patrick Venture7af157b2018-10-30 11:24:40 -0700154std::string getSensorPath(const std::string& type, const std::string& id)
Patrick Venture863b9242018-03-08 08:29:23 -0800155{
156 std::string layer = type;
157 if (type == "fan")
158 {
159 layer = "fan_tach";
160 }
161 else if (type == "temp")
162 {
163 layer = "temperature";
164 }
165 else
166 {
167 layer = "unknown"; // TODO(venture): Need to handle.
168 }
169
170 return std::string("/xyz/openbmc_project/sensors/" + layer + "/" + id);
171}
172
Patrick Venture7af157b2018-10-30 11:24:40 -0700173std::string getMatch(const std::string& type, const std::string& id)
Patrick Venture863b9242018-03-08 08:29:23 -0800174{
175 return std::string("type='signal',"
176 "interface='org.freedesktop.DBus.Properties',"
177 "member='PropertiesChanged',"
Patrick Ventureda4a5dd2018-08-31 09:42:48 -0700178 "path='" +
Patrick Venture7af157b2018-10-30 11:24:40 -0700179 getSensorPath(type, id) + "'");
Patrick Venture863b9242018-03-08 08:29:23 -0800180}
181
Patrick Venture7af157b2018-10-30 11:24:40 -0700182bool validType(const std::string& type)
Patrick Venture0ef1faf2018-06-13 12:50:53 -0700183{
184 static std::set<std::string> valid = {"fan", "temp"};
185 return (valid.find(type) != valid.end());
186}
James Feist75eb7692019-02-25 12:50:02 -0800187
188void scaleSensorReading(const double min, const double max, double& value)
189{
190 if (max <= 0)
191 {
192 return;
193 }
194 value /= (max - min);
195}