#include "dbusSensor.hpp" #include "virtualSensor.hpp" #include #include #include static constexpr auto sensorIntf = sdbusplus::common::xyz::openbmc_project::sensor::Value::interface; /** When the Entity Manager removes the sensor, the interfaceRemoveSignal sent * uses the path /xyz/openbmc_project/sensors * */ static constexpr auto interfacesSensorPath = "/xyz/openbmc_project/sensors"; namespace phosphor::virtual_sensor { DbusSensor::DbusSensor(sdbusplus::bus_t& bus, const std::string& path, VirtualSensor& virtualSensor) : bus(bus), path(path), virtualSensor(virtualSensor), signalPropChange( bus, sdbusplus::bus::match::rules::propertiesChanged(path, sensorIntf), [this](sdbusplus::message_t& message) { handleDbusSignalPropChange(message); }), signalRemove( bus, sdbusplus::bus::match::rules::interfacesRemoved(interfacesSensorPath), [this](sdbusplus::message_t& message) { handleDbusSignalRemove(message); }) { initSensorValue(); } double DbusSensor::getSensorValue() { return value; } void DbusSensor::initSensorValue() { try { // If servName is not empty, reduce one DbusCall if (servName.empty()) { value = std::numeric_limits::quiet_NaN(); servName = getService(bus, path, sensorIntf); } if (!servName.empty()) { signalNameOwnerChanged.reset(); signalNameOwnerChanged = std::make_unique( bus, sdbusplus::bus::match::rules::nameOwnerChanged() + sdbusplus::bus::match::rules::arg0namespace(servName), [this](sdbusplus::message_t& message) { handleDbusSignalNameOwnerChanged(message); }); value = getDbusProperty(bus, servName, path, sensorIntf, "Value"); } } catch (const std::exception& e) { value = std::numeric_limits::quiet_NaN(); } return; } void DbusSensor::handleDbusSignalNameOwnerChanged(sdbusplus::message_t& msg) { try { auto [name, oldOwner, newOwner] = msg.unpack(); if (!oldOwner.empty() && !name.empty()) { if (name == servName) { // Connection removed value = std::numeric_limits::quiet_NaN(); virtualSensor.updateVirtualSensor(); } } } catch (const std::exception& e) { lg2::error("Error in dbusSensor NameOwnerChanged: {PATH} {ERROR}", "PATH", path, "ERROR", e); } } void DbusSensor::handleDbusSignalPropChange(sdbusplus::message_t& msg) { try { using SensorValuePropertiesVariant = sdbusplus::server::xyz:: openbmc_project::sensor::Value::PropertiesVariant; auto [msgIfce, msgData] = msg.unpack>(); std::string path = msg.get_path(); if (auto itr = msgData.find("Value"); itr != msgData.end()) { value = std::get(itr->second); if (!std::isfinite(value)) { value = std::numeric_limits::quiet_NaN(); } virtualSensor.updateVirtualSensor(); } } catch (const std::exception& e) { lg2::error("Error in dbusSensor PropertyChange: {PATH} {ERROR}", "PATH", path, "ERROR", e); } } void DbusSensor::handleDbusSignalRemove(sdbusplus::message_t& msg) { try { auto objPath = msg.unpack(); if (this->path == objPath) { value = std::numeric_limits::quiet_NaN(); virtualSensor.updateVirtualSensor(); } } catch (const std::exception& e) { lg2::error("Error in dbusSensor interfaceRemove: {PATH} {ERROR}", "PATH", path, "ERROR", e); } } } // namespace phosphor::virtual_sensor