1e73bd0a1SAndrew Jeffery #pragma once
2e73bd0a1SAndrew Jeffery
3e73bd0a1SAndrew Jeffery #include "VariantVisitors.hpp"
4e73bd0a1SAndrew Jeffery
5e73bd0a1SAndrew Jeffery #include <boost/algorithm/string/replace.hpp>
6e73bd0a1SAndrew Jeffery #include <boost/asio/steady_timer.hpp>
7e73bd0a1SAndrew Jeffery #include <boost/container/flat_map.hpp>
8e73bd0a1SAndrew Jeffery #include <sdbusplus/asio/connection.hpp>
9e73bd0a1SAndrew Jeffery #include <sdbusplus/asio/object_server.hpp>
1018b6186eSEd Tanous #include <sdbusplus/bus/match.hpp>
1118b6186eSEd Tanous #include <sdbusplus/message.hpp>
1218b6186eSEd Tanous #include <sdbusplus/message/native_types.hpp>
13e73bd0a1SAndrew Jeffery
1418b6186eSEd Tanous #include <algorithm>
1518b6186eSEd Tanous #include <charconv>
1618b6186eSEd Tanous #include <chrono>
1718b6186eSEd Tanous #include <cmath>
1818b6186eSEd Tanous #include <cstddef>
1918b6186eSEd Tanous #include <cstdint>
20e73bd0a1SAndrew Jeffery #include <filesystem>
21e73bd0a1SAndrew Jeffery #include <functional>
22e73bd0a1SAndrew Jeffery #include <iostream>
23e73bd0a1SAndrew Jeffery #include <memory>
24e73bd0a1SAndrew Jeffery #include <optional>
25e73bd0a1SAndrew Jeffery #include <regex>
2618b6186eSEd Tanous #include <set>
27e73bd0a1SAndrew Jeffery #include <span>
2818b6186eSEd Tanous #include <stdexcept>
29e73bd0a1SAndrew Jeffery #include <string>
3018b6186eSEd Tanous #include <string_view>
3118b6186eSEd Tanous #include <system_error>
32e73bd0a1SAndrew Jeffery #include <tuple>
33e73bd0a1SAndrew Jeffery #include <utility>
34e73bd0a1SAndrew Jeffery #include <variant>
35e73bd0a1SAndrew Jeffery #include <vector>
36e73bd0a1SAndrew Jeffery
37e73bd0a1SAndrew Jeffery const constexpr char* jsonStore = "/var/configuration/flattened.json";
38e73bd0a1SAndrew Jeffery const constexpr char* inventoryPath = "/xyz/openbmc_project/inventory";
39e73bd0a1SAndrew Jeffery const constexpr char* entityManagerName = "xyz.openbmc_project.EntityManager";
40e73bd0a1SAndrew Jeffery
41e73bd0a1SAndrew Jeffery constexpr const char* cpuInventoryPath =
42e73bd0a1SAndrew Jeffery "/xyz/openbmc_project/inventory/system/chassis/motherboard";
43e73bd0a1SAndrew Jeffery const std::regex illegalDbusRegex("[^A-Za-z0-9_]");
44e73bd0a1SAndrew Jeffery
45e73bd0a1SAndrew Jeffery using BasicVariantType =
46e73bd0a1SAndrew Jeffery std::variant<std::vector<std::string>, std::string, int64_t, uint64_t,
47e73bd0a1SAndrew Jeffery double, int32_t, uint32_t, int16_t, uint16_t, uint8_t, bool>;
48e73bd0a1SAndrew Jeffery using SensorBaseConfigMap =
49e73bd0a1SAndrew Jeffery boost::container::flat_map<std::string, BasicVariantType>;
50e73bd0a1SAndrew Jeffery using SensorBaseConfiguration = std::pair<std::string, SensorBaseConfigMap>;
51e73bd0a1SAndrew Jeffery using SensorData = boost::container::flat_map<std::string, SensorBaseConfigMap>;
52e73bd0a1SAndrew Jeffery using ManagedObjectType =
53e73bd0a1SAndrew Jeffery boost::container::flat_map<sdbusplus::message::object_path, SensorData>;
54e73bd0a1SAndrew Jeffery
55e73bd0a1SAndrew Jeffery using GetSubTreeType = std::vector<
56e73bd0a1SAndrew Jeffery std::pair<std::string,
57e73bd0a1SAndrew Jeffery std::vector<std::pair<std::string, std::vector<std::string>>>>>;
58e73bd0a1SAndrew Jeffery using Association = std::tuple<std::string, std::string, std::string>;
59e73bd0a1SAndrew Jeffery
escapeName(const std::string & sensorName)60e73bd0a1SAndrew Jeffery inline std::string escapeName(const std::string& sensorName)
61e73bd0a1SAndrew Jeffery {
62e73bd0a1SAndrew Jeffery return boost::replace_all_copy(sensorName, " ", "_");
63e73bd0a1SAndrew Jeffery }
64e73bd0a1SAndrew Jeffery
65e73bd0a1SAndrew Jeffery enum class PowerState
66e73bd0a1SAndrew Jeffery {
67e73bd0a1SAndrew Jeffery on,
68e73bd0a1SAndrew Jeffery biosPost,
69e73bd0a1SAndrew Jeffery always,
70e73bd0a1SAndrew Jeffery chassisOn
71e73bd0a1SAndrew Jeffery };
72e73bd0a1SAndrew Jeffery
73e73bd0a1SAndrew Jeffery std::optional<std::string> openAndRead(const std::string& hwmonFile);
742aaf7175SPatrick Williams std::optional<std::string> getFullHwmonFilePath(
752aaf7175SPatrick Williams const std::string& directory, const std::string& hwmonBaseName,
76e73bd0a1SAndrew Jeffery const std::set<std::string>& permitSet);
77e73bd0a1SAndrew Jeffery std::set<std::string> getPermitSet(const SensorBaseConfigMap& config);
78e73bd0a1SAndrew Jeffery bool findFiles(const std::filesystem::path& dirPath,
79e73bd0a1SAndrew Jeffery std::string_view matchString,
80e73bd0a1SAndrew Jeffery std::vector<std::filesystem::path>& foundPaths,
81e73bd0a1SAndrew Jeffery int symlinkDepth = 1);
82201a1015SEd Tanous bool isPowerOn();
83201a1015SEd Tanous bool hasBiosPost();
84201a1015SEd Tanous bool isChassisOn();
85e73bd0a1SAndrew Jeffery void setupPowerMatchCallback(
86e73bd0a1SAndrew Jeffery const std::shared_ptr<sdbusplus::asio::connection>& conn,
87e73bd0a1SAndrew Jeffery std::function<void(PowerState type, bool state)>&& callback);
88e73bd0a1SAndrew Jeffery void setupPowerMatch(const std::shared_ptr<sdbusplus::asio::connection>& conn);
89e73bd0a1SAndrew Jeffery bool getSensorConfiguration(
90e73bd0a1SAndrew Jeffery const std::string& type,
91e73bd0a1SAndrew Jeffery const std::shared_ptr<sdbusplus::asio::connection>& dbusConnection,
92e73bd0a1SAndrew Jeffery ManagedObjectType& resp, bool useCache);
93e73bd0a1SAndrew Jeffery
94e73bd0a1SAndrew Jeffery void createAssociation(
95e73bd0a1SAndrew Jeffery std::shared_ptr<sdbusplus::asio::dbus_interface>& association,
96e73bd0a1SAndrew Jeffery const std::string& path);
97e73bd0a1SAndrew Jeffery
98e73bd0a1SAndrew Jeffery // replaces limits if MinReading and MaxReading are found.
99e73bd0a1SAndrew Jeffery void findLimits(std::pair<double, double>& limits,
100e73bd0a1SAndrew Jeffery const SensorBaseConfiguration* data);
101e73bd0a1SAndrew Jeffery
102e73bd0a1SAndrew Jeffery bool readingStateGood(const PowerState& powerState);
103e73bd0a1SAndrew Jeffery
104e73bd0a1SAndrew Jeffery constexpr const char* configInterfacePrefix =
105e73bd0a1SAndrew Jeffery "xyz.openbmc_project.Configuration.";
106e73bd0a1SAndrew Jeffery
configInterfaceName(const std::string & type)107e73bd0a1SAndrew Jeffery inline std::string configInterfaceName(const std::string& type)
108e73bd0a1SAndrew Jeffery {
109e73bd0a1SAndrew Jeffery return std::string(configInterfacePrefix) + type;
110e73bd0a1SAndrew Jeffery }
111e73bd0a1SAndrew Jeffery
112e73bd0a1SAndrew Jeffery namespace mapper
113e73bd0a1SAndrew Jeffery {
114e73bd0a1SAndrew Jeffery constexpr const char* busName = "xyz.openbmc_project.ObjectMapper";
115e73bd0a1SAndrew Jeffery constexpr const char* path = "/xyz/openbmc_project/object_mapper";
116e73bd0a1SAndrew Jeffery constexpr const char* interface = "xyz.openbmc_project.ObjectMapper";
117e73bd0a1SAndrew Jeffery constexpr const char* subtree = "GetSubTree";
118e73bd0a1SAndrew Jeffery } // namespace mapper
119e73bd0a1SAndrew Jeffery
120e73bd0a1SAndrew Jeffery namespace properties
121e73bd0a1SAndrew Jeffery {
122e73bd0a1SAndrew Jeffery constexpr const char* interface = "org.freedesktop.DBus.Properties";
123e73bd0a1SAndrew Jeffery constexpr const char* get = "Get";
124e73bd0a1SAndrew Jeffery constexpr const char* set = "Set";
125e73bd0a1SAndrew Jeffery } // namespace properties
126e73bd0a1SAndrew Jeffery
127e73bd0a1SAndrew Jeffery namespace power
128e73bd0a1SAndrew Jeffery {
129ef85e0bbSPotin Lai const static constexpr char* busname = "xyz.openbmc_project.State.Host0";
130e73bd0a1SAndrew Jeffery const static constexpr char* interface = "xyz.openbmc_project.State.Host";
131e73bd0a1SAndrew Jeffery const static constexpr char* path = "/xyz/openbmc_project/state/host0";
132e73bd0a1SAndrew Jeffery const static constexpr char* property = "CurrentHostState";
133e73bd0a1SAndrew Jeffery } // namespace power
134e73bd0a1SAndrew Jeffery
135e73bd0a1SAndrew Jeffery namespace chassis
136e73bd0a1SAndrew Jeffery {
137ea14f14aSPatrick Williams const static constexpr char* busname = "xyz.openbmc_project.State.Chassis0";
138e73bd0a1SAndrew Jeffery const static constexpr char* interface = "xyz.openbmc_project.State.Chassis";
139e73bd0a1SAndrew Jeffery const static constexpr char* path = "/xyz/openbmc_project/state/chassis0";
140e73bd0a1SAndrew Jeffery const static constexpr char* property = "CurrentPowerState";
141819eb323SThang Tran const static constexpr char* sOn = ".On";
142e73bd0a1SAndrew Jeffery } // namespace chassis
143e73bd0a1SAndrew Jeffery
144e73bd0a1SAndrew Jeffery namespace post
145e73bd0a1SAndrew Jeffery {
146ef85e0bbSPotin Lai const static constexpr char* busname = "xyz.openbmc_project.State.Host0";
147e73bd0a1SAndrew Jeffery const static constexpr char* interface =
148e73bd0a1SAndrew Jeffery "xyz.openbmc_project.State.OperatingSystem.Status";
149ef85e0bbSPotin Lai const static constexpr char* path = "/xyz/openbmc_project/state/host0";
150e73bd0a1SAndrew Jeffery const static constexpr char* property = "OperatingSystemState";
151e73bd0a1SAndrew Jeffery } // namespace post
152e73bd0a1SAndrew Jeffery
153e73bd0a1SAndrew Jeffery namespace association
154e73bd0a1SAndrew Jeffery {
155e73bd0a1SAndrew Jeffery const static constexpr char* interface =
156e73bd0a1SAndrew Jeffery "xyz.openbmc_project.Association.Definitions";
157e73bd0a1SAndrew Jeffery } // namespace association
158e73bd0a1SAndrew Jeffery
159e73bd0a1SAndrew Jeffery template <typename T>
loadVariant(const SensorBaseConfigMap & data,const std::string & key)160e73bd0a1SAndrew Jeffery inline T loadVariant(const SensorBaseConfigMap& data, const std::string& key)
161e73bd0a1SAndrew Jeffery {
162e73bd0a1SAndrew Jeffery auto it = data.find(key);
163e73bd0a1SAndrew Jeffery if (it == data.end())
164e73bd0a1SAndrew Jeffery {
165e73bd0a1SAndrew Jeffery std::cerr << "Configuration missing " << key << "\n";
166e73bd0a1SAndrew Jeffery throw std::invalid_argument("Key Missing");
167e73bd0a1SAndrew Jeffery }
168e73bd0a1SAndrew Jeffery if constexpr (std::is_same_v<T, double>)
169e73bd0a1SAndrew Jeffery {
170e73bd0a1SAndrew Jeffery return std::visit(VariantToDoubleVisitor(), it->second);
171e73bd0a1SAndrew Jeffery }
172e73bd0a1SAndrew Jeffery else if constexpr (std::is_unsigned_v<T>)
173e73bd0a1SAndrew Jeffery {
174e73bd0a1SAndrew Jeffery return std::visit(VariantToUnsignedIntVisitor(), it->second);
175e73bd0a1SAndrew Jeffery }
176e73bd0a1SAndrew Jeffery else if constexpr (std::is_same_v<T, std::string>)
177e73bd0a1SAndrew Jeffery {
178e73bd0a1SAndrew Jeffery return std::visit(VariantToStringVisitor(), it->second);
179e73bd0a1SAndrew Jeffery }
180e73bd0a1SAndrew Jeffery else
181e73bd0a1SAndrew Jeffery {
182e73bd0a1SAndrew Jeffery static_assert(!std::is_same_v<T, T>, "Type Not Implemented");
183e73bd0a1SAndrew Jeffery }
184e73bd0a1SAndrew Jeffery }
185e73bd0a1SAndrew Jeffery
setReadState(const std::string & str,PowerState & val)186e73bd0a1SAndrew Jeffery inline void setReadState(const std::string& str, PowerState& val)
187e73bd0a1SAndrew Jeffery {
188e73bd0a1SAndrew Jeffery if (str == "On")
189e73bd0a1SAndrew Jeffery {
190e73bd0a1SAndrew Jeffery val = PowerState::on;
191e73bd0a1SAndrew Jeffery }
192e73bd0a1SAndrew Jeffery else if (str == "BiosPost")
193e73bd0a1SAndrew Jeffery {
194e73bd0a1SAndrew Jeffery val = PowerState::biosPost;
195e73bd0a1SAndrew Jeffery }
196e73bd0a1SAndrew Jeffery else if (str == "Always")
197e73bd0a1SAndrew Jeffery {
198e73bd0a1SAndrew Jeffery val = PowerState::always;
199e73bd0a1SAndrew Jeffery }
200e73bd0a1SAndrew Jeffery else if (str == "ChassisOn")
201e73bd0a1SAndrew Jeffery {
202e73bd0a1SAndrew Jeffery val = PowerState::chassisOn;
203e73bd0a1SAndrew Jeffery }
204e73bd0a1SAndrew Jeffery }
205e73bd0a1SAndrew Jeffery
getPowerState(const SensorBaseConfigMap & cfg)206e73bd0a1SAndrew Jeffery inline PowerState getPowerState(const SensorBaseConfigMap& cfg)
207e73bd0a1SAndrew Jeffery {
208e73bd0a1SAndrew Jeffery PowerState state = PowerState::always;
209e73bd0a1SAndrew Jeffery auto findPowerState = cfg.find("PowerState");
210e73bd0a1SAndrew Jeffery if (findPowerState != cfg.end())
211e73bd0a1SAndrew Jeffery {
2122aaf7175SPatrick Williams std::string powerState =
2132aaf7175SPatrick Williams std::visit(VariantToStringVisitor(), findPowerState->second);
214e73bd0a1SAndrew Jeffery setReadState(powerState, state);
215e73bd0a1SAndrew Jeffery }
216e73bd0a1SAndrew Jeffery return state;
217e73bd0a1SAndrew Jeffery }
218e73bd0a1SAndrew Jeffery
getPollRate(const SensorBaseConfigMap & cfg,float dflt)219e73bd0a1SAndrew Jeffery inline float getPollRate(const SensorBaseConfigMap& cfg, float dflt)
220e73bd0a1SAndrew Jeffery {
221e73bd0a1SAndrew Jeffery float pollRate = dflt;
222e73bd0a1SAndrew Jeffery auto findPollRate = cfg.find("PollRate");
223e73bd0a1SAndrew Jeffery if (findPollRate != cfg.end())
224e73bd0a1SAndrew Jeffery {
225e73bd0a1SAndrew Jeffery pollRate = std::visit(VariantToFloatVisitor(), findPollRate->second);
226e73bd0a1SAndrew Jeffery if (!std::isfinite(pollRate) || pollRate <= 0.0F)
227e73bd0a1SAndrew Jeffery {
228e73bd0a1SAndrew Jeffery pollRate = dflt; // poll time invalid, fall back to default
229e73bd0a1SAndrew Jeffery }
230e73bd0a1SAndrew Jeffery }
231e73bd0a1SAndrew Jeffery return pollRate;
232e73bd0a1SAndrew Jeffery }
233e73bd0a1SAndrew Jeffery
setLed(const std::shared_ptr<sdbusplus::asio::connection> & conn,const std::string & name,bool on)234e73bd0a1SAndrew Jeffery inline void setLed(const std::shared_ptr<sdbusplus::asio::connection>& conn,
235e73bd0a1SAndrew Jeffery const std::string& name, bool on)
236e73bd0a1SAndrew Jeffery {
237e73bd0a1SAndrew Jeffery conn->async_method_call(
238e73bd0a1SAndrew Jeffery [name](const boost::system::error_code ec) {
239e73bd0a1SAndrew Jeffery if (ec)
240e73bd0a1SAndrew Jeffery {
241e73bd0a1SAndrew Jeffery std::cerr << "Failed to set LED " << name << "\n";
242e73bd0a1SAndrew Jeffery }
243e73bd0a1SAndrew Jeffery },
244e73bd0a1SAndrew Jeffery "xyz.openbmc_project.LED.GroupManager",
245e73bd0a1SAndrew Jeffery "/xyz/openbmc_project/led/groups/" + name, properties::interface,
246e73bd0a1SAndrew Jeffery properties::set, "xyz.openbmc_project.Led.Group", "Asserted",
247e73bd0a1SAndrew Jeffery std::variant<bool>(on));
248e73bd0a1SAndrew Jeffery }
249e73bd0a1SAndrew Jeffery
250e73bd0a1SAndrew Jeffery void createInventoryAssoc(
251e73bd0a1SAndrew Jeffery const std::shared_ptr<sdbusplus::asio::connection>& conn,
252e73bd0a1SAndrew Jeffery const std::shared_ptr<sdbusplus::asio::dbus_interface>& association,
253e73bd0a1SAndrew Jeffery const std::string& path);
254e73bd0a1SAndrew Jeffery
255e73bd0a1SAndrew Jeffery struct GetSensorConfiguration :
256e73bd0a1SAndrew Jeffery std::enable_shared_from_this<GetSensorConfiguration>
257e73bd0a1SAndrew Jeffery {
GetSensorConfigurationGetSensorConfiguration258e73bd0a1SAndrew Jeffery GetSensorConfiguration(
259e73bd0a1SAndrew Jeffery std::shared_ptr<sdbusplus::asio::connection> connection,
260e73bd0a1SAndrew Jeffery std::function<void(ManagedObjectType& resp)>&& callbackFunc) :
2612aaf7175SPatrick Williams dbusConnection(std::move(connection)), callback(std::move(callbackFunc))
262e73bd0a1SAndrew Jeffery {}
263e73bd0a1SAndrew Jeffery
getPathGetSensorConfiguration264e73bd0a1SAndrew Jeffery void getPath(const std::string& path, const std::string& interface,
265e73bd0a1SAndrew Jeffery const std::string& owner, size_t retries = 5)
266e73bd0a1SAndrew Jeffery {
267e73bd0a1SAndrew Jeffery if (retries > 5)
268e73bd0a1SAndrew Jeffery {
269e73bd0a1SAndrew Jeffery retries = 5;
270e73bd0a1SAndrew Jeffery }
271e73bd0a1SAndrew Jeffery std::shared_ptr<GetSensorConfiguration> self = shared_from_this();
272e73bd0a1SAndrew Jeffery
273e73bd0a1SAndrew Jeffery self->dbusConnection->async_method_call(
274e73bd0a1SAndrew Jeffery [self, path, interface, owner, retries](
275e73bd0a1SAndrew Jeffery const boost::system::error_code ec, SensorBaseConfigMap& data) {
276e73bd0a1SAndrew Jeffery if (ec)
277e73bd0a1SAndrew Jeffery {
278e73bd0a1SAndrew Jeffery if (retries == 0U)
279e73bd0a1SAndrew Jeffery {
280291c295bSPatrick Rudolph std::cerr << "Error getting " << path
281291c295bSPatrick Rudolph << ": no retries left\n";
282e73bd0a1SAndrew Jeffery return;
283e73bd0a1SAndrew Jeffery }
284291c295bSPatrick Rudolph std::cerr << "Error getting " << path << ": " << retries - 1
285291c295bSPatrick Rudolph << " retries left\n";
286e73bd0a1SAndrew Jeffery auto timer = std::make_shared<boost::asio::steady_timer>(
287e73bd0a1SAndrew Jeffery self->dbusConnection->get_io_context());
288e73bd0a1SAndrew Jeffery timer->expires_after(std::chrono::seconds(10));
289e73bd0a1SAndrew Jeffery timer->async_wait([self, timer, path, interface, owner,
290e73bd0a1SAndrew Jeffery retries](boost::system::error_code ec) {
291e73bd0a1SAndrew Jeffery if (ec)
292e73bd0a1SAndrew Jeffery {
293e73bd0a1SAndrew Jeffery std::cerr << "Timer error!\n";
294e73bd0a1SAndrew Jeffery return;
295e73bd0a1SAndrew Jeffery }
296e73bd0a1SAndrew Jeffery self->getPath(path, interface, owner, retries - 1);
297e73bd0a1SAndrew Jeffery });
298e73bd0a1SAndrew Jeffery return;
299e73bd0a1SAndrew Jeffery }
300e73bd0a1SAndrew Jeffery
301e73bd0a1SAndrew Jeffery self->respData[path][interface] = std::move(data);
302e73bd0a1SAndrew Jeffery },
303e73bd0a1SAndrew Jeffery owner, path, "org.freedesktop.DBus.Properties", "GetAll",
304e73bd0a1SAndrew Jeffery interface);
305e73bd0a1SAndrew Jeffery }
306e73bd0a1SAndrew Jeffery
getConfigurationGetSensorConfiguration307e73bd0a1SAndrew Jeffery void getConfiguration(const std::vector<std::string>& types,
308e73bd0a1SAndrew Jeffery size_t retries = 0)
309e73bd0a1SAndrew Jeffery {
310e73bd0a1SAndrew Jeffery if (retries > 5)
311e73bd0a1SAndrew Jeffery {
312e73bd0a1SAndrew Jeffery retries = 5;
313e73bd0a1SAndrew Jeffery }
314e73bd0a1SAndrew Jeffery
315e73bd0a1SAndrew Jeffery std::vector<std::string> interfaces(types.size());
316e73bd0a1SAndrew Jeffery for (const auto& type : types)
317e73bd0a1SAndrew Jeffery {
318e73bd0a1SAndrew Jeffery interfaces.push_back(configInterfaceName(type));
319e73bd0a1SAndrew Jeffery }
320e73bd0a1SAndrew Jeffery
321e73bd0a1SAndrew Jeffery std::shared_ptr<GetSensorConfiguration> self = shared_from_this();
322e73bd0a1SAndrew Jeffery dbusConnection->async_method_call(
323e73bd0a1SAndrew Jeffery [self, interfaces, retries](const boost::system::error_code ec,
324e73bd0a1SAndrew Jeffery const GetSubTreeType& ret) {
325e73bd0a1SAndrew Jeffery if (ec)
326e73bd0a1SAndrew Jeffery {
327e73bd0a1SAndrew Jeffery std::cerr << "Error calling mapper\n";
328e73bd0a1SAndrew Jeffery if (retries == 0U)
329e73bd0a1SAndrew Jeffery {
330e73bd0a1SAndrew Jeffery return;
331e73bd0a1SAndrew Jeffery }
332e73bd0a1SAndrew Jeffery auto timer = std::make_shared<boost::asio::steady_timer>(
333e73bd0a1SAndrew Jeffery self->dbusConnection->get_io_context());
334e73bd0a1SAndrew Jeffery timer->expires_after(std::chrono::seconds(10));
335e73bd0a1SAndrew Jeffery timer->async_wait([self, timer, interfaces,
336e73bd0a1SAndrew Jeffery retries](boost::system::error_code ec) {
337e73bd0a1SAndrew Jeffery if (ec)
338e73bd0a1SAndrew Jeffery {
339e73bd0a1SAndrew Jeffery std::cerr << "Timer error!\n";
340e73bd0a1SAndrew Jeffery return;
341e73bd0a1SAndrew Jeffery }
342e73bd0a1SAndrew Jeffery self->getConfiguration(interfaces, retries - 1);
343e73bd0a1SAndrew Jeffery });
344e73bd0a1SAndrew Jeffery
345e73bd0a1SAndrew Jeffery return;
346e73bd0a1SAndrew Jeffery }
347e73bd0a1SAndrew Jeffery for (const auto& [path, objDict] : ret)
348e73bd0a1SAndrew Jeffery {
349e73bd0a1SAndrew Jeffery if (objDict.empty())
350e73bd0a1SAndrew Jeffery {
351e73bd0a1SAndrew Jeffery return;
352e73bd0a1SAndrew Jeffery }
353e73bd0a1SAndrew Jeffery const std::string& owner = objDict.begin()->first;
354e73bd0a1SAndrew Jeffery
355e73bd0a1SAndrew Jeffery for (const std::string& interface : objDict.begin()->second)
356e73bd0a1SAndrew Jeffery {
357e73bd0a1SAndrew Jeffery // anything that starts with a requested configuration
358e73bd0a1SAndrew Jeffery // is good
3592aaf7175SPatrick Williams if (std::find_if(
3602aaf7175SPatrick Williams interfaces.begin(), interfaces.end(),
361e73bd0a1SAndrew Jeffery [interface](const std::string& possible) {
362e73bd0a1SAndrew Jeffery return interface.starts_with(possible);
363e73bd0a1SAndrew Jeffery }) == interfaces.end())
364e73bd0a1SAndrew Jeffery {
365e73bd0a1SAndrew Jeffery continue;
366e73bd0a1SAndrew Jeffery }
367e73bd0a1SAndrew Jeffery self->getPath(path, interface, owner);
368e73bd0a1SAndrew Jeffery }
369e73bd0a1SAndrew Jeffery }
370e73bd0a1SAndrew Jeffery },
371e73bd0a1SAndrew Jeffery mapper::busName, mapper::path, mapper::interface, mapper::subtree,
372e73bd0a1SAndrew Jeffery "/", 0, interfaces);
373e73bd0a1SAndrew Jeffery }
374e73bd0a1SAndrew Jeffery
~GetSensorConfigurationGetSensorConfiguration375e73bd0a1SAndrew Jeffery ~GetSensorConfiguration()
376e73bd0a1SAndrew Jeffery {
377e73bd0a1SAndrew Jeffery callback(respData);
378e73bd0a1SAndrew Jeffery }
379e73bd0a1SAndrew Jeffery
380e73bd0a1SAndrew Jeffery std::shared_ptr<sdbusplus::asio::connection> dbusConnection;
381e73bd0a1SAndrew Jeffery std::function<void(ManagedObjectType& resp)> callback;
382e73bd0a1SAndrew Jeffery ManagedObjectType respData;
383e73bd0a1SAndrew Jeffery };
384e73bd0a1SAndrew Jeffery
385e73bd0a1SAndrew Jeffery // The common scheme for sysfs files naming is: <type><number>_<item>.
386e73bd0a1SAndrew Jeffery // This function returns optionally these 3 elements as a tuple.
387*556e04b8SPatrick Williams std::optional<std::tuple<std::string, std::string, std::string>> splitFileName(
388*556e04b8SPatrick Williams const std::filesystem::path& filePath);
389e73bd0a1SAndrew Jeffery std::optional<double> readFile(const std::string& thresholdFile,
390e73bd0a1SAndrew Jeffery const double& scaleFactor);
391e73bd0a1SAndrew Jeffery void setupManufacturingModeMatch(sdbusplus::asio::connection& conn);
392e73bd0a1SAndrew Jeffery bool getManufacturingMode();
393e73bd0a1SAndrew Jeffery std::vector<std::unique_ptr<sdbusplus::bus::match_t>>
394e73bd0a1SAndrew Jeffery setupPropertiesChangedMatches(
395e73bd0a1SAndrew Jeffery sdbusplus::asio::connection& bus, std::span<const char* const> types,
396e73bd0a1SAndrew Jeffery const std::function<void(sdbusplus::message_t&)>& handler);
397278e177fSTom Tung
398278e177fSTom Tung template <typename T>
getDeviceBusAddr(const std::string & deviceName,T & bus,T & addr)399278e177fSTom Tung bool getDeviceBusAddr(const std::string& deviceName, T& bus, T& addr)
400278e177fSTom Tung {
401278e177fSTom Tung auto findHyphen = deviceName.find('-');
402278e177fSTom Tung if (findHyphen == std::string::npos)
403278e177fSTom Tung {
404278e177fSTom Tung std::cerr << "found bad device " << deviceName << "\n";
405278e177fSTom Tung return false;
406278e177fSTom Tung }
407278e177fSTom Tung std::string busStr = deviceName.substr(0, findHyphen);
408278e177fSTom Tung std::string addrStr = deviceName.substr(findHyphen + 1);
409278e177fSTom Tung
410278e177fSTom Tung std::from_chars_result res{};
411278e177fSTom Tung res = std::from_chars(&*busStr.begin(), &*busStr.end(), bus);
412278e177fSTom Tung if (res.ec != std::errc{} || res.ptr != &*busStr.end())
413278e177fSTom Tung {
414278e177fSTom Tung std::cerr << "Error finding bus for " << deviceName << "\n";
415278e177fSTom Tung return false;
416278e177fSTom Tung }
417278e177fSTom Tung res = std::from_chars(&*addrStr.begin(), &*addrStr.end(), addr, 16);
418278e177fSTom Tung if (res.ec != std::errc{} || res.ptr != &*addrStr.end())
419278e177fSTom Tung {
420278e177fSTom Tung std::cerr << "Error finding addr for " << deviceName << "\n";
421278e177fSTom Tung return false;
422278e177fSTom Tung }
423278e177fSTom Tung
424278e177fSTom Tung return true;
425278e177fSTom Tung }
426