| #pragma once |
| #include <chrono> |
| #include <vector> |
| #include <cassert> |
| #include <algorithm> |
| #include <sdbusplus/bus.hpp> |
| #include "fan.hpp" |
| #include "types.hpp" |
| #include "timer.hpp" |
| |
| namespace phosphor |
| { |
| namespace fan |
| { |
| namespace control |
| { |
| |
| /** |
| * The mode fan control will run in: |
| * - init - only do the initialization steps |
| * - control - run normal control algorithms |
| */ |
| enum class Mode |
| { |
| init, |
| control |
| }; |
| |
| /** |
| * @class Represents a fan control zone, which is a group of fans |
| * that behave the same. |
| */ |
| class Zone |
| { |
| public: |
| |
| Zone() = delete; |
| Zone(const Zone&) = delete; |
| Zone(Zone&&) = delete; |
| Zone& operator=(const Zone&) = delete; |
| Zone& operator=(Zone&&) = delete; |
| ~Zone() = default; |
| |
| /** |
| * Constructor |
| * Creates the appropriate fan objects based on |
| * the zone definition data passed in. |
| * |
| * @param[in] mode - mode of fan control |
| * @param[in] bus - the dbus object |
| * @param[in] events - sd_event pointer |
| * @param[in] def - the fan zone definition data |
| */ |
| Zone(Mode mode, |
| sdbusplus::bus::bus& bus, |
| phosphor::fan::event::EventPtr& events, |
| const ZoneDefinition& def); |
| |
| /** |
| * Sets all fans in the zone to the speed |
| * passed in when the zone is active |
| * |
| * @param[in] speed - the fan speed |
| */ |
| void setSpeed(uint64_t speed); |
| |
| /** |
| * Sets the zone to full speed regardless of zone's active state |
| */ |
| void setFullSpeed(); |
| |
| /** |
| * @brief Sets the automatic fan control allowed active state |
| * |
| * @param[in] group - A group that affects the active state |
| * @param[in] isActiveAllow - Active state according to group |
| */ |
| void setActiveAllow(const Group* group, bool isActiveAllow); |
| |
| /** |
| * @brief Sets the floor change allowed state |
| * |
| * @param[in] group - A group that affects floor changes |
| * @param[in] isAllow - Allow state according to group |
| */ |
| inline void setFloorChangeAllow(const Group* group, bool isAllow) |
| { |
| _floorChange[*(group)] = isAllow; |
| } |
| |
| /** |
| * @brief Sets a given object's property value |
| * |
| * @param[in] object - Name of the object containing the property |
| * @param[in] interface - Interface name containing the property |
| * @param[in] property - Property name |
| * @param[in] value - Property value |
| */ |
| template <typename T> |
| void setPropertyValue(const char* object, |
| const char* interface, |
| const char* property, |
| T value) |
| { |
| _properties[object][interface][property] = value; |
| }; |
| |
| /** |
| * @brief Get the value of an object's property |
| * |
| * @param[in] object - Name of the object containing the property |
| * @param[in] interface - Interface name containing the property |
| * @param[in] property - Property name |
| * |
| * @return - The property value |
| */ |
| template <typename T> |
| inline auto getPropertyValue(const std::string& object, |
| const std::string& interface, |
| const std::string& property) |
| { |
| return sdbusplus::message::variant_ns::get<T>( |
| _properties.at(object).at(interface).at(property)); |
| }; |
| |
| /** |
| * @brief Get the object's property variant |
| * |
| * @param[in] object - Name of the object containing the property |
| * @param[in] interface - Interface name containing the property |
| * @param[in] property - Property name |
| * |
| * @return - The property variant |
| */ |
| inline auto getPropValueVariant(const std::string& object, |
| const std::string& interface, |
| const std::string& property) |
| { |
| return _properties.at(object).at(interface).at(property); |
| }; |
| |
| /** |
| * @brief Remove a service associated to a group |
| * |
| * @param[in] group - Group associated with service |
| * @param[in] name - Service name to remove |
| */ |
| void removeService(const Group* group, |
| const std::string& name); |
| |
| /** |
| * @brief Set or update a service name owner in use |
| * |
| * @param[in] group - Group associated with service |
| * @param[in] name - Service name |
| * @param[in] hasOwner - Whether the service is owned or not |
| */ |
| void setServiceOwner(const Group* group, |
| const std::string& name, |
| const bool hasOwner); |
| |
| /** |
| * @brief Set or update all services for a group |
| * |
| * @param[in] group - Group to get service names for |
| */ |
| void setServices(const Group* group); |
| |
| /** |
| * @brief Get the group's list of service names |
| * |
| * @param[in] group - Group to get service names for |
| * |
| * @return - The list of service names |
| */ |
| inline auto getGroupServices(const Group* group) |
| { |
| return _services.at(*group); |
| } |
| |
| /** |
| * @brief Initialize a set speed event properties and actions |
| * |
| * @param[in] event - Set speed event |
| */ |
| void initEvent(const SetSpeedEvent& event); |
| |
| /** |
| * @brief Removes all the set speed event properties and actions |
| * |
| * @param[in] event - Set speed event |
| */ |
| void removeEvent(const SetSpeedEvent& event); |
| |
| /** |
| * @brief Get the default floor speed |
| * |
| * @return - The defined default floor speed |
| */ |
| inline auto getDefFloor() |
| { |
| return _defFloorSpeed; |
| }; |
| |
| /** |
| * @brief Get the ceiling speed |
| * |
| * @return - The current ceiling speed |
| */ |
| inline auto& getCeiling() const |
| { |
| return _ceilingSpeed; |
| }; |
| |
| /** |
| * @brief Set the ceiling speed to the given speed |
| * |
| * @param[in] speed - Speed to set the ceiling to |
| */ |
| inline void setCeiling(uint64_t speed) |
| { |
| _ceilingSpeed = speed; |
| }; |
| |
| /** |
| * @brief Swaps the ceiling key value with what's given and |
| * returns the value that was swapped. |
| * |
| * @param[in] keyValue - New ceiling key value |
| * |
| * @return - Ceiling key value prior to swapping |
| */ |
| inline auto swapCeilingKeyValue(int64_t keyValue) |
| { |
| std::swap(_ceilingKeyValue, keyValue); |
| return keyValue; |
| }; |
| |
| /** |
| * @brief Get the increase speed delta |
| * |
| * @return - The current increase speed delta |
| */ |
| inline auto& getIncSpeedDelta() const |
| { |
| return _incSpeedDelta; |
| }; |
| |
| /** |
| * @brief Get the decrease speed delta |
| * |
| * @return - The current decrease speed delta |
| */ |
| inline auto& getDecSpeedDelta() const |
| { |
| return _decSpeedDelta; |
| }; |
| |
| /** |
| * @brief Set the floor speed to the given speed and increase target |
| * speed to the floor when target is below floor where floor changes |
| * are allowed. |
| * |
| * @param[in] speed - Speed to set the floor to |
| */ |
| void setFloor(uint64_t speed); |
| |
| /** |
| * @brief Set the requested speed base to be used as the speed to |
| * base a new requested speed target from |
| * |
| * @param[in] speedBase - Base speed value to use |
| */ |
| inline void setRequestSpeedBase(uint64_t speedBase) |
| { |
| _requestSpeedBase = speedBase; |
| }; |
| |
| /** |
| * @brief Calculate the requested target speed from the given delta |
| * and increase the fan speeds, not going above the ceiling. |
| * |
| * @param[in] targetDelta - The delta to increase the target speed by |
| */ |
| void requestSpeedIncrease(uint64_t targetDelta); |
| |
| /** |
| * @brief Calculate the requested target speed from the given delta |
| * and increase the fan speeds, not going above the ceiling. |
| * |
| * @param[in] targetDelta - The delta to increase the target speed by |
| */ |
| void requestSpeedDecrease(uint64_t targetDelta); |
| |
| /** |
| * @brief Callback function for the increase timer that delays |
| * processing of requested speed increases while fans are increasing |
| */ |
| void incTimerExpired(); |
| |
| /** |
| * @brief Callback function for the decrease timer that processes any |
| * requested speed decreases if allowed |
| */ |
| void decTimerExpired(); |
| |
| /** |
| * @brief Get the event pointer used with this zone's timers |
| * |
| * @return - The Dbus event pointer for timers |
| */ |
| inline auto& getEventPtr() |
| { |
| return _sdEvents; |
| } |
| |
| /** |
| * @brief Get the list of timer events |
| * |
| * @return - List of timer events |
| */ |
| inline auto& getTimerEvents() |
| { |
| return _timerEvents; |
| } |
| |
| /** |
| * @brief Find the first instance of a timer event |
| * |
| * @param[in] eventGroup - Group associated with a timer |
| * @param[in] eventActions - List of actions associated with a timer |
| * |
| * @return - Iterator to the timer event |
| */ |
| std::vector<TimerEvent>::iterator findTimer( |
| const Group& eventGroup, |
| const std::vector<Action>& eventActions); |
| |
| /** |
| * @brief Add a timer to the list of timer based events |
| * |
| * @param[in] data - Event data for timer |
| * @param[in] timer - Timer to be added |
| */ |
| inline void addTimer( |
| std::unique_ptr<EventData>&& data, |
| std::unique_ptr<phosphor::fan::util::Timer>&& timer) |
| { |
| _timerEvents.emplace_back(std::move(data), std::move(timer)); |
| }; |
| |
| /** |
| * @brief Remove the given timer event |
| * |
| * @param[in] teIter - Iterator pointing to the timer event to remove |
| */ |
| inline void removeTimer(std::vector<TimerEvent>::iterator& teIter) |
| { |
| assert(teIter != std::end(_timerEvents)); |
| std::get<timerEventDataPos>(*teIter).reset(); |
| std::get<timerTimerPos>(*teIter).reset(); |
| _timerEvents.erase(teIter); |
| } |
| |
| /** |
| * @brief Callback function for event timers that processes the given |
| * actions for a group |
| * |
| * @param[in] eventGroup - Group to process actions on |
| * @param[in] eventActions - List of event actions to run |
| */ |
| void timerExpired(Group eventGroup, std::vector<Action> eventActions); |
| |
| private: |
| |
| /** |
| * The dbus object |
| */ |
| sdbusplus::bus::bus& _bus; |
| |
| /** |
| * Full speed for the zone |
| */ |
| const uint64_t _fullSpeed; |
| |
| /** |
| * The zone number |
| */ |
| const size_t _zoneNum; |
| |
| /** |
| * The default floor speed for the zone |
| */ |
| const uint64_t _defFloorSpeed; |
| |
| /** |
| * The default ceiling speed for the zone |
| */ |
| const uint64_t _defCeilingSpeed; |
| |
| /** |
| * The floor speed to not go below |
| */ |
| uint64_t _floorSpeed = _defFloorSpeed; |
| |
| /** |
| * The ceiling speed to not go above |
| */ |
| uint64_t _ceilingSpeed = _defCeilingSpeed; |
| |
| /** |
| * The previous sensor value for calculating the ceiling |
| */ |
| int64_t _ceilingKeyValue = 0; |
| |
| /** |
| * Automatic fan control active state |
| */ |
| bool _isActive = true; |
| |
| /** |
| * Target speed for this zone |
| */ |
| uint64_t _targetSpeed = _fullSpeed; |
| |
| /** |
| * Speed increase delta |
| */ |
| uint64_t _incSpeedDelta = 0; |
| |
| /** |
| * Speed decrease delta |
| */ |
| uint64_t _decSpeedDelta = 0; |
| |
| /** |
| * Requested speed base |
| */ |
| uint64_t _requestSpeedBase = 0; |
| |
| /** |
| * Speed increase delay in seconds |
| */ |
| std::chrono::seconds _incDelay; |
| |
| /** |
| * Speed decrease interval in seconds |
| */ |
| std::chrono::seconds _decInterval; |
| |
| /** |
| * The increase timer object |
| */ |
| phosphor::fan::util::Timer _incTimer; |
| |
| /** |
| * The decrease timer object |
| */ |
| phosphor::fan::util::Timer _decTimer; |
| |
| /** |
| * Dbus event used on set speed event timers |
| */ |
| phosphor::fan::event::EventPtr& _sdEvents; |
| |
| /** |
| * The vector of fans in this zone |
| */ |
| std::vector<std::unique_ptr<Fan>> _fans; |
| |
| /** |
| * @brief Map of object property values |
| */ |
| std::map<std::string, |
| std::map<std::string, |
| std::map<std::string, |
| PropertyVariantType>>> _properties; |
| |
| /** |
| * @brief Map of active fan control allowed by groups |
| */ |
| std::map<const Group, bool> _active; |
| |
| /** |
| * @brief Map of floor change allowed by groups |
| */ |
| std::map<const Group, bool> _floorChange; |
| |
| /** |
| * @brief Map of group service names |
| */ |
| std::map<const Group, std::vector<Service>> _services; |
| |
| /** |
| * @brief List of signal event arguments and Dbus matches for callbacks |
| */ |
| std::vector<SignalEvent> _signalEvents; |
| |
| /** |
| * @brief List of timers for events |
| */ |
| std::vector<TimerEvent> _timerEvents; |
| |
| /** |
| * @brief Get the request speed base if defined, otherwise the |
| * the current target speed is returned |
| * |
| * @return - The request speed base or current target speed |
| */ |
| inline auto getRequestSpeedBase() const |
| { |
| return (_requestSpeedBase != 0) ? _requestSpeedBase : _targetSpeed; |
| }; |
| |
| /** |
| * @brief Dbus signal change callback handler |
| * |
| * @param[in] msg - Expanded sdbusplus message data |
| * @param[in] eventData - The single event's data |
| */ |
| void handleEvent(sdbusplus::message::message& msg, |
| const EventData* eventData); |
| }; |
| |
| } |
| } |
| } |