xref: /openbmc/phosphor-virtual-sensor/src/dbusSensor.cpp (revision 6272a39308bf6c1945edabf54891157c8079165a)
1*6272a393SAlexander Hansen #include "dbusSensor.hpp"
2*6272a393SAlexander Hansen 
3*6272a393SAlexander Hansen #include "virtualSensor.hpp"
4*6272a393SAlexander Hansen 
5*6272a393SAlexander Hansen #include <sdbusplus/bus.hpp>
6*6272a393SAlexander Hansen #include <sdbusplus/bus/match.hpp>
7*6272a393SAlexander Hansen 
8*6272a393SAlexander Hansen #include <cmath>
9*6272a393SAlexander Hansen static constexpr auto sensorIntf =
10*6272a393SAlexander Hansen     sdbusplus::common::xyz::openbmc_project::sensor::Value::interface;
11*6272a393SAlexander Hansen 
12*6272a393SAlexander Hansen /** When the Entity Manager removes the sensor, the interfaceRemoveSignal sent
13*6272a393SAlexander Hansen  * uses the path /xyz/openbmc_project/sensors
14*6272a393SAlexander Hansen  * */
15*6272a393SAlexander Hansen static constexpr auto interfacesSensorPath = "/xyz/openbmc_project/sensors";
16*6272a393SAlexander Hansen 
17*6272a393SAlexander Hansen namespace phosphor::virtual_sensor
18*6272a393SAlexander Hansen {
19*6272a393SAlexander Hansen 
DbusSensor(sdbusplus::bus_t & bus,const std::string & path,VirtualSensor & virtualSensor)20*6272a393SAlexander Hansen DbusSensor::DbusSensor(sdbusplus::bus_t& bus, const std::string& path,
21*6272a393SAlexander Hansen                        VirtualSensor& virtualSensor) :
22*6272a393SAlexander Hansen     bus(bus), path(path), virtualSensor(virtualSensor),
23*6272a393SAlexander Hansen     signalPropChange(
24*6272a393SAlexander Hansen         bus, sdbusplus::bus::match::rules::propertiesChanged(path, sensorIntf),
25*6272a393SAlexander Hansen         [this](sdbusplus::message_t& message) {
26*6272a393SAlexander Hansen             handleDbusSignalPropChange(message);
27*6272a393SAlexander Hansen         }),
28*6272a393SAlexander Hansen     signalRemove(
29*6272a393SAlexander Hansen         bus,
30*6272a393SAlexander Hansen         sdbusplus::bus::match::rules::interfacesRemoved(interfacesSensorPath),
__anoncb7820ff0202(sdbusplus::message_t& message) 31*6272a393SAlexander Hansen         [this](sdbusplus::message_t& message) {
32*6272a393SAlexander Hansen             handleDbusSignalRemove(message);
33*6272a393SAlexander Hansen         })
34*6272a393SAlexander Hansen {
35*6272a393SAlexander Hansen     initSensorValue();
36*6272a393SAlexander Hansen }
37*6272a393SAlexander Hansen 
getSensorValue()38*6272a393SAlexander Hansen double DbusSensor::getSensorValue()
39*6272a393SAlexander Hansen {
40*6272a393SAlexander Hansen     return value;
41*6272a393SAlexander Hansen }
42*6272a393SAlexander Hansen 
initSensorValue()43*6272a393SAlexander Hansen void DbusSensor::initSensorValue()
44*6272a393SAlexander Hansen {
45*6272a393SAlexander Hansen     try
46*6272a393SAlexander Hansen     {
47*6272a393SAlexander Hansen         // If servName is not empty, reduce one DbusCall
48*6272a393SAlexander Hansen         if (servName.empty())
49*6272a393SAlexander Hansen         {
50*6272a393SAlexander Hansen             value = std::numeric_limits<double>::quiet_NaN();
51*6272a393SAlexander Hansen             servName = getService(bus, path, sensorIntf);
52*6272a393SAlexander Hansen         }
53*6272a393SAlexander Hansen 
54*6272a393SAlexander Hansen         if (!servName.empty())
55*6272a393SAlexander Hansen         {
56*6272a393SAlexander Hansen             signalNameOwnerChanged.reset();
57*6272a393SAlexander Hansen             signalNameOwnerChanged = std::make_unique<sdbusplus::bus::match_t>(
58*6272a393SAlexander Hansen                 bus,
59*6272a393SAlexander Hansen                 sdbusplus::bus::match::rules::nameOwnerChanged() +
60*6272a393SAlexander Hansen                     sdbusplus::bus::match::rules::arg0namespace(servName),
61*6272a393SAlexander Hansen                 [this](sdbusplus::message_t& message) {
62*6272a393SAlexander Hansen                     handleDbusSignalNameOwnerChanged(message);
63*6272a393SAlexander Hansen                 });
64*6272a393SAlexander Hansen 
65*6272a393SAlexander Hansen             value = getDbusProperty<double>(bus, servName, path, sensorIntf,
66*6272a393SAlexander Hansen                                             "Value");
67*6272a393SAlexander Hansen         }
68*6272a393SAlexander Hansen     }
69*6272a393SAlexander Hansen     catch (const std::exception& e)
70*6272a393SAlexander Hansen     {
71*6272a393SAlexander Hansen         value = std::numeric_limits<double>::quiet_NaN();
72*6272a393SAlexander Hansen     }
73*6272a393SAlexander Hansen 
74*6272a393SAlexander Hansen     return;
75*6272a393SAlexander Hansen }
76*6272a393SAlexander Hansen 
handleDbusSignalNameOwnerChanged(sdbusplus::message_t & msg)77*6272a393SAlexander Hansen void DbusSensor::handleDbusSignalNameOwnerChanged(sdbusplus::message_t& msg)
78*6272a393SAlexander Hansen {
79*6272a393SAlexander Hansen     try
80*6272a393SAlexander Hansen     {
81*6272a393SAlexander Hansen         auto [name, oldOwner,
82*6272a393SAlexander Hansen               newOwner] = msg.unpack<std::string, std::string, std::string>();
83*6272a393SAlexander Hansen 
84*6272a393SAlexander Hansen         if (!oldOwner.empty() && !name.empty())
85*6272a393SAlexander Hansen         {
86*6272a393SAlexander Hansen             if (name == servName)
87*6272a393SAlexander Hansen             {
88*6272a393SAlexander Hansen                 // Connection removed
89*6272a393SAlexander Hansen 
90*6272a393SAlexander Hansen                 value = std::numeric_limits<double>::quiet_NaN();
91*6272a393SAlexander Hansen                 virtualSensor.updateVirtualSensor();
92*6272a393SAlexander Hansen             }
93*6272a393SAlexander Hansen         }
94*6272a393SAlexander Hansen     }
95*6272a393SAlexander Hansen     catch (const std::exception& e)
96*6272a393SAlexander Hansen     {
97*6272a393SAlexander Hansen         lg2::error("Error in dbusSensor NameOwnerChanged: {PATH}  {ERROR}",
98*6272a393SAlexander Hansen                    "PATH", path, "ERROR", e);
99*6272a393SAlexander Hansen     }
100*6272a393SAlexander Hansen }
101*6272a393SAlexander Hansen 
handleDbusSignalPropChange(sdbusplus::message_t & msg)102*6272a393SAlexander Hansen void DbusSensor::handleDbusSignalPropChange(sdbusplus::message_t& msg)
103*6272a393SAlexander Hansen {
104*6272a393SAlexander Hansen     try
105*6272a393SAlexander Hansen     {
106*6272a393SAlexander Hansen         using SensorValuePropertiesVariant = sdbusplus::server::xyz::
107*6272a393SAlexander Hansen             openbmc_project::sensor::Value::PropertiesVariant;
108*6272a393SAlexander Hansen         auto [msgIfce, msgData] =
109*6272a393SAlexander Hansen             msg.unpack<std::string,
110*6272a393SAlexander Hansen                        std::map<std::string, SensorValuePropertiesVariant>>();
111*6272a393SAlexander Hansen 
112*6272a393SAlexander Hansen         if (auto itr = msgData.find("Value"); itr != msgData.end())
113*6272a393SAlexander Hansen         {
114*6272a393SAlexander Hansen             double tmpValue = std::get<double>(itr->second);
115*6272a393SAlexander Hansen             if (!std::isfinite(tmpValue))
116*6272a393SAlexander Hansen             {
117*6272a393SAlexander Hansen                 if (std::isnan(value))
118*6272a393SAlexander Hansen                 {
119*6272a393SAlexander Hansen                     return;
120*6272a393SAlexander Hansen                 }
121*6272a393SAlexander Hansen 
122*6272a393SAlexander Hansen                 tmpValue = std::numeric_limits<double>::quiet_NaN();
123*6272a393SAlexander Hansen             }
124*6272a393SAlexander Hansen 
125*6272a393SAlexander Hansen             if (tmpValue != value)
126*6272a393SAlexander Hansen             {
127*6272a393SAlexander Hansen                 value = tmpValue;
128*6272a393SAlexander Hansen                 virtualSensor.updateVirtualSensor();
129*6272a393SAlexander Hansen             }
130*6272a393SAlexander Hansen         }
131*6272a393SAlexander Hansen     }
132*6272a393SAlexander Hansen     catch (const std::exception& e)
133*6272a393SAlexander Hansen     {
134*6272a393SAlexander Hansen         lg2::error("Error in dbusSensor PropertyChange: {PATH}  {ERROR}",
135*6272a393SAlexander Hansen                    "PATH", path, "ERROR", e);
136*6272a393SAlexander Hansen     }
137*6272a393SAlexander Hansen }
138*6272a393SAlexander Hansen 
handleDbusSignalRemove(sdbusplus::message_t & msg)139*6272a393SAlexander Hansen void DbusSensor::handleDbusSignalRemove(sdbusplus::message_t& msg)
140*6272a393SAlexander Hansen {
141*6272a393SAlexander Hansen     try
142*6272a393SAlexander Hansen     {
143*6272a393SAlexander Hansen         auto objPath = msg.unpack<sdbusplus::message::object_path>();
144*6272a393SAlexander Hansen 
145*6272a393SAlexander Hansen         if (this->path == objPath)
146*6272a393SAlexander Hansen         {
147*6272a393SAlexander Hansen             value = std::numeric_limits<double>::quiet_NaN();
148*6272a393SAlexander Hansen             virtualSensor.updateVirtualSensor();
149*6272a393SAlexander Hansen         }
150*6272a393SAlexander Hansen     }
151*6272a393SAlexander Hansen     catch (const std::exception& e)
152*6272a393SAlexander Hansen     {
153*6272a393SAlexander Hansen         lg2::error("Error in dbusSensor interfaceRemove: {PATH}  {ERROR}",
154*6272a393SAlexander Hansen                    "PATH", path, "ERROR", e);
155*6272a393SAlexander Hansen     }
156*6272a393SAlexander Hansen }
157*6272a393SAlexander Hansen 
158*6272a393SAlexander Hansen } // namespace phosphor::virtual_sensor
159