blob: 615d42d34cddb8405ef6048c6550acac07bc8a9c [file] [log] [blame]
Wludzik, Jozef76833cb2020-12-21 14:42:41 +01001#include "trigger_factory.hpp"
2
Szymon Dompkef763c9e2021-03-12 09:19:22 +01003#include "discrete_threshold.hpp"
Wludzik, Jozef1477fe62021-01-02 11:56:10 +01004#include "numeric_threshold.hpp"
Szymon Dompkef763c9e2021-03-12 09:19:22 +01005#include "on_change_threshold.hpp"
Wludzik, Jozef1477fe62021-01-02 11:56:10 +01006#include "sensor.hpp"
Wludzik, Jozef76833cb2020-12-21 14:42:41 +01007#include "trigger.hpp"
Wludzik, Jozefd960e1f2021-01-08 09:25:59 +01008#include "trigger_actions.hpp"
Szymon Dompkeb7b7e1b2022-05-19 10:15:48 +02009#include "utils/clock.hpp"
Wludzik, Jozef1477fe62021-01-02 11:56:10 +010010#include "utils/dbus_mapper.hpp"
Cezary Zwolak4416fce2021-03-17 03:21:06 +010011#include "utils/transform.hpp"
12
13namespace ts = utils::tstring;
Wludzik, Jozef76833cb2020-12-21 14:42:41 +010014
15TriggerFactory::TriggerFactory(
16 std::shared_ptr<sdbusplus::asio::connection> bus,
Wludzik, Jozef1477fe62021-01-02 11:56:10 +010017 std::shared_ptr<sdbusplus::asio::object_server> objServer,
Krzysztof Grobelnye6d48872022-02-08 13:41:30 +010018 SensorCache& sensorCache) :
Wludzik, Jozef76833cb2020-12-21 14:42:41 +010019 bus(std::move(bus)),
Krzysztof Grobelnye6d48872022-02-08 13:41:30 +010020 objServer(std::move(objServer)), sensorCache(sensorCache)
Wludzik, Jozef76833cb2020-12-21 14:42:41 +010021{}
22
Szymon Dompke94f71c52021-12-10 07:16:33 +010023void TriggerFactory::updateDiscreteThresholds(
24 std::vector<std::shared_ptr<interfaces::Threshold>>& currentThresholds,
Szymon Dompkeb7b7e1b2022-05-19 10:15:48 +020025 const std::string& triggerId,
Szymon Dompke94f71c52021-12-10 07:16:33 +010026 const std::vector<TriggerAction>& triggerActions,
27 const std::shared_ptr<std::vector<std::string>>& reportIds,
28 const Sensors& sensors,
29 const std::vector<discrete::LabeledThresholdParam>& newParams) const
30{
31 auto oldThresholds = currentThresholds;
32 std::vector<std::shared_ptr<interfaces::Threshold>> newThresholds;
33
34 bool isCurrentOnChange = false;
35 if (oldThresholds.size() == 1 &&
36 std::holds_alternative<std::monostate>(
37 oldThresholds.back()->getThresholdParam()))
38 {
39 isCurrentOnChange = true;
40 }
41
42 newThresholds.reserve(newParams.size());
43
44 if (!isCurrentOnChange)
45 {
46 for (const auto& labeledThresholdParam : newParams)
47 {
48 auto paramChecker = [labeledThresholdParam](auto threshold) {
49 return labeledThresholdParam ==
50 std::get<discrete::LabeledThresholdParam>(
51 threshold->getThresholdParam());
52 };
53 if (auto existing = std::find_if(oldThresholds.begin(),
54 oldThresholds.end(), paramChecker);
55 existing != oldThresholds.end())
56 {
57 newThresholds.emplace_back(*existing);
58 oldThresholds.erase(existing);
59 continue;
60 }
61
Szymon Dompkeb7b7e1b2022-05-19 10:15:48 +020062 makeDiscreteThreshold(newThresholds, triggerId, triggerActions,
63 reportIds, sensors, labeledThresholdParam);
Szymon Dompke94f71c52021-12-10 07:16:33 +010064 }
65 }
66 else
67 {
68 for (const auto& labeledThresholdParam : newParams)
69 {
Szymon Dompkeb7b7e1b2022-05-19 10:15:48 +020070 makeDiscreteThreshold(newThresholds, triggerId, triggerActions,
71 reportIds, sensors, labeledThresholdParam);
Szymon Dompke94f71c52021-12-10 07:16:33 +010072 }
73 }
74 if (newParams.empty())
75 {
76 if (isCurrentOnChange)
77 {
78 newThresholds.emplace_back(*oldThresholds.begin());
79 }
80 else
81 {
Szymon Dompkeb7b7e1b2022-05-19 10:15:48 +020082 makeOnChangeThreshold(newThresholds, triggerId, triggerActions,
83 reportIds, sensors);
Szymon Dompke94f71c52021-12-10 07:16:33 +010084 }
85 }
86 currentThresholds = std::move(newThresholds);
87}
88
89void TriggerFactory::updateNumericThresholds(
90 std::vector<std::shared_ptr<interfaces::Threshold>>& currentThresholds,
Szymon Dompkeb7b7e1b2022-05-19 10:15:48 +020091 const std::string& triggerId,
Szymon Dompke94f71c52021-12-10 07:16:33 +010092 const std::vector<TriggerAction>& triggerActions,
93 const std::shared_ptr<std::vector<std::string>>& reportIds,
94 const Sensors& sensors,
95 const std::vector<numeric::LabeledThresholdParam>& newParams) const
96{
97 auto oldThresholds = currentThresholds;
98 std::vector<std::shared_ptr<interfaces::Threshold>> newThresholds;
99
100 newThresholds.reserve(newParams.size());
101
102 for (const auto& labeledThresholdParam : newParams)
103 {
104 auto paramChecker = [labeledThresholdParam](auto threshold) {
105 return labeledThresholdParam ==
106 std::get<numeric::LabeledThresholdParam>(
107 threshold->getThresholdParam());
108 };
109 if (auto existing = std::find_if(oldThresholds.begin(),
110 oldThresholds.end(), paramChecker);
111 existing != oldThresholds.end())
112 {
113 newThresholds.emplace_back(*existing);
114 oldThresholds.erase(existing);
115 continue;
116 }
117
Szymon Dompkeb7b7e1b2022-05-19 10:15:48 +0200118 makeNumericThreshold(newThresholds, triggerId, triggerActions,
119 reportIds, sensors, labeledThresholdParam);
Szymon Dompke94f71c52021-12-10 07:16:33 +0100120 }
121 currentThresholds = std::move(newThresholds);
122}
123
124void TriggerFactory::updateThresholds(
125 std::vector<std::shared_ptr<interfaces::Threshold>>& currentThresholds,
Szymon Dompkeb7b7e1b2022-05-19 10:15:48 +0200126 const std::string& triggerId,
Szymon Dompke94f71c52021-12-10 07:16:33 +0100127 const std::vector<TriggerAction>& triggerActions,
128 const std::shared_ptr<std::vector<std::string>>& reportIds,
129 const Sensors& sensors,
130 const LabeledTriggerThresholdParams& newParams) const
131{
132 if (isTriggerThresholdDiscrete(newParams))
133 {
134 const auto& labeledDiscreteThresholdParams =
135 std::get<std::vector<discrete::LabeledThresholdParam>>(newParams);
136
Szymon Dompkeb7b7e1b2022-05-19 10:15:48 +0200137 updateDiscreteThresholds(currentThresholds, triggerId, triggerActions,
138 reportIds, sensors,
139 labeledDiscreteThresholdParams);
Szymon Dompke94f71c52021-12-10 07:16:33 +0100140 }
141 else
142 {
143 const auto& labeledNumericThresholdParams =
144 std::get<std::vector<numeric::LabeledThresholdParam>>(newParams);
145
Szymon Dompkeb7b7e1b2022-05-19 10:15:48 +0200146 updateNumericThresholds(currentThresholds, triggerId, triggerActions,
147 reportIds, sensors,
148 labeledNumericThresholdParams);
Szymon Dompke94f71c52021-12-10 07:16:33 +0100149 }
150}
151
152void TriggerFactory::makeDiscreteThreshold(
153 std::vector<std::shared_ptr<interfaces::Threshold>>& thresholds,
Szymon Dompkeb7b7e1b2022-05-19 10:15:48 +0200154 const std::string& triggerId,
Szymon Dompke94f71c52021-12-10 07:16:33 +0100155 const std::vector<TriggerAction>& triggerActions,
156 const std::shared_ptr<std::vector<std::string>>& reportIds,
157 const Sensors& sensors,
158 const discrete::LabeledThresholdParam& thresholdParam) const
159{
160 std::vector<std::unique_ptr<interfaces::TriggerAction>> actions;
161
Szymon Dompkeb7b7e1b2022-05-19 10:15:48 +0200162 const std::string& thresholdName = thresholdParam.at_label<ts::UserId>();
Szymon Dompke94f71c52021-12-10 07:16:33 +0100163 discrete::Severity severity = thresholdParam.at_label<ts::Severity>();
164 auto dwellTime = Milliseconds(thresholdParam.at_label<ts::DwellTime>());
Szymon Dompkeb7b7e1b2022-05-19 10:15:48 +0200165 const std::string& thresholdValue =
166 thresholdParam.at_label<ts::ThresholdValue>();
Szymon Dompke94f71c52021-12-10 07:16:33 +0100167
168 action::discrete::fillActions(actions, triggerActions, severity,
Krzysztof Grobelnye6d48872022-02-08 13:41:30 +0100169 bus->get_io_context(), reportIds);
Szymon Dompke94f71c52021-12-10 07:16:33 +0100170
171 thresholds.emplace_back(std::make_shared<DiscreteThreshold>(
Szymon Dompkeb7b7e1b2022-05-19 10:15:48 +0200172 bus->get_io_context(), triggerId, sensors, std::move(actions),
173 Milliseconds(dwellTime), thresholdValue, thresholdName, severity,
174 std::make_unique<Clock>()));
Szymon Dompke94f71c52021-12-10 07:16:33 +0100175}
176
177void TriggerFactory::makeNumericThreshold(
178 std::vector<std::shared_ptr<interfaces::Threshold>>& thresholds,
Szymon Dompkeb7b7e1b2022-05-19 10:15:48 +0200179 const std::string& triggerId,
Szymon Dompke94f71c52021-12-10 07:16:33 +0100180 const std::vector<TriggerAction>& triggerActions,
181 const std::shared_ptr<std::vector<std::string>>& reportIds,
182 const Sensors& sensors,
183 const numeric::LabeledThresholdParam& thresholdParam) const
184{
185 std::vector<std::unique_ptr<interfaces::TriggerAction>> actions;
186
187 auto type = thresholdParam.at_label<ts::Type>();
188 auto dwellTime = Milliseconds(thresholdParam.at_label<ts::DwellTime>());
189 auto direction = thresholdParam.at_label<ts::Direction>();
190 auto thresholdValue = double{thresholdParam.at_label<ts::ThresholdValue>()};
191
192 action::numeric::fillActions(actions, triggerActions, type, thresholdValue,
Krzysztof Grobelnye6d48872022-02-08 13:41:30 +0100193 bus->get_io_context(), reportIds);
Szymon Dompke94f71c52021-12-10 07:16:33 +0100194
195 thresholds.emplace_back(std::make_shared<NumericThreshold>(
Szymon Dompkeb7b7e1b2022-05-19 10:15:48 +0200196 bus->get_io_context(), triggerId, sensors, std::move(actions),
197 dwellTime, direction, thresholdValue, type, std::make_unique<Clock>()));
Szymon Dompke94f71c52021-12-10 07:16:33 +0100198}
199
200void TriggerFactory::makeOnChangeThreshold(
201 std::vector<std::shared_ptr<interfaces::Threshold>>& thresholds,
Szymon Dompkeb7b7e1b2022-05-19 10:15:48 +0200202 const std::string& triggerId,
Szymon Dompke94f71c52021-12-10 07:16:33 +0100203 const std::vector<TriggerAction>& triggerActions,
204 const std::shared_ptr<std::vector<std::string>>& reportIds,
205 const Sensors& sensors) const
206{
207 std::vector<std::unique_ptr<interfaces::TriggerAction>> actions;
208
209 action::discrete::onChange::fillActions(actions, triggerActions,
Krzysztof Grobelnye6d48872022-02-08 13:41:30 +0100210 bus->get_io_context(), reportIds);
Szymon Dompke94f71c52021-12-10 07:16:33 +0100211
Szymon Dompkeb7b7e1b2022-05-19 10:15:48 +0200212 thresholds.emplace_back(std::make_shared<OnChangeThreshold>(
213 triggerId, sensors, std::move(actions), std::make_unique<Clock>()));
Szymon Dompke94f71c52021-12-10 07:16:33 +0100214}
215
Cezary Zwolak4416fce2021-03-17 03:21:06 +0100216std::unique_ptr<interfaces::Trigger> TriggerFactory::make(
Szymon Dompkeb7b7e1b2022-05-19 10:15:48 +0200217 const std::string& idIn, const std::string& name,
Szymon Dompkee28aa532021-10-27 12:33:12 +0200218 const std::vector<std::string>& triggerActionsIn,
Szymon Dompke94f71c52021-12-10 07:16:33 +0100219 const std::vector<std::string>& reportIdsIn,
Cezary Zwolak4416fce2021-03-17 03:21:06 +0100220 interfaces::TriggerManager& triggerManager,
221 interfaces::JsonStorage& triggerStorage,
222 const LabeledTriggerThresholdParams& labeledThresholdParams,
223 const std::vector<LabeledSensorInfo>& labeledSensorsInfo) const
Wludzik, Jozef76833cb2020-12-21 14:42:41 +0100224{
Szymon Dompke94f71c52021-12-10 07:16:33 +0100225 const auto& sensors = getSensors(labeledSensorsInfo);
226 auto triggerActions =
227 utils::transform(triggerActionsIn, [](const auto& triggerActionStr) {
228 return toTriggerAction(triggerActionStr);
229 });
Wludzik, Jozef1477fe62021-01-02 11:56:10 +0100230 std::vector<std::shared_ptr<interfaces::Threshold>> thresholds;
Szymon Dompkeb7b7e1b2022-05-19 10:15:48 +0200231 auto id = std::make_unique<const std::string>(idIn);
Wludzik, Jozef1477fe62021-01-02 11:56:10 +0100232
Szymon Dompke94f71c52021-12-10 07:16:33 +0100233 auto reportIds = std::make_shared<std::vector<std::string>>(reportIdsIn);
Cezary Zwolak4416fce2021-03-17 03:21:06 +0100234
Szymon Dompkeb7b7e1b2022-05-19 10:15:48 +0200235 updateThresholds(thresholds, *id, triggerActions, reportIds, sensors,
Szymon Dompke94f71c52021-12-10 07:16:33 +0100236 labeledThresholdParams);
Wludzik, Jozef1477fe62021-01-02 11:56:10 +0100237
238 return std::make_unique<Trigger>(
Szymon Dompkeb7b7e1b2022-05-19 10:15:48 +0200239 bus->get_io_context(), objServer, std::move(id), name, triggerActions,
240 reportIds, std::move(thresholds), triggerManager, triggerStorage, *this,
241 sensors);
Wludzik, Jozef1477fe62021-01-02 11:56:10 +0100242}
243
Szymon Dompke94f71c52021-12-10 07:16:33 +0100244Sensors TriggerFactory::getSensors(
Krzysztof Grobelnydcc4e192021-03-08 09:09:34 +0000245 const std::vector<LabeledSensorInfo>& labeledSensorsInfo) const
Wludzik, Jozef1477fe62021-01-02 11:56:10 +0100246{
Krzysztof Grobelnydcc4e192021-03-08 09:09:34 +0000247 Sensors sensors;
Szymon Dompke94f71c52021-12-10 07:16:33 +0100248 updateSensors(sensors, labeledSensorsInfo);
249 return sensors;
250}
251
252void TriggerFactory::updateSensors(
253 Sensors& currentSensors,
254 const std::vector<LabeledSensorInfo>& labeledSensorsInfo) const
255{
256 Sensors oldSensors = currentSensors;
257 Sensors newSensors;
Wludzik, Jozef1477fe62021-01-02 11:56:10 +0100258
Cezary Zwolak4416fce2021-03-17 03:21:06 +0100259 for (const auto& labeledSensorInfo : labeledSensorsInfo)
260 {
Szymon Dompke94f71c52021-12-10 07:16:33 +0100261 auto existing = std::find_if(oldSensors.begin(), oldSensors.end(),
262 [labeledSensorInfo](auto sensor) {
263 return labeledSensorInfo ==
264 sensor->getLabeledSensorInfo();
265 });
266
267 if (existing != oldSensors.end())
268 {
269 newSensors.emplace_back(*existing);
270 oldSensors.erase(existing);
271 continue;
272 }
273
Cezary Zwolak4416fce2021-03-17 03:21:06 +0100274 const auto& service = labeledSensorInfo.at_label<ts::Service>();
Szymon Dompke94f71c52021-12-10 07:16:33 +0100275 const auto& sensorPath = labeledSensorInfo.at_label<ts::Path>();
Krzysztof Grobelnyb8cc78d2021-11-29 15:54:53 +0100276 const auto& metadata = labeledSensorInfo.at_label<ts::Metadata>();
Cezary Zwolak4416fce2021-03-17 03:21:06 +0100277
Szymon Dompke94f71c52021-12-10 07:16:33 +0100278 newSensors.emplace_back(sensorCache.makeSensor<Sensor>(
Krzysztof Grobelnyb8cc78d2021-11-29 15:54:53 +0100279 service, sensorPath, metadata, bus->get_io_context(), bus));
Wludzik, Jozef1477fe62021-01-02 11:56:10 +0100280 }
Cezary Zwolak4416fce2021-03-17 03:21:06 +0100281
Szymon Dompke94f71c52021-12-10 07:16:33 +0100282 currentSensors = std::move(newSensors);
Wludzik, Jozef76833cb2020-12-21 14:42:41 +0100283}
Cezary Zwolak4416fce2021-03-17 03:21:06 +0100284
285std::vector<LabeledSensorInfo>
286 TriggerFactory::getLabeledSensorsInfo(boost::asio::yield_context& yield,
287 const SensorsInfo& sensorsInfo) const
288{
Szymon Dompke94f71c52021-12-10 07:16:33 +0100289 if (sensorsInfo.empty())
290 {
291 return {};
292 }
Cezary Zwolak4416fce2021-03-17 03:21:06 +0100293 auto tree = utils::getSubTreeSensors(yield, bus);
Szymon Dompke94f71c52021-12-10 07:16:33 +0100294 return parseSensorTree(tree, sensorsInfo);
295}
Cezary Zwolak4416fce2021-03-17 03:21:06 +0100296
Szymon Dompke94f71c52021-12-10 07:16:33 +0100297std::vector<LabeledSensorInfo>
298 TriggerFactory::getLabeledSensorsInfo(const SensorsInfo& sensorsInfo) const
299{
300 if (sensorsInfo.empty())
301 {
302 return {};
303 }
304 auto tree = utils::getSubTreeSensors(bus);
305 return parseSensorTree(tree, sensorsInfo);
306}
307
308std::vector<LabeledSensorInfo>
309 TriggerFactory::parseSensorTree(const std::vector<utils::SensorTree>& tree,
310 const SensorsInfo& sensorsInfo)
311{
Cezary Zwolak4416fce2021-03-17 03:21:06 +0100312 return utils::transform(sensorsInfo, [&tree](const auto& item) {
313 const auto& [sensorPath, metadata] = item;
314 auto found = std::find_if(
315 tree.begin(), tree.end(),
Krzysztof Grobelnyfbeb5bf2022-01-03 09:41:29 +0100316 [path = sensorPath](const auto& x) { return x.first == path; });
Cezary Zwolak4416fce2021-03-17 03:21:06 +0100317
318 if (tree.end() != found)
319 {
320 const auto& [service, ifaces] = found->second.front();
321 return LabeledSensorInfo(service, sensorPath, metadata);
322 }
323 throw std::runtime_error("Not found");
324 });
325}