#include "IpmbSDRSensor.hpp" #include "IpmbSensor.hpp" #include "Utils.hpp" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include std::unique_ptr initCmdTimer; boost::container::flat_map> sensors; boost::container::flat_map> sdrsensor; void sdrHandler( boost::container::flat_map> sdrsensor, sdbusplus::message_t& message, std::shared_ptr& dbusConnection) { std::string objectName; SensorBaseConfigMap values; message.read(objectName, values); auto findBus = values.find("Bus"); if (findBus == values.end()) { return; } uint8_t busIndex = loadVariant(values, "Bus"); auto& sdrsen = sdrsensor[busIndex]; sdrsen = nullptr; sdrsen = std::make_shared(dbusConnection, busIndex); sdrsen->getSDRRepositoryInfo(); } void reinitSensors(sdbusplus::message_t& message) { constexpr const size_t reinitWaitSeconds = 2; std::string objectName; boost::container::flat_map> values; message.read(objectName, values); auto findStatus = values.find(power::property); if (findStatus != values.end()) { bool powerStatus = std::get(findStatus->second).ends_with(".Running"); if (powerStatus) { if (!initCmdTimer) { // this should be impossible return; } // we seem to send this command too fast sometimes, wait before // sending initCmdTimer->expires_after( std::chrono::seconds(reinitWaitSeconds)); initCmdTimer->async_wait([](const boost::system::error_code ec) { if (ec == boost::asio::error::operation_aborted) { return; // we're being canceled } for (const auto& [name, sensor] : sensors) { if (sensor) { sensor->runInitCmd(); } } }); } } } int main() { boost::asio::io_context io; auto systemBus = std::make_shared(io); sdbusplus::asio::object_server objectServer(systemBus, true); objectServer.add_manager("/xyz/openbmc_project/sensors"); systemBus->request_name("xyz.openbmc_project.IpmbSensor"); initCmdTimer = std::make_unique(io); boost::asio::post(io, [&]() { createSensors(io, objectServer, sensors, systemBus); }); boost::asio::steady_timer configTimer(io); std::function eventHandler = [&](sdbusplus::message_t&) { configTimer.expires_after(std::chrono::seconds(1)); // create a timer because normally multiple properties change configTimer.async_wait([&](const boost::system::error_code& ec) { if (ec == boost::asio::error::operation_aborted) { return; // we're being canceled } createSensors(io, objectServer, sensors, systemBus); if (sensors.empty()) { std::cout << "Configuration not detected\n"; } }); }; std::vector> matches = setupPropertiesChangedMatches( *systemBus, std::to_array({sensorType}), eventHandler); sdbusplus::bus::match_t powerChangeMatch( static_cast(*systemBus), "type='signal',interface='" + std::string(properties::interface) + "',path='" + std::string(power::path) + "',arg0='" + std::string(power::interface) + "'", reinitSensors); auto matchSignal = std::make_shared( static_cast(*systemBus), "type='signal',member='PropertiesChanged',path_namespace='" + std::string(inventoryPath) + "',arg0namespace='" + configInterfaceName(sdrInterface) + "'", [&systemBus](sdbusplus::message_t& msg) { sdrHandler(sdrsensor, msg, systemBus); }); // Watch for entity-manager to remove configuration interfaces // so the corresponding sensors can be removed. auto ifaceRemovedMatch = std::make_shared( static_cast(*systemBus), "type='signal',member='InterfacesRemoved',arg0path='" + std::string(inventoryPath) + "/'", [](sdbusplus::message_t& msg) { interfaceRemoved(msg, sensors); }); setupManufacturingModeMatch(*systemBus); io.run(); return 0; }