blob: da5a64c6291d3fb49fcfe69dafb093e460d7c89d [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"
Wludzik, Jozef1477fe62021-01-02 11:56:10 +01009#include "utils/dbus_mapper.hpp"
Cezary Zwolak4416fce2021-03-17 03:21:06 +010010#include "utils/transform.hpp"
11
12namespace ts = utils::tstring;
Wludzik, Jozef76833cb2020-12-21 14:42:41 +010013
14TriggerFactory::TriggerFactory(
15 std::shared_ptr<sdbusplus::asio::connection> bus,
Wludzik, Jozef1477fe62021-01-02 11:56:10 +010016 std::shared_ptr<sdbusplus::asio::object_server> objServer,
Krzysztof Grobelnye6d48872022-02-08 13:41:30 +010017 SensorCache& sensorCache) :
Wludzik, Jozef76833cb2020-12-21 14:42:41 +010018 bus(std::move(bus)),
Krzysztof Grobelnye6d48872022-02-08 13:41:30 +010019 objServer(std::move(objServer)), sensorCache(sensorCache)
Wludzik, Jozef76833cb2020-12-21 14:42:41 +010020{}
21
Szymon Dompke94f71c52021-12-10 07:16:33 +010022void TriggerFactory::updateDiscreteThresholds(
23 std::vector<std::shared_ptr<interfaces::Threshold>>& currentThresholds,
24 const std::vector<TriggerAction>& triggerActions,
25 const std::shared_ptr<std::vector<std::string>>& reportIds,
26 const Sensors& sensors,
27 const std::vector<discrete::LabeledThresholdParam>& newParams) const
28{
29 auto oldThresholds = currentThresholds;
30 std::vector<std::shared_ptr<interfaces::Threshold>> newThresholds;
31
32 bool isCurrentOnChange = false;
33 if (oldThresholds.size() == 1 &&
34 std::holds_alternative<std::monostate>(
35 oldThresholds.back()->getThresholdParam()))
36 {
37 isCurrentOnChange = true;
38 }
39
40 newThresholds.reserve(newParams.size());
41
42 if (!isCurrentOnChange)
43 {
44 for (const auto& labeledThresholdParam : newParams)
45 {
46 auto paramChecker = [labeledThresholdParam](auto threshold) {
47 return labeledThresholdParam ==
48 std::get<discrete::LabeledThresholdParam>(
49 threshold->getThresholdParam());
50 };
51 if (auto existing = std::find_if(oldThresholds.begin(),
52 oldThresholds.end(), paramChecker);
53 existing != oldThresholds.end())
54 {
55 newThresholds.emplace_back(*existing);
56 oldThresholds.erase(existing);
57 continue;
58 }
59
60 makeDiscreteThreshold(newThresholds, triggerActions, reportIds,
61 sensors, labeledThresholdParam);
62 }
63 }
64 else
65 {
66 for (const auto& labeledThresholdParam : newParams)
67 {
68 makeDiscreteThreshold(newThresholds, triggerActions, reportIds,
69 sensors, labeledThresholdParam);
70 }
71 }
72 if (newParams.empty())
73 {
74 if (isCurrentOnChange)
75 {
76 newThresholds.emplace_back(*oldThresholds.begin());
77 }
78 else
79 {
80 makeOnChangeThreshold(newThresholds, triggerActions, reportIds,
81 sensors);
82 }
83 }
84 currentThresholds = std::move(newThresholds);
85}
86
87void TriggerFactory::updateNumericThresholds(
88 std::vector<std::shared_ptr<interfaces::Threshold>>& currentThresholds,
89 const std::vector<TriggerAction>& triggerActions,
90 const std::shared_ptr<std::vector<std::string>>& reportIds,
91 const Sensors& sensors,
92 const std::vector<numeric::LabeledThresholdParam>& newParams) const
93{
94 auto oldThresholds = currentThresholds;
95 std::vector<std::shared_ptr<interfaces::Threshold>> newThresholds;
96
97 newThresholds.reserve(newParams.size());
98
99 for (const auto& labeledThresholdParam : newParams)
100 {
101 auto paramChecker = [labeledThresholdParam](auto threshold) {
102 return labeledThresholdParam ==
103 std::get<numeric::LabeledThresholdParam>(
104 threshold->getThresholdParam());
105 };
106 if (auto existing = std::find_if(oldThresholds.begin(),
107 oldThresholds.end(), paramChecker);
108 existing != oldThresholds.end())
109 {
110 newThresholds.emplace_back(*existing);
111 oldThresholds.erase(existing);
112 continue;
113 }
114
115 makeNumericThreshold(newThresholds, triggerActions, reportIds, sensors,
116 labeledThresholdParam);
117 }
118 currentThresholds = std::move(newThresholds);
119}
120
121void TriggerFactory::updateThresholds(
122 std::vector<std::shared_ptr<interfaces::Threshold>>& currentThresholds,
123 const std::vector<TriggerAction>& triggerActions,
124 const std::shared_ptr<std::vector<std::string>>& reportIds,
125 const Sensors& sensors,
126 const LabeledTriggerThresholdParams& newParams) const
127{
128 if (isTriggerThresholdDiscrete(newParams))
129 {
130 const auto& labeledDiscreteThresholdParams =
131 std::get<std::vector<discrete::LabeledThresholdParam>>(newParams);
132
133 updateDiscreteThresholds(currentThresholds, triggerActions, reportIds,
134 sensors, labeledDiscreteThresholdParams);
135 }
136 else
137 {
138 const auto& labeledNumericThresholdParams =
139 std::get<std::vector<numeric::LabeledThresholdParam>>(newParams);
140
141 updateNumericThresholds(currentThresholds, triggerActions, reportIds,
142 sensors, labeledNumericThresholdParams);
143 }
144}
145
146void TriggerFactory::makeDiscreteThreshold(
147 std::vector<std::shared_ptr<interfaces::Threshold>>& thresholds,
148 const std::vector<TriggerAction>& triggerActions,
149 const std::shared_ptr<std::vector<std::string>>& reportIds,
150 const Sensors& sensors,
151 const discrete::LabeledThresholdParam& thresholdParam) const
152{
153 std::vector<std::unique_ptr<interfaces::TriggerAction>> actions;
154
155 std::string thresholdName = thresholdParam.at_label<ts::UserId>();
156 discrete::Severity severity = thresholdParam.at_label<ts::Severity>();
157 auto dwellTime = Milliseconds(thresholdParam.at_label<ts::DwellTime>());
158 std::string thresholdValue = thresholdParam.at_label<ts::ThresholdValue>();
159
160 action::discrete::fillActions(actions, triggerActions, severity,
Krzysztof Grobelnye6d48872022-02-08 13:41:30 +0100161 bus->get_io_context(), reportIds);
Szymon Dompke94f71c52021-12-10 07:16:33 +0100162
163 thresholds.emplace_back(std::make_shared<DiscreteThreshold>(
164 bus->get_io_context(), sensors, std::move(actions),
165 Milliseconds(dwellTime), std::stod(thresholdValue), thresholdName,
166 severity));
167}
168
169void TriggerFactory::makeNumericThreshold(
170 std::vector<std::shared_ptr<interfaces::Threshold>>& thresholds,
171 const std::vector<TriggerAction>& triggerActions,
172 const std::shared_ptr<std::vector<std::string>>& reportIds,
173 const Sensors& sensors,
174 const numeric::LabeledThresholdParam& thresholdParam) const
175{
176 std::vector<std::unique_ptr<interfaces::TriggerAction>> actions;
177
178 auto type = thresholdParam.at_label<ts::Type>();
179 auto dwellTime = Milliseconds(thresholdParam.at_label<ts::DwellTime>());
180 auto direction = thresholdParam.at_label<ts::Direction>();
181 auto thresholdValue = double{thresholdParam.at_label<ts::ThresholdValue>()};
182
183 action::numeric::fillActions(actions, triggerActions, type, thresholdValue,
Krzysztof Grobelnye6d48872022-02-08 13:41:30 +0100184 bus->get_io_context(), reportIds);
Szymon Dompke94f71c52021-12-10 07:16:33 +0100185
186 thresholds.emplace_back(std::make_shared<NumericThreshold>(
187 bus->get_io_context(), sensors, std::move(actions), dwellTime,
188 direction, thresholdValue, type));
189}
190
191void TriggerFactory::makeOnChangeThreshold(
192 std::vector<std::shared_ptr<interfaces::Threshold>>& thresholds,
193 const std::vector<TriggerAction>& triggerActions,
194 const std::shared_ptr<std::vector<std::string>>& reportIds,
195 const Sensors& sensors) const
196{
197 std::vector<std::unique_ptr<interfaces::TriggerAction>> actions;
198
199 action::discrete::onChange::fillActions(actions, triggerActions,
Krzysztof Grobelnye6d48872022-02-08 13:41:30 +0100200 bus->get_io_context(), reportIds);
Szymon Dompke94f71c52021-12-10 07:16:33 +0100201
202 thresholds.emplace_back(
203 std::make_shared<OnChangeThreshold>(sensors, std::move(actions)));
204}
205
Cezary Zwolak4416fce2021-03-17 03:21:06 +0100206std::unique_ptr<interfaces::Trigger> TriggerFactory::make(
Szymon Dompkee28aa532021-10-27 12:33:12 +0200207 const std::string& id, const std::string& name,
208 const std::vector<std::string>& triggerActionsIn,
Szymon Dompke94f71c52021-12-10 07:16:33 +0100209 const std::vector<std::string>& reportIdsIn,
Cezary Zwolak4416fce2021-03-17 03:21:06 +0100210 interfaces::TriggerManager& triggerManager,
211 interfaces::JsonStorage& triggerStorage,
212 const LabeledTriggerThresholdParams& labeledThresholdParams,
213 const std::vector<LabeledSensorInfo>& labeledSensorsInfo) const
Wludzik, Jozef76833cb2020-12-21 14:42:41 +0100214{
Szymon Dompke94f71c52021-12-10 07:16:33 +0100215 const auto& sensors = getSensors(labeledSensorsInfo);
216 auto triggerActions =
217 utils::transform(triggerActionsIn, [](const auto& triggerActionStr) {
218 return toTriggerAction(triggerActionStr);
219 });
Wludzik, Jozef1477fe62021-01-02 11:56:10 +0100220 std::vector<std::shared_ptr<interfaces::Threshold>> thresholds;
221
Szymon Dompke94f71c52021-12-10 07:16:33 +0100222 auto reportIds = std::make_shared<std::vector<std::string>>(reportIdsIn);
Cezary Zwolak4416fce2021-03-17 03:21:06 +0100223
Szymon Dompke94f71c52021-12-10 07:16:33 +0100224 updateThresholds(thresholds, triggerActions, reportIds, sensors,
225 labeledThresholdParams);
Wludzik, Jozef1477fe62021-01-02 11:56:10 +0100226
227 return std::make_unique<Trigger>(
Szymon Dompke94f71c52021-12-10 07:16:33 +0100228 bus->get_io_context(), objServer, id, name, triggerActions, reportIds,
Krzysztof Grobelnye6d48872022-02-08 13:41:30 +0100229 std::move(thresholds), triggerManager, triggerStorage, *this, sensors);
Wludzik, Jozef1477fe62021-01-02 11:56:10 +0100230}
231
Szymon Dompke94f71c52021-12-10 07:16:33 +0100232Sensors TriggerFactory::getSensors(
Krzysztof Grobelnydcc4e192021-03-08 09:09:34 +0000233 const std::vector<LabeledSensorInfo>& labeledSensorsInfo) const
Wludzik, Jozef1477fe62021-01-02 11:56:10 +0100234{
Krzysztof Grobelnydcc4e192021-03-08 09:09:34 +0000235 Sensors sensors;
Szymon Dompke94f71c52021-12-10 07:16:33 +0100236 updateSensors(sensors, labeledSensorsInfo);
237 return sensors;
238}
239
240void TriggerFactory::updateSensors(
241 Sensors& currentSensors,
242 const std::vector<LabeledSensorInfo>& labeledSensorsInfo) const
243{
244 Sensors oldSensors = currentSensors;
245 Sensors newSensors;
Wludzik, Jozef1477fe62021-01-02 11:56:10 +0100246
Cezary Zwolak4416fce2021-03-17 03:21:06 +0100247 for (const auto& labeledSensorInfo : labeledSensorsInfo)
248 {
Szymon Dompke94f71c52021-12-10 07:16:33 +0100249 auto existing = std::find_if(oldSensors.begin(), oldSensors.end(),
250 [labeledSensorInfo](auto sensor) {
251 return labeledSensorInfo ==
252 sensor->getLabeledSensorInfo();
253 });
254
255 if (existing != oldSensors.end())
256 {
257 newSensors.emplace_back(*existing);
258 oldSensors.erase(existing);
259 continue;
260 }
261
Cezary Zwolak4416fce2021-03-17 03:21:06 +0100262 const auto& service = labeledSensorInfo.at_label<ts::Service>();
Szymon Dompke94f71c52021-12-10 07:16:33 +0100263 const auto& sensorPath = labeledSensorInfo.at_label<ts::Path>();
Krzysztof Grobelnyb8cc78d2021-11-29 15:54:53 +0100264 const auto& metadata = labeledSensorInfo.at_label<ts::Metadata>();
Cezary Zwolak4416fce2021-03-17 03:21:06 +0100265
Szymon Dompke94f71c52021-12-10 07:16:33 +0100266 newSensors.emplace_back(sensorCache.makeSensor<Sensor>(
Krzysztof Grobelnyb8cc78d2021-11-29 15:54:53 +0100267 service, sensorPath, metadata, bus->get_io_context(), bus));
Wludzik, Jozef1477fe62021-01-02 11:56:10 +0100268 }
Cezary Zwolak4416fce2021-03-17 03:21:06 +0100269
Szymon Dompke94f71c52021-12-10 07:16:33 +0100270 currentSensors = std::move(newSensors);
Wludzik, Jozef76833cb2020-12-21 14:42:41 +0100271}
Cezary Zwolak4416fce2021-03-17 03:21:06 +0100272
273std::vector<LabeledSensorInfo>
274 TriggerFactory::getLabeledSensorsInfo(boost::asio::yield_context& yield,
275 const SensorsInfo& sensorsInfo) const
276{
Szymon Dompke94f71c52021-12-10 07:16:33 +0100277 if (sensorsInfo.empty())
278 {
279 return {};
280 }
Cezary Zwolak4416fce2021-03-17 03:21:06 +0100281 auto tree = utils::getSubTreeSensors(yield, bus);
Szymon Dompke94f71c52021-12-10 07:16:33 +0100282 return parseSensorTree(tree, sensorsInfo);
283}
Cezary Zwolak4416fce2021-03-17 03:21:06 +0100284
Szymon Dompke94f71c52021-12-10 07:16:33 +0100285std::vector<LabeledSensorInfo>
286 TriggerFactory::getLabeledSensorsInfo(const SensorsInfo& sensorsInfo) const
287{
288 if (sensorsInfo.empty())
289 {
290 return {};
291 }
292 auto tree = utils::getSubTreeSensors(bus);
293 return parseSensorTree(tree, sensorsInfo);
294}
295
296std::vector<LabeledSensorInfo>
297 TriggerFactory::parseSensorTree(const std::vector<utils::SensorTree>& tree,
298 const SensorsInfo& sensorsInfo)
299{
Cezary Zwolak4416fce2021-03-17 03:21:06 +0100300 return utils::transform(sensorsInfo, [&tree](const auto& item) {
301 const auto& [sensorPath, metadata] = item;
302 auto found = std::find_if(
303 tree.begin(), tree.end(),
Krzysztof Grobelnyfbeb5bf2022-01-03 09:41:29 +0100304 [path = sensorPath](const auto& x) { return x.first == path; });
Cezary Zwolak4416fce2021-03-17 03:21:06 +0100305
306 if (tree.end() != found)
307 {
308 const auto& [service, ifaces] = found->second.front();
309 return LabeledSensorInfo(service, sensorPath, metadata);
310 }
311 throw std::runtime_error("Not found");
312 });
313}