UpdateVirtualSensor uses information from signals
UpdateVirtualSensor uses information obtained from signals to avoid
extensive dbus queries.
Tested:
1:Execute DBus cmd to see if VirtualSensor can correctly obtain the
value of DbusSensor
busctl tree xyz.openbmc_project.VirtualSensor
busctl introspect xyz.openbmc_project.VirtualSensor xxx
2:Waiting for the value change of DbusSensor,Check if the value of
the virtual sensor has changed after the dbusSensor changes.
Fixes openbmc/phosphor-virtual-sensor#1
Change-Id: If11f9017b31ce5cf06f910a38c65637c55d74b24
Signed-off-by: Tao Lin <lintao.lc@ieisystem.com>
diff --git a/dbusSensor.cpp b/dbusSensor.cpp
new file mode 100644
index 0000000..f79705b
--- /dev/null
+++ b/dbusSensor.cpp
@@ -0,0 +1,152 @@
+#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