blob: 4dc2ec3ab6b7088e79927506d648157704a0b03d [file] [log] [blame]
Brad Bishop00b52082017-07-25 19:52:22 -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 */
Brad Bishop00b52082017-07-25 19:52:22 -040016#include "anyof.hpp"
Matthew Barth2d2caa32020-05-26 11:07:24 -050017
Brad Bishop00b52082017-07-25 19:52:22 -040018#include "fan.hpp"
Matt Spinlerc65d91d2021-04-21 13:09:49 -050019#include "get_power_state.hpp"
Brad Bishop00b52082017-07-25 19:52:22 -040020#include "psensor.hpp"
21
Matthew Barth2d2caa32020-05-26 11:07:24 -050022#include <phosphor-logging/log.hpp>
23
24#include <algorithm>
25
Brad Bishop00b52082017-07-25 19:52:22 -040026namespace phosphor
27{
28namespace fan
29{
30namespace presence
31{
Matt Spinlerc65d91d2021-04-21 13:09:49 -050032
33using namespace std::chrono_literals;
34static const auto powerOnDelayTime = 5s;
35
Matthew Barth2d2caa32020-05-26 11:07:24 -050036AnyOf::AnyOf(const Fan& fan,
37 const std::vector<std::reference_wrapper<PresenceSensor>>& s) :
38 RedundancyPolicy(fan),
Matt Spinlerc65d91d2021-04-21 13:09:49 -050039 state(), _powerState(getPowerStateObject()),
40 _powerOnDelayTimer(sdeventplus::Event::get_default(),
41 std::bind(&AnyOf::delayedAfterPowerOn, this)),
42 _powerOn(false)
Brad Bishop00b52082017-07-25 19:52:22 -040043{
Matthew Barth2d2caa32020-05-26 11:07:24 -050044 for (auto& sensor : s)
Brad Bishop00b52082017-07-25 19:52:22 -040045 {
Matt Spinlerc65d91d2021-04-21 13:09:49 -050046 state.emplace_back(sensor, false, false);
47 }
48
49 _powerState->addCallback(
50 std::get<1>(fan) + "-anyOf",
51 std::bind(&AnyOf::powerStateChanged, this, std::placeholders::_1));
52
53 // If power is already on, give the fans some time to spin up
54 // before considering power to actually be on.
55 if (_powerState->isPowerOn())
56 {
57 _powerOnDelayTimer.restartOnce(powerOnDelayTime);
Brad Bishop00b52082017-07-25 19:52:22 -040058 }
59}
60
61void AnyOf::stateChanged(bool present, PresenceSensor& sensor)
62{
63 // Find the sensor that changed state.
Matthew Barth2d2caa32020-05-26 11:07:24 -050064 auto sit =
65 std::find_if(state.begin(), state.end(), [&sensor](const auto& s) {
Matt Spinlerc65d91d2021-04-21 13:09:49 -050066 return std::get<sensorPos>(s).get() == sensor;
Matthew Barth2d2caa32020-05-26 11:07:24 -050067 });
Brad Bishop00b52082017-07-25 19:52:22 -040068 if (sit != state.end())
69 {
Matt Spinlerc65d91d2021-04-21 13:09:49 -050070 auto origState =
71 std::any_of(state.begin(), state.end(),
72 [](const auto& s) { return std::get<presentPos>(s); });
73
Brad Bishop00b52082017-07-25 19:52:22 -040074 // Update our cache of the sensors state and re-evaluate.
Matt Spinlerc65d91d2021-04-21 13:09:49 -050075 std::get<presentPos>(*sit) = present;
Matthew Barth2d2caa32020-05-26 11:07:24 -050076 auto newState =
77 std::any_of(state.begin(), state.end(),
Matt Spinlerc65d91d2021-04-21 13:09:49 -050078 [](const auto& s) { return std::get<presentPos>(s); });
Brad Bishop00b52082017-07-25 19:52:22 -040079 setPresence(fan, newState);
Matt Spinlerc65d91d2021-04-21 13:09:49 -050080
81 // At least 1 sensor said a fan was present, check if any disagree.
82 if (newState)
83 {
84 if (!origState)
85 {
86 // Fan plug detected, re-enable conflict logging
87 std::for_each(state.begin(), state.end(), [](auto& s) {
88 std::get<conflictPos>(s) = false;
89 });
90 }
91
92 checkSensorConflicts();
93 }
Brad Bishop00b52082017-07-25 19:52:22 -040094 }
95}
96
97void AnyOf::monitor()
98{
99 // Start all sensors in the anyof redundancy set.
100
Matthew Barth2d2caa32020-05-26 11:07:24 -0500101 for (auto& s : state)
Brad Bishop00b52082017-07-25 19:52:22 -0400102 {
Matt Spinlerc65d91d2021-04-21 13:09:49 -0500103 auto& sensor = std::get<sensorPos>(s);
104 std::get<presentPos>(s) = sensor.get().start();
Brad Bishop00b52082017-07-25 19:52:22 -0400105 }
106
Matt Spinlerc65d91d2021-04-21 13:09:49 -0500107 auto present = std::any_of(state.begin(), state.end(), [](const auto& s) {
108 return std::get<presentPos>(s);
109 });
Brad Bishop00b52082017-07-25 19:52:22 -0400110 setPresence(fan, present);
Matt Spinlerc65d91d2021-04-21 13:09:49 -0500111
112 // At least one of the contained methods indicated present,
113 // so check that they all agree.
114 if (present)
115 {
116 checkSensorConflicts();
117 }
118}
119
120void AnyOf::checkSensorConflicts()
121{
122 if (!isPowerOn())
123 {
124 return;
125 }
126
127 // If at least one, but not all, sensors indicate present, then
128 // tell the not present ones to log a conflict if not already done.
129 if (std::any_of(
130 state.begin(), state.end(),
131 [this](const auto& s) { return std::get<presentPos>(s); }) &&
132 !std::all_of(state.begin(), state.end(),
133 [this](const auto& s) { return std::get<presentPos>(s); }))
134 {
135 for (auto& [sensor, present, conflict] : state)
136 {
137 if (!present && !conflict)
138 {
139 sensor.get().logConflict(invNamespace + std::get<1>(fan));
140 conflict = true;
141 }
142 }
143 }
144}
145
146void AnyOf::powerStateChanged(bool powerOn)
147{
148 if (powerOn)
149 {
150 // Clear the conflict state from last time
151 std::for_each(state.begin(), state.end(), [](auto& state) {
152 std::get<conflictPos>(state) = false;
153 });
154
155 // Wait to give the fans time to start spinning before
156 // considering power actually on.
157 _powerOnDelayTimer.restartOnce(powerOnDelayTime);
158 }
159 else
160 {
161 _powerOn = false;
162
163 if (_powerOnDelayTimer.isEnabled())
164 {
165 _powerOnDelayTimer.setEnabled(false);
166 }
167 }
168}
169
170void AnyOf::delayedAfterPowerOn()
171{
172 _powerOn = true;
173 checkSensorConflicts();
Brad Bishop00b52082017-07-25 19:52:22 -0400174}
175
176} // namespace presence
177} // namespace fan
178} // namespace phosphor