#include "sensor.hpp" #include #include #include #include Sensor::Sensor(interfaces::Sensor::Id sensorId, boost::asio::io_context& ioc, const std::shared_ptr& bus) : sensorId(std::move(sensorId)), ioc(ioc), bus(bus) {} Sensor::Id Sensor::makeId(std::string_view service, std::string_view path) { return Id("Sensor", service, path); } Sensor::Id Sensor::id() const { return sensorId; } void Sensor::async_read() { uniqueCall([this](auto lock) { async_read(std::move(lock)); }); } void Sensor::async_read(std::shared_ptr lock) { makeSignalMonitor(); sdbusplus::asio::getProperty( *bus, sensorId.service, sensorId.path, "xyz.openbmc_project.Sensor.Value", "Value", [lock, id = sensorId, weakSelf = weak_from_this()]( boost::system::error_code ec, double newValue) { if (ec) { phosphor::logging::log( "DBus 'GetProperty' call failed on Sensor Value", phosphor::logging::entry("SENSOR_PATH=%s", id.path.c_str()), phosphor::logging::entry("ERROR_CODE=%d", ec.value())); return; } if (auto self = weakSelf.lock()) { self->updateValue(newValue); } }); } void Sensor::registerForUpdates( const std::weak_ptr& weakListener) { listeners.erase( std::remove_if(listeners.begin(), listeners.end(), [](const auto& listener) { return listener.expired(); }), listeners.end()); if (auto listener = weakListener.lock()) { listeners.emplace_back(weakListener); if (value) { listener->sensorUpdated(*this, timestamp, *value); } else { async_read(); } } } void Sensor::unregisterFromUpdates( const std::weak_ptr& weakListener) { if (auto listener = weakListener.lock()) { listeners.erase( std::remove_if( listeners.begin(), listeners.end(), [listenerToUnregister = listener.get()](const auto& listener) { return (listener.expired() || listener.lock().get() == listenerToUnregister); }), listeners.end()); } } void Sensor::updateValue(double newValue) { timestamp = std::time(0); if (value == newValue) { for (const auto& weakListener : listeners) { if (auto listener = weakListener.lock()) { listener->sensorUpdated(*this, timestamp); } } } else { value = newValue; for (const auto& weakListener : listeners) { if (auto listener = weakListener.lock()) { listener->sensorUpdated(*this, timestamp, *value); } } } } void Sensor::makeSignalMonitor() { if (signalMonitor) { return; } using namespace std::string_literals; const auto param = "type='signal',member='PropertiesChanged',path='"s + sensorId.path + "',arg0='xyz.openbmc_project.Sensor.Value'"s; signalMonitor = std::make_unique( *bus, param, [weakSelf = weak_from_this()](sdbusplus::message::message& message) { signalProc(weakSelf, message); }); } void Sensor::signalProc(const std::weak_ptr& weakSelf, sdbusplus::message::message& message) { if (auto self = weakSelf.lock()) { std::string iface; boost::container::flat_map changed_properties; std::vector invalidated_properties; message.read(iface, changed_properties, invalidated_properties); if (iface == "xyz.openbmc_project.Sensor.Value") { const auto it = changed_properties.find("Value"); if (it != changed_properties.end()) { if (auto val = std::get_if(&it->second)) { self->updateValue(*val); } else { phosphor::logging::log( "Failed to receive Value from Sensor " "PropertiesChanged signal", phosphor::logging::entry("SENSOR_PATH=%s", self->sensorId.path.c_str())); } } } } }