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