blob: 10a052b4255f72817907e6023b680ffef1a75286 [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>
Patrick Venture863b9242018-03-08 08:29:23 -08007
Patrick Venture863b9242018-03-08 08:29:23 -08008using Property = std::string;
James Feist36b7d8e2018-10-05 15:39:01 -07009using Value = sdbusplus::message::variant<int64_t, double, std::string, bool>;
Patrick Venture863b9242018-03-08 08:29:23 -080010using PropertyMap = std::map<Property, Value>;
11
Patrick Venture34ddc902018-10-30 11:05:17 -070012using namespace phosphor::logging;
13
Patrick Venture863b9242018-03-08 08:29:23 -080014/* TODO(venture): Basically all phosphor apps need this, maybe it should be a
15 * part of sdbusplus. There is an old version in libmapper.
16 */
Patrick Venture563a3562018-10-30 09:31:26 -070017std::string DbusHelper::getService(sdbusplus::bus::bus& bus,
Patrick Venture0df7c0f2018-06-13 09:02:13 -070018 const std::string& intf,
19 const std::string& path)
Patrick Venture863b9242018-03-08 08:29:23 -080020{
Patrick Ventureda4a5dd2018-08-31 09:42:48 -070021 auto mapper =
22 bus.new_method_call("xyz.openbmc_project.ObjectMapper",
23 "/xyz/openbmc_project/object_mapper",
24 "xyz.openbmc_project.ObjectMapper", "GetObject");
Patrick Venture863b9242018-03-08 08:29:23 -080025
26 mapper.append(path);
27 mapper.append(std::vector<std::string>({intf}));
28
Patrick Venture863b9242018-03-08 08:29:23 -080029 std::map<std::string, std::vector<std::string>> response;
Patrick Venture34ddc902018-10-30 11:05:17 -070030
31 try
32 {
33 auto responseMsg = bus.call(mapper);
34
35 responseMsg.read(response);
36 }
37 catch (const sdbusplus::exception::SdBusError& ex)
38 {
39 log<level::ERR>("ObjectMapper call failure",
40 entry("WHAT=%s", ex.what()));
41 throw;
42 }
Patrick Venture863b9242018-03-08 08:29:23 -080043
44 if (response.begin() == response.end())
45 {
46 throw std::runtime_error("Unable to find Object: " + path);
47 }
48
49 return response.begin()->first;
50}
51
Patrick Venture563a3562018-10-30 09:31:26 -070052void DbusHelper::getProperties(sdbusplus::bus::bus& bus,
Patrick Venture0df7c0f2018-06-13 09:02:13 -070053 const std::string& service,
54 const std::string& path,
55 struct SensorProperties* prop)
Patrick Venture863b9242018-03-08 08:29:23 -080056{
Patrick Ventureda4a5dd2018-08-31 09:42:48 -070057 auto pimMsg = bus.new_method_call(service.c_str(), path.c_str(),
58 propertiesintf.c_str(), "GetAll");
Patrick Venture863b9242018-03-08 08:29:23 -080059
60 pimMsg.append(sensorintf);
Patrick Venture863b9242018-03-08 08:29:23 -080061
Patrick Venture7dbc5172018-10-30 12:18:45 -070062 PropertyMap propMap;
63
64 try
Patrick Venture863b9242018-03-08 08:29:23 -080065 {
Patrick Venture7dbc5172018-10-30 12:18:45 -070066 auto valueResponseMsg = bus.call(pimMsg);
67 valueResponseMsg.read(propMap);
68 }
69 catch (const sdbusplus::exception::SdBusError& ex)
70 {
71 log<level::ERR>("GetAll Properties Failed",
72 entry("WHAT=%s", ex.what()));
73 throw;
Patrick Venture863b9242018-03-08 08:29:23 -080074 }
75
76 // The PropertyMap returned will look like this because it's always
77 // reading a Sensor.Value interface.
78 // a{sv} 3:
79 // "Value" x 24875
80 // "Unit" s "xyz.openbmc_project.Sensor.Value.Unit.DegreesC"
81 // "Scale" x -3
Patrick Venture863b9242018-03-08 08:29:23 -080082
Patrick Venture0d73b102018-05-09 10:29:42 -070083 // If no error was set, the values should all be there.
James Feistc065cf12018-07-05 10:23:11 -070084 auto findUnit = propMap.find("Unit");
85 if (findUnit != propMap.end())
86 {
87 prop->unit =
88 sdbusplus::message::variant_ns::get<std::string>(findUnit->second);
89 }
90 auto findScale = propMap.find("Scale");
91 if (findScale != propMap.end())
92 {
93 prop->scale =
94 sdbusplus::message::variant_ns::get<int64_t>(findScale->second);
95 }
96 else
97 {
98 prop->scale = 0;
99 }
100
William A. Kennington III4a0c0612018-11-12 17:07:28 -0800101 prop->value = sdbusplus::message::variant_ns::visit(
James Feistd7a55bf2018-10-11 14:40:07 -0700102 VariantToDoubleVisitor(), propMap["Value"]);
Patrick Venture863b9242018-03-08 08:29:23 -0800103
104 return;
105}
106
Patrick Venture563a3562018-10-30 09:31:26 -0700107bool DbusHelper::thresholdsAsserted(sdbusplus::bus::bus& bus,
James Feist36b7d8e2018-10-05 15:39:01 -0700108 const std::string& service,
109 const std::string& path)
110{
111
112 auto critical = bus.new_method_call(service.c_str(), path.c_str(),
113 propertiesintf.c_str(), "GetAll");
114 critical.append(criticalThreshInf);
115 PropertyMap criticalMap;
116
117 try
118 {
119 auto msg = bus.call(critical);
Patrick Venture4fd8cff2018-10-31 14:24:12 -0700120 msg.read(criticalMap);
James Feist36b7d8e2018-10-05 15:39:01 -0700121 }
122 catch (sdbusplus::exception_t&)
123 {
124 // do nothing, sensors don't have to expose critical thresholds
125 return false;
126 }
127
128 auto findCriticalLow = criticalMap.find("CriticalAlarmLow");
129 auto findCriticalHigh = criticalMap.find("CriticalAlarmHigh");
130
131 bool asserted = false;
132 if (findCriticalLow != criticalMap.end())
133 {
134 asserted =
135 sdbusplus::message::variant_ns::get<bool>(findCriticalLow->second);
136 }
137
138 // as we are catching properties changed, a sensor could theoretically jump
139 // from one threshold to the other in one event, so check both thresholds
140 if (!asserted && findCriticalHigh != criticalMap.end())
141 {
142 asserted =
143 sdbusplus::message::variant_ns::get<bool>(findCriticalHigh->second);
144 }
145 return asserted;
146}
147
Patrick Venture7af157b2018-10-30 11:24:40 -0700148std::string getSensorPath(const std::string& type, const std::string& id)
Patrick Venture863b9242018-03-08 08:29:23 -0800149{
150 std::string layer = type;
151 if (type == "fan")
152 {
153 layer = "fan_tach";
154 }
155 else if (type == "temp")
156 {
157 layer = "temperature";
158 }
159 else
160 {
161 layer = "unknown"; // TODO(venture): Need to handle.
162 }
163
164 return std::string("/xyz/openbmc_project/sensors/" + layer + "/" + id);
165}
166
Patrick Venture7af157b2018-10-30 11:24:40 -0700167std::string getMatch(const std::string& type, const std::string& id)
Patrick Venture863b9242018-03-08 08:29:23 -0800168{
169 return std::string("type='signal',"
170 "interface='org.freedesktop.DBus.Properties',"
171 "member='PropertiesChanged',"
Patrick Ventureda4a5dd2018-08-31 09:42:48 -0700172 "path='" +
Patrick Venture7af157b2018-10-30 11:24:40 -0700173 getSensorPath(type, id) + "'");
Patrick Venture863b9242018-03-08 08:29:23 -0800174}
175
Patrick Venture7af157b2018-10-30 11:24:40 -0700176bool validType(const std::string& type)
Patrick Venture0ef1faf2018-06-13 12:50:53 -0700177{
178 static std::set<std::string> valid = {"fan", "temp"};
179 return (valid.find(type) != valid.end());
180}