blob: 6cddc2360e715d2c0be43d131f0270c3b6f4d86b [file] [log] [blame]
Brad Bishopdd62e362017-06-14 16:54:03 -04001/**
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 Barth2d2caa32020-05-26 11:07:24 -050016#include "tach.hpp"
17
18#include "rpolicy.hpp"
19
Brad Bishopd37c0f82017-07-28 21:47:00 -040020#include <phosphor-logging/log.hpp>
Matthew Barth2d2caa32020-05-26 11:07:24 -050021
Brad Bishopdd62e362017-06-14 16:54:03 -040022#include <string>
23#include <tuple>
24#include <vector>
Brad Bishopdd62e362017-06-14 16:54:03 -040025
26namespace phosphor
27{
28namespace fan
29{
30namespace presence
31{
32
Brad Bishopd37c0f82017-07-28 21:47:00 -040033using namespace phosphor::logging;
Brad Bishopdd62e362017-06-14 16:54:03 -040034using namespace std::literals::string_literals;
35
36static const auto tachNamespace = "/xyz/openbmc_project/sensors/fan_tach/"s;
37static const auto tachIface = "xyz.openbmc_project.Sensor.Value"s;
38static const auto tachProperty = "Value"s;
39
Matthew Barth2d2caa32020-05-26 11:07:24 -050040Tach::Tach(const std::vector<std::string>& sensors) : currentState(false)
Brad Bishopdd62e362017-06-14 16:54:03 -040041{
42 // Initialize state.
43 for (const auto& s : sensors)
44 {
45 state.emplace_back(s, nullptr, 0);
46 }
47}
48
49bool Tach::start()
50{
51 for (size_t i = 0; i < state.size(); ++i)
52 {
53 auto& s = state[i];
54 auto tachPath = tachNamespace + std::get<std::string>(s);
55
56 // Register for signal callbacks.
57 std::get<1>(s) = std::make_unique<sdbusplus::bus::match::match>(
Matthew Barth2d2caa32020-05-26 11:07:24 -050058 util::SDBusPlus::getBus(),
59 sdbusplus::bus::match::rules::propertiesChanged(tachPath,
60 tachIface),
61 [this, i](auto& msg) { this->propertiesChanged(i, msg); });
Brad Bishopdd62e362017-06-14 16:54:03 -040062
63 // Get an initial tach speed.
Brad Bishopd37c0f82017-07-28 21:47:00 -040064 try
65 {
Matthew Barthad2cd242020-08-13 13:36:19 -050066 std::get<double>(s) = util::SDBusPlus::getProperty<double>(
Matthew Barth2d2caa32020-05-26 11:07:24 -050067 tachPath, tachIface, tachProperty);
Brad Bishopd37c0f82017-07-28 21:47:00 -040068 }
69 catch (std::exception&)
70 {
71 // Assume not spinning.
72
Matthew Barthad2cd242020-08-13 13:36:19 -050073 std::get<double>(s) = 0;
Matthew Barth2d2caa32020-05-26 11:07:24 -050074 log<level::INFO>("Unable to read fan tach sensor.",
75 entry("SENSOR=%s", tachPath.c_str()));
Brad Bishopd37c0f82017-07-28 21:47:00 -040076 }
Brad Bishopdd62e362017-06-14 16:54:03 -040077 }
78
79 // Set the initial state of the sensor.
Matthew Barth2d2caa32020-05-26 11:07:24 -050080 currentState = std::any_of(state.begin(), state.end(), [](const auto& s) {
Matthew Barthad2cd242020-08-13 13:36:19 -050081 return std::get<double>(s) != 0;
Matthew Barth2d2caa32020-05-26 11:07:24 -050082 });
Brad Bishopdd62e362017-06-14 16:54:03 -040083
84 return currentState;
85}
86
87void Tach::stop()
88{
89 for (auto& s : state)
90 {
91 // De-register signal callbacks.
92 std::get<1>(s) = nullptr;
93 }
94}
95
96bool Tach::present()
97{
98 // Live query the tach readings.
Matthew Barthad2cd242020-08-13 13:36:19 -050099 std::vector<double> values;
Brad Bishopdd62e362017-06-14 16:54:03 -0400100 for (const auto& s : state)
101 {
Matthew Barthad2cd242020-08-13 13:36:19 -0500102 values.push_back(util::SDBusPlus::getProperty<double>(
Matthew Barth2d2caa32020-05-26 11:07:24 -0500103 tachNamespace + std::get<std::string>(s), tachIface, tachProperty));
Brad Bishopdd62e362017-06-14 16:54:03 -0400104 }
105
Matthew Barth2d2caa32020-05-26 11:07:24 -0500106 return std::any_of(values.begin(), values.end(),
107 [](const auto& v) { return v != 0; });
Brad Bishopdd62e362017-06-14 16:54:03 -0400108}
109
Matthew Barth2d2caa32020-05-26 11:07:24 -0500110void Tach::propertiesChanged(size_t sensor, sdbusplus::message::message& msg)
Brad Bishopdd62e362017-06-14 16:54:03 -0400111{
112 std::string iface;
Matthew Barthad2cd242020-08-13 13:36:19 -0500113 util::Properties<double> properties;
Brad Bishopdd62e362017-06-14 16:54:03 -0400114 msg.read(iface, properties);
115
116 propertiesChanged(sensor, properties);
117}
118
Matthew Barth2d2caa32020-05-26 11:07:24 -0500119void Tach::propertiesChanged(size_t sensor,
Matthew Barthad2cd242020-08-13 13:36:19 -0500120 const util::Properties<double>& props)
Brad Bishopdd62e362017-06-14 16:54:03 -0400121{
Brad Bishopdd62e362017-06-14 16:54:03 -0400122 // Find the Value property containing the speed.
123 auto it = props.find(tachProperty);
124 if (it != props.end())
125 {
Matthew Barth9f93bd32020-05-28 16:57:14 -0500126 auto& s = state[sensor];
Matthew Barthad2cd242020-08-13 13:36:19 -0500127 std::get<double>(s) = std::get<double>(it->second);
Brad Bishopdd62e362017-06-14 16:54:03 -0400128
Matthew Barth2d2caa32020-05-26 11:07:24 -0500129 auto newState =
Matthew Barthad2cd242020-08-13 13:36:19 -0500130 std::any_of(state.begin(), state.end(),
131 [](const auto& s) { return std::get<double>(s) != 0; });
Brad Bishopdd62e362017-06-14 16:54:03 -0400132
133 if (currentState != newState)
134 {
Brad Bishop11083ec2017-07-25 19:08:53 -0400135 getPolicy().stateChanged(newState, *this);
Brad Bishopdd62e362017-06-14 16:54:03 -0400136 currentState = newState;
137 }
138 }
139}
140
141} // namespace presence
142} // namespace fan
143} // namespace phosphor