blob: 04928df9449fc94f6cd225795a324c01c144baf9 [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,
Wludzik, Jozefd960e1f2021-01-08 09:25:59 +010017 SensorCache& sensorCache, interfaces::ReportManager& reportManager) :
Wludzik, Jozef76833cb2020-12-21 14:42:41 +010018 bus(std::move(bus)),
Wludzik, Jozefd960e1f2021-01-08 09:25:59 +010019 objServer(std::move(objServer)), sensorCache(sensorCache),
20 reportManager(reportManager)
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,
25 const std::vector<TriggerAction>& triggerActions,
26 const std::shared_ptr<std::vector<std::string>>& reportIds,
27 const Sensors& sensors,
28 const std::vector<discrete::LabeledThresholdParam>& newParams) const
29{
30 auto oldThresholds = currentThresholds;
31 std::vector<std::shared_ptr<interfaces::Threshold>> newThresholds;
32
33 bool isCurrentOnChange = false;
34 if (oldThresholds.size() == 1 &&
35 std::holds_alternative<std::monostate>(
36 oldThresholds.back()->getThresholdParam()))
37 {
38 isCurrentOnChange = true;
39 }
40
41 newThresholds.reserve(newParams.size());
42
43 if (!isCurrentOnChange)
44 {
45 for (const auto& labeledThresholdParam : newParams)
46 {
47 auto paramChecker = [labeledThresholdParam](auto threshold) {
48 return labeledThresholdParam ==
49 std::get<discrete::LabeledThresholdParam>(
50 threshold->getThresholdParam());
51 };
52 if (auto existing = std::find_if(oldThresholds.begin(),
53 oldThresholds.end(), paramChecker);
54 existing != oldThresholds.end())
55 {
56 newThresholds.emplace_back(*existing);
57 oldThresholds.erase(existing);
58 continue;
59 }
60
61 makeDiscreteThreshold(newThresholds, triggerActions, reportIds,
62 sensors, labeledThresholdParam);
63 }
64 }
65 else
66 {
67 for (const auto& labeledThresholdParam : newParams)
68 {
69 makeDiscreteThreshold(newThresholds, triggerActions, reportIds,
70 sensors, labeledThresholdParam);
71 }
72 }
73 if (newParams.empty())
74 {
75 if (isCurrentOnChange)
76 {
77 newThresholds.emplace_back(*oldThresholds.begin());
78 }
79 else
80 {
81 makeOnChangeThreshold(newThresholds, triggerActions, reportIds,
82 sensors);
83 }
84 }
85 currentThresholds = std::move(newThresholds);
86}
87
88void TriggerFactory::updateNumericThresholds(
89 std::vector<std::shared_ptr<interfaces::Threshold>>& currentThresholds,
90 const std::vector<TriggerAction>& triggerActions,
91 const std::shared_ptr<std::vector<std::string>>& reportIds,
92 const Sensors& sensors,
93 const std::vector<numeric::LabeledThresholdParam>& newParams) const
94{
95 auto oldThresholds = currentThresholds;
96 std::vector<std::shared_ptr<interfaces::Threshold>> newThresholds;
97
98 newThresholds.reserve(newParams.size());
99
100 for (const auto& labeledThresholdParam : newParams)
101 {
102 auto paramChecker = [labeledThresholdParam](auto threshold) {
103 return labeledThresholdParam ==
104 std::get<numeric::LabeledThresholdParam>(
105 threshold->getThresholdParam());
106 };
107 if (auto existing = std::find_if(oldThresholds.begin(),
108 oldThresholds.end(), paramChecker);
109 existing != oldThresholds.end())
110 {
111 newThresholds.emplace_back(*existing);
112 oldThresholds.erase(existing);
113 continue;
114 }
115
116 makeNumericThreshold(newThresholds, triggerActions, reportIds, sensors,
117 labeledThresholdParam);
118 }
119 currentThresholds = std::move(newThresholds);
120}
121
122void TriggerFactory::updateThresholds(
123 std::vector<std::shared_ptr<interfaces::Threshold>>& currentThresholds,
124 const std::vector<TriggerAction>& triggerActions,
125 const std::shared_ptr<std::vector<std::string>>& reportIds,
126 const Sensors& sensors,
127 const LabeledTriggerThresholdParams& newParams) const
128{
129 if (isTriggerThresholdDiscrete(newParams))
130 {
131 const auto& labeledDiscreteThresholdParams =
132 std::get<std::vector<discrete::LabeledThresholdParam>>(newParams);
133
134 updateDiscreteThresholds(currentThresholds, triggerActions, reportIds,
135 sensors, labeledDiscreteThresholdParams);
136 }
137 else
138 {
139 const auto& labeledNumericThresholdParams =
140 std::get<std::vector<numeric::LabeledThresholdParam>>(newParams);
141
142 updateNumericThresholds(currentThresholds, triggerActions, reportIds,
143 sensors, labeledNumericThresholdParams);
144 }
145}
146
147void TriggerFactory::makeDiscreteThreshold(
148 std::vector<std::shared_ptr<interfaces::Threshold>>& thresholds,
149 const std::vector<TriggerAction>& triggerActions,
150 const std::shared_ptr<std::vector<std::string>>& reportIds,
151 const Sensors& sensors,
152 const discrete::LabeledThresholdParam& thresholdParam) const
153{
154 std::vector<std::unique_ptr<interfaces::TriggerAction>> actions;
155
156 std::string thresholdName = thresholdParam.at_label<ts::UserId>();
157 discrete::Severity severity = thresholdParam.at_label<ts::Severity>();
158 auto dwellTime = Milliseconds(thresholdParam.at_label<ts::DwellTime>());
159 std::string thresholdValue = thresholdParam.at_label<ts::ThresholdValue>();
160
161 action::discrete::fillActions(actions, triggerActions, severity,
162 reportManager, reportIds);
163
164 thresholds.emplace_back(std::make_shared<DiscreteThreshold>(
165 bus->get_io_context(), sensors, std::move(actions),
166 Milliseconds(dwellTime), std::stod(thresholdValue), thresholdName,
167 severity));
168}
169
170void TriggerFactory::makeNumericThreshold(
171 std::vector<std::shared_ptr<interfaces::Threshold>>& thresholds,
172 const std::vector<TriggerAction>& triggerActions,
173 const std::shared_ptr<std::vector<std::string>>& reportIds,
174 const Sensors& sensors,
175 const numeric::LabeledThresholdParam& thresholdParam) const
176{
177 std::vector<std::unique_ptr<interfaces::TriggerAction>> actions;
178
179 auto type = thresholdParam.at_label<ts::Type>();
180 auto dwellTime = Milliseconds(thresholdParam.at_label<ts::DwellTime>());
181 auto direction = thresholdParam.at_label<ts::Direction>();
182 auto thresholdValue = double{thresholdParam.at_label<ts::ThresholdValue>()};
183
184 action::numeric::fillActions(actions, triggerActions, type, thresholdValue,
185 reportManager, reportIds);
186
187 thresholds.emplace_back(std::make_shared<NumericThreshold>(
188 bus->get_io_context(), sensors, std::move(actions), dwellTime,
189 direction, thresholdValue, type));
190}
191
192void TriggerFactory::makeOnChangeThreshold(
193 std::vector<std::shared_ptr<interfaces::Threshold>>& thresholds,
194 const std::vector<TriggerAction>& triggerActions,
195 const std::shared_ptr<std::vector<std::string>>& reportIds,
196 const Sensors& sensors) const
197{
198 std::vector<std::unique_ptr<interfaces::TriggerAction>> actions;
199
200 action::discrete::onChange::fillActions(actions, triggerActions,
201 reportManager, reportIds);
202
203 thresholds.emplace_back(
204 std::make_shared<OnChangeThreshold>(sensors, std::move(actions)));
205}
206
Cezary Zwolak4416fce2021-03-17 03:21:06 +0100207std::unique_ptr<interfaces::Trigger> TriggerFactory::make(
Szymon Dompkee28aa532021-10-27 12:33:12 +0200208 const std::string& id, const std::string& name,
209 const std::vector<std::string>& triggerActionsIn,
Szymon Dompke94f71c52021-12-10 07:16:33 +0100210 const std::vector<std::string>& reportIdsIn,
Cezary Zwolak4416fce2021-03-17 03:21:06 +0100211 interfaces::TriggerManager& triggerManager,
212 interfaces::JsonStorage& triggerStorage,
213 const LabeledTriggerThresholdParams& labeledThresholdParams,
214 const std::vector<LabeledSensorInfo>& labeledSensorsInfo) const
Wludzik, Jozef76833cb2020-12-21 14:42:41 +0100215{
Szymon Dompke94f71c52021-12-10 07:16:33 +0100216 const auto& sensors = getSensors(labeledSensorsInfo);
217 auto triggerActions =
218 utils::transform(triggerActionsIn, [](const auto& triggerActionStr) {
219 return toTriggerAction(triggerActionStr);
220 });
Wludzik, Jozef1477fe62021-01-02 11:56:10 +0100221 std::vector<std::shared_ptr<interfaces::Threshold>> thresholds;
222
Szymon Dompke94f71c52021-12-10 07:16:33 +0100223 auto reportIds = std::make_shared<std::vector<std::string>>(reportIdsIn);
Cezary Zwolak4416fce2021-03-17 03:21:06 +0100224
Szymon Dompke94f71c52021-12-10 07:16:33 +0100225 updateThresholds(thresholds, triggerActions, reportIds, sensors,
226 labeledThresholdParams);
Wludzik, Jozef1477fe62021-01-02 11:56:10 +0100227
228 return std::make_unique<Trigger>(
Szymon Dompke94f71c52021-12-10 07:16:33 +0100229 bus->get_io_context(), objServer, id, name, triggerActions, reportIds,
Szymon Dompkeb4ef22e2022-02-07 15:15:12 +0100230 std::move(thresholds), triggerManager, triggerStorage, *this, sensors,
231 reportManager);
Wludzik, Jozef1477fe62021-01-02 11:56:10 +0100232}
233
Szymon Dompke94f71c52021-12-10 07:16:33 +0100234Sensors TriggerFactory::getSensors(
Krzysztof Grobelnydcc4e192021-03-08 09:09:34 +0000235 const std::vector<LabeledSensorInfo>& labeledSensorsInfo) const
Wludzik, Jozef1477fe62021-01-02 11:56:10 +0100236{
Krzysztof Grobelnydcc4e192021-03-08 09:09:34 +0000237 Sensors sensors;
Szymon Dompke94f71c52021-12-10 07:16:33 +0100238 updateSensors(sensors, labeledSensorsInfo);
239 return sensors;
240}
241
242void TriggerFactory::updateSensors(
243 Sensors& currentSensors,
244 const std::vector<LabeledSensorInfo>& labeledSensorsInfo) const
245{
246 Sensors oldSensors = currentSensors;
247 Sensors newSensors;
Wludzik, Jozef1477fe62021-01-02 11:56:10 +0100248
Cezary Zwolak4416fce2021-03-17 03:21:06 +0100249 for (const auto& labeledSensorInfo : labeledSensorsInfo)
250 {
Szymon Dompke94f71c52021-12-10 07:16:33 +0100251 auto existing = std::find_if(oldSensors.begin(), oldSensors.end(),
252 [labeledSensorInfo](auto sensor) {
253 return labeledSensorInfo ==
254 sensor->getLabeledSensorInfo();
255 });
256
257 if (existing != oldSensors.end())
258 {
259 newSensors.emplace_back(*existing);
260 oldSensors.erase(existing);
261 continue;
262 }
263
Cezary Zwolak4416fce2021-03-17 03:21:06 +0100264 const auto& service = labeledSensorInfo.at_label<ts::Service>();
Szymon Dompke94f71c52021-12-10 07:16:33 +0100265 const auto& sensorPath = labeledSensorInfo.at_label<ts::Path>();
Krzysztof Grobelnyb8cc78d2021-11-29 15:54:53 +0100266 const auto& metadata = labeledSensorInfo.at_label<ts::Metadata>();
Cezary Zwolak4416fce2021-03-17 03:21:06 +0100267
Szymon Dompke94f71c52021-12-10 07:16:33 +0100268 newSensors.emplace_back(sensorCache.makeSensor<Sensor>(
Krzysztof Grobelnyb8cc78d2021-11-29 15:54:53 +0100269 service, sensorPath, metadata, bus->get_io_context(), bus));
Wludzik, Jozef1477fe62021-01-02 11:56:10 +0100270 }
Cezary Zwolak4416fce2021-03-17 03:21:06 +0100271
Szymon Dompke94f71c52021-12-10 07:16:33 +0100272 currentSensors = std::move(newSensors);
Wludzik, Jozef76833cb2020-12-21 14:42:41 +0100273}
Cezary Zwolak4416fce2021-03-17 03:21:06 +0100274
275std::vector<LabeledSensorInfo>
276 TriggerFactory::getLabeledSensorsInfo(boost::asio::yield_context& yield,
277 const SensorsInfo& sensorsInfo) const
278{
Szymon Dompke94f71c52021-12-10 07:16:33 +0100279 if (sensorsInfo.empty())
280 {
281 return {};
282 }
Cezary Zwolak4416fce2021-03-17 03:21:06 +0100283 auto tree = utils::getSubTreeSensors(yield, bus);
Szymon Dompke94f71c52021-12-10 07:16:33 +0100284 return parseSensorTree(tree, sensorsInfo);
285}
Cezary Zwolak4416fce2021-03-17 03:21:06 +0100286
Szymon Dompke94f71c52021-12-10 07:16:33 +0100287std::vector<LabeledSensorInfo>
288 TriggerFactory::getLabeledSensorsInfo(const SensorsInfo& sensorsInfo) const
289{
290 if (sensorsInfo.empty())
291 {
292 return {};
293 }
294 auto tree = utils::getSubTreeSensors(bus);
295 return parseSensorTree(tree, sensorsInfo);
296}
297
298std::vector<LabeledSensorInfo>
299 TriggerFactory::parseSensorTree(const std::vector<utils::SensorTree>& tree,
300 const SensorsInfo& sensorsInfo)
301{
Cezary Zwolak4416fce2021-03-17 03:21:06 +0100302 return utils::transform(sensorsInfo, [&tree](const auto& item) {
303 const auto& [sensorPath, metadata] = item;
304 auto found = std::find_if(
305 tree.begin(), tree.end(),
Krzysztof Grobelnyfbeb5bf2022-01-03 09:41:29 +0100306 [path = sensorPath](const auto& x) { return x.first == path; });
Cezary Zwolak4416fce2021-03-17 03:21:06 +0100307
308 if (tree.end() != found)
309 {
310 const auto& [service, ifaces] = found->second.front();
311 return LabeledSensorInfo(service, sensorPath, metadata);
312 }
313 throw std::runtime_error("Not found");
314 });
315}