blob: cdc4bb98deaf666601e10ac9af6541c87f6bdb87 [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 Venture0ef1faf2018-06-13 12:50:53 -07005#include <set>
Patrick Venture863b9242018-03-08 08:29:23 -08006
Patrick Venture863b9242018-03-08 08:29:23 -08007using Property = std::string;
James Feist36b7d8e2018-10-05 15:39:01 -07008using Value = sdbusplus::message::variant<int64_t, double, std::string, bool>;
Patrick Venture863b9242018-03-08 08:29:23 -08009using PropertyMap = std::map<Property, Value>;
10
11/* TODO(venture): Basically all phosphor apps need this, maybe it should be a
12 * part of sdbusplus. There is an old version in libmapper.
13 */
Patrick Venture0df7c0f2018-06-13 09:02:13 -070014std::string DbusHelper::GetService(sdbusplus::bus::bus& bus,
15 const std::string& intf,
16 const std::string& path)
Patrick Venture863b9242018-03-08 08:29:23 -080017{
Patrick Ventureda4a5dd2018-08-31 09:42:48 -070018 auto mapper =
19 bus.new_method_call("xyz.openbmc_project.ObjectMapper",
20 "/xyz/openbmc_project/object_mapper",
21 "xyz.openbmc_project.ObjectMapper", "GetObject");
Patrick Venture863b9242018-03-08 08:29:23 -080022
23 mapper.append(path);
24 mapper.append(std::vector<std::string>({intf}));
25
26 auto responseMsg = bus.call(mapper);
27 if (responseMsg.is_method_error())
28 {
29 throw std::runtime_error("ObjectMapper Call Failure");
30 }
31
32 std::map<std::string, std::vector<std::string>> response;
33 responseMsg.read(response);
34
35 if (response.begin() == response.end())
36 {
37 throw std::runtime_error("Unable to find Object: " + path);
38 }
39
40 return response.begin()->first;
41}
42
Patrick Venture0df7c0f2018-06-13 09:02:13 -070043void DbusHelper::GetProperties(sdbusplus::bus::bus& bus,
44 const std::string& service,
45 const std::string& path,
46 struct SensorProperties* prop)
Patrick Venture863b9242018-03-08 08:29:23 -080047{
Patrick Ventureda4a5dd2018-08-31 09:42:48 -070048 auto pimMsg = bus.new_method_call(service.c_str(), path.c_str(),
49 propertiesintf.c_str(), "GetAll");
Patrick Venture863b9242018-03-08 08:29:23 -080050
51 pimMsg.append(sensorintf);
52 auto valueResponseMsg = bus.call(pimMsg);
53
54 if (valueResponseMsg.is_method_error())
55 {
56 std::cerr << "Error in value call\n";
57 throw std::runtime_error("ERROR in value call.");
58 }
59
60 // The PropertyMap returned will look like this because it's always
61 // reading a Sensor.Value interface.
62 // a{sv} 3:
63 // "Value" x 24875
64 // "Unit" s "xyz.openbmc_project.Sensor.Value.Unit.DegreesC"
65 // "Scale" x -3
66 PropertyMap propMap;
67 valueResponseMsg.read(propMap);
68
Patrick Venture0d73b102018-05-09 10:29:42 -070069 // If no error was set, the values should all be there.
James Feistc065cf12018-07-05 10:23:11 -070070 auto findUnit = propMap.find("Unit");
71 if (findUnit != propMap.end())
72 {
73 prop->unit =
74 sdbusplus::message::variant_ns::get<std::string>(findUnit->second);
75 }
76 auto findScale = propMap.find("Scale");
77 if (findScale != propMap.end())
78 {
79 prop->scale =
80 sdbusplus::message::variant_ns::get<int64_t>(findScale->second);
81 }
82 else
83 {
84 prop->scale = 0;
85 }
86
James Feistd7a55bf2018-10-11 14:40:07 -070087 prop->value = sdbusplus::message::variant_ns::apply_visitor(
88 VariantToDoubleVisitor(), propMap["Value"]);
Patrick Venture863b9242018-03-08 08:29:23 -080089
90 return;
91}
92
James Feist36b7d8e2018-10-05 15:39:01 -070093bool DbusHelper::ThresholdsAsserted(sdbusplus::bus::bus& bus,
94 const std::string& service,
95 const std::string& path)
96{
97
98 auto critical = bus.new_method_call(service.c_str(), path.c_str(),
99 propertiesintf.c_str(), "GetAll");
100 critical.append(criticalThreshInf);
101 PropertyMap criticalMap;
102
103 try
104 {
105 auto msg = bus.call(critical);
106 if (!msg.is_method_error())
107 {
108 msg.read(criticalMap);
109 }
110 }
111 catch (sdbusplus::exception_t&)
112 {
113 // do nothing, sensors don't have to expose critical thresholds
114 return false;
115 }
116
117 auto findCriticalLow = criticalMap.find("CriticalAlarmLow");
118 auto findCriticalHigh = criticalMap.find("CriticalAlarmHigh");
119
120 bool asserted = false;
121 if (findCriticalLow != criticalMap.end())
122 {
123 asserted =
124 sdbusplus::message::variant_ns::get<bool>(findCriticalLow->second);
125 }
126
127 // as we are catching properties changed, a sensor could theoretically jump
128 // from one threshold to the other in one event, so check both thresholds
129 if (!asserted && findCriticalHigh != criticalMap.end())
130 {
131 asserted =
132 sdbusplus::message::variant_ns::get<bool>(findCriticalHigh->second);
133 }
134 return asserted;
135}
136
Patrick Venture863b9242018-03-08 08:29:23 -0800137std::string GetSensorPath(const std::string& type, const std::string& id)
138{
139 std::string layer = type;
140 if (type == "fan")
141 {
142 layer = "fan_tach";
143 }
144 else if (type == "temp")
145 {
146 layer = "temperature";
147 }
148 else
149 {
150 layer = "unknown"; // TODO(venture): Need to handle.
151 }
152
153 return std::string("/xyz/openbmc_project/sensors/" + layer + "/" + id);
154}
155
156std::string GetMatch(const std::string& type, const std::string& id)
157{
158 return std::string("type='signal',"
159 "interface='org.freedesktop.DBus.Properties',"
160 "member='PropertiesChanged',"
Patrick Ventureda4a5dd2018-08-31 09:42:48 -0700161 "path='" +
162 GetSensorPath(type, id) + "'");
Patrick Venture863b9242018-03-08 08:29:23 -0800163}
164
Patrick Venture0ef1faf2018-06-13 12:50:53 -0700165bool ValidType(const std::string& type)
166{
167 static std::set<std::string> valid = {"fan", "temp"};
168 return (valid.find(type) != valid.end());
169}