Added discrete threshold trigger support
Implemented discrete threshold logic
Discrete trigger with empty threshold array is handled as 'onChange'
Added unit tests coverage for discrete trigger
Supported scenarios:
-discrete threshold with value and dwell time
-discrete threshold with value, without dwell time
-discrete trigger without threshold ('onChange')
Tests:
-Unit tests passed
Change-Id: Id60a48f4113bd955d97e154888c00d1b6e5490af
Signed-off-by: Szymon Dompke <szymon.dompke@intel.com>
diff --git a/src/discrete_threshold.cpp b/src/discrete_threshold.cpp
new file mode 100644
index 0000000..a93f682
--- /dev/null
+++ b/src/discrete_threshold.cpp
@@ -0,0 +1,103 @@
+#include "discrete_threshold.hpp"
+
+#include <phosphor-logging/log.hpp>
+
+DiscreteThreshold::DiscreteThreshold(
+ boost::asio::io_context& ioc,
+ std::vector<std::shared_ptr<interfaces::Sensor>> sensorsIn,
+ std::vector<std::string> sensorNames,
+ std::vector<std::unique_ptr<interfaces::TriggerAction>> actionsIn,
+ std::chrono::milliseconds dwellTimeIn, double thresholdValueIn,
+ std::string name) :
+ ioc(ioc),
+ sensors(std::move(sensorsIn)), actions(std::move(actionsIn)),
+ dwellTime(dwellTimeIn), thresholdValue(thresholdValueIn), name(name)
+{
+ details.reserve(sensors.size());
+ for (size_t i = 0; i < sensors.size(); i++)
+ {
+ details.emplace_back(sensorNames[i], false, ioc);
+ }
+}
+
+void DiscreteThreshold::initialize()
+{
+ for (auto& sensor : sensors)
+ {
+ sensor->registerForUpdates(weak_from_this());
+ }
+}
+
+DiscreteThreshold::ThresholdDetail&
+ DiscreteThreshold::getDetails(interfaces::Sensor& sensor)
+{
+ auto it =
+ std::find_if(sensors.begin(), sensors.end(),
+ [&sensor](const auto& x) { return &sensor == x.get(); });
+ auto index = std::distance(sensors.begin(), it);
+ return details.at(index);
+}
+
+void DiscreteThreshold::sensorUpdated(interfaces::Sensor& sensor,
+ uint64_t timestamp)
+{}
+
+void DiscreteThreshold::sensorUpdated(interfaces::Sensor& sensor,
+ uint64_t timestamp, double value)
+{
+ auto& [sensorName, dwell, timer] = getDetails(sensor);
+
+ if (thresholdValue)
+ {
+ if (dwell && value != thresholdValue)
+ {
+ timer.cancel();
+ dwell = false;
+ }
+ else if (value == thresholdValue)
+ {
+ startTimer(sensor, timestamp, value);
+ }
+ }
+}
+
+void DiscreteThreshold::startTimer(interfaces::Sensor& sensor,
+ uint64_t timestamp, double value)
+{
+ auto& [sensorName, dwell, timer] = getDetails(sensor);
+ if (dwellTime == std::chrono::milliseconds::zero())
+ {
+ commit(sensorName, timestamp, value);
+ }
+ else
+ {
+ dwell = true;
+ timer.expires_after(dwellTime);
+ timer.async_wait([this, &sensor, timestamp,
+ value](const boost::system::error_code ec) {
+ if (ec)
+ {
+ phosphor::logging::log<phosphor::logging::level::DEBUG>(
+ "Timer has been canceled");
+ return;
+ }
+ auto& [sensorName, dwell, timer] = getDetails(sensor);
+ commit(sensorName, timestamp, value);
+ dwell = false;
+ });
+ }
+}
+
+void DiscreteThreshold::commit(const std::string& sensorName,
+ uint64_t timestamp, double value)
+{
+ for (const auto& action : actions)
+ {
+ action->commit(sensorName, timestamp, value);
+ }
+}
+
+const char* DiscreteThreshold::getName() const
+{
+ return name.c_str();
+}