control: Handle adding timers and when they expire
Timers are added to the manager object with a package of data that's
used when the timer expires and runs a set of actions. Each timer added
creates a new timer instance and `oneshot` timers are removed when they
expire.
Change-Id: I1c47878fd3f68a1121b0fd0dfdfe3e66f9ff783f
Signed-off-by: Matthew Barth <msbarth@us.ibm.com>
diff --git a/control/json/manager.cpp b/control/json/manager.cpp
index 3508307..a072f49 100644
--- a/control/json/manager.cpp
+++ b/control/json/manager.cpp
@@ -17,7 +17,9 @@
#include "manager.hpp"
+#include "action.hpp"
#include "fan.hpp"
+#include "group.hpp"
#include "json_config.hpp"
#include "profile.hpp"
#include "zone.hpp"
@@ -25,9 +27,16 @@
#include <nlohmann/json.hpp>
#include <sdbusplus/bus.hpp>
#include <sdeventplus/event.hpp>
+#include <sdeventplus/utility/timer.hpp>
#include <algorithm>
+#include <chrono>
#include <filesystem>
+#include <functional>
+#include <map>
+#include <memory>
+#include <tuple>
+#include <utility>
#include <vector>
namespace phosphor::fan::control::json
@@ -106,6 +115,55 @@
return false;
}
+void Manager::addTimer(const TimerType type,
+ const std::chrono::microseconds interval,
+ std::unique_ptr<TimerPkg> pkg)
+{
+ auto dataPtr =
+ std::make_unique<TimerData>(std::make_pair(type, std::move(*pkg)));
+ Timer timer(_event,
+ std::bind(&Manager::timerExpired, this, std::ref(*dataPtr)));
+ if (type == TimerType::repeating)
+ {
+ timer.restart(interval);
+ }
+ else if (type == TimerType::oneshot)
+ {
+ timer.restartOnce(interval);
+ }
+ else
+ {
+ throw std::invalid_argument("Invalid Timer Type");
+ }
+ _timers.emplace_back(std::move(dataPtr), std::move(timer));
+}
+
+void Manager::timerExpired(TimerData& data)
+{
+ auto& actions =
+ std::get<std::vector<std::unique_ptr<ActionBase>>&>(data.second);
+ // Perform the actions in the timer data
+ std::for_each(actions.begin(), actions.end(),
+ [zone = std::ref(std::get<Zone&>(data.second)),
+ group = std::cref(std::get<const Group&>(data.second))](
+ auto& action) { action->run(zone, group); });
+
+ // Remove oneshot timers after they expired
+ if (data.first == TimerType::oneshot)
+ {
+ auto itTimer = std::find_if(
+ _timers.begin(), _timers.end(), [&data](const auto& timer) {
+ return (data.first == timer.first->first &&
+ (std::get<std::string>(data.second) ==
+ std::get<std::string>(timer.first->second)));
+ });
+ if (itTimer != std::end(_timers))
+ {
+ _timers.erase(itTimer);
+ }
+ }
+}
+
unsigned int Manager::getPowerOnDelay()
{
auto powerOnDelay = 0;