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)
44 {}
45 
46 void DiscreteThreshold::sensorUpdated(interfaces::Sensor& sensor,
47                                       Milliseconds timestamp, double value)
48 {
49     auto& details = getDetails(sensor);
50     auto& [sensorName, dwell, timer] = details;
51 
52     if (thresholdValue)
53     {
54         if (dwell && value != thresholdValue)
55         {
56             timer.cancel();
57             dwell = false;
58         }
59         else if (value == thresholdValue)
60         {
61             startTimer(details, timestamp, value);
62         }
63     }
64 }
65 
66 void DiscreteThreshold::startTimer(DiscreteThreshold::ThresholdDetail& details,
67                                    Milliseconds timestamp, double value)
68 {
69     const auto& sensorName = details.sensorName;
70     auto& dwell = details.dwell;
71     auto& timer = details.timer;
72 
73     if (dwellTime == Milliseconds::zero())
74     {
75         commit(sensorName, timestamp, value);
76     }
77     else
78     {
79         dwell = true;
80         timer.expires_after(dwellTime);
81         timer.async_wait([this, &sensorName, &dwell, timestamp,
82                           value](const boost::system::error_code ec) {
83             if (ec)
84             {
85                 phosphor::logging::log<phosphor::logging::level::DEBUG>(
86                     "Timer has been canceled");
87                 return;
88             }
89             commit(sensorName, timestamp, value);
90             dwell = false;
91         });
92     }
93 }
94 
95 void DiscreteThreshold::commit(const std::string& sensorName,
96                                Milliseconds timestamp, double value)
97 {
98     for (const auto& action : actions)
99     {
100         action->commit(sensorName, timestamp, value);
101     }
102 }
103 
104 LabeledThresholdParam DiscreteThreshold::getThresholdParam() const
105 {
106     return discrete::LabeledThresholdParam(name, severity, dwellTime.count(),
107                                            std::to_string(thresholdValue));
108 }
109