blob: 644de2ff1bd04a7ead8a6e3a8975f25e8c1d6b5d [file] [log] [blame]
Krzysztof Grobelnyb5645942020-09-29 11:52:45 +02001#include "sensor.hpp"
2
Krzysztof Grobelnyb5645942020-09-29 11:52:45 +02003#include <boost/container/flat_map.hpp>
4#include <phosphor-logging/log.hpp>
5#include <sdbusplus/asio/property.hpp>
Krzysztof Grobelnyb5645942020-09-29 11:52:45 +02006
7#include <functional>
Krzysztof Grobelnyb5645942020-09-29 11:52:45 +02008
9Sensor::Sensor(interfaces::Sensor::Id sensorId, boost::asio::io_context& ioc,
10 const std::shared_ptr<sdbusplus::asio::connection>& bus) :
11 sensorId(std::move(sensorId)),
12 ioc(ioc), bus(bus)
13{}
14
15Sensor::Id Sensor::makeId(std::string_view service, std::string_view path)
16{
17 return Id("Sensor", service, path);
18}
19
20Sensor::Id Sensor::id() const
21{
22 return sensorId;
23}
24
25void Sensor::async_read()
26{
27 uniqueCall([this](auto lock) { async_read(std::move(lock)); });
28}
29
30void Sensor::async_read(std::shared_ptr<utils::UniqueCall::Lock> lock)
31{
32 makeSignalMonitor();
33
34 sdbusplus::asio::getProperty<double>(
35 *bus, sensorId.service, sensorId.path,
36 "xyz.openbmc_project.Sensor.Value", "Value",
Ed Tanous0e7ae5d2021-02-23 14:06:49 -080037 [lock, id = sensorId, weakSelf = weak_from_this()](
38 boost::system::error_code ec, double newValue) {
39 if (ec)
40 {
41 phosphor::logging::log<phosphor::logging::level::WARNING>(
42 "DBus 'GetProperty' call failed on Sensor Value",
43 phosphor::logging::entry("SENSOR_PATH=%s", id.path.c_str()),
44 phosphor::logging::entry("ERROR_CODE=%d", ec.value()));
45 return;
46 }
Krzysztof Grobelnyb5645942020-09-29 11:52:45 +020047 if (auto self = weakSelf.lock())
48 {
49 self->updateValue(newValue);
50 }
51 });
52}
53
54void Sensor::registerForUpdates(
55 const std::weak_ptr<interfaces::SensorListener>& weakListener)
56{
Krzysztof Grobelnyd2238192020-12-02 09:27:28 +000057 listeners.erase(
58 std::remove_if(listeners.begin(), listeners.end(),
59 [](const auto& listener) { return listener.expired(); }),
60 listeners.end());
61
Krzysztof Grobelnyb5645942020-09-29 11:52:45 +020062 if (auto listener = weakListener.lock())
63 {
64 listeners.emplace_back(weakListener);
65
66 if (value)
67 {
68 listener->sensorUpdated(*this, timestamp, *value);
69 }
70 else
71 {
72 async_read();
73 }
74 }
75}
76
Lukasz Kazmierczak7e098e92021-09-16 15:59:56 +020077void Sensor::unregisterFromUpdates(
78 const std::weak_ptr<interfaces::SensorListener>& weakListener)
79{
80 if (auto listener = weakListener.lock())
81 {
82 listeners.erase(
83 std::remove_if(
84 listeners.begin(), listeners.end(),
85 [listenerToUnregister = listener.get()](const auto& listener) {
86 return (listener.expired() ||
87 listener.lock().get() == listenerToUnregister);
88 }),
89 listeners.end());
90 }
91}
92
Krzysztof Grobelnyb5645942020-09-29 11:52:45 +020093void Sensor::updateValue(double newValue)
94{
95 timestamp = std::time(0);
96
97 if (value == newValue)
98 {
99 for (const auto& weakListener : listeners)
100 {
101 if (auto listener = weakListener.lock())
102 {
103 listener->sensorUpdated(*this, timestamp);
104 }
105 }
106 }
107 else
108 {
109 value = newValue;
110
111 for (const auto& weakListener : listeners)
112 {
113 if (auto listener = weakListener.lock())
114 {
115 listener->sensorUpdated(*this, timestamp, *value);
116 }
117 }
118 }
119}
120
121void Sensor::makeSignalMonitor()
122{
123 if (signalMonitor)
124 {
125 return;
126 }
127
128 using namespace std::string_literals;
129
130 const auto param = "type='signal',member='PropertiesChanged',path='"s +
131 sensorId.path +
132 "',arg0='xyz.openbmc_project.Sensor.Value'"s;
133
Patrick Williams3a62ee12021-12-03 10:13:25 -0600134 signalMonitor = std::make_unique<sdbusplus::bus::match_t>(
Krzysztof Grobelnyb5645942020-09-29 11:52:45 +0200135 *bus, param,
136 [weakSelf = weak_from_this()](sdbusplus::message::message& message) {
137 signalProc(weakSelf, message);
138 });
139}
140
141void Sensor::signalProc(const std::weak_ptr<Sensor>& weakSelf,
142 sdbusplus::message::message& message)
143{
144 if (auto self = weakSelf.lock())
145 {
146 std::string iface;
147 boost::container::flat_map<std::string, ValueVariant>
148 changed_properties;
149 std::vector<std::string> invalidated_properties;
150
151 message.read(iface, changed_properties, invalidated_properties);
152
153 if (iface == "xyz.openbmc_project.Sensor.Value")
154 {
155 const auto it = changed_properties.find("Value");
156 if (it != changed_properties.end())
157 {
158 if (auto val = std::get_if<double>(&it->second))
159 {
160 self->updateValue(*val);
161 }
162 else
163 {
164 phosphor::logging::log<phosphor::logging::level::ERR>(
165 "Failed to receive Value from Sensor "
166 "PropertiesChanged signal",
Wludzik, Jozef982c5b52021-01-02 12:05:21 +0100167 phosphor::logging::entry("SENSOR_PATH=%s",
Krzysztof Grobelnyb5645942020-09-29 11:52:45 +0200168 self->sensorId.path.c_str()));
169 }
170 }
171 }
172 }
173}