xref: /openbmc/telemetry/src/sensor.cpp (revision 583ba441654657bb4ba9d051b747144a7258c159)
1b5645947SKrzysztof Grobelny #include "sensor.hpp"
2b5645947SKrzysztof Grobelny 
3b8cc78ddSKrzysztof Grobelny #include "utils/clock.hpp"
4b8cc78ddSKrzysztof Grobelny 
5b5645947SKrzysztof Grobelny #include <boost/container/flat_map.hpp>
6b5645947SKrzysztof Grobelny #include <phosphor-logging/log.hpp>
7b5645947SKrzysztof Grobelny #include <sdbusplus/asio/property.hpp>
8b5645947SKrzysztof Grobelny 
9b5645947SKrzysztof Grobelny #include <functional>
10b5645947SKrzysztof Grobelny 
Sensor(interfaces::Sensor::Id sensorId,const std::string & sensorMetadata,boost::asio::io_context & ioc,const std::shared_ptr<sdbusplus::asio::connection> & bus)11b8cc78ddSKrzysztof Grobelny Sensor::Sensor(interfaces::Sensor::Id sensorId,
12b8cc78ddSKrzysztof Grobelny                const std::string& sensorMetadata, boost::asio::io_context& ioc,
13b5645947SKrzysztof Grobelny                const std::shared_ptr<sdbusplus::asio::connection>& bus) :
14f535cad6SPatrick Williams     sensorId(std::move(sensorId)), sensorMetadata(sensorMetadata), ioc(ioc),
15f535cad6SPatrick Williams     bus(bus)
16b5645947SKrzysztof Grobelny {}
17b5645947SKrzysztof Grobelny 
makeId(std::string_view service,std::string_view path)18b5645947SKrzysztof Grobelny Sensor::Id Sensor::makeId(std::string_view service, std::string_view path)
19b5645947SKrzysztof Grobelny {
20b5645947SKrzysztof Grobelny     return Id("Sensor", service, path);
21b5645947SKrzysztof Grobelny }
22b5645947SKrzysztof Grobelny 
id() const23b5645947SKrzysztof Grobelny Sensor::Id Sensor::id() const
24b5645947SKrzysztof Grobelny {
25b5645947SKrzysztof Grobelny     return sensorId;
26b5645947SKrzysztof Grobelny }
27b5645947SKrzysztof Grobelny 
metadata() const28b8cc78ddSKrzysztof Grobelny std::string Sensor::metadata() const
29b8cc78ddSKrzysztof Grobelny {
30b8cc78ddSKrzysztof Grobelny     return sensorMetadata;
31b8cc78ddSKrzysztof Grobelny }
32b8cc78ddSKrzysztof Grobelny 
getName() const3394f71c51SSzymon Dompke std::string Sensor::getName() const
3494f71c51SSzymon Dompke {
3594f71c51SSzymon Dompke     return sensorMetadata.empty() ? sensorId.path : sensorMetadata;
3694f71c51SSzymon Dompke }
3794f71c51SSzymon Dompke 
async_read()38b5645947SKrzysztof Grobelny void Sensor::async_read()
39b5645947SKrzysztof Grobelny {
40b5645947SKrzysztof Grobelny     uniqueCall([this](auto lock) { async_read(std::move(lock)); });
41b5645947SKrzysztof Grobelny }
42b5645947SKrzysztof Grobelny 
async_read(std::shared_ptr<utils::UniqueCall::Lock> lock)43b5645947SKrzysztof Grobelny void Sensor::async_read(std::shared_ptr<utils::UniqueCall::Lock> lock)
44b5645947SKrzysztof Grobelny {
45b5645947SKrzysztof Grobelny     makeSignalMonitor();
46b5645947SKrzysztof Grobelny 
47b5645947SKrzysztof Grobelny     sdbusplus::asio::getProperty<double>(
48b5645947SKrzysztof Grobelny         *bus, sensorId.service, sensorId.path,
49b5645947SKrzysztof Grobelny         "xyz.openbmc_project.Sensor.Value", "Value",
500e7ae5dbSEd Tanous         [lock, id = sensorId, weakSelf = weak_from_this()](
510e7ae5dbSEd Tanous             boost::system::error_code ec, double newValue) {
520e7ae5dbSEd Tanous             if (ec)
530e7ae5dbSEd Tanous             {
545ade2b1dSWludzik, Jozef                 phosphor::logging::log<phosphor::logging::level::WARNING>(
55b5645947SKrzysztof Grobelny                     "DBus 'GetProperty' call failed on Sensor Value",
56982c5b5bSWludzik, Jozef                     phosphor::logging::entry("SENSOR_PATH=%s", id.path.c_str()),
57982c5b5bSWludzik, Jozef                     phosphor::logging::entry("ERROR_CODE=%d", ec.value()));
580e7ae5dbSEd Tanous                 return;
590e7ae5dbSEd Tanous             }
60b5645947SKrzysztof Grobelny             if (auto self = weakSelf.lock())
61b5645947SKrzysztof Grobelny             {
62b5645947SKrzysztof Grobelny                 self->updateValue(newValue);
63b5645947SKrzysztof Grobelny             }
64b5645947SKrzysztof Grobelny         });
65b5645947SKrzysztof Grobelny }
66b5645947SKrzysztof Grobelny 
registerForUpdates(const std::weak_ptr<interfaces::SensorListener> & weakListener)67b5645947SKrzysztof Grobelny void Sensor::registerForUpdates(
68b5645947SKrzysztof Grobelny     const std::weak_ptr<interfaces::SensorListener>& weakListener)
69b5645947SKrzysztof Grobelny {
70d2238194SKrzysztof Grobelny     listeners.erase(
71d2238194SKrzysztof Grobelny         std::remove_if(listeners.begin(), listeners.end(),
72d2238194SKrzysztof Grobelny                        [](const auto& listener) { return listener.expired(); }),
73d2238194SKrzysztof Grobelny         listeners.end());
74d2238194SKrzysztof Grobelny 
75b5645947SKrzysztof Grobelny     if (auto listener = weakListener.lock())
76b5645947SKrzysztof Grobelny     {
77b5645947SKrzysztof Grobelny         listeners.emplace_back(weakListener);
78b5645947SKrzysztof Grobelny 
79b5645947SKrzysztof Grobelny         if (value)
80b5645947SKrzysztof Grobelny         {
81b5645947SKrzysztof Grobelny             listener->sensorUpdated(*this, timestamp, *value);
82b5645947SKrzysztof Grobelny         }
83b5645947SKrzysztof Grobelny         else
84b5645947SKrzysztof Grobelny         {
85b5645947SKrzysztof Grobelny             async_read();
86b5645947SKrzysztof Grobelny         }
87b5645947SKrzysztof Grobelny     }
88b5645947SKrzysztof Grobelny }
89b5645947SKrzysztof Grobelny 
unregisterFromUpdates(const std::weak_ptr<interfaces::SensorListener> & weakListener)907e098e93SLukasz Kazmierczak void Sensor::unregisterFromUpdates(
917e098e93SLukasz Kazmierczak     const std::weak_ptr<interfaces::SensorListener>& weakListener)
927e098e93SLukasz Kazmierczak {
937e098e93SLukasz Kazmierczak     if (auto listener = weakListener.lock())
947e098e93SLukasz Kazmierczak     {
95*583ba441SPatrick Williams         listeners.erase(
96*583ba441SPatrick Williams             std::remove_if(
97*583ba441SPatrick Williams                 listeners.begin(), listeners.end(),
98*583ba441SPatrick Williams                 [listenerToUnregister = listener.get()](const auto& listener) {
997e098e93SLukasz Kazmierczak                     return (listener.expired() ||
1007e098e93SLukasz Kazmierczak                             listener.lock().get() == listenerToUnregister);
1017e098e93SLukasz Kazmierczak                 }),
1027e098e93SLukasz Kazmierczak             listeners.end());
1037e098e93SLukasz Kazmierczak     }
1047e098e93SLukasz Kazmierczak }
1057e098e93SLukasz Kazmierczak 
updateValue(double newValue)106b5645947SKrzysztof Grobelny void Sensor::updateValue(double newValue)
107b5645947SKrzysztof Grobelny {
10851f0fd50SKrzysztof Grobelny     timestamp = Clock().steadyTimestamp();
109b5645947SKrzysztof Grobelny 
110f7ea2997SKrzysztof Grobelny     if (value != newValue)
111b5645947SKrzysztof Grobelny     {
112b5645947SKrzysztof Grobelny         value = newValue;
113b5645947SKrzysztof Grobelny 
114b5645947SKrzysztof Grobelny         for (const auto& weakListener : listeners)
115b5645947SKrzysztof Grobelny         {
116b5645947SKrzysztof Grobelny             if (auto listener = weakListener.lock())
117b5645947SKrzysztof Grobelny             {
118b5645947SKrzysztof Grobelny                 listener->sensorUpdated(*this, timestamp, *value);
119b5645947SKrzysztof Grobelny             }
120b5645947SKrzysztof Grobelny         }
121b5645947SKrzysztof Grobelny     }
122b5645947SKrzysztof Grobelny }
123b5645947SKrzysztof Grobelny 
makeSignalMonitor()124b5645947SKrzysztof Grobelny void Sensor::makeSignalMonitor()
125b5645947SKrzysztof Grobelny {
126b5645947SKrzysztof Grobelny     if (signalMonitor)
127b5645947SKrzysztof Grobelny     {
128b5645947SKrzysztof Grobelny         return;
129b5645947SKrzysztof Grobelny     }
130b5645947SKrzysztof Grobelny 
131b5645947SKrzysztof Grobelny     using namespace std::string_literals;
132b5645947SKrzysztof Grobelny 
133*583ba441SPatrick Williams     const auto param =
134*583ba441SPatrick Williams         "type='signal',member='PropertiesChanged',path='"s + sensorId.path +
135b5645947SKrzysztof Grobelny         "',arg0='xyz.openbmc_project.Sensor.Value'"s;
136b5645947SKrzysztof Grobelny 
1373a62ee15SPatrick Williams     signalMonitor = std::make_unique<sdbusplus::bus::match_t>(
138b5645947SKrzysztof Grobelny         *bus, param,
13939cc6ac9SPatrick Williams         [weakSelf = weak_from_this()](sdbusplus::message_t& message) {
140b5645947SKrzysztof Grobelny             signalProc(weakSelf, message);
141b5645947SKrzysztof Grobelny         });
142b5645947SKrzysztof Grobelny }
143b5645947SKrzysztof Grobelny 
signalProc(const std::weak_ptr<Sensor> & weakSelf,sdbusplus::message_t & message)144b5645947SKrzysztof Grobelny void Sensor::signalProc(const std::weak_ptr<Sensor>& weakSelf,
14539cc6ac9SPatrick Williams                         sdbusplus::message_t& message)
146b5645947SKrzysztof Grobelny {
147b5645947SKrzysztof Grobelny     if (auto self = weakSelf.lock())
148b5645947SKrzysztof Grobelny     {
149b5645947SKrzysztof Grobelny         std::string iface;
150b5645947SKrzysztof Grobelny         boost::container::flat_map<std::string, ValueVariant>
151b5645947SKrzysztof Grobelny             changed_properties;
152b5645947SKrzysztof Grobelny         std::vector<std::string> invalidated_properties;
153b5645947SKrzysztof Grobelny 
154b5645947SKrzysztof Grobelny         message.read(iface, changed_properties, invalidated_properties);
155b5645947SKrzysztof Grobelny 
156b5645947SKrzysztof Grobelny         if (iface == "xyz.openbmc_project.Sensor.Value")
157b5645947SKrzysztof Grobelny         {
158b5645947SKrzysztof Grobelny             const auto it = changed_properties.find("Value");
159b5645947SKrzysztof Grobelny             if (it != changed_properties.end())
160b5645947SKrzysztof Grobelny             {
161b5645947SKrzysztof Grobelny                 if (auto val = std::get_if<double>(&it->second))
162b5645947SKrzysztof Grobelny                 {
163b5645947SKrzysztof Grobelny                     self->updateValue(*val);
164b5645947SKrzysztof Grobelny                 }
165b5645947SKrzysztof Grobelny                 else
166b5645947SKrzysztof Grobelny                 {
167b5645947SKrzysztof Grobelny                     phosphor::logging::log<phosphor::logging::level::ERR>(
168b5645947SKrzysztof Grobelny                         "Failed to receive Value from Sensor "
169b5645947SKrzysztof Grobelny                         "PropertiesChanged signal",
170982c5b5bSWludzik, Jozef                         phosphor::logging::entry("SENSOR_PATH=%s",
171b5645947SKrzysztof Grobelny                                                  self->sensorId.path.c_str()));
172b5645947SKrzysztof Grobelny                 }
173b5645947SKrzysztof Grobelny             }
174b5645947SKrzysztof Grobelny         }
175b5645947SKrzysztof Grobelny     }
176b5645947SKrzysztof Grobelny }
17794f71c51SSzymon Dompke 
getLabeledSensorInfo() const17894f71c51SSzymon Dompke LabeledSensorInfo Sensor::getLabeledSensorInfo() const
17994f71c51SSzymon Dompke {
18094f71c51SSzymon Dompke     return LabeledSensorInfo(sensorId.service, sensorId.path, sensorMetadata);
18194f71c51SSzymon Dompke }
182