blob: 048dc52ece17dcaef73a532d04789c95edb71799 [file] [log] [blame]
Krzysztof Grobelnyb5645942020-09-29 11:52:45 +02001#include "sensor.hpp"
2
Krzysztof Grobelnyb8cc78d2021-11-29 15:54:53 +01003#include "utils/clock.hpp"
4
Krzysztof Grobelnyb5645942020-09-29 11:52:45 +02005#include <boost/container/flat_map.hpp>
6#include <phosphor-logging/log.hpp>
7#include <sdbusplus/asio/property.hpp>
Krzysztof Grobelnyb5645942020-09-29 11:52:45 +02008
9#include <functional>
Krzysztof Grobelnyb5645942020-09-29 11:52:45 +020010
Krzysztof Grobelnyb8cc78d2021-11-29 15:54:53 +010011Sensor::Sensor(interfaces::Sensor::Id sensorId,
12 const std::string& sensorMetadata, boost::asio::io_context& ioc,
Krzysztof Grobelnyb5645942020-09-29 11:52:45 +020013 const std::shared_ptr<sdbusplus::asio::connection>& bus) :
14 sensorId(std::move(sensorId)),
Krzysztof Grobelnyb8cc78d2021-11-29 15:54:53 +010015 sensorMetadata(sensorMetadata), ioc(ioc), bus(bus)
Krzysztof Grobelnyb5645942020-09-29 11:52:45 +020016{}
17
18Sensor::Id Sensor::makeId(std::string_view service, std::string_view path)
19{
20 return Id("Sensor", service, path);
21}
22
23Sensor::Id Sensor::id() const
24{
25 return sensorId;
26}
27
Krzysztof Grobelnyb8cc78d2021-11-29 15:54:53 +010028std::string Sensor::metadata() const
29{
30 return sensorMetadata;
31}
32
Szymon Dompke94f71c52021-12-10 07:16:33 +010033std::string Sensor::getName() const
34{
35 return sensorMetadata.empty() ? sensorId.path : sensorMetadata;
36}
37
Krzysztof Grobelnyb5645942020-09-29 11:52:45 +020038void Sensor::async_read()
39{
40 uniqueCall([this](auto lock) { async_read(std::move(lock)); });
41}
42
43void Sensor::async_read(std::shared_ptr<utils::UniqueCall::Lock> lock)
44{
45 makeSignalMonitor();
46
47 sdbusplus::asio::getProperty<double>(
48 *bus, sensorId.service, sensorId.path,
49 "xyz.openbmc_project.Sensor.Value", "Value",
Ed Tanous0e7ae5d2021-02-23 14:06:49 -080050 [lock, id = sensorId, weakSelf = weak_from_this()](
51 boost::system::error_code ec, double newValue) {
Patrick Williams3a1c2972023-05-10 07:51:04 -050052 if (ec)
53 {
54 phosphor::logging::log<phosphor::logging::level::WARNING>(
55 "DBus 'GetProperty' call failed on Sensor Value",
56 phosphor::logging::entry("SENSOR_PATH=%s", id.path.c_str()),
57 phosphor::logging::entry("ERROR_CODE=%d", ec.value()));
58 return;
59 }
60 if (auto self = weakSelf.lock())
61 {
62 self->updateValue(newValue);
63 }
Patrick Williamsc7935fa2023-10-20 11:19:30 -050064 });
Krzysztof Grobelnyb5645942020-09-29 11:52:45 +020065}
66
67void Sensor::registerForUpdates(
68 const std::weak_ptr<interfaces::SensorListener>& weakListener)
69{
Krzysztof Grobelnyd2238192020-12-02 09:27:28 +000070 listeners.erase(
71 std::remove_if(listeners.begin(), listeners.end(),
72 [](const auto& listener) { return listener.expired(); }),
73 listeners.end());
74
Krzysztof Grobelnyb5645942020-09-29 11:52:45 +020075 if (auto listener = weakListener.lock())
76 {
77 listeners.emplace_back(weakListener);
78
79 if (value)
80 {
81 listener->sensorUpdated(*this, timestamp, *value);
82 }
83 else
84 {
85 async_read();
86 }
87 }
88}
89
Lukasz Kazmierczak7e098e92021-09-16 15:59:56 +020090void Sensor::unregisterFromUpdates(
91 const std::weak_ptr<interfaces::SensorListener>& weakListener)
92{
93 if (auto listener = weakListener.lock())
94 {
Patrick Williamsc7935fa2023-10-20 11:19:30 -050095 listeners.erase(std::remove_if(listeners.begin(), listeners.end(),
96 [listenerToUnregister = listener.get()](
97 const auto& listener) {
Patrick Williams3a1c2972023-05-10 07:51:04 -050098 return (listener.expired() ||
99 listener.lock().get() == listenerToUnregister);
Patrick Williamsc7935fa2023-10-20 11:19:30 -0500100 }),
101 listeners.end());
Lukasz Kazmierczak7e098e92021-09-16 15:59:56 +0200102 }
103}
104
Krzysztof Grobelnyb5645942020-09-29 11:52:45 +0200105void Sensor::updateValue(double newValue)
106{
Krzysztof Grobelny51f0fd52021-12-28 16:32:08 +0100107 timestamp = Clock().steadyTimestamp();
Krzysztof Grobelnyb5645942020-09-29 11:52:45 +0200108
Krzysztof Grobelnyf7ea2992022-01-27 11:04:58 +0100109 if (value != newValue)
Krzysztof Grobelnyb5645942020-09-29 11:52:45 +0200110 {
111 value = newValue;
112
113 for (const auto& weakListener : listeners)
114 {
115 if (auto listener = weakListener.lock())
116 {
117 listener->sensorUpdated(*this, timestamp, *value);
118 }
119 }
120 }
121}
122
123void Sensor::makeSignalMonitor()
124{
125 if (signalMonitor)
126 {
127 return;
128 }
129
130 using namespace std::string_literals;
131
132 const auto param = "type='signal',member='PropertiesChanged',path='"s +
133 sensorId.path +
134 "',arg0='xyz.openbmc_project.Sensor.Value'"s;
135
Patrick Williams3a62ee12021-12-03 10:13:25 -0600136 signalMonitor = std::make_unique<sdbusplus::bus::match_t>(
Krzysztof Grobelnyb5645942020-09-29 11:52:45 +0200137 *bus, param,
Patrick Williams39cc6ac2022-07-22 19:26:56 -0500138 [weakSelf = weak_from_this()](sdbusplus::message_t& message) {
Patrick Williams3a1c2972023-05-10 07:51:04 -0500139 signalProc(weakSelf, message);
Patrick Williamsc7935fa2023-10-20 11:19:30 -0500140 });
Krzysztof Grobelnyb5645942020-09-29 11:52:45 +0200141}
142
143void Sensor::signalProc(const std::weak_ptr<Sensor>& weakSelf,
Patrick Williams39cc6ac2022-07-22 19:26:56 -0500144 sdbusplus::message_t& message)
Krzysztof Grobelnyb5645942020-09-29 11:52:45 +0200145{
146 if (auto self = weakSelf.lock())
147 {
148 std::string iface;
149 boost::container::flat_map<std::string, ValueVariant>
150 changed_properties;
151 std::vector<std::string> invalidated_properties;
152
153 message.read(iface, changed_properties, invalidated_properties);
154
155 if (iface == "xyz.openbmc_project.Sensor.Value")
156 {
157 const auto it = changed_properties.find("Value");
158 if (it != changed_properties.end())
159 {
160 if (auto val = std::get_if<double>(&it->second))
161 {
162 self->updateValue(*val);
163 }
164 else
165 {
166 phosphor::logging::log<phosphor::logging::level::ERR>(
167 "Failed to receive Value from Sensor "
168 "PropertiesChanged signal",
Wludzik, Jozef982c5b52021-01-02 12:05:21 +0100169 phosphor::logging::entry("SENSOR_PATH=%s",
Krzysztof Grobelnyb5645942020-09-29 11:52:45 +0200170 self->sensorId.path.c_str()));
171 }
172 }
173 }
174 }
175}
Szymon Dompke94f71c52021-12-10 07:16:33 +0100176
177LabeledSensorInfo Sensor::getLabeledSensorInfo() const
178{
179 return LabeledSensorInfo(sensorId.service, sensorId.path, sensorMetadata);
180}