blob: 5a572d07c5ee9f3ba2173e1b829f0f8f4c0718fe [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");
91 if (findScale != propMap.end())
92 {
James Feist1f802f52019-02-08 13:51:43 -080093 prop->scale = std::get<int64_t>(findScale->second);
James Feistc065cf12018-07-05 10:23:11 -070094 }
95 else
96 {
97 prop->scale = 0;
98 }
99
James Feist1f802f52019-02-08 13:51:43 -0800100 prop->value = std::visit(VariantToDoubleVisitor(), propMap["Value"]);
Patrick Venture863b9242018-03-08 08:29:23 -0800101
102 return;
103}
104
Patrick Venture563a3562018-10-30 09:31:26 -0700105bool DbusHelper::thresholdsAsserted(sdbusplus::bus::bus& bus,
James Feist36b7d8e2018-10-05 15:39:01 -0700106 const std::string& service,
107 const std::string& path)
108{
109
110 auto critical = bus.new_method_call(service.c_str(), path.c_str(),
111 propertiesintf.c_str(), "GetAll");
112 critical.append(criticalThreshInf);
113 PropertyMap criticalMap;
114
115 try
116 {
117 auto msg = bus.call(critical);
Patrick Venture4fd8cff2018-10-31 14:24:12 -0700118 msg.read(criticalMap);
James Feist36b7d8e2018-10-05 15:39:01 -0700119 }
120 catch (sdbusplus::exception_t&)
121 {
122 // do nothing, sensors don't have to expose critical thresholds
123 return false;
124 }
125
126 auto findCriticalLow = criticalMap.find("CriticalAlarmLow");
127 auto findCriticalHigh = criticalMap.find("CriticalAlarmHigh");
128
129 bool asserted = false;
130 if (findCriticalLow != criticalMap.end())
131 {
James Feist1f802f52019-02-08 13:51:43 -0800132 asserted = std::get<bool>(findCriticalLow->second);
James Feist36b7d8e2018-10-05 15:39:01 -0700133 }
134
135 // as we are catching properties changed, a sensor could theoretically jump
136 // from one threshold to the other in one event, so check both thresholds
137 if (!asserted && findCriticalHigh != criticalMap.end())
138 {
James Feist1f802f52019-02-08 13:51:43 -0800139 asserted = std::get<bool>(findCriticalHigh->second);
James Feist36b7d8e2018-10-05 15:39:01 -0700140 }
141 return asserted;
142}
143
Patrick Venture7af157b2018-10-30 11:24:40 -0700144std::string getSensorPath(const std::string& type, const std::string& id)
Patrick Venture863b9242018-03-08 08:29:23 -0800145{
146 std::string layer = type;
147 if (type == "fan")
148 {
149 layer = "fan_tach";
150 }
151 else if (type == "temp")
152 {
153 layer = "temperature";
154 }
155 else
156 {
157 layer = "unknown"; // TODO(venture): Need to handle.
158 }
159
160 return std::string("/xyz/openbmc_project/sensors/" + layer + "/" + id);
161}
162
Patrick Venture7af157b2018-10-30 11:24:40 -0700163std::string getMatch(const std::string& type, const std::string& id)
Patrick Venture863b9242018-03-08 08:29:23 -0800164{
165 return std::string("type='signal',"
166 "interface='org.freedesktop.DBus.Properties',"
167 "member='PropertiesChanged',"
Patrick Ventureda4a5dd2018-08-31 09:42:48 -0700168 "path='" +
Patrick Venture7af157b2018-10-30 11:24:40 -0700169 getSensorPath(type, id) + "'");
Patrick Venture863b9242018-03-08 08:29:23 -0800170}
171
Patrick Venture7af157b2018-10-30 11:24:40 -0700172bool validType(const std::string& type)
Patrick Venture0ef1faf2018-06-13 12:50:53 -0700173{
174 static std::set<std::string> valid = {"fan", "temp"};
175 return (valid.find(type) != valid.end());
176}