blob: 9a98e37bda3dc44fbac12d0378fdcb6fc89c0f82 [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
29constexpr auto FAN_SENSOR_PATH = "/xyz/openbmc_project/sensors/fan_tach/";
Matt Spinlerebaae612017-04-27 14:21:48 -050030constexpr auto FAN_SENSOR_CONTROL_INTF = "xyz.openbmc_project.Control.FanSpeed";
31constexpr auto FAN_SENSOR_VALUE_INTF = "xyz.openbmc_project.Sensor.Value";
32constexpr auto FAN_TARGET_PROPERTY = "Target";
33constexpr auto FAN_VALUE_PROPERTY = "Value";
34
35
36/**
37 * @brief Helper function to read a property
38 *
39 * @param[in] interface - the interface the property is on
40 * @param[in] propertName - the name of the property
41 * @param[in] path - the dbus path
Matt Spinlerebaae612017-04-27 14:21:48 -050042 * @param[in] bus - the dbus object
43 * @param[out] value - filled in with the property value
44 */
45template<typename T>
46static void readProperty(const std::string& interface,
47 const std::string& propertyName,
48 const std::string& path,
Matt Spinlerebaae612017-04-27 14:21:48 -050049 sdbusplus::bus::bus& bus,
50 T& value)
51{
Matt Spinlerebaae612017-04-27 14:21:48 -050052 try
53 {
Brad Bishop2a58e2c2017-07-30 13:49:09 -040054 value = util::SDBusPlus::getProperty<T>(bus,
55 path,
56 interface,
57 propertyName);
Matt Spinlerebaae612017-04-27 14:21:48 -050058 }
59 catch (std::exception& e)
60 {
61 phosphor::logging::log<phosphor::logging::level::ERR>(e.what());
62 }
63}
Matt Spinlerabf8da32017-04-27 14:08:45 -050064
65
66TachSensor::TachSensor(sdbusplus::bus::bus& bus,
67 Fan& fan,
68 const std::string& id,
69 bool hasTarget,
Matt Spinlera9406a72017-04-27 14:29:24 -050070 size_t timeout,
Matt Spinlere824f982017-05-11 10:07:55 -050071 phosphor::fan::event::EventPtr& events) :
Matt Spinlerabf8da32017-04-27 14:08:45 -050072 _bus(bus),
73 _fan(fan),
74 _name(FAN_SENSOR_PATH + id),
75 _hasTarget(hasTarget),
Matt Spinlera9406a72017-04-27 14:29:24 -050076 _timeout(timeout),
77 _timer(events, [this, &fan](){ fan.timerExpired(*this); })
Matt Spinlerabf8da32017-04-27 14:08:45 -050078{
Matt Spinlerebaae612017-04-27 14:21:48 -050079 //Load in starting Target and Input values
Brad Bishopedaeb312017-07-30 19:38:20 -040080
81 try
82 {
83 // Use getProperty directly to allow a missing sensor object
84 // to abort construction.
85 _tachInput = util::SDBusPlus::getProperty<decltype(_tachInput)>(
86 _bus,
87 _name,
88 FAN_SENSOR_VALUE_INTF,
89 FAN_VALUE_PROPERTY);
90 }
91 catch (std::exception& e)
92 {
93 throw InvalidSensorError();
94 }
Matt Spinlerebaae612017-04-27 14:21:48 -050095
96 if (_hasTarget)
97 {
98 readProperty(FAN_SENSOR_CONTROL_INTF,
99 FAN_TARGET_PROPERTY,
100 _name,
Matt Spinlerebaae612017-04-27 14:21:48 -0500101 _bus,
102 _tachTarget);
103 }
104
105 auto match = getMatchString(FAN_SENSOR_VALUE_INTF);
106
107 tachSignal = std::make_unique<sdbusplus::server::match::match>(
108 _bus,
109 match.c_str(),
Brad Bishop771659f2017-07-30 19:52:21 -0400110 [this](auto& msg){ this->handleTachChange(msg); });
Matt Spinlerebaae612017-04-27 14:21:48 -0500111
112 if (_hasTarget)
113 {
114 match = getMatchString(FAN_SENSOR_CONTROL_INTF);
115
116 targetSignal = std::make_unique<sdbusplus::server::match::match>(
117 _bus,
118 match.c_str(),
Brad Bishop771659f2017-07-30 19:52:21 -0400119 [this](auto& msg){ this->handleTargetChange(msg); });
Matt Spinlerebaae612017-04-27 14:21:48 -0500120 }
121
122}
123
124
Matt Spinlerebaae612017-04-27 14:21:48 -0500125std::string TachSensor::getMatchString(const std::string& interface)
126{
Brad Bishop78b58452017-07-30 19:44:49 -0400127 return sdbusplus::bus::match::rules::propertiesChanged(
128 _name, interface);
Matt Spinlerebaae612017-04-27 14:21:48 -0500129}
130
131
Matt Spinlerebaae612017-04-27 14:21:48 -0500132/**
133 * @brief Reads a property from the input message and stores it in value.
134 * T is the value type.
135 *
136 * Note: This can only be called once per message.
137 *
138 * @param[in] msg - the dbus message that contains the data
139 * @param[in] interface - the interface the property is on
140 * @param[in] propertName - the name of the property
141 * @param[out] value - the value to store the property value in
142 */
143template<typename T>
144static void readPropertyFromMessage(sdbusplus::message::message& msg,
145 const std::string& interface,
146 const std::string& propertyName,
147 T& value)
148{
149 std::string sensor;
150 std::map<std::string, sdbusplus::message::variant<T>> data;
151 msg.read(sensor, data);
152
153 if (sensor.compare(interface) == 0)
154 {
155 auto propertyMap = data.find(propertyName);
156 if (propertyMap != data.end())
157 {
158 value = sdbusplus::message::variant_ns::get<T>(
159 propertyMap->second);
160 }
161 }
162}
163
164
Brad Bishop771659f2017-07-30 19:52:21 -0400165void TachSensor::handleTargetChange(sdbusplus::message::message& msg)
Matt Spinlerebaae612017-04-27 14:21:48 -0500166{
167 readPropertyFromMessage(msg,
168 FAN_SENSOR_CONTROL_INTF,
169 FAN_TARGET_PROPERTY,
170 _tachTarget);
171
172 //Check all tach sensors on the fan against the target
173 _fan.tachChanged();
174}
175
176
Brad Bishop771659f2017-07-30 19:52:21 -0400177void TachSensor::handleTachChange(sdbusplus::message::message& msg)
Matt Spinlerebaae612017-04-27 14:21:48 -0500178{
179 readPropertyFromMessage(msg,
180 FAN_SENSOR_VALUE_INTF,
181 FAN_VALUE_PROPERTY,
182 _tachInput);
183
184 //Check just this sensor against the target
185 _fan.tachChanged(*this);
Matt Spinlerabf8da32017-04-27 14:08:45 -0500186}
187
188
Matt Spinlera9406a72017-04-27 14:29:24 -0500189std::chrono::microseconds TachSensor::getTimeout()
190{
191 using namespace std::chrono;
192
193 return duration_cast<microseconds>(seconds(_timeout));
194}
195
196
Matt Spinlerabf8da32017-04-27 14:08:45 -0500197}
198}
199}