Add timer option to run set speed event actions
For groups within set speed events where the property values of the
group may not signal its action to occur, an optional timer may be added
to the event. This timer is configured as a repeating timer on the
interval provided where upon timer expiration, the event's action is
run.
Change-Id: I4cbe8a0ab1b734bfc7828706a6515af7f6d78b52
Signed-off-by: Matthew Barth <msbarth@us.ibm.com>
diff --git a/control/gen-fan-zone-defs.py b/control/gen-fan-zone-defs.py
index 45ca774..a2a49a8 100755
--- a/control/gen-fan-zone-defs.py
+++ b/control/gen-fan-zone-defs.py
@@ -112,6 +112,9 @@
%endif
%endfor
)),
+ Timer{
+ ${event['timer']['interval']}
+ },
std::vector<PropertyChange>{
%for s in event['signal']:
PropertyChange{
@@ -146,6 +149,9 @@
%if ('pc' in event) and (event['pc'] is not None):
}
)),
+ Timer{
+ ${event['pc']['pctime']['interval']}
+ },
std::vector<PropertyChange>{
%for s in event['pc']['pcsig']:
PropertyChange{
@@ -264,6 +270,20 @@
signal.append(signals)
precond['pcsig'] = signal
+ # Add optional action call timer
+ timer = {}
+ interval = "static_cast<std::chrono::seconds>"
+ if ('timer' in event['precondition']) and \
+ (event['precondition']['timer'] is not None):
+ timer['interval'] = (interval +
+ "(" +
+ str(event['precondition']['timer']['interval']) +
+ ")")
+ else:
+ timer['interval'] = (interval +
+ "(" + str(0) + ")")
+ precond['pctime'] = timer
+
return precond
@@ -350,6 +370,18 @@
signal.append(signals)
event['signal'] = signal
+ # Add optional action call timer
+ timer = {}
+ interval = "static_cast<std::chrono::seconds>"
+ if ('timer' in e) and \
+ (e['timer'] is not None):
+ timer['interval'] = (interval +
+ "(" + str(e['timer']['interval']) + ")")
+ else:
+ timer['interval'] = (interval +
+ "(" + str(0) + ")")
+ event['timer'] = timer
+
events.append(event)
return events
diff --git a/control/types.hpp b/control/types.hpp
index bac5402..b788ac5 100644
--- a/control/types.hpp
+++ b/control/types.hpp
@@ -3,6 +3,7 @@
#include <tuple>
#include <vector>
#include <sdbusplus/server.hpp>
+#include "timer.hpp"
namespace phosphor
{
@@ -52,15 +53,20 @@
std::string,
PropertyVariantType>;
+constexpr auto intervalPos = 0;
+using Timer = std::tuple<std::chrono::seconds>;
+
constexpr auto signaturePos = 0;
constexpr auto handlerObjPos = 1;
using PropertyChange = std::tuple<std::string, Handler>;
constexpr auto groupPos = 0;
constexpr auto actionPos = 1;
-constexpr auto propChangeListPos = 2;
+constexpr auto timerPos = 2;
+constexpr auto propChangeListPos = 3;
using SetSpeedEvent = std::tuple<Group,
Action,
+ Timer,
std::vector<PropertyChange>>;
constexpr auto eventGroupPos = 0;
@@ -68,6 +74,9 @@
constexpr auto eventActionPos = 2;
using EventData = std::tuple<Group, Handler, Action>;
+constexpr auto timerTimerPos = 0;
+using TimerEvent = std::tuple<phosphor::fan::util::Timer>;
+
constexpr auto signalEventDataPos = 0;
constexpr auto signalMatchPos = 1;
using SignalEvent =
diff --git a/control/zone.cpp b/control/zone.cpp
index cef375c..9670127 100644
--- a/control/zone.cpp
+++ b/control/zone.cpp
@@ -29,6 +29,7 @@
{
using namespace std::chrono;
+using namespace phosphor::fan;
using namespace phosphor::logging;
using InternalFailure = sdbusplus::xyz::openbmc_project::Common::
Error::InternalFailure;
@@ -45,7 +46,8 @@
_incDelay(std::get<incDelayPos>(def)),
_decInterval(std::get<decIntervalPos>(def)),
_incTimer(events, [this](){ this->incTimerExpired(); }),
- _decTimer(events, [this](){ this->decTimerExpired(); })
+ _decTimer(events, [this](){ this->decTimerExpired(); }),
+ _sdEvents(events)
{
auto& fanDefs = std::get<fanListPos>(def);
@@ -216,6 +218,26 @@
);
_signalEvents.emplace_back(std::move(eventData), std::move(match));
}
+ // Attach a timer to run the action of an event
+ auto eventTimer = std::get<timerPos>(event);
+ if (std::get<intervalPos>(eventTimer) != seconds(0))
+ {
+ std::unique_ptr<util::Timer> timer =
+ std::make_unique<util::Timer>(
+ _sdEvents,
+ [this,
+ action = &(std::get<actionPos>(event)),
+ group = &(std::get<groupPos>(event))]()
+ {
+ this->timerExpired(*group, *action);
+ });
+ if (!timer->running())
+ {
+ timer->start(std::get<intervalPos>(eventTimer),
+ util::Timer::TimerType::repeating);
+ }
+ _timerEvents.emplace_back(std::move(timer));
+ }
// Run action function for initial event state
std::get<actionPos>(event)(*this,
std::get<groupPos>(event));
@@ -279,6 +301,12 @@
hostResponseMsg.read(value);
}
+void Zone::timerExpired(Group eventGroup, Action eventAction)
+{
+ // Perform the action
+ eventAction(*this, eventGroup);
+}
+
void Zone::handleEvent(sdbusplus::message::message& msg,
const EventData* eventData)
{
diff --git a/control/zone.hpp b/control/zone.hpp
index a56b1c7..6e81bd1 100644
--- a/control/zone.hpp
+++ b/control/zone.hpp
@@ -247,6 +247,15 @@
*/
void decTimerExpired();
+ /**
+ * @brief Callback function for event timers that processes the given
+ * action for a group
+ *
+ * @param[in] eventGroup - Group to process action on
+ * @param[in] eventAction - Event action to run
+ */
+ void timerExpired(Group eventGroup, Action eventAction);
+
private:
/**
@@ -330,6 +339,11 @@
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;
@@ -353,6 +367,11 @@
std::vector<SignalEvent> _signalEvents;
/**
+ * @brief List of timers for events
+ */
+ std::vector<std::unique_ptr<phosphor::fan::util::Timer>> _timerEvents;
+
+ /**
* @brief Refresh the given property's cached value
*
* @param[in] bus - the bus to use