blob: ce25a86400975f2015d122993603b64b9300a2e1 [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) {
52 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 }
Krzysztof Grobelnyb5645942020-09-29 11:52:45 +020060 if (auto self = weakSelf.lock())
61 {
62 self->updateValue(newValue);
63 }
64 });
65}
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 {
95 listeners.erase(
96 std::remove_if(
97 listeners.begin(), listeners.end(),
98 [listenerToUnregister = listener.get()](const auto& listener) {
99 return (listener.expired() ||
100 listener.lock().get() == listenerToUnregister);
101 }),
102 listeners.end());
103 }
104}
105
Krzysztof Grobelnyb5645942020-09-29 11:52:45 +0200106void Sensor::updateValue(double newValue)
107{
Krzysztof Grobelny51f0fd52021-12-28 16:32:08 +0100108 timestamp = Clock().steadyTimestamp();
Krzysztof Grobelnyb5645942020-09-29 11:52:45 +0200109
Krzysztof Grobelnyf7ea2992022-01-27 11:04:58 +0100110 if (value != newValue)
Krzysztof Grobelnyb5645942020-09-29 11:52:45 +0200111 {
112 value = newValue;
113
114 for (const auto& weakListener : listeners)
115 {
116 if (auto listener = weakListener.lock())
117 {
118 listener->sensorUpdated(*this, timestamp, *value);
119 }
120 }
121 }
122}
123
124void Sensor::makeSignalMonitor()
125{
126 if (signalMonitor)
127 {
128 return;
129 }
130
131 using namespace std::string_literals;
132
133 const auto param = "type='signal',member='PropertiesChanged',path='"s +
134 sensorId.path +
135 "',arg0='xyz.openbmc_project.Sensor.Value'"s;
136
Patrick Williams3a62ee12021-12-03 10:13:25 -0600137 signalMonitor = std::make_unique<sdbusplus::bus::match_t>(
Krzysztof Grobelnyb5645942020-09-29 11:52:45 +0200138 *bus, param,
Patrick Williams39cc6ac2022-07-22 19:26:56 -0500139 [weakSelf = weak_from_this()](sdbusplus::message_t& message) {
Krzysztof Grobelnyb5645942020-09-29 11:52:45 +0200140 signalProc(weakSelf, message);
141 });
142}
143
144void Sensor::signalProc(const std::weak_ptr<Sensor>& weakSelf,
Patrick Williams39cc6ac2022-07-22 19:26:56 -0500145 sdbusplus::message_t& message)
Krzysztof Grobelnyb5645942020-09-29 11:52:45 +0200146{
147 if (auto self = weakSelf.lock())
148 {
149 std::string iface;
150 boost::container::flat_map<std::string, ValueVariant>
151 changed_properties;
152 std::vector<std::string> invalidated_properties;
153
154 message.read(iface, changed_properties, invalidated_properties);
155
156 if (iface == "xyz.openbmc_project.Sensor.Value")
157 {
158 const auto it = changed_properties.find("Value");
159 if (it != changed_properties.end())
160 {
161 if (auto val = std::get_if<double>(&it->second))
162 {
163 self->updateValue(*val);
164 }
165 else
166 {
167 phosphor::logging::log<phosphor::logging::level::ERR>(
168 "Failed to receive Value from Sensor "
169 "PropertiesChanged signal",
Wludzik, Jozef982c5b52021-01-02 12:05:21 +0100170 phosphor::logging::entry("SENSOR_PATH=%s",
Krzysztof Grobelnyb5645942020-09-29 11:52:45 +0200171 self->sensorId.path.c_str()));
172 }
173 }
174 }
175 }
176}
Szymon Dompke94f71c52021-12-10 07:16:33 +0100177
178LabeledSensorInfo Sensor::getLabeledSensorInfo() const
179{
180 return LabeledSensorInfo(sensorId.service, sensorId.path, sensorMetadata);
181}