blob: 8a6f673e20dca6cc3a00218337df7a6d1964608c [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",
38 [lock, id = sensorId,
39 weakSelf = weak_from_this()](boost::system::error_code ec) {
Wludzik, Jozef5ade2b12020-11-16 14:00:23 +010040 phosphor::logging::log<phosphor::logging::level::WARNING>(
Krzysztof Grobelnyb5645942020-09-29 11:52:45 +020041 "DBus 'GetProperty' call failed on Sensor Value",
42 phosphor::logging::entry("sensor=%s, ec=%lu", id.str().c_str(),
43 ec.value()));
Krzysztof Grobelnyb5645942020-09-29 11:52:45 +020044 },
45 [lock, weakSelf = weak_from_this()](double newValue) {
46 if (auto self = weakSelf.lock())
47 {
48 self->updateValue(newValue);
49 }
50 });
51}
52
53void Sensor::registerForUpdates(
54 const std::weak_ptr<interfaces::SensorListener>& weakListener)
55{
Krzysztof Grobelnyd2238192020-12-02 09:27:28 +000056 listeners.erase(
57 std::remove_if(listeners.begin(), listeners.end(),
58 [](const auto& listener) { return listener.expired(); }),
59 listeners.end());
60
Krzysztof Grobelnyb5645942020-09-29 11:52:45 +020061 if (auto listener = weakListener.lock())
62 {
63 listeners.emplace_back(weakListener);
64
65 if (value)
66 {
67 listener->sensorUpdated(*this, timestamp, *value);
68 }
69 else
70 {
71 async_read();
72 }
73 }
74}
75
76void Sensor::updateValue(double newValue)
77{
78 timestamp = std::time(0);
79
80 if (value == newValue)
81 {
82 for (const auto& weakListener : listeners)
83 {
84 if (auto listener = weakListener.lock())
85 {
86 listener->sensorUpdated(*this, timestamp);
87 }
88 }
89 }
90 else
91 {
92 value = newValue;
93
94 for (const auto& weakListener : listeners)
95 {
96 if (auto listener = weakListener.lock())
97 {
98 listener->sensorUpdated(*this, timestamp, *value);
99 }
100 }
101 }
102}
103
104void Sensor::makeSignalMonitor()
105{
106 if (signalMonitor)
107 {
108 return;
109 }
110
111 using namespace std::string_literals;
112
113 const auto param = "type='signal',member='PropertiesChanged',path='"s +
114 sensorId.path +
115 "',arg0='xyz.openbmc_project.Sensor.Value'"s;
116
117 signalMonitor = std::make_unique<sdbusplus::bus::match::match>(
118 *bus, param,
119 [weakSelf = weak_from_this()](sdbusplus::message::message& message) {
120 signalProc(weakSelf, message);
121 });
122}
123
124void Sensor::signalProc(const std::weak_ptr<Sensor>& weakSelf,
125 sdbusplus::message::message& message)
126{
127 if (auto self = weakSelf.lock())
128 {
129 std::string iface;
130 boost::container::flat_map<std::string, ValueVariant>
131 changed_properties;
132 std::vector<std::string> invalidated_properties;
133
134 message.read(iface, changed_properties, invalidated_properties);
135
136 if (iface == "xyz.openbmc_project.Sensor.Value")
137 {
138 const auto it = changed_properties.find("Value");
139 if (it != changed_properties.end())
140 {
141 if (auto val = std::get_if<double>(&it->second))
142 {
143 self->updateValue(*val);
144 }
145 else
146 {
147 phosphor::logging::log<phosphor::logging::level::ERR>(
148 "Failed to receive Value from Sensor "
149 "PropertiesChanged signal",
150 phosphor::logging::entry("sensor=%s",
151 self->sensorId.path.c_str()));
152 }
153 }
154 }
155 }
156}