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