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