blob: 22875a2ff3fd02a22b1a4a8826ba96c6705a8f21 [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 */
Matthew Barth4d982852017-11-17 09:37:13 -060016#include <experimental/filesystem>
Matt Spinlerabf8da32017-04-27 14:08:45 -050017#include <phosphor-logging/log.hpp>
18#include "fan.hpp"
Brad Bishop2a58e2c2017-07-30 13:49:09 -040019#include "sdbusplus.hpp"
Matt Spinlerabf8da32017-04-27 14:08:45 -050020#include "tach_sensor.hpp"
Matthew Barth4d982852017-11-17 09:37:13 -060021#include "utility.hpp"
Matt Spinlerabf8da32017-04-27 14:08:45 -050022
23namespace phosphor
24{
25namespace fan
26{
27namespace monitor
28{
29
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
Matthew Barth4d982852017-11-17 09:37:13 -060035using namespace std::experimental::filesystem;
Matt Spinlerebaae612017-04-27 14:21:48 -050036
37/**
38 * @brief Helper function to read a property
39 *
40 * @param[in] interface - the interface the property is on
41 * @param[in] propertName - the name of the property
42 * @param[in] path - the dbus path
Matt Spinlerebaae612017-04-27 14:21:48 -050043 * @param[in] bus - the dbus object
44 * @param[out] value - filled in with the property value
45 */
46template<typename T>
47static void readProperty(const std::string& interface,
48 const std::string& propertyName,
49 const std::string& path,
Matt Spinlerebaae612017-04-27 14:21:48 -050050 sdbusplus::bus::bus& bus,
51 T& value)
52{
Matt Spinlerebaae612017-04-27 14:21:48 -050053 try
54 {
Brad Bishop2a58e2c2017-07-30 13:49:09 -040055 value = util::SDBusPlus::getProperty<T>(bus,
56 path,
57 interface,
58 propertyName);
Matt Spinlerebaae612017-04-27 14:21:48 -050059 }
60 catch (std::exception& e)
61 {
62 phosphor::logging::log<phosphor::logging::level::ERR>(e.what());
63 }
64}
Matt Spinlerabf8da32017-04-27 14:08:45 -050065
66
Matthew Barth0a9fe162018-01-26 12:53:15 -060067TachSensor::TachSensor(Mode mode,
68 sdbusplus::bus::bus& bus,
Matt Spinlerabf8da32017-04-27 14:08:45 -050069 Fan& fan,
70 const std::string& id,
71 bool hasTarget,
Matt Spinlera9406a72017-04-27 14:29:24 -050072 size_t timeout,
Matt Spinlere824f982017-05-11 10:07:55 -050073 phosphor::fan::event::EventPtr& events) :
Matt Spinlerabf8da32017-04-27 14:08:45 -050074 _bus(bus),
75 _fan(fan),
76 _name(FAN_SENSOR_PATH + id),
Matthew Barth4d982852017-11-17 09:37:13 -060077 _invName(path(fan.getName()) / id),
Matt Spinlerabf8da32017-04-27 14:08:45 -050078 _hasTarget(hasTarget),
Matt Spinlera9406a72017-04-27 14:29:24 -050079 _timeout(timeout),
80 _timer(events, [this, &fan](){ fan.timerExpired(*this); })
Matt Spinlerabf8da32017-04-27 14:08:45 -050081{
Matthew Barthd199dcd2017-11-20 10:36:41 -060082 // Start from a known state of functional
Matthew Barth7f7df312018-01-15 16:27:50 -060083 setFunctional(true);
Brad Bishopedaeb312017-07-30 19:38:20 -040084
Matthew Barth0a9fe162018-01-26 12:53:15 -060085 // Load in current Target and Input values when entering monitor mode
86 if (mode != Mode::init)
Brad Bishopedaeb312017-07-30 19:38:20 -040087 {
Matthew Barth0a9fe162018-01-26 12:53:15 -060088 try
89 {
90 // Use getProperty directly to allow a missing sensor object
91 // to abort construction.
92 _tachInput = util::SDBusPlus::getProperty<decltype(_tachInput)>(
93 _bus,
94 _name,
95 FAN_SENSOR_VALUE_INTF,
96 FAN_VALUE_PROPERTY);
97 }
98 catch (std::exception& e)
99 {
100 throw InvalidSensorError();
101 }
102
103 if (_hasTarget)
104 {
105 readProperty(FAN_SENSOR_CONTROL_INTF,
106 FAN_TARGET_PROPERTY,
107 _name,
108 _bus,
109 _tachTarget);
110 }
111
112 auto match = getMatchString(FAN_SENSOR_VALUE_INTF);
113
114 tachSignal = std::make_unique<sdbusplus::server::match::match>(
Brad Bishopedaeb312017-07-30 19:38:20 -0400115 _bus,
Matthew Barth0a9fe162018-01-26 12:53:15 -0600116 match.c_str(),
117 [this](auto& msg){ this->handleTachChange(msg); });
118
119 if (_hasTarget)
120 {
121 match = getMatchString(FAN_SENSOR_CONTROL_INTF);
122
123 targetSignal = std::make_unique<sdbusplus::server::match::match>(
124 _bus,
125 match.c_str(),
126 [this](auto& msg){ this->handleTargetChange(msg); });
127 }
Brad Bishopedaeb312017-07-30 19:38:20 -0400128 }
Matt Spinlerebaae612017-04-27 14:21:48 -0500129}
130
Matt Spinlerebaae612017-04-27 14:21:48 -0500131std::string TachSensor::getMatchString(const std::string& interface)
132{
Brad Bishop78b58452017-07-30 19:44:49 -0400133 return sdbusplus::bus::match::rules::propertiesChanged(
134 _name, interface);
Matt Spinlerebaae612017-04-27 14:21:48 -0500135}
136
Matthew Barthf552ea52018-01-15 16:22:04 -0600137uint64_t TachSensor::getTarget() const
138{
139 if (!_hasTarget)
140 {
141 return _fan.findTargetSpeed();
142 }
143 return _tachTarget;
144}
145
Matthew Barthd199dcd2017-11-20 10:36:41 -0600146void TachSensor::setFunctional(bool functional)
147{
148 _functional = functional;
149 updateInventory(_functional);
150}
Matt Spinlerebaae612017-04-27 14:21:48 -0500151
Matt Spinlerebaae612017-04-27 14:21:48 -0500152/**
153 * @brief Reads a property from the input message and stores it in value.
154 * T is the value type.
155 *
156 * Note: This can only be called once per message.
157 *
158 * @param[in] msg - the dbus message that contains the data
159 * @param[in] interface - the interface the property is on
160 * @param[in] propertName - the name of the property
161 * @param[out] value - the value to store the property value in
162 */
163template<typename T>
164static void readPropertyFromMessage(sdbusplus::message::message& msg,
165 const std::string& interface,
166 const std::string& propertyName,
167 T& value)
168{
169 std::string sensor;
170 std::map<std::string, sdbusplus::message::variant<T>> data;
171 msg.read(sensor, data);
172
173 if (sensor.compare(interface) == 0)
174 {
175 auto propertyMap = data.find(propertyName);
176 if (propertyMap != data.end())
177 {
178 value = sdbusplus::message::variant_ns::get<T>(
179 propertyMap->second);
180 }
181 }
182}
183
184
Brad Bishop771659f2017-07-30 19:52:21 -0400185void TachSensor::handleTargetChange(sdbusplus::message::message& msg)
Matt Spinlerebaae612017-04-27 14:21:48 -0500186{
187 readPropertyFromMessage(msg,
188 FAN_SENSOR_CONTROL_INTF,
189 FAN_TARGET_PROPERTY,
190 _tachTarget);
191
192 //Check all tach sensors on the fan against the target
193 _fan.tachChanged();
194}
195
196
Brad Bishop771659f2017-07-30 19:52:21 -0400197void TachSensor::handleTachChange(sdbusplus::message::message& msg)
Matt Spinlerebaae612017-04-27 14:21:48 -0500198{
199 readPropertyFromMessage(msg,
200 FAN_SENSOR_VALUE_INTF,
201 FAN_VALUE_PROPERTY,
202 _tachInput);
203
204 //Check just this sensor against the target
205 _fan.tachChanged(*this);
Matt Spinlerabf8da32017-04-27 14:08:45 -0500206}
207
208
Matt Spinlera9406a72017-04-27 14:29:24 -0500209std::chrono::microseconds TachSensor::getTimeout()
210{
211 using namespace std::chrono;
212
213 return duration_cast<microseconds>(seconds(_timeout));
214}
215
Matthew Barth4d982852017-11-17 09:37:13 -0600216void TachSensor::updateInventory(bool functional)
217{
218 auto objectMap = util::getObjMap<bool>(
219 _invName,
220 util::OPERATIONAL_STATUS_INTF,
221 util::FUNCTIONAL_PROPERTY,
222 functional);
223 auto response = util::SDBusPlus::lookupAndCallMethod(
224 _bus,
225 util::INVENTORY_PATH,
226 util::INVENTORY_INTF,
227 "Notify",
228 objectMap);
229 if (response.is_method_error())
230 {
231 log<level::ERR>("Error in notify update of tach sensor inventory");
232 }
233}
Matt Spinlera9406a72017-04-27 14:29:24 -0500234
Matt Spinlerabf8da32017-04-27 14:08:45 -0500235}
236}
237}