blob: f79705bd964e5bc58ef78e23de600030ceb30537 [file] [log] [blame]
#include "dbusSensor.hpp"
#include "virtualSensor.hpp"
#include <sdbusplus/bus.hpp>
#include <sdbusplus/bus/match.hpp>
#include <cmath>
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<double>::quiet_NaN();
servName = getService(bus, path, sensorIntf);
}
if (!servName.empty())
{
signalNameOwnerChanged.reset();
signalNameOwnerChanged = std::make_unique<sdbusplus::bus::match_t>(
bus,
sdbusplus::bus::match::rules::nameOwnerChanged() +
sdbusplus::bus::match::rules::arg0namespace(servName),
[this](sdbusplus::message_t& message) {
handleDbusSignalNameOwnerChanged(message);
});
value = getDbusProperty<double>(bus, servName, path, sensorIntf,
"Value");
}
}
catch (const std::exception& e)
{
value = std::numeric_limits<double>::quiet_NaN();
}
return;
}
void DbusSensor::handleDbusSignalNameOwnerChanged(sdbusplus::message_t& msg)
{
try
{
auto [name, oldOwner,
newOwner] = msg.unpack<std::string, std::string, std::string>();
if (!oldOwner.empty() && !name.empty())
{
if (name == servName)
{
// Connection removed
value = std::numeric_limits<double>::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,
std::map<std::string, SensorValuePropertiesVariant>>();
std::string path = msg.get_path();
if (auto itr = msgData.find("Value"); itr != msgData.end())
{
value = std::get<double>(itr->second);
if (!std::isfinite(value))
{
value = std::numeric_limits<double>::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<sdbusplus::message::object_path>();
if (this->path == objPath)
{
value = std::numeric_limits<double>::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