blob: 20f79497434e317d25a82bd0871163b0c9e09bdf [file] [log] [blame]
Ed Tanous8a57ec02020-10-09 12:46:52 -07001#include <Thresholds.hpp>
2#include <VariantVisitors.hpp>
James Feist6714a252018-09-10 15:26:18 -07003#include <boost/algorithm/string/replace.hpp>
Patrick Venture96e97db2019-10-31 13:44:38 -07004#include <boost/container/flat_map.hpp>
Ed Tanous8a57ec02020-10-09 12:46:52 -07005#include <sensor.hpp>
James Feist38fb5982020-05-28 10:09:54 -07006
7#include <array>
James Feistdc6c55f2018-10-31 12:53:20 -07008#include <cmath>
James Feist6714a252018-09-10 15:26:18 -07009#include <fstream>
10#include <iostream>
Patrick Venture96e97db2019-10-31 13:44:38 -070011#include <memory>
12#include <stdexcept>
13#include <string>
Zbigniew Kurzynski0a4c4802020-04-01 11:22:27 +020014#include <tuple>
Patrick Venture96e97db2019-10-31 13:44:38 -070015#include <utility>
16#include <variant>
17#include <vector>
James Feist6714a252018-09-10 15:26:18 -070018
Ed Tanous8a57ec02020-10-09 12:46:52 -070019static constexpr bool debug = false;
Jayashree Dhanapal45f27022021-12-07 12:56:35 +053020static constexpr int thresLevel = 2;
James Feist6714a252018-09-10 15:26:18 -070021namespace thresholds
22{
Jayashree Dhanapal45f27022021-12-07 12:56:35 +053023Level findThresholdLevel(uint8_t sev, const std::string& direct)
James Feist6714a252018-09-10 15:26:18 -070024{
Jayashree Dhanapal45f27022021-12-07 12:56:35 +053025 for (Sensor::ThresholdProperty prop : Sensor::thresProp)
James Feist6714a252018-09-10 15:26:18 -070026 {
Jayashree Dhanapal45f27022021-12-07 12:56:35 +053027 if ((prop.sevOrder == sev) && (prop.dirOrder == direct))
James Feist6714a252018-09-10 15:26:18 -070028 {
Jayashree Dhanapal45f27022021-12-07 12:56:35 +053029 return prop.level;
James Feist6714a252018-09-10 15:26:18 -070030 }
31 }
Jayashree Dhanapal45f27022021-12-07 12:56:35 +053032 return Level::ERROR;
James Feist6714a252018-09-10 15:26:18 -070033}
34
Jayashree Dhanapal45f27022021-12-07 12:56:35 +053035Direction findThresholdDirection(uint8_t sev, const std::string& direct)
James Feist6714a252018-09-10 15:26:18 -070036{
Jayashree Dhanapal45f27022021-12-07 12:56:35 +053037 for (Sensor::ThresholdProperty prop : Sensor::thresProp)
James Feist6714a252018-09-10 15:26:18 -070038 {
Jayashree Dhanapal45f27022021-12-07 12:56:35 +053039 if ((prop.sevOrder == sev) && (prop.dirOrder == direct))
James Feist6714a252018-09-10 15:26:18 -070040 {
Jayashree Dhanapal45f27022021-12-07 12:56:35 +053041 return prop.direction;
James Feist6714a252018-09-10 15:26:18 -070042 }
43 }
Jayashree Dhanapal45f27022021-12-07 12:56:35 +053044 return Direction::ERROR;
James Feist6714a252018-09-10 15:26:18 -070045}
46
Jae Hyun Yoo9ced0a32018-10-25 10:42:39 -070047bool parseThresholdsFromConfig(
James Feistd8705872019-02-08 13:26:09 -080048 const SensorData& sensorData,
49 std::vector<thresholds::Threshold>& thresholdVector,
Matt Spinler5636d522021-03-17 14:52:18 -050050 const std::string* matchLabel, const int* sensorIndex)
James Feist6714a252018-09-10 15:26:18 -070051{
James Feistd8705872019-02-08 13:26:09 -080052 for (const auto& item : sensorData)
James Feist6714a252018-09-10 15:26:18 -070053 {
54 if (item.first.find("Thresholds") == std::string::npos)
55 {
56 continue;
57 }
58 if (matchLabel != nullptr)
59 {
60 auto labelFind = item.second.find("Label");
61 if (labelFind == item.second.end())
Ed Tanous8a57ec02020-10-09 12:46:52 -070062 {
James Feist6714a252018-09-10 15:26:18 -070063 continue;
Ed Tanous8a57ec02020-10-09 12:46:52 -070064 }
James Feist3eb82622019-02-08 13:10:22 -080065 if (std::visit(VariantToStringVisitor(), labelFind->second) !=
66 *matchLabel)
Ed Tanous8a57ec02020-10-09 12:46:52 -070067 {
James Feist6714a252018-09-10 15:26:18 -070068 continue;
Ed Tanous8a57ec02020-10-09 12:46:52 -070069 }
James Feist6714a252018-09-10 15:26:18 -070070 }
Matt Spinler5636d522021-03-17 14:52:18 -050071
72 if (sensorIndex != nullptr)
73 {
74 auto indexFind = item.second.find("Index");
75
76 // If we're checking for index 1, a missing Index is OK.
77 if ((indexFind == item.second.end()) && (*sensorIndex != 1))
78 {
79 continue;
80 }
81
82 if ((indexFind != item.second.end()) &&
83 (std::visit(VariantToIntVisitor(), indexFind->second) !=
84 *sensorIndex))
85 {
86 continue;
87 }
88 }
89
Rashmica Gupta1e34cec2021-08-31 16:47:39 +100090 double hysteresis = std::numeric_limits<double>::quiet_NaN();
91 auto hysteresisFind = item.second.find("Hysteresis");
92 if (hysteresisFind != item.second.end())
93 {
94 hysteresis =
95 std::visit(VariantToDoubleVisitor(), hysteresisFind->second);
96 }
97
James Feist6714a252018-09-10 15:26:18 -070098 auto directionFind = item.second.find("Direction");
99 auto severityFind = item.second.find("Severity");
100 auto valueFind = item.second.find("Value");
101 if (valueFind == item.second.end() ||
102 severityFind == item.second.end() ||
103 directionFind == item.second.end())
104 {
Matt Spinler5636d522021-03-17 14:52:18 -0500105 std::cerr << "Malformed threshold on configuration interface "
106 << item.first << "\n";
James Feist6714a252018-09-10 15:26:18 -0700107 return false;
108 }
Jayashree Dhanapal45f27022021-12-07 12:56:35 +0530109 uint8_t severity =
110 std::visit(VariantToUnsignedIntVisitor(), severityFind->second);
111
112 std::string directions =
113 std::visit(VariantToStringVisitor(), directionFind->second);
114
115 Level level = findThresholdLevel(severity, directions);
116 Direction direction = findThresholdDirection(severity, directions);
117
118 if ((static_cast<int>(level) == thresLevel) ||
119 (static_cast<int>(direction) == thresLevel))
James Feist6714a252018-09-10 15:26:18 -0700120 {
Jayashree Dhanapal45f27022021-12-07 12:56:35 +0530121 continue;
James Feist6714a252018-09-10 15:26:18 -0700122 }
James Feist13f340b2019-03-07 16:36:11 -0800123 double val = std::visit(VariantToDoubleVisitor(), valueFind->second);
James Feist6714a252018-09-10 15:26:18 -0700124
Rashmica Gupta1e34cec2021-08-31 16:47:39 +1000125 thresholdVector.emplace_back(level, direction, val, hysteresis);
James Feist6714a252018-09-10 15:26:18 -0700126 }
127 return true;
128}
129
James Feistd8705872019-02-08 13:26:09 -0800130void persistThreshold(const std::string& path, const std::string& baseInterface,
131 const thresholds::Threshold& threshold,
James Feista222ba72019-03-01 15:57:51 -0800132 std::shared_ptr<sdbusplus::asio::connection>& conn,
Cheng C Yang6b1247a2020-03-09 23:48:39 +0800133 size_t thresholdCount, const std::string& labelMatch)
James Feist6714a252018-09-10 15:26:18 -0700134{
Brad Bishopfbb44ad2019-11-08 09:42:37 -0500135 for (size_t ii = 0; ii < thresholdCount; ii++)
James Feist6714a252018-09-10 15:26:18 -0700136 {
137 std::string thresholdInterface =
138 baseInterface + ".Thresholds" + std::to_string(ii);
139 conn->async_method_call(
Cheng C Yang6b1247a2020-03-09 23:48:39 +0800140 [&, path, threshold, thresholdInterface, labelMatch](
James Feistd8705872019-02-08 13:26:09 -0800141 const boost::system::error_code& ec,
142 const boost::container::flat_map<std::string, BasicVariantType>&
143 result) {
James Feist6714a252018-09-10 15:26:18 -0700144 if (ec)
145 {
146 return; // threshold not supported
147 }
148
Cheng C Yang6b1247a2020-03-09 23:48:39 +0800149 if (!labelMatch.empty())
150 {
151 auto labelFind = result.find("Label");
152 if (labelFind == result.end())
153 {
154 std::cerr << "No label in threshold configuration\n";
155 return;
156 }
157 std::string label =
158 std::visit(VariantToStringVisitor(), labelFind->second);
159 if (label != labelMatch)
160 {
161 return;
162 }
163 }
164
James Feist6714a252018-09-10 15:26:18 -0700165 auto directionFind = result.find("Direction");
166 auto severityFind = result.find("Severity");
167 auto valueFind = result.find("Value");
168 if (valueFind == result.end() || severityFind == result.end() ||
169 directionFind == result.end())
170 {
171 std::cerr << "Malformed threshold in configuration\n";
172 return;
173 }
James Feist3eb82622019-02-08 13:10:22 -0800174 unsigned int level = std::visit(VariantToUnsignedIntVisitor(),
175 severityFind->second);
James Feist6714a252018-09-10 15:26:18 -0700176
James Feist3eb82622019-02-08 13:10:22 -0800177 std::string dir =
178 std::visit(VariantToStringVisitor(), directionFind->second);
Jayashree Dhanapal45f27022021-12-07 12:56:35 +0530179 if (((findThresholdLevel(level, dir)) != threshold.level) ||
180 ((findThresholdDirection(level, dir)) !=
181 threshold.direction))
James Feist6714a252018-09-10 15:26:18 -0700182 {
183 return; // not the droid we're looking for
184 }
185
James Feist3eb82622019-02-08 13:10:22 -0800186 std::variant<double> value(threshold.value);
James Feist6714a252018-09-10 15:26:18 -0700187 conn->async_method_call(
James Feistd8705872019-02-08 13:26:09 -0800188 [](const boost::system::error_code& ec) {
James Feist6714a252018-09-10 15:26:18 -0700189 if (ec)
190 {
191 std::cerr << "Error setting threshold " << ec
192 << "\n";
193 }
194 },
Jae Hyun Yoo9ced0a32018-10-25 10:42:39 -0700195 entityManagerName, path, "org.freedesktop.DBus.Properties",
196 "Set", thresholdInterface, "Value", value);
James Feist6714a252018-09-10 15:26:18 -0700197 },
Jae Hyun Yoo9ced0a32018-10-25 10:42:39 -0700198 entityManagerName, path, "org.freedesktop.DBus.Properties",
James Feist6714a252018-09-10 15:26:18 -0700199 "GetAll", thresholdInterface);
200 }
201}
202
Jae Hyun Yoo95b8a2d2019-02-25 20:15:09 -0800203void updateThresholds(Sensor* sensor)
204{
205 if (sensor->thresholds.empty())
206 {
207 return;
208 }
209
210 for (const auto& threshold : sensor->thresholds)
211 {
212 std::shared_ptr<sdbusplus::asio::dbus_interface> interface;
Jae Hyun Yoo95b8a2d2019-02-25 20:15:09 -0800213 if (threshold.level == thresholds::Level::CRITICAL)
214 {
215 interface = sensor->thresholdInterfaceCritical;
Jae Hyun Yoo95b8a2d2019-02-25 20:15:09 -0800216 }
217 else if (threshold.level == thresholds::Level::WARNING)
218 {
219 interface = sensor->thresholdInterfaceWarning;
Jae Hyun Yoo95b8a2d2019-02-25 20:15:09 -0800220 }
221 else
222 {
223 continue;
224 }
225 if (!interface)
226 {
227 continue;
228 }
Jayashree Dhanapal45f27022021-12-07 12:56:35 +0530229
230 std::string property =
231 sensor->propertyLevel(threshold.level, threshold.direction);
232 if (property.empty())
233 {
234 continue;
235 }
Jae Hyun Yoo95b8a2d2019-02-25 20:15:09 -0800236 interface->set_property(property, threshold.value);
237 }
238}
239
Josh Lehan883fb3a2020-02-27 14:41:39 -0800240// Debugging counters
241static int cHiTrue = 0;
242static int cHiFalse = 0;
243static int cHiMidstate = 0;
244static int cLoTrue = 0;
245static int cLoFalse = 0;
246static int cLoMidstate = 0;
247static int cDebugThrottle = 0;
Zhikui Rend3da1282020-09-11 17:02:01 -0700248static constexpr int assertLogCount = 10;
Josh Lehan883fb3a2020-02-27 14:41:39 -0800249
Zhikui Ren59b8b9e2020-06-26 18:34:22 -0700250struct ChangeParam
James Feist251c7822018-09-12 12:54:15 -0700251{
Zhikui Ren59b8b9e2020-06-26 18:34:22 -0700252 ChangeParam(Threshold whichThreshold, bool status, double value) :
253 threshold(whichThreshold), asserted(status), assertValue(value)
254 {}
255
256 Threshold threshold;
257 bool asserted;
258 double assertValue;
259};
260
261static std::vector<ChangeParam> checkThresholds(Sensor* sensor, double value)
262{
263 std::vector<ChangeParam> thresholdChanges;
James Feist251c7822018-09-12 12:54:15 -0700264 if (sensor->thresholds.empty())
265 {
James Feist46342ec2019-03-06 14:03:41 -0800266 return thresholdChanges;
James Feist251c7822018-09-12 12:54:15 -0700267 }
James Feist46342ec2019-03-06 14:03:41 -0800268
James Feistd8705872019-02-08 13:26:09 -0800269 for (auto& threshold : sensor->thresholds)
James Feist251c7822018-09-12 12:54:15 -0700270 {
Josh Lehan883fb3a2020-02-27 14:41:39 -0800271 // Use "Schmitt trigger" logic to avoid threshold trigger spam,
272 // if value is noisy while hovering very close to a threshold.
273 // When a threshold is crossed, indicate true immediately,
274 // but require more distance to be crossed the other direction,
275 // before resetting the indicator back to false.
James Feist46342ec2019-03-06 14:03:41 -0800276 if (threshold.direction == thresholds::Direction::HIGH)
James Feistdc6c55f2018-10-31 12:53:20 -0700277 {
James Feist551087a2019-12-09 11:17:12 -0800278 if (value >= threshold.value)
James Feist251c7822018-09-12 12:54:15 -0700279 {
Zhikui Ren59b8b9e2020-06-26 18:34:22 -0700280 thresholdChanges.emplace_back(threshold, true, value);
Zhikui Rend3da1282020-09-11 17:02:01 -0700281 if (++cHiTrue < assertLogCount)
282 {
283 std::cerr << "Sensor " << sensor->name << " high threshold "
284 << threshold.value << " assert: value " << value
285 << " raw data " << sensor->rawValue << "\n";
286 }
Josh Lehan883fb3a2020-02-27 14:41:39 -0800287 }
Rashmica Gupta1e34cec2021-08-31 16:47:39 +1000288 else if (value < (threshold.value - threshold.hysteresis))
Josh Lehan883fb3a2020-02-27 14:41:39 -0800289 {
Zhikui Ren59b8b9e2020-06-26 18:34:22 -0700290 thresholdChanges.emplace_back(threshold, false, value);
Josh Lehan883fb3a2020-02-27 14:41:39 -0800291 ++cHiFalse;
James Feist251c7822018-09-12 12:54:15 -0700292 }
Patrick Venture66235d42019-10-11 08:31:27 -0700293 else
James Feist251c7822018-09-12 12:54:15 -0700294 {
Josh Lehan883fb3a2020-02-27 14:41:39 -0800295 ++cHiMidstate;
James Feist251c7822018-09-12 12:54:15 -0700296 }
297 }
Josh Lehan883fb3a2020-02-27 14:41:39 -0800298 else if (threshold.direction == thresholds::Direction::LOW)
James Feist251c7822018-09-12 12:54:15 -0700299 {
James Feist551087a2019-12-09 11:17:12 -0800300 if (value <= threshold.value)
James Feist251c7822018-09-12 12:54:15 -0700301 {
Zhikui Ren59b8b9e2020-06-26 18:34:22 -0700302 thresholdChanges.emplace_back(threshold, true, value);
Zhikui Rend3da1282020-09-11 17:02:01 -0700303 if (++cLoTrue < assertLogCount)
304 {
305 std::cerr << "Sensor " << sensor->name << " low threshold "
306 << threshold.value << " assert: value "
307 << sensor->value << " raw data "
308 << sensor->rawValue << "\n";
309 }
Josh Lehan883fb3a2020-02-27 14:41:39 -0800310 }
Rashmica Gupta1e34cec2021-08-31 16:47:39 +1000311 else if (value > (threshold.value + threshold.hysteresis))
Josh Lehan883fb3a2020-02-27 14:41:39 -0800312 {
Zhikui Ren59b8b9e2020-06-26 18:34:22 -0700313 thresholdChanges.emplace_back(threshold, false, value);
Josh Lehan883fb3a2020-02-27 14:41:39 -0800314 ++cLoFalse;
James Feist251c7822018-09-12 12:54:15 -0700315 }
Patrick Venture66235d42019-10-11 08:31:27 -0700316 else
James Feist251c7822018-09-12 12:54:15 -0700317 {
Josh Lehan883fb3a2020-02-27 14:41:39 -0800318 ++cLoMidstate;
James Feist251c7822018-09-12 12:54:15 -0700319 }
320 }
Josh Lehan883fb3a2020-02-27 14:41:39 -0800321 else
322 {
323 std::cerr << "Error determining threshold direction\n";
324 }
James Feist251c7822018-09-12 12:54:15 -0700325 }
Josh Lehan883fb3a2020-02-27 14:41:39 -0800326
Ed Tanous8a17c302021-09-02 15:07:11 -0700327 // Throttle debug output, so that it does not continuously spam
328 ++cDebugThrottle;
329 if (cDebugThrottle >= 1000)
Josh Lehan883fb3a2020-02-27 14:41:39 -0800330 {
Ed Tanous8a17c302021-09-02 15:07:11 -0700331 cDebugThrottle = 0;
332 if constexpr (debug)
Josh Lehan883fb3a2020-02-27 14:41:39 -0800333 {
Josh Lehan883fb3a2020-02-27 14:41:39 -0800334 std::cerr << "checkThresholds: High T=" << cHiTrue
335 << " F=" << cHiFalse << " M=" << cHiMidstate
336 << ", Low T=" << cLoTrue << " F=" << cLoFalse
337 << " M=" << cLoMidstate << "\n";
338 }
339 }
340
James Feist46342ec2019-03-06 14:03:41 -0800341 return thresholdChanges;
342}
343
Zhikui Ren12c2c0e2021-04-28 17:21:21 -0700344void ThresholdTimer::startTimer(const std::weak_ptr<Sensor>& weakSensor,
345 const Threshold& threshold, bool assert,
Jeff Lind9cd7042020-11-20 15:49:28 +0800346 double assertValue)
347{
348 struct TimerUsed timerUsed = {};
349 constexpr const size_t waitTime = 5;
350 TimerPair* pair = nullptr;
351
352 for (TimerPair& timer : timers)
353 {
354 if (!timer.first.used)
355 {
356 pair = &timer;
357 break;
358 }
359 }
360 if (pair == nullptr)
361 {
362 pair = &timers.emplace_back(timerUsed, boost::asio::deadline_timer(io));
363 }
364
365 pair->first.used = true;
366 pair->first.level = threshold.level;
367 pair->first.direction = threshold.direction;
368 pair->first.assert = assert;
369 pair->second.expires_from_now(boost::posix_time::seconds(waitTime));
Zhikui Ren12c2c0e2021-04-28 17:21:21 -0700370 pair->second.async_wait([weakSensor, pair, threshold, assert,
Jeff Lind9cd7042020-11-20 15:49:28 +0800371 assertValue](boost::system::error_code ec) {
Zhikui Ren12c2c0e2021-04-28 17:21:21 -0700372 auto sensorPtr = weakSensor.lock();
373 if (!sensorPtr)
374 {
375 return; // owner sensor has been destructed
376 }
377 // pair is valid as long as sensor is valid
Jeff Lind9cd7042020-11-20 15:49:28 +0800378 pair->first.used = false;
379
380 if (ec == boost::asio::error::operation_aborted)
381 {
382 return; // we're being canceled
383 }
384 if (ec)
385 {
386 std::cerr << "timer error: " << ec.message() << "\n";
387 return;
388 }
Zhikui Ren12c2c0e2021-04-28 17:21:21 -0700389 if (sensorPtr->readingStateGood())
Jeff Lind9cd7042020-11-20 15:49:28 +0800390 {
Zhikui Ren12c2c0e2021-04-28 17:21:21 -0700391 assertThresholds(sensorPtr.get(), assertValue, threshold.level,
Jeff Lind9cd7042020-11-20 15:49:28 +0800392 threshold.direction, assert);
393 }
394 });
395}
396
James Feist46342ec2019-03-06 14:03:41 -0800397bool checkThresholds(Sensor* sensor)
398{
James Feist7b18b1e2019-05-14 13:42:09 -0700399 bool status = true;
Zhikui Ren59b8b9e2020-06-26 18:34:22 -0700400 std::vector<ChangeParam> changes = checkThresholds(sensor, sensor->value);
401 for (const auto& change : changes)
James Feist46342ec2019-03-06 14:03:41 -0800402 {
Zhikui Ren59b8b9e2020-06-26 18:34:22 -0700403 assertThresholds(sensor, change.assertValue, change.threshold.level,
404 change.threshold.direction, change.asserted);
405 if (change.threshold.level == thresholds::Level::CRITICAL &&
406 change.asserted)
James Feist46342ec2019-03-06 14:03:41 -0800407 {
James Feist7b18b1e2019-05-14 13:42:09 -0700408 status = false;
James Feist46342ec2019-03-06 14:03:41 -0800409 }
410 }
411
James Feistdc6c55f2018-10-31 12:53:20 -0700412 return status;
James Feist251c7822018-09-12 12:54:15 -0700413}
414
Zhikui Ren12c2c0e2021-04-28 17:21:21 -0700415void checkThresholdsPowerDelay(const std::weak_ptr<Sensor>& weakSensor,
416 ThresholdTimer& thresholdTimer)
James Feist46342ec2019-03-06 14:03:41 -0800417{
Zhikui Ren12c2c0e2021-04-28 17:21:21 -0700418 auto sensorPtr = weakSensor.lock();
419 if (!sensorPtr)
420 {
421 return; // sensor is destructed, should never be here
422 }
James Feist46342ec2019-03-06 14:03:41 -0800423
Zhikui Ren12c2c0e2021-04-28 17:21:21 -0700424 Sensor* sensor = sensorPtr.get();
Zhikui Ren59b8b9e2020-06-26 18:34:22 -0700425 std::vector<ChangeParam> changes = checkThresholds(sensor, sensor->value);
426 for (const auto& change : changes)
James Feist46342ec2019-03-06 14:03:41 -0800427 {
Zhikui Renbf7cbc82020-07-02 08:44:00 -0700428 // When CPU is powered off, some volatges are expected to
429 // go below low thresholds. Filter these events with thresholdTimer.
430 // 1. always delay the assertion of low events to see if they are
431 // caused by power off event.
432 // 2. conditional delay the de-assertion of low events if there is
433 // an existing timer for assertion.
434 // 3. no delays for de-assert of low events if there is an existing
435 // de-assert for low event. This means 2nd de-assert would happen
436 // first and when timer expires for the previous one, no additional
437 // signal will be logged.
438 // 4. no delays for all high events.
439 if (change.threshold.direction == thresholds::Direction::LOW)
James Feist46342ec2019-03-06 14:03:41 -0800440 {
Zhikui Renbf7cbc82020-07-02 08:44:00 -0700441 if (change.asserted || thresholdTimer.hasActiveTimer(
442 change.threshold, !change.asserted))
443 {
Zhikui Ren12c2c0e2021-04-28 17:21:21 -0700444 thresholdTimer.startTimer(weakSensor, change.threshold,
445 change.asserted, change.assertValue);
Zhikui Renbf7cbc82020-07-02 08:44:00 -0700446 continue;
447 }
James Feist46342ec2019-03-06 14:03:41 -0800448 }
Zhikui Renbf7cbc82020-07-02 08:44:00 -0700449 assertThresholds(sensor, change.assertValue, change.threshold.level,
450 change.threshold.direction, change.asserted);
James Feist46342ec2019-03-06 14:03:41 -0800451 }
452}
453
Zhikui Ren59b8b9e2020-06-26 18:34:22 -0700454void assertThresholds(Sensor* sensor, double assertValue,
455 thresholds::Level level, thresholds::Direction direction,
456 bool assert)
James Feist251c7822018-09-12 12:54:15 -0700457{
James Feist251c7822018-09-12 12:54:15 -0700458 std::shared_ptr<sdbusplus::asio::dbus_interface> interface;
Jayashree Dhanapal45f27022021-12-07 12:56:35 +0530459 if (level == thresholds::Level::WARNING)
James Feist251c7822018-09-12 12:54:15 -0700460 {
James Feist251c7822018-09-12 12:54:15 -0700461 interface = sensor->thresholdInterfaceWarning;
462 }
Jayashree Dhanapal45f27022021-12-07 12:56:35 +0530463 else if (level == thresholds::Level::CRITICAL)
James Feist251c7822018-09-12 12:54:15 -0700464 {
James Feist251c7822018-09-12 12:54:15 -0700465 interface = sensor->thresholdInterfaceCritical;
466 }
467 else
468 {
Jayashree Dhanapal45f27022021-12-07 12:56:35 +0530469 std::cerr << "Unknown threshold, level " << static_cast<int>(level)
470 << "direction " << static_cast<int>(direction) << "\n";
James Feist251c7822018-09-12 12:54:15 -0700471 return;
472 }
473 if (!interface)
474 {
475 std::cout << "trying to set uninitialized interface\n";
476 return;
477 }
Zhikui Ren59b8b9e2020-06-26 18:34:22 -0700478
Jayashree Dhanapal45f27022021-12-07 12:56:35 +0530479 std::string property = sensor->propertyAlarm(level, direction);
480 if (property.empty())
481 {
482 std::cout << "Alarm property is empty \n";
483 return;
484 }
Zhikui Ren59b8b9e2020-06-26 18:34:22 -0700485 if (interface->set_property<bool, true>(property, assert))
486 {
487 try
488 {
489 // msg.get_path() is interface->get_object_path()
490 sdbusplus::message::message msg =
491 interface->new_signal("ThresholdAsserted");
492
493 msg.append(sensor->name, interface->get_interface_name(), property,
494 assert, assertValue);
495 msg.signal_send();
496 }
497 catch (const sdbusplus::exception::exception& e)
498 {
499 std::cerr
500 << "Failed to send thresholdAsserted signal with assertValue\n";
501 }
502 }
James Feist251c7822018-09-12 12:54:15 -0700503}
504
Jae Hyun Yoo9ced0a32018-10-25 10:42:39 -0700505bool parseThresholdsFromAttr(
James Feistd8705872019-02-08 13:26:09 -0800506 std::vector<thresholds::Threshold>& thresholdVector,
Vijay Khemka86dea2b2019-06-06 11:14:37 -0700507 const std::string& inputPath, const double& scaleFactor,
508 const double& offset)
James Feist6714a252018-09-10 15:26:18 -0700509{
Zbigniew Kurzynski0a4c4802020-04-01 11:22:27 +0200510 const boost::container::flat_map<
511 std::string, std::vector<std::tuple<const char*, thresholds::Level,
512 thresholds::Direction, double>>>
513 map = {
514 {"average",
515 {
516 std::make_tuple("average_min", Level::WARNING, Direction::LOW,
517 0.0),
518 std::make_tuple("average_max", Level::WARNING, Direction::HIGH,
519 0.0),
520 }},
521 {"input",
522 {
523 std::make_tuple("min", Level::WARNING, Direction::LOW, 0.0),
524 std::make_tuple("max", Level::WARNING, Direction::HIGH, 0.0),
525 std::make_tuple("lcrit", Level::CRITICAL, Direction::LOW, 0.0),
526 std::make_tuple("crit", Level::CRITICAL, Direction::HIGH,
527 offset),
528 }},
529 };
530
531 if (auto fileParts = splitFileName(inputPath))
James Feist6714a252018-09-10 15:26:18 -0700532 {
Zbigniew Kurzynskidbfd4662020-09-28 18:06:00 +0200533 auto& [type, nr, item] = *fileParts;
Zbigniew Kurzynski0a4c4802020-04-01 11:22:27 +0200534 if (map.count(item) != 0)
Jae Hyun Yoo9ced0a32018-10-25 10:42:39 -0700535 {
Zbigniew Kurzynski0a4c4802020-04-01 11:22:27 +0200536 for (const auto& t : map.at(item))
537 {
Zbigniew Kurzynskidbfd4662020-09-28 18:06:00 +0200538 auto& [suffix, level, direction, offset] = t;
Zbigniew Kurzynski0a4c4802020-04-01 11:22:27 +0200539 auto attrPath =
540 boost::replace_all_copy(inputPath, item, suffix);
541 if (auto val = readFile(attrPath, scaleFactor))
542 {
543 *val += offset;
Ed Tanous8a57ec02020-10-09 12:46:52 -0700544 if (debug)
Zbigniew Kurzynski0a4c4802020-04-01 11:22:27 +0200545 {
546 std::cout << "Threshold: " << attrPath << ": " << *val
547 << "\n";
548 }
549 thresholdVector.emplace_back(level, direction, *val);
550 }
551 }
Jae Hyun Yoo9ced0a32018-10-25 10:42:39 -0700552 }
James Feist6714a252018-09-10 15:26:18 -0700553 }
James Feist6714a252018-09-10 15:26:18 -0700554 return true;
555}
556
Jae Hyun Yoo9ced0a32018-10-25 10:42:39 -0700557bool hasCriticalInterface(
James Feistd8705872019-02-08 13:26:09 -0800558 const std::vector<thresholds::Threshold>& thresholdVector)
James Feist6714a252018-09-10 15:26:18 -0700559{
James Feistd8705872019-02-08 13:26:09 -0800560 for (auto& threshold : thresholdVector)
James Feist6714a252018-09-10 15:26:18 -0700561 {
562 if (threshold.level == Level::CRITICAL)
Jae Hyun Yoo9ced0a32018-10-25 10:42:39 -0700563 {
James Feist6714a252018-09-10 15:26:18 -0700564 return true;
Jae Hyun Yoo9ced0a32018-10-25 10:42:39 -0700565 }
James Feist6714a252018-09-10 15:26:18 -0700566 }
567 return false;
568}
569
Jae Hyun Yoo9ced0a32018-10-25 10:42:39 -0700570bool hasWarningInterface(
James Feistd8705872019-02-08 13:26:09 -0800571 const std::vector<thresholds::Threshold>& thresholdVector)
James Feist6714a252018-09-10 15:26:18 -0700572{
James Feistd8705872019-02-08 13:26:09 -0800573 for (auto& threshold : thresholdVector)
James Feist6714a252018-09-10 15:26:18 -0700574 {
575 if (threshold.level == Level::WARNING)
Jae Hyun Yoo9ced0a32018-10-25 10:42:39 -0700576 {
James Feist6714a252018-09-10 15:26:18 -0700577 return true;
Jae Hyun Yoo9ced0a32018-10-25 10:42:39 -0700578 }
James Feist6714a252018-09-10 15:26:18 -0700579 }
580 return false;
581}
582} // namespace thresholds