blob: ffdfe1f02f7d4ec3657084b5a228c00e6c3529ee [file] [log] [blame]
Patrick Venture863b9242018-03-08 08:29:23 -08001#include <iostream>
Patrick Venture0ef1faf2018-06-13 12:50:53 -07002#include <set>
Patrick Venture863b9242018-03-08 08:29:23 -08003
4#include "dbus/util.hpp"
5
6using Property = std::string;
James Feistc065cf12018-07-05 10:23:11 -07007using Value = sdbusplus::message::variant<int64_t, double, std::string>;
Patrick Venture863b9242018-03-08 08:29:23 -08008using PropertyMap = std::map<Property, Value>;
9
10/* TODO(venture): Basically all phosphor apps need this, maybe it should be a
11 * part of sdbusplus. There is an old version in libmapper.
12 */
Patrick Venture0df7c0f2018-06-13 09:02:13 -070013std::string DbusHelper::GetService(sdbusplus::bus::bus& bus,
14 const std::string& intf,
15 const std::string& path)
Patrick Venture863b9242018-03-08 08:29:23 -080016{
17 auto mapper = bus.new_method_call(
18 "xyz.openbmc_project.ObjectMapper",
19 "/xyz/openbmc_project/object_mapper",
20 "xyz.openbmc_project.ObjectMapper",
21 "GetObject");
22
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 Venture863b9242018-03-08 08:29:23 -080048 auto pimMsg = bus.new_method_call(service.c_str(),
49 path.c_str(),
50 propertiesintf.c_str(),
51 "GetAll");
52
53 pimMsg.append(sensorintf);
54 auto valueResponseMsg = bus.call(pimMsg);
55
56 if (valueResponseMsg.is_method_error())
57 {
58 std::cerr << "Error in value call\n";
59 throw std::runtime_error("ERROR in value call.");
60 }
61
62 // The PropertyMap returned will look like this because it's always
63 // reading a Sensor.Value interface.
64 // a{sv} 3:
65 // "Value" x 24875
66 // "Unit" s "xyz.openbmc_project.Sensor.Value.Unit.DegreesC"
67 // "Scale" x -3
68 PropertyMap propMap;
69 valueResponseMsg.read(propMap);
70
Patrick Venture0d73b102018-05-09 10:29:42 -070071 // If no error was set, the values should all be there.
James Feistc065cf12018-07-05 10:23:11 -070072 auto findUnit = propMap.find("Unit");
73 if (findUnit != propMap.end())
74 {
75 prop->unit =
76 sdbusplus::message::variant_ns::get<std::string>(findUnit->second);
77 }
78 auto findScale = propMap.find("Scale");
79 if (findScale != propMap.end())
80 {
81 prop->scale =
82 sdbusplus::message::variant_ns::get<int64_t>(findScale->second);
83 }
84 else
85 {
86 prop->scale = 0;
87 }
88
89 prop->value =
90 mapbox::util::apply_visitor(VariantToDoubleVisitor(), propMap["Value"]);
Patrick Venture863b9242018-03-08 08:29:23 -080091
92 return;
93}
94
95std::string GetSensorPath(const std::string& type, const std::string& id)
96{
97 std::string layer = type;
98 if (type == "fan")
99 {
100 layer = "fan_tach";
101 }
102 else if (type == "temp")
103 {
104 layer = "temperature";
105 }
106 else
107 {
108 layer = "unknown"; // TODO(venture): Need to handle.
109 }
110
111 return std::string("/xyz/openbmc_project/sensors/" + layer + "/" + id);
112}
113
114std::string GetMatch(const std::string& type, const std::string& id)
115{
116 return std::string("type='signal',"
117 "interface='org.freedesktop.DBus.Properties',"
118 "member='PropertiesChanged',"
119 "path='" + GetSensorPath(type, id) + "'");
120}
121
Patrick Venture0ef1faf2018-06-13 12:50:53 -0700122bool ValidType(const std::string& type)
123{
124 static std::set<std::string> valid = {"fan", "temp"};
125 return (valid.find(type) != valid.end());
126}