blob: 0b60dac848809069f509962c2dc5e0f9df9207c6 [file] [log] [blame]
Wludzik, Jozef1477fe62021-01-02 11:56:10 +01001#include "numeric_threshold.hpp"
2
3#include <phosphor-logging/log.hpp>
4
5NumericThreshold::NumericThreshold(
Szymon Dompkeb7b7e1b2022-05-19 10:15:48 +02006 boost::asio::io_context& ioc, const std::string& triggerIdIn,
7 Sensors sensorsIn,
Wludzik, Jozef1477fe62021-01-02 11:56:10 +01008 std::vector<std::unique_ptr<interfaces::TriggerAction>> actionsIn,
Szymon Dompke94f71c52021-12-10 07:16:33 +01009 Milliseconds dwellTimeIn, numeric::Direction directionIn,
Szymon Dompkeb7b7e1b2022-05-19 10:15:48 +020010 double thresholdValueIn, numeric::Type typeIn,
11 std::unique_ptr<interfaces::Clock> clockIn) :
Wludzik, Jozef1477fe62021-01-02 11:56:10 +010012 ioc(ioc),
Szymon Dompkeb7b7e1b2022-05-19 10:15:48 +020013 triggerId(triggerIdIn), actions(std::move(actionsIn)),
14 dwellTime(dwellTimeIn), direction(directionIn),
15 thresholdValue(thresholdValueIn), type(typeIn), clock(std::move(clockIn))
Wludzik, Jozef1477fe62021-01-02 11:56:10 +010016{
Szymon Dompke94f71c52021-12-10 07:16:33 +010017 for (const auto& sensor : sensorsIn)
Wludzik, Jozef1477fe62021-01-02 11:56:10 +010018 {
Szymon Dompke94f71c52021-12-10 07:16:33 +010019 sensorDetails.emplace(sensor, makeDetails(sensor->getName()));
Wludzik, Jozef1477fe62021-01-02 11:56:10 +010020 }
21}
22
Wludzik, Jozef1477fe62021-01-02 11:56:10 +010023void NumericThreshold::initialize()
24{
Krzysztof Grobelny41fa80d2022-06-09 13:27:16 +020025 ThresholdOperations::initialize(this);
Szymon Dompke94f71c52021-12-10 07:16:33 +010026}
27
28void NumericThreshold::updateSensors(Sensors newSensors)
29{
Krzysztof Grobelny41fa80d2022-06-09 13:27:16 +020030 ThresholdOperations::updateSensors(this, std::move(newSensors));
Wludzik, Jozef1477fe62021-01-02 11:56:10 +010031}
32
33NumericThreshold::ThresholdDetail&
Szymon Dompke94f71c52021-12-10 07:16:33 +010034 NumericThreshold::getDetails(const interfaces::Sensor& sensor)
Wludzik, Jozef1477fe62021-01-02 11:56:10 +010035{
Krzysztof Grobelny41fa80d2022-06-09 13:27:16 +020036 return ThresholdOperations::getDetails(this, sensor);
Szymon Dompke94f71c52021-12-10 07:16:33 +010037}
38
39std::shared_ptr<NumericThreshold::ThresholdDetail>
40 NumericThreshold::makeDetails(const std::string& sensorName)
41{
Szymon Dompke162b9762022-06-07 12:45:48 +020042 return std::make_shared<ThresholdDetail>(sensorName, ioc);
Wludzik, Jozef1477fe62021-01-02 11:56:10 +010043}
44
45void NumericThreshold::sensorUpdated(interfaces::Sensor& sensor,
Krzysztof Grobelny51f0fd52021-12-28 16:32:08 +010046 Milliseconds timestamp, double value)
Wludzik, Jozef1477fe62021-01-02 11:56:10 +010047{
Szymon Dompke94f71c52021-12-10 07:16:33 +010048 auto& details = getDetails(sensor);
Szymon Dompke162b9762022-06-07 12:45:48 +020049 auto& prevValue = details.prevValue;
50 auto& prevDirection = details.prevDirection;
51 auto& dwell = details.dwell;
52 auto& timer = details.timer;
Wludzik, Jozef1477fe62021-01-02 11:56:10 +010053
Szymon Dompke162b9762022-06-07 12:45:48 +020054 if (!prevValue)
55 {
56 prevValue = value;
57 return;
58 }
59
60 bool crossedDecreasing =
61 thresholdValue < prevValue && thresholdValue > value;
62 bool crossedIncreasing =
63 thresholdValue > prevValue && thresholdValue < value;
64
65 if (!crossedDecreasing && !crossedIncreasing && thresholdValue == prevValue)
66 {
67 crossedDecreasing = prevDirection == numeric::Direction::decreasing &&
68 thresholdValue > value;
69 crossedIncreasing = prevDirection == numeric::Direction::increasing &&
70 thresholdValue < value;
71 }
72
73 if (dwell && (crossedIncreasing || crossedDecreasing))
Wludzik, Jozef1477fe62021-01-02 11:56:10 +010074 {
75 timer.cancel();
76 dwell = false;
77 }
Szymon Dompke162b9762022-06-07 12:45:48 +020078 if ((direction == numeric::Direction::decreasing && crossedDecreasing) ||
79 (direction == numeric::Direction::increasing && crossedIncreasing) ||
80 (direction == numeric::Direction::either &&
81 (crossedIncreasing || crossedDecreasing)))
Wludzik, Jozef1477fe62021-01-02 11:56:10 +010082 {
Szymon Dompkeb7b7e1b2022-05-19 10:15:48 +020083 startTimer(details, value);
Wludzik, Jozef1477fe62021-01-02 11:56:10 +010084 }
85
Szymon Dompke162b9762022-06-07 12:45:48 +020086 prevDirection = value > prevValue ? numeric::Direction::increasing
87 : value < prevValue ? numeric::Direction::decreasing
88 : numeric::Direction::either;
Wludzik, Jozef1477fe62021-01-02 11:56:10 +010089 prevValue = value;
90}
91
Szymon Dompke94f71c52021-12-10 07:16:33 +010092void NumericThreshold::startTimer(NumericThreshold::ThresholdDetail& details,
Szymon Dompkeb7b7e1b2022-05-19 10:15:48 +020093 double value)
Wludzik, Jozef1477fe62021-01-02 11:56:10 +010094{
Szymon Dompke162b9762022-06-07 12:45:48 +020095 auto& sensorName = details.getSensorName();
Szymon Dompke94f71c52021-12-10 07:16:33 +010096 auto& dwell = details.dwell;
97 auto& timer = details.timer;
98
Krzysztof Grobelnydcc4e192021-03-08 09:09:34 +000099 if (dwellTime == Milliseconds::zero())
Wludzik, Jozef1477fe62021-01-02 11:56:10 +0100100 {
Szymon Dompkeb7b7e1b2022-05-19 10:15:48 +0200101 commit(sensorName, value);
Wludzik, Jozef1477fe62021-01-02 11:56:10 +0100102 }
103 else
104 {
105 dwell = true;
106 timer.expires_after(dwellTime);
Szymon Dompkeb7b7e1b2022-05-19 10:15:48 +0200107 timer.async_wait([this, &sensorName, &dwell,
Szymon Dompke94f71c52021-12-10 07:16:33 +0100108 value](const boost::system::error_code ec) {
Wludzik, Jozef1477fe62021-01-02 11:56:10 +0100109 if (ec)
110 {
111 phosphor::logging::log<phosphor::logging::level::DEBUG>(
112 "Timer has been canceled");
113 return;
114 }
Szymon Dompkeb7b7e1b2022-05-19 10:15:48 +0200115 commit(sensorName, value);
Wludzik, Jozef1477fe62021-01-02 11:56:10 +0100116 dwell = false;
117 });
118 }
119}
120
Szymon Dompkeb7b7e1b2022-05-19 10:15:48 +0200121void NumericThreshold::commit(const std::string& sensorName, double value)
Wludzik, Jozef1477fe62021-01-02 11:56:10 +0100122{
Szymon Dompkeb7b7e1b2022-05-19 10:15:48 +0200123 Milliseconds timestamp = clock->systemTimestamp();
Wludzik, Jozef1477fe62021-01-02 11:56:10 +0100124 for (const auto& action : actions)
125 {
Szymon Dompkeb7b7e1b2022-05-19 10:15:48 +0200126 action->commit(triggerId, std::nullopt, sensorName, timestamp, value);
Wludzik, Jozef1477fe62021-01-02 11:56:10 +0100127 }
128}
Szymon Dompke94f71c52021-12-10 07:16:33 +0100129
130LabeledThresholdParam NumericThreshold::getThresholdParam() const
131{
132 return numeric::LabeledThresholdParam(type, dwellTime.count(), direction,
133 thresholdValue);
134}