blob: 040e8f9e9c7b754e0a5ee528251bdd8e20fbb7bf [file] [log] [blame]
Matt Spinlerabf8da32017-04-27 14:08:45 -05001/**
2 * Copyright © 2017 IBM Corporation
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16#include <phosphor-logging/log.hpp>
17#include "fan.hpp"
Brad Bishop2a58e2c2017-07-30 13:49:09 -040018#include "sdbusplus.hpp"
Matt Spinlerabf8da32017-04-27 14:08:45 -050019#include "tach_sensor.hpp"
20#include "../utility.hpp"
21
22namespace phosphor
23{
24namespace fan
25{
26namespace monitor
27{
28
Matt Spinlerebaae612017-04-27 14:21:48 -050029constexpr auto FAN_SENSOR_CONTROL_INTF = "xyz.openbmc_project.Control.FanSpeed";
30constexpr auto FAN_SENSOR_VALUE_INTF = "xyz.openbmc_project.Sensor.Value";
31constexpr auto FAN_TARGET_PROPERTY = "Target";
32constexpr auto FAN_VALUE_PROPERTY = "Value";
33
34
35/**
36 * @brief Helper function to read a property
37 *
38 * @param[in] interface - the interface the property is on
39 * @param[in] propertName - the name of the property
40 * @param[in] path - the dbus path
Matt Spinlerebaae612017-04-27 14:21:48 -050041 * @param[in] bus - the dbus object
42 * @param[out] value - filled in with the property value
43 */
44template<typename T>
45static void readProperty(const std::string& interface,
46 const std::string& propertyName,
47 const std::string& path,
Matt Spinlerebaae612017-04-27 14:21:48 -050048 sdbusplus::bus::bus& bus,
49 T& value)
50{
Matt Spinlerebaae612017-04-27 14:21:48 -050051 try
52 {
Brad Bishop2a58e2c2017-07-30 13:49:09 -040053 value = util::SDBusPlus::getProperty<T>(bus,
54 path,
55 interface,
56 propertyName);
Matt Spinlerebaae612017-04-27 14:21:48 -050057 }
58 catch (std::exception& e)
59 {
60 phosphor::logging::log<phosphor::logging::level::ERR>(e.what());
61 }
62}
Matt Spinlerabf8da32017-04-27 14:08:45 -050063
64
65TachSensor::TachSensor(sdbusplus::bus::bus& bus,
66 Fan& fan,
67 const std::string& id,
68 bool hasTarget,
Matt Spinlera9406a72017-04-27 14:29:24 -050069 size_t timeout,
Matt Spinlere824f982017-05-11 10:07:55 -050070 phosphor::fan::event::EventPtr& events) :
Matt Spinlerabf8da32017-04-27 14:08:45 -050071 _bus(bus),
72 _fan(fan),
73 _name(FAN_SENSOR_PATH + id),
74 _hasTarget(hasTarget),
Matt Spinlera9406a72017-04-27 14:29:24 -050075 _timeout(timeout),
76 _timer(events, [this, &fan](){ fan.timerExpired(*this); })
Matt Spinlerabf8da32017-04-27 14:08:45 -050077{
Matt Spinlerebaae612017-04-27 14:21:48 -050078 //Load in starting Target and Input values
Brad Bishopedaeb312017-07-30 19:38:20 -040079
80 try
81 {
82 // Use getProperty directly to allow a missing sensor object
83 // to abort construction.
84 _tachInput = util::SDBusPlus::getProperty<decltype(_tachInput)>(
85 _bus,
86 _name,
87 FAN_SENSOR_VALUE_INTF,
88 FAN_VALUE_PROPERTY);
89 }
90 catch (std::exception& e)
91 {
92 throw InvalidSensorError();
93 }
Matt Spinlerebaae612017-04-27 14:21:48 -050094
95 if (_hasTarget)
96 {
97 readProperty(FAN_SENSOR_CONTROL_INTF,
98 FAN_TARGET_PROPERTY,
99 _name,
Matt Spinlerebaae612017-04-27 14:21:48 -0500100 _bus,
101 _tachTarget);
102 }
103
104 auto match = getMatchString(FAN_SENSOR_VALUE_INTF);
105
106 tachSignal = std::make_unique<sdbusplus::server::match::match>(
107 _bus,
108 match.c_str(),
Brad Bishop771659f2017-07-30 19:52:21 -0400109 [this](auto& msg){ this->handleTachChange(msg); });
Matt Spinlerebaae612017-04-27 14:21:48 -0500110
111 if (_hasTarget)
112 {
113 match = getMatchString(FAN_SENSOR_CONTROL_INTF);
114
115 targetSignal = std::make_unique<sdbusplus::server::match::match>(
116 _bus,
117 match.c_str(),
Brad Bishop771659f2017-07-30 19:52:21 -0400118 [this](auto& msg){ this->handleTargetChange(msg); });
Matt Spinlerebaae612017-04-27 14:21:48 -0500119 }
120
121}
122
123
Matt Spinlerebaae612017-04-27 14:21:48 -0500124std::string TachSensor::getMatchString(const std::string& interface)
125{
Brad Bishop78b58452017-07-30 19:44:49 -0400126 return sdbusplus::bus::match::rules::propertiesChanged(
127 _name, interface);
Matt Spinlerebaae612017-04-27 14:21:48 -0500128}
129
130
Matt Spinlerebaae612017-04-27 14:21:48 -0500131/**
132 * @brief Reads a property from the input message and stores it in value.
133 * T is the value type.
134 *
135 * Note: This can only be called once per message.
136 *
137 * @param[in] msg - the dbus message that contains the data
138 * @param[in] interface - the interface the property is on
139 * @param[in] propertName - the name of the property
140 * @param[out] value - the value to store the property value in
141 */
142template<typename T>
143static void readPropertyFromMessage(sdbusplus::message::message& msg,
144 const std::string& interface,
145 const std::string& propertyName,
146 T& value)
147{
148 std::string sensor;
149 std::map<std::string, sdbusplus::message::variant<T>> data;
150 msg.read(sensor, data);
151
152 if (sensor.compare(interface) == 0)
153 {
154 auto propertyMap = data.find(propertyName);
155 if (propertyMap != data.end())
156 {
157 value = sdbusplus::message::variant_ns::get<T>(
158 propertyMap->second);
159 }
160 }
161}
162
163
Brad Bishop771659f2017-07-30 19:52:21 -0400164void TachSensor::handleTargetChange(sdbusplus::message::message& msg)
Matt Spinlerebaae612017-04-27 14:21:48 -0500165{
166 readPropertyFromMessage(msg,
167 FAN_SENSOR_CONTROL_INTF,
168 FAN_TARGET_PROPERTY,
169 _tachTarget);
170
171 //Check all tach sensors on the fan against the target
172 _fan.tachChanged();
173}
174
175
Brad Bishop771659f2017-07-30 19:52:21 -0400176void TachSensor::handleTachChange(sdbusplus::message::message& msg)
Matt Spinlerebaae612017-04-27 14:21:48 -0500177{
178 readPropertyFromMessage(msg,
179 FAN_SENSOR_VALUE_INTF,
180 FAN_VALUE_PROPERTY,
181 _tachInput);
182
183 //Check just this sensor against the target
184 _fan.tachChanged(*this);
Matt Spinlerabf8da32017-04-27 14:08:45 -0500185}
186
187
Matt Spinlera9406a72017-04-27 14:29:24 -0500188std::chrono::microseconds TachSensor::getTimeout()
189{
190 using namespace std::chrono;
191
192 return duration_cast<microseconds>(seconds(_timeout));
193}
194
195
Matt Spinlerabf8da32017-04-27 14:08:45 -0500196}
197}
198}