1 /**
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 <algorithm>
17 #include <phosphor-logging/log.hpp>
18 #include "fan.hpp"
19 #include "types.hpp"
20 
21 namespace phosphor
22 {
23 namespace fan
24 {
25 namespace monitor
26 {
27 
28 using namespace phosphor::logging;
29 
30 Fan::Fan(sdbusplus::bus::bus& bus,
31          std::shared_ptr<sd_event>&  events,
32          const FanDefinition& def) :
33     _bus(bus),
34     _name(std::get<fanNameField>(def)),
35     _deviation(std::get<fanDeviationField>(def)),
36     _numSensorFailsForNonFunc(std::get<numSensorFailsForNonfuncField>(def))
37 {
38     auto& sensors = std::get<sensorListField>(def);
39 
40     for (auto& s : sensors)
41     {
42         _sensors.emplace_back(
43             std::make_unique<TachSensor>(bus,
44                                          *this,
45                                          std::get<sensorNameField>(s),
46                                          std::get<hasTargetField>(s),
47                                          std::get<timeoutField>(def)));
48 
49     }
50 
51 }
52 
53 
54 void Fan::tachChanged()
55 {
56     for (auto& s : _sensors)
57     {
58         tachChanged(*s);
59     }
60 }
61 
62 
63 void Fan::tachChanged(TachSensor& sensor)
64 {
65     //TODO
66 }
67 
68 
69 uint64_t Fan::getTargetSpeed(const TachSensor& sensor)
70 {
71     uint64_t target = 0;
72 
73     if (sensor.hasTarget())
74     {
75         target = sensor.getTarget();
76     }
77     else
78     {
79         //The sensor doesn't support a target,
80         //so get it from another sensor.
81         auto s = std::find_if(_sensors.begin(), _sensors.end(),
82                               [](const auto& s)
83                               {
84                                   return s->hasTarget();
85                               });
86 
87         if (s != _sensors.end())
88         {
89             target = (*s)->getTarget();
90         }
91     }
92 
93     return target;
94 }
95 
96 
97 bool Fan::tooManySensorsNonfunctional()
98 {
99     size_t numFailed =  std::count_if(_sensors.begin(), _sensors.end(),
100                                       [](const auto& s)
101                                       {
102                                           return !s->functional();
103                                       });
104 
105     return (numFailed >= _numSensorFailsForNonFunc);
106 }
107 
108 
109 bool Fan::outOfRange(const TachSensor& sensor)
110 {
111     auto actual = static_cast<uint64_t>(sensor.getInput());
112     auto target = getTargetSpeed(sensor);
113 
114     uint64_t min = target * (100 - _deviation) / 100;
115     uint64_t max = target * (100 + _deviation) / 100;
116 
117     if ((actual < min) || (actual > max))
118     {
119         return true;
120     }
121 
122     return false;
123 }
124 
125 
126 }
127 }
128 }
129