1 /**
2  * Copyright © 2021 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 #pragma once
17 
18 #include "../zone.hpp"
19 #include "action.hpp"
20 #include "group.hpp"
21 
22 #include <nlohmann/json.hpp>
23 
24 namespace phosphor::fan::control::json
25 {
26 
27 using json = nlohmann::json;
28 
29 /**
30  * @class CountStateFloor - Action to set a floor when members are at a state
31  *
32  * Sets the fans to a configured floor when a number of members within the
33  * group are at a configured state. Once the number of members at the given
34  * state falls below the configured count, the floor hold is released.
35  *
36  * Example JSON:
37  *    {
38  *      "name": "count_state_floor",
39  *      "count": 1,
40  *      "state": false,
41  *      "floor": 5000
42  *    }
43  *
44  * There is an optional 'delay' field that that prevents the floor from
45  * being changed until the count has been met for that amount of time.
46  */
47 class CountStateFloor :
48     public ActionBase,
49     public ActionRegister<CountStateFloor>
50 {
51   public:
52     /* Name of this action */
53     static constexpr auto name = "count_state_floor";
54 
55     CountStateFloor() = delete;
56     CountStateFloor(const CountStateFloor&) = delete;
57     CountStateFloor(CountStateFloor&&) = delete;
58     CountStateFloor& operator=(const CountStateFloor&) = delete;
59     CountStateFloor& operator=(CountStateFloor&&) = delete;
60     ~CountStateFloor() = default;
61 
62     /**
63      * @brief Set floor when a number of members are at a given state
64      *
65      * @param[in] jsonObj - JSON configuration of this action
66      * @param[in] groups - Groups of dbus objects the action uses
67      */
68     CountStateFloor(const json& jsonObj, const std::vector<Group>& groups);
69 
70     /**
71      * @brief Run the action
72      *
73      * Counts the number of members within a group are equal to a given state
74      * and when the number of members are at or above the given state, the
75      * zone is set to the configured floor, with a hold.  The hold is released
76      * when the number of members goes below the configured count.
77      *
78      * @param[in] zone - Zone to run the action on
79      */
80     void run(Zone& zone) override;
81 
82   private:
83     /**
84      * @brief Parse and set the count
85      *
86      * @param[in] jsonObj - JSON object for the action
87      *
88      * Sets the number of members that must equal the state
89      */
90     void setCount(const json& jsonObj);
91 
92     /**
93      * @brief Parse and set the state
94      *
95      * @param[in] jsonObj - JSON object for the action
96      *
97      * Sets the state for each member to equal to set the floor
98      */
99     void setState(const json& jsonObj);
100 
101     /**
102      * @brief Parse and set the floor
103      *
104      * @param[in] jsonObj - JSON object for the action
105      *
106      * Sets the floor to use when running the action
107      */
108     void setFloor(const json& jsonObj);
109 
110     /**
111      * @brief Parse and set the delay
112      *
113      * @param[in] jsonObj - JSON object for the action
114      */
115     void setDelayTime(const json& jsonObj);
116 
117     /**
118      * @brief Counts the number of members that are equal to the state.
119      *
120      * @return bool - If the count is reached or not.
121      */
122     bool doCount();
123 
124     /* Number of group members */
125     size_t _count;
126 
127     /* State the members must be at to set the floor */
128     PropertyVariantType _state;
129 
130     /* Floor for this action */
131     uint64_t _floor;
132 
133     /* Amount of time the count has to be met */
134     std::chrono::seconds _delayTime{0};
135 
136     /* Timer used for checking the delay */
137     std::unique_ptr<Timer> _timer;
138 };
139 
140 } // namespace phosphor::fan::control::json
141