1 #include "occ_dbus.hpp"
2
3 #include "utils.hpp"
4
5 #include <phosphor-logging/log.hpp>
6
7 #include <format>
8 #include <iostream>
9
10 namespace open_power
11 {
12 namespace occ
13 {
14 namespace dbus
15 {
16
17 using namespace phosphor::logging;
18 using namespace std::string_literals;
19 const auto defaultChassisPath =
20 "/xyz/openbmc_project/inventory/system/chassis"s;
21 const auto chassisInterface = "xyz.openbmc_project.Inventory.Item.Chassis"s;
22
setMaxValue(const std::string & path,double value)23 bool OccDBusSensors::setMaxValue(const std::string& path, double value)
24 {
25 if (path.empty())
26 {
27 return false;
28 }
29
30 if (!sensors.contains(path))
31 {
32 sensors.emplace(
33 path, std::make_unique<SensorIntf>(utils::getBus(), path.c_str()));
34 }
35
36 sensors.at(path)->maxValue(value);
37 return true;
38 }
39
getMaxValue(const std::string & path) const40 double OccDBusSensors::getMaxValue(const std::string& path) const
41 {
42 if (sensors.find(path) != sensors.end())
43 {
44 return sensors.at(path)->maxValue();
45 }
46
47 throw std::invalid_argument("Failed to get MaxValue property.");
48 }
49
setMinValue(const std::string & path,double value)50 bool OccDBusSensors::setMinValue(const std::string& path, double value)
51 {
52 if (path.empty())
53 {
54 return false;
55 }
56
57 if (!sensors.contains(path))
58 {
59 sensors.emplace(
60 path, std::make_unique<SensorIntf>(utils::getBus(), path.c_str()));
61 }
62
63 sensors.at(path)->minValue(value);
64 return true;
65 }
66
getMinValue(const std::string & path) const67 double OccDBusSensors::getMinValue(const std::string& path) const
68 {
69 if (sensors.find(path) != sensors.end())
70 {
71 return sensors.at(path)->minValue();
72 }
73
74 throw std::invalid_argument("Failed to get MinValue property.");
75 }
76
setValue(const std::string & path,double value)77 bool OccDBusSensors::setValue(const std::string& path, double value)
78 {
79 if (path.empty())
80 {
81 return false;
82 }
83
84 if (!sensors.contains(path))
85 {
86 sensors.emplace(
87 path, std::make_unique<SensorIntf>(utils::getBus(), path.c_str()));
88 }
89
90 sensors.at(path)->value(value);
91 return true;
92 }
93
getValue(const std::string & path) const94 double OccDBusSensors::getValue(const std::string& path) const
95 {
96 if (sensors.find(path) != sensors.end())
97 {
98 return sensors.at(path)->value();
99 }
100
101 throw std::invalid_argument("Failed to get Value property.");
102 }
103
setUnit(const std::string & path,const std::string & value)104 bool OccDBusSensors::setUnit(const std::string& path, const std::string& value)
105 {
106 if (path.empty())
107 {
108 return false;
109 }
110
111 if (!sensors.contains(path))
112 {
113 sensors.emplace(
114 path, std::make_unique<SensorIntf>(utils::getBus(), path.c_str()));
115 }
116
117 try
118 {
119 sensors.at(path)->unit(SensorIntf::convertUnitFromString(value));
120 }
121 catch (const std::exception& e)
122 {
123 log<level::ERR>("set Unit propety failed", entry("ERROR=%s", e.what()));
124 return false;
125 }
126
127 return true;
128 }
129
getUnit(const std::string & path) const130 std::string OccDBusSensors::getUnit(const std::string& path) const
131 {
132 if (sensors.find(path) != sensors.end())
133 {
134 try
135 {
136 return SensorIntf::convertUnitToString(sensors.at(path)->unit());
137 }
138 catch (const std::exception& e)
139 {
140 log<level::ERR>("get Unit propety failed",
141 entry("ERROR=%s", e.what()));
142 }
143 }
144
145 throw std::invalid_argument("Failed to get Unit property.");
146 }
147
setOperationalStatus(const std::string & path,bool value)148 bool OccDBusSensors::setOperationalStatus(const std::string& path, bool value)
149 {
150 if (path.empty())
151 {
152 return false;
153 }
154
155 if (!operationalStatus.contains(path))
156 {
157 operationalStatus.emplace(path, std::make_unique<OperationalStatusIntf>(
158 utils::getBus(), path.c_str()));
159 }
160
161 operationalStatus.at(path)->functional(value);
162 return true;
163 }
164
getOperationalStatus(const std::string & path) const165 bool OccDBusSensors::getOperationalStatus(const std::string& path) const
166 {
167 if (operationalStatus.find(path) != operationalStatus.end())
168 {
169 return operationalStatus.at(path)->functional();
170 }
171
172 throw std::invalid_argument("Failed to get OperationalStatus property.");
173 }
174
setChassisAssociation(const std::string & path)175 void OccDBusSensors::setChassisAssociation(const std::string& path)
176 {
177 using AssociationsEntry = std::tuple<std::string, std::string, std::string>;
178 using AssociationsProperty = std::vector<AssociationsEntry>;
179 using PropVariant = sdbusplus::xyz::openbmc_project::Association::server::
180 Definitions::PropertiesVariant;
181
182 if (chassisPath.empty())
183 {
184 chassisPath = getChassisPath();
185 }
186
187 AssociationsProperty associations{
188 AssociationsEntry{"chassis", "all_sensors", chassisPath}};
189 PropVariant value{std::move(associations)};
190
191 std::map<std::string, PropVariant> properties;
192 properties.emplace("Associations", std::move(value));
193
194 chassisAssociations.emplace(
195 path, std::make_unique<AssociationIntf>(utils::getBus(), path.c_str(),
196 properties));
197 }
198
getChassisPath()199 std::string OccDBusSensors::getChassisPath()
200 {
201 try
202 {
203 auto paths = utils::getSubtreePaths(std::vector{chassisInterface});
204
205 // For now, support either 1 chassis, or multiple as long as one
206 // of them has the standard name, which we will use. If this ever
207 // fails, then someone would have to figure out how to identify the
208 // chassis the OCCs are on.
209 if (paths.size() == 1)
210 {
211 return paths[0];
212 }
213 else if (std::find(paths.begin(), paths.end(), defaultChassisPath) ==
214 paths.end())
215 {
216 log<level::ERR>(
217 std::format(
218 "Could not find a chassis out of {} chassis objects",
219 paths.size())
220 .c_str());
221 // Can't throw an exception here, the sdeventplus timer
222 // just catches it.
223 abort();
224 }
225 }
226 catch (const std::exception& e)
227 {
228 log<level::ERR>(
229 std::format("Error looking up chassis objects: {}", e.what())
230 .c_str());
231 abort();
232 }
233
234 return defaultChassisPath;
235 }
236
hasDvfsTemp(const std::string & path) const237 bool OccDBusSensors::hasDvfsTemp(const std::string& path) const
238 {
239 return dvfsTemps.find(path) != dvfsTemps.end();
240 }
241
setDvfsTemp(const std::string & path,double value)242 void OccDBusSensors::setDvfsTemp(const std::string& path, double value)
243 {
244 dvfsTemps[path] = std::make_unique<SensorIntf>(utils::getBus(),
245 path.c_str());
246 dvfsTemps[path]->value(value);
247 }
248
249 } // namespace dbus
250 } // namespace occ
251 } // namespace open_power
252