| /** |
| * Copyright © 2017 IBM Corporation |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| #include <phosphor-logging/log.hpp> |
| #include <string> |
| #include <tuple> |
| #include <vector> |
| #include "tach.hpp" |
| #include "rpolicy.hpp" |
| |
| namespace phosphor |
| { |
| namespace fan |
| { |
| namespace presence |
| { |
| |
| using namespace phosphor::logging; |
| using namespace std::literals::string_literals; |
| |
| static const auto tachNamespace = "/xyz/openbmc_project/sensors/fan_tach/"s; |
| static const auto tachIface = "xyz.openbmc_project.Sensor.Value"s; |
| static const auto tachProperty = "Value"s; |
| |
| Tach::Tach( |
| const std::vector<std::string>& sensors) : currentState(false) |
| { |
| // Initialize state. |
| for (const auto& s : sensors) |
| { |
| state.emplace_back(s, nullptr, 0); |
| } |
| } |
| |
| bool Tach::start() |
| { |
| for (size_t i = 0; i < state.size(); ++i) |
| { |
| auto& s = state[i]; |
| auto tachPath = tachNamespace + std::get<std::string>(s); |
| |
| // Register for signal callbacks. |
| std::get<1>(s) = std::make_unique<sdbusplus::bus::match::match>( |
| util::SDBusPlus::getBus(), |
| sdbusplus::bus::match::rules::propertiesChanged( |
| tachPath, tachIface), |
| [this, i](auto& msg){ this->propertiesChanged(i, msg);}); |
| |
| // Get an initial tach speed. |
| try |
| { |
| std::get<int64_t>(s) = util::SDBusPlus::getProperty<int64_t>( |
| tachPath, |
| tachIface, |
| tachProperty); |
| } |
| catch (std::exception&) |
| { |
| // Assume not spinning. |
| |
| std::get<int64_t>(s) = 0; |
| log<level::INFO>( |
| "Unable to read fan tach sensor.", |
| entry("SENSOR=%s", tachPath)); |
| |
| } |
| } |
| |
| // Set the initial state of the sensor. |
| currentState = std::any_of( |
| state.begin(), |
| state.end(), |
| [](const auto & s) |
| { |
| return std::get<int64_t>(s) != 0; |
| }); |
| |
| return currentState; |
| } |
| |
| void Tach::stop() |
| { |
| for (auto& s : state) |
| { |
| // De-register signal callbacks. |
| std::get<1>(s) = nullptr; |
| } |
| } |
| |
| bool Tach::present() |
| { |
| // Live query the tach readings. |
| std::vector<int64_t> values; |
| for (const auto& s : state) |
| { |
| values.push_back( |
| util::SDBusPlus::getProperty<int64_t>( |
| tachNamespace + std::get<std::string>(s), |
| tachIface, |
| tachProperty)); |
| } |
| |
| return std::any_of( |
| values.begin(), |
| values.end(), |
| [](const auto & v) {return v != 0;}); |
| } |
| |
| void Tach::propertiesChanged( |
| size_t sensor, |
| sdbusplus::message::message& msg) |
| { |
| std::string iface; |
| util::Properties<int64_t> properties; |
| msg.read(iface, properties); |
| |
| propertiesChanged(sensor, properties); |
| } |
| |
| void Tach::propertiesChanged( |
| size_t sensor, |
| const util::Properties<int64_t>& props) |
| { |
| auto& s = state[sensor]; |
| |
| // Find the Value property containing the speed. |
| auto it = props.find(tachProperty); |
| if (it != props.end()) |
| { |
| std::get<int64_t>(s) = |
| sdbusplus::message::variant_ns::get<int64_t>(it->second); |
| |
| auto newState = std::any_of( |
| state.begin(), |
| state.end(), |
| [](const auto & s) |
| { |
| return std::get<int64_t>(s) != 0; |
| }); |
| |
| if (currentState != newState) |
| { |
| getPolicy().stateChanged(newState, *this); |
| currentState = newState; |
| } |
| } |
| } |
| |
| } // namespace presence |
| } // namespace fan |
| } // namespace phosphor |