1 #include "discrete_threshold.hpp"
2 
3 #include <phosphor-logging/log.hpp>
4 
5 DiscreteThreshold::DiscreteThreshold(
6     boost::asio::io_context& ioc, Sensors sensorsIn,
7     std::vector<std::unique_ptr<interfaces::TriggerAction>> actionsIn,
8     Milliseconds dwellTimeIn, double thresholdValueIn,
9     const std::string& nameIn, const discrete::Severity severityIn) :
10     ioc(ioc),
11     actions(std::move(actionsIn)), dwellTime(dwellTimeIn),
12     thresholdValue(thresholdValueIn), name(nameIn), severity(severityIn)
13 {
14     for (const auto& sensor : sensorsIn)
15     {
16         sensorDetails.emplace(sensor, makeDetails(sensor->getName()));
17     }
18 }
19 
20 void DiscreteThreshold::initialize()
21 {
22     ThresholdOperations().initialize(this);
23 }
24 
25 void DiscreteThreshold::updateSensors(Sensors newSensors)
26 {
27     ThresholdOperations().updateSensors(this, std::move(newSensors));
28 }
29 
30 DiscreteThreshold::ThresholdDetail&
31     DiscreteThreshold::getDetails(const interfaces::Sensor& sensor)
32 {
33     return ThresholdOperations().getDetails(this, sensor);
34 }
35 
36 std::shared_ptr<DiscreteThreshold::ThresholdDetail>
37     DiscreteThreshold::makeDetails(const std::string& sensorName)
38 {
39     return std::make_shared<ThresholdDetail>(sensorName, false, ioc);
40 }
41 
42 void DiscreteThreshold::sensorUpdated(interfaces::Sensor& sensor,
43                                       Milliseconds timestamp, double value)
44 {
45     auto& details = getDetails(sensor);
46     auto& [sensorName, dwell, timer] = details;
47 
48     if (thresholdValue)
49     {
50         if (dwell && value != thresholdValue)
51         {
52             timer.cancel();
53             dwell = false;
54         }
55         else if (value == thresholdValue)
56         {
57             startTimer(details, timestamp, value);
58         }
59     }
60 }
61 
62 void DiscreteThreshold::startTimer(DiscreteThreshold::ThresholdDetail& details,
63                                    Milliseconds timestamp, double value)
64 {
65     const auto& sensorName = details.sensorName;
66     auto& dwell = details.dwell;
67     auto& timer = details.timer;
68 
69     if (dwellTime == Milliseconds::zero())
70     {
71         commit(sensorName, timestamp, value);
72     }
73     else
74     {
75         dwell = true;
76         timer.expires_after(dwellTime);
77         timer.async_wait([this, &sensorName, &dwell, timestamp,
78                           value](const boost::system::error_code ec) {
79             if (ec)
80             {
81                 phosphor::logging::log<phosphor::logging::level::DEBUG>(
82                     "Timer has been canceled");
83                 return;
84             }
85             commit(sensorName, timestamp, value);
86             dwell = false;
87         });
88     }
89 }
90 
91 void DiscreteThreshold::commit(const std::string& sensorName,
92                                Milliseconds timestamp, double value)
93 {
94     for (const auto& action : actions)
95     {
96         action->commit(sensorName, timestamp, value);
97     }
98 }
99 
100 LabeledThresholdParam DiscreteThreshold::getThresholdParam() const
101 {
102     return discrete::LabeledThresholdParam(name, severity, dwellTime.count(),
103                                            std::to_string(thresholdValue));
104 }
105