blob: 23f06fd3805c647457e3d0f8bcaf8547afbd723e [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);
61 auto valueResponseMsg = bus.call(pimMsg);
62
63 if (valueResponseMsg.is_method_error())
64 {
65 std::cerr << "Error in value call\n";
66 throw std::runtime_error("ERROR in value call.");
67 }
68
69 // The PropertyMap returned will look like this because it's always
70 // reading a Sensor.Value interface.
71 // a{sv} 3:
72 // "Value" x 24875
73 // "Unit" s "xyz.openbmc_project.Sensor.Value.Unit.DegreesC"
74 // "Scale" x -3
75 PropertyMap propMap;
76 valueResponseMsg.read(propMap);
77
Patrick Venture0d73b102018-05-09 10:29:42 -070078 // If no error was set, the values should all be there.
James Feistc065cf12018-07-05 10:23:11 -070079 auto findUnit = propMap.find("Unit");
80 if (findUnit != propMap.end())
81 {
82 prop->unit =
83 sdbusplus::message::variant_ns::get<std::string>(findUnit->second);
84 }
85 auto findScale = propMap.find("Scale");
86 if (findScale != propMap.end())
87 {
88 prop->scale =
89 sdbusplus::message::variant_ns::get<int64_t>(findScale->second);
90 }
91 else
92 {
93 prop->scale = 0;
94 }
95
James Feistd7a55bf2018-10-11 14:40:07 -070096 prop->value = sdbusplus::message::variant_ns::apply_visitor(
97 VariantToDoubleVisitor(), propMap["Value"]);
Patrick Venture863b9242018-03-08 08:29:23 -080098
99 return;
100}
101
Patrick Venture563a3562018-10-30 09:31:26 -0700102bool DbusHelper::thresholdsAsserted(sdbusplus::bus::bus& bus,
James Feist36b7d8e2018-10-05 15:39:01 -0700103 const std::string& service,
104 const std::string& path)
105{
106
107 auto critical = bus.new_method_call(service.c_str(), path.c_str(),
108 propertiesintf.c_str(), "GetAll");
109 critical.append(criticalThreshInf);
110 PropertyMap criticalMap;
111
112 try
113 {
114 auto msg = bus.call(critical);
115 if (!msg.is_method_error())
116 {
117 msg.read(criticalMap);
118 }
119 }
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 {
132 asserted =
133 sdbusplus::message::variant_ns::get<bool>(findCriticalLow->second);
134 }
135
136 // as we are catching properties changed, a sensor could theoretically jump
137 // from one threshold to the other in one event, so check both thresholds
138 if (!asserted && findCriticalHigh != criticalMap.end())
139 {
140 asserted =
141 sdbusplus::message::variant_ns::get<bool>(findCriticalHigh->second);
142 }
143 return asserted;
144}
145
Patrick Venture7af157b2018-10-30 11:24:40 -0700146std::string getSensorPath(const std::string& type, const std::string& id)
Patrick Venture863b9242018-03-08 08:29:23 -0800147{
148 std::string layer = type;
149 if (type == "fan")
150 {
151 layer = "fan_tach";
152 }
153 else if (type == "temp")
154 {
155 layer = "temperature";
156 }
157 else
158 {
159 layer = "unknown"; // TODO(venture): Need to handle.
160 }
161
162 return std::string("/xyz/openbmc_project/sensors/" + layer + "/" + id);
163}
164
Patrick Venture7af157b2018-10-30 11:24:40 -0700165std::string getMatch(const std::string& type, const std::string& id)
Patrick Venture863b9242018-03-08 08:29:23 -0800166{
167 return std::string("type='signal',"
168 "interface='org.freedesktop.DBus.Properties',"
169 "member='PropertiesChanged',"
Patrick Ventureda4a5dd2018-08-31 09:42:48 -0700170 "path='" +
Patrick Venture7af157b2018-10-30 11:24:40 -0700171 getSensorPath(type, id) + "'");
Patrick Venture863b9242018-03-08 08:29:23 -0800172}
173
Patrick Venture7af157b2018-10-30 11:24:40 -0700174bool validType(const std::string& type)
Patrick Venture0ef1faf2018-06-13 12:50:53 -0700175{
176 static std::set<std::string> valid = {"fan", "temp"};
177 return (valid.find(type) != valid.end());
178}