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