1b5645947SKrzysztof Grobelny #include "sensor.hpp"
2b5645947SKrzysztof Grobelny
3b8cc78ddSKrzysztof Grobelny #include "utils/clock.hpp"
4b8cc78ddSKrzysztof Grobelny
5b5645947SKrzysztof Grobelny #include <boost/container/flat_map.hpp>
6b5645947SKrzysztof Grobelny #include <phosphor-logging/log.hpp>
7b5645947SKrzysztof Grobelny #include <sdbusplus/asio/property.hpp>
8b5645947SKrzysztof Grobelny
9b5645947SKrzysztof Grobelny #include <functional>
10b5645947SKrzysztof Grobelny
Sensor(interfaces::Sensor::Id sensorId,const std::string & sensorMetadata,boost::asio::io_context & ioc,const std::shared_ptr<sdbusplus::asio::connection> & bus)11b8cc78ddSKrzysztof Grobelny Sensor::Sensor(interfaces::Sensor::Id sensorId,
12b8cc78ddSKrzysztof Grobelny const std::string& sensorMetadata, boost::asio::io_context& ioc,
13b5645947SKrzysztof Grobelny const std::shared_ptr<sdbusplus::asio::connection>& bus) :
14f535cad6SPatrick Williams sensorId(std::move(sensorId)), sensorMetadata(sensorMetadata), ioc(ioc),
15f535cad6SPatrick Williams bus(bus)
16b5645947SKrzysztof Grobelny {}
17b5645947SKrzysztof Grobelny
makeId(std::string_view service,std::string_view path)18b5645947SKrzysztof Grobelny Sensor::Id Sensor::makeId(std::string_view service, std::string_view path)
19b5645947SKrzysztof Grobelny {
20b5645947SKrzysztof Grobelny return Id("Sensor", service, path);
21b5645947SKrzysztof Grobelny }
22b5645947SKrzysztof Grobelny
id() const23b5645947SKrzysztof Grobelny Sensor::Id Sensor::id() const
24b5645947SKrzysztof Grobelny {
25b5645947SKrzysztof Grobelny return sensorId;
26b5645947SKrzysztof Grobelny }
27b5645947SKrzysztof Grobelny
metadata() const28b8cc78ddSKrzysztof Grobelny std::string Sensor::metadata() const
29b8cc78ddSKrzysztof Grobelny {
30b8cc78ddSKrzysztof Grobelny return sensorMetadata;
31b8cc78ddSKrzysztof Grobelny }
32b8cc78ddSKrzysztof Grobelny
getName() const3394f71c51SSzymon Dompke std::string Sensor::getName() const
3494f71c51SSzymon Dompke {
3594f71c51SSzymon Dompke return sensorMetadata.empty() ? sensorId.path : sensorMetadata;
3694f71c51SSzymon Dompke }
3794f71c51SSzymon Dompke
async_read()38b5645947SKrzysztof Grobelny void Sensor::async_read()
39b5645947SKrzysztof Grobelny {
40b5645947SKrzysztof Grobelny uniqueCall([this](auto lock) { async_read(std::move(lock)); });
41b5645947SKrzysztof Grobelny }
42b5645947SKrzysztof Grobelny
async_read(std::shared_ptr<utils::UniqueCall::Lock> lock)43b5645947SKrzysztof Grobelny void Sensor::async_read(std::shared_ptr<utils::UniqueCall::Lock> lock)
44b5645947SKrzysztof Grobelny {
45b5645947SKrzysztof Grobelny makeSignalMonitor();
46b5645947SKrzysztof Grobelny
47b5645947SKrzysztof Grobelny sdbusplus::asio::getProperty<double>(
48b5645947SKrzysztof Grobelny *bus, sensorId.service, sensorId.path,
49b5645947SKrzysztof Grobelny "xyz.openbmc_project.Sensor.Value", "Value",
500e7ae5dbSEd Tanous [lock, id = sensorId, weakSelf = weak_from_this()](
510e7ae5dbSEd Tanous boost::system::error_code ec, double newValue) {
520e7ae5dbSEd Tanous if (ec)
530e7ae5dbSEd Tanous {
545ade2b1dSWludzik, Jozef phosphor::logging::log<phosphor::logging::level::WARNING>(
55b5645947SKrzysztof Grobelny "DBus 'GetProperty' call failed on Sensor Value",
56982c5b5bSWludzik, Jozef phosphor::logging::entry("SENSOR_PATH=%s", id.path.c_str()),
57982c5b5bSWludzik, Jozef phosphor::logging::entry("ERROR_CODE=%d", ec.value()));
580e7ae5dbSEd Tanous return;
590e7ae5dbSEd Tanous }
60b5645947SKrzysztof Grobelny if (auto self = weakSelf.lock())
61b5645947SKrzysztof Grobelny {
62b5645947SKrzysztof Grobelny self->updateValue(newValue);
63b5645947SKrzysztof Grobelny }
64b5645947SKrzysztof Grobelny });
65b5645947SKrzysztof Grobelny }
66b5645947SKrzysztof Grobelny
registerForUpdates(const std::weak_ptr<interfaces::SensorListener> & weakListener)67b5645947SKrzysztof Grobelny void Sensor::registerForUpdates(
68b5645947SKrzysztof Grobelny const std::weak_ptr<interfaces::SensorListener>& weakListener)
69b5645947SKrzysztof Grobelny {
70d2238194SKrzysztof Grobelny listeners.erase(
71d2238194SKrzysztof Grobelny std::remove_if(listeners.begin(), listeners.end(),
72d2238194SKrzysztof Grobelny [](const auto& listener) { return listener.expired(); }),
73d2238194SKrzysztof Grobelny listeners.end());
74d2238194SKrzysztof Grobelny
75b5645947SKrzysztof Grobelny if (auto listener = weakListener.lock())
76b5645947SKrzysztof Grobelny {
77b5645947SKrzysztof Grobelny listeners.emplace_back(weakListener);
78b5645947SKrzysztof Grobelny
79b5645947SKrzysztof Grobelny if (value)
80b5645947SKrzysztof Grobelny {
81b5645947SKrzysztof Grobelny listener->sensorUpdated(*this, timestamp, *value);
82b5645947SKrzysztof Grobelny }
83b5645947SKrzysztof Grobelny else
84b5645947SKrzysztof Grobelny {
85b5645947SKrzysztof Grobelny async_read();
86b5645947SKrzysztof Grobelny }
87b5645947SKrzysztof Grobelny }
88b5645947SKrzysztof Grobelny }
89b5645947SKrzysztof Grobelny
unregisterFromUpdates(const std::weak_ptr<interfaces::SensorListener> & weakListener)907e098e93SLukasz Kazmierczak void Sensor::unregisterFromUpdates(
917e098e93SLukasz Kazmierczak const std::weak_ptr<interfaces::SensorListener>& weakListener)
927e098e93SLukasz Kazmierczak {
937e098e93SLukasz Kazmierczak if (auto listener = weakListener.lock())
947e098e93SLukasz Kazmierczak {
95*583ba441SPatrick Williams listeners.erase(
96*583ba441SPatrick Williams std::remove_if(
97*583ba441SPatrick Williams listeners.begin(), listeners.end(),
98*583ba441SPatrick Williams [listenerToUnregister = listener.get()](const auto& listener) {
997e098e93SLukasz Kazmierczak return (listener.expired() ||
1007e098e93SLukasz Kazmierczak listener.lock().get() == listenerToUnregister);
1017e098e93SLukasz Kazmierczak }),
1027e098e93SLukasz Kazmierczak listeners.end());
1037e098e93SLukasz Kazmierczak }
1047e098e93SLukasz Kazmierczak }
1057e098e93SLukasz Kazmierczak
updateValue(double newValue)106b5645947SKrzysztof Grobelny void Sensor::updateValue(double newValue)
107b5645947SKrzysztof Grobelny {
10851f0fd50SKrzysztof Grobelny timestamp = Clock().steadyTimestamp();
109b5645947SKrzysztof Grobelny
110f7ea2997SKrzysztof Grobelny if (value != newValue)
111b5645947SKrzysztof Grobelny {
112b5645947SKrzysztof Grobelny value = newValue;
113b5645947SKrzysztof Grobelny
114b5645947SKrzysztof Grobelny for (const auto& weakListener : listeners)
115b5645947SKrzysztof Grobelny {
116b5645947SKrzysztof Grobelny if (auto listener = weakListener.lock())
117b5645947SKrzysztof Grobelny {
118b5645947SKrzysztof Grobelny listener->sensorUpdated(*this, timestamp, *value);
119b5645947SKrzysztof Grobelny }
120b5645947SKrzysztof Grobelny }
121b5645947SKrzysztof Grobelny }
122b5645947SKrzysztof Grobelny }
123b5645947SKrzysztof Grobelny
makeSignalMonitor()124b5645947SKrzysztof Grobelny void Sensor::makeSignalMonitor()
125b5645947SKrzysztof Grobelny {
126b5645947SKrzysztof Grobelny if (signalMonitor)
127b5645947SKrzysztof Grobelny {
128b5645947SKrzysztof Grobelny return;
129b5645947SKrzysztof Grobelny }
130b5645947SKrzysztof Grobelny
131b5645947SKrzysztof Grobelny using namespace std::string_literals;
132b5645947SKrzysztof Grobelny
133*583ba441SPatrick Williams const auto param =
134*583ba441SPatrick Williams "type='signal',member='PropertiesChanged',path='"s + sensorId.path +
135b5645947SKrzysztof Grobelny "',arg0='xyz.openbmc_project.Sensor.Value'"s;
136b5645947SKrzysztof Grobelny
1373a62ee15SPatrick Williams signalMonitor = std::make_unique<sdbusplus::bus::match_t>(
138b5645947SKrzysztof Grobelny *bus, param,
13939cc6ac9SPatrick Williams [weakSelf = weak_from_this()](sdbusplus::message_t& message) {
140b5645947SKrzysztof Grobelny signalProc(weakSelf, message);
141b5645947SKrzysztof Grobelny });
142b5645947SKrzysztof Grobelny }
143b5645947SKrzysztof Grobelny
signalProc(const std::weak_ptr<Sensor> & weakSelf,sdbusplus::message_t & message)144b5645947SKrzysztof Grobelny void Sensor::signalProc(const std::weak_ptr<Sensor>& weakSelf,
14539cc6ac9SPatrick Williams sdbusplus::message_t& message)
146b5645947SKrzysztof Grobelny {
147b5645947SKrzysztof Grobelny if (auto self = weakSelf.lock())
148b5645947SKrzysztof Grobelny {
149b5645947SKrzysztof Grobelny std::string iface;
150b5645947SKrzysztof Grobelny boost::container::flat_map<std::string, ValueVariant>
151b5645947SKrzysztof Grobelny changed_properties;
152b5645947SKrzysztof Grobelny std::vector<std::string> invalidated_properties;
153b5645947SKrzysztof Grobelny
154b5645947SKrzysztof Grobelny message.read(iface, changed_properties, invalidated_properties);
155b5645947SKrzysztof Grobelny
156b5645947SKrzysztof Grobelny if (iface == "xyz.openbmc_project.Sensor.Value")
157b5645947SKrzysztof Grobelny {
158b5645947SKrzysztof Grobelny const auto it = changed_properties.find("Value");
159b5645947SKrzysztof Grobelny if (it != changed_properties.end())
160b5645947SKrzysztof Grobelny {
161b5645947SKrzysztof Grobelny if (auto val = std::get_if<double>(&it->second))
162b5645947SKrzysztof Grobelny {
163b5645947SKrzysztof Grobelny self->updateValue(*val);
164b5645947SKrzysztof Grobelny }
165b5645947SKrzysztof Grobelny else
166b5645947SKrzysztof Grobelny {
167b5645947SKrzysztof Grobelny phosphor::logging::log<phosphor::logging::level::ERR>(
168b5645947SKrzysztof Grobelny "Failed to receive Value from Sensor "
169b5645947SKrzysztof Grobelny "PropertiesChanged signal",
170982c5b5bSWludzik, Jozef phosphor::logging::entry("SENSOR_PATH=%s",
171b5645947SKrzysztof Grobelny self->sensorId.path.c_str()));
172b5645947SKrzysztof Grobelny }
173b5645947SKrzysztof Grobelny }
174b5645947SKrzysztof Grobelny }
175b5645947SKrzysztof Grobelny }
176b5645947SKrzysztof Grobelny }
17794f71c51SSzymon Dompke
getLabeledSensorInfo() const17894f71c51SSzymon Dompke LabeledSensorInfo Sensor::getLabeledSensorInfo() const
17994f71c51SSzymon Dompke {
18094f71c51SSzymon Dompke return LabeledSensorInfo(sensorId.service, sensorId.path, sensorMetadata);
18194f71c51SSzymon Dompke }
182