blob: bc6bb8403f8c014c48eb654115880939be8cf1c5 [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
Jayashree Dhanapal56678082022-01-04 17:27:20 +053047bool findOrder(Level lev, Direction dir)
48{
49 for (Sensor::ThresholdProperty prop : Sensor::thresProp)
50 {
51 if ((prop.level == lev) && (prop.direction == dir))
52 {
53 return true;
54 }
55 }
56 return false;
57}
58
Jae Hyun Yoo9ced0a32018-10-25 10:42:39 -070059bool parseThresholdsFromConfig(
James Feistd8705872019-02-08 13:26:09 -080060 const SensorData& sensorData,
61 std::vector<thresholds::Threshold>& thresholdVector,
Matt Spinler5636d522021-03-17 14:52:18 -050062 const std::string* matchLabel, const int* sensorIndex)
James Feist6714a252018-09-10 15:26:18 -070063{
James Feistd8705872019-02-08 13:26:09 -080064 for (const auto& item : sensorData)
James Feist6714a252018-09-10 15:26:18 -070065 {
66 if (item.first.find("Thresholds") == std::string::npos)
67 {
68 continue;
69 }
70 if (matchLabel != nullptr)
71 {
72 auto labelFind = item.second.find("Label");
73 if (labelFind == item.second.end())
Ed Tanous8a57ec02020-10-09 12:46:52 -070074 {
James Feist6714a252018-09-10 15:26:18 -070075 continue;
Ed Tanous8a57ec02020-10-09 12:46:52 -070076 }
James Feist3eb82622019-02-08 13:10:22 -080077 if (std::visit(VariantToStringVisitor(), labelFind->second) !=
78 *matchLabel)
Ed Tanous8a57ec02020-10-09 12:46:52 -070079 {
James Feist6714a252018-09-10 15:26:18 -070080 continue;
Ed Tanous8a57ec02020-10-09 12:46:52 -070081 }
James Feist6714a252018-09-10 15:26:18 -070082 }
Matt Spinler5636d522021-03-17 14:52:18 -050083
84 if (sensorIndex != nullptr)
85 {
86 auto indexFind = item.second.find("Index");
87
88 // If we're checking for index 1, a missing Index is OK.
89 if ((indexFind == item.second.end()) && (*sensorIndex != 1))
90 {
91 continue;
92 }
93
94 if ((indexFind != item.second.end()) &&
95 (std::visit(VariantToIntVisitor(), indexFind->second) !=
96 *sensorIndex))
97 {
98 continue;
99 }
100 }
101
Rashmica Gupta1e34cec2021-08-31 16:47:39 +1000102 double hysteresis = std::numeric_limits<double>::quiet_NaN();
103 auto hysteresisFind = item.second.find("Hysteresis");
104 if (hysteresisFind != item.second.end())
105 {
106 hysteresis =
107 std::visit(VariantToDoubleVisitor(), hysteresisFind->second);
108 }
109
James Feist6714a252018-09-10 15:26:18 -0700110 auto directionFind = item.second.find("Direction");
111 auto severityFind = item.second.find("Severity");
112 auto valueFind = item.second.find("Value");
113 if (valueFind == item.second.end() ||
114 severityFind == item.second.end() ||
115 directionFind == item.second.end())
116 {
Matt Spinler5636d522021-03-17 14:52:18 -0500117 std::cerr << "Malformed threshold on configuration interface "
118 << item.first << "\n";
James Feist6714a252018-09-10 15:26:18 -0700119 return false;
120 }
Jayashree Dhanapal45f27022021-12-07 12:56:35 +0530121 uint8_t severity =
122 std::visit(VariantToUnsignedIntVisitor(), severityFind->second);
123
124 std::string directions =
125 std::visit(VariantToStringVisitor(), directionFind->second);
126
127 Level level = findThresholdLevel(severity, directions);
128 Direction direction = findThresholdDirection(severity, directions);
129
130 if ((static_cast<int>(level) == thresLevel) ||
131 (static_cast<int>(direction) == thresLevel))
James Feist6714a252018-09-10 15:26:18 -0700132 {
Jayashree Dhanapal45f27022021-12-07 12:56:35 +0530133 continue;
James Feist6714a252018-09-10 15:26:18 -0700134 }
James Feist13f340b2019-03-07 16:36:11 -0800135 double val = std::visit(VariantToDoubleVisitor(), valueFind->second);
James Feist6714a252018-09-10 15:26:18 -0700136
Rashmica Gupta1e34cec2021-08-31 16:47:39 +1000137 thresholdVector.emplace_back(level, direction, val, hysteresis);
James Feist6714a252018-09-10 15:26:18 -0700138 }
139 return true;
140}
141
James Feistd8705872019-02-08 13:26:09 -0800142void persistThreshold(const std::string& path, const std::string& baseInterface,
143 const thresholds::Threshold& threshold,
James Feista222ba72019-03-01 15:57:51 -0800144 std::shared_ptr<sdbusplus::asio::connection>& conn,
Cheng C Yang6b1247a2020-03-09 23:48:39 +0800145 size_t thresholdCount, const std::string& labelMatch)
James Feist6714a252018-09-10 15:26:18 -0700146{
Brad Bishopfbb44ad2019-11-08 09:42:37 -0500147 for (size_t ii = 0; ii < thresholdCount; ii++)
James Feist6714a252018-09-10 15:26:18 -0700148 {
149 std::string thresholdInterface =
150 baseInterface + ".Thresholds" + std::to_string(ii);
151 conn->async_method_call(
Cheng C Yang6b1247a2020-03-09 23:48:39 +0800152 [&, path, threshold, thresholdInterface, labelMatch](
James Feistd8705872019-02-08 13:26:09 -0800153 const boost::system::error_code& ec,
154 const boost::container::flat_map<std::string, BasicVariantType>&
155 result) {
James Feist6714a252018-09-10 15:26:18 -0700156 if (ec)
157 {
158 return; // threshold not supported
159 }
160
Cheng C Yang6b1247a2020-03-09 23:48:39 +0800161 if (!labelMatch.empty())
162 {
163 auto labelFind = result.find("Label");
164 if (labelFind == result.end())
165 {
166 std::cerr << "No label in threshold configuration\n";
167 return;
168 }
169 std::string label =
170 std::visit(VariantToStringVisitor(), labelFind->second);
171 if (label != labelMatch)
172 {
173 return;
174 }
175 }
176
James Feist6714a252018-09-10 15:26:18 -0700177 auto directionFind = result.find("Direction");
178 auto severityFind = result.find("Severity");
179 auto valueFind = result.find("Value");
180 if (valueFind == result.end() || severityFind == result.end() ||
181 directionFind == result.end())
182 {
183 std::cerr << "Malformed threshold in configuration\n";
184 return;
185 }
James Feist3eb82622019-02-08 13:10:22 -0800186 unsigned int level = std::visit(VariantToUnsignedIntVisitor(),
187 severityFind->second);
James Feist6714a252018-09-10 15:26:18 -0700188
James Feist3eb82622019-02-08 13:10:22 -0800189 std::string dir =
190 std::visit(VariantToStringVisitor(), directionFind->second);
Jayashree Dhanapal45f27022021-12-07 12:56:35 +0530191 if (((findThresholdLevel(level, dir)) != threshold.level) ||
192 ((findThresholdDirection(level, dir)) !=
193 threshold.direction))
James Feist6714a252018-09-10 15:26:18 -0700194 {
195 return; // not the droid we're looking for
196 }
197
James Feist3eb82622019-02-08 13:10:22 -0800198 std::variant<double> value(threshold.value);
James Feist6714a252018-09-10 15:26:18 -0700199 conn->async_method_call(
James Feistd8705872019-02-08 13:26:09 -0800200 [](const boost::system::error_code& ec) {
James Feist6714a252018-09-10 15:26:18 -0700201 if (ec)
202 {
203 std::cerr << "Error setting threshold " << ec
204 << "\n";
205 }
206 },
Jae Hyun Yoo9ced0a32018-10-25 10:42:39 -0700207 entityManagerName, path, "org.freedesktop.DBus.Properties",
208 "Set", thresholdInterface, "Value", value);
James Feist6714a252018-09-10 15:26:18 -0700209 },
Jae Hyun Yoo9ced0a32018-10-25 10:42:39 -0700210 entityManagerName, path, "org.freedesktop.DBus.Properties",
James Feist6714a252018-09-10 15:26:18 -0700211 "GetAll", thresholdInterface);
212 }
213}
214
Jae Hyun Yoo95b8a2d2019-02-25 20:15:09 -0800215void updateThresholds(Sensor* sensor)
216{
217 if (sensor->thresholds.empty())
218 {
219 return;
220 }
221
222 for (const auto& threshold : sensor->thresholds)
223 {
Jayashree Dhanapal56678082022-01-04 17:27:20 +0530224 if (!findOrder(threshold.level, threshold.direction))
Jae Hyun Yoo95b8a2d2019-02-25 20:15:09 -0800225 {
226 continue;
227 }
Jayashree Dhanapal56678082022-01-04 17:27:20 +0530228 std::shared_ptr<sdbusplus::asio::dbus_interface> interface =
229 sensor->getThresholdInterface(threshold.level);
230
Jae Hyun Yoo95b8a2d2019-02-25 20:15:09 -0800231 if (!interface)
232 {
233 continue;
234 }
Jayashree Dhanapal45f27022021-12-07 12:56:35 +0530235
236 std::string property =
237 sensor->propertyLevel(threshold.level, threshold.direction);
238 if (property.empty())
239 {
240 continue;
241 }
Jae Hyun Yoo95b8a2d2019-02-25 20:15:09 -0800242 interface->set_property(property, threshold.value);
243 }
244}
245
Josh Lehan883fb3a2020-02-27 14:41:39 -0800246// Debugging counters
247static int cHiTrue = 0;
248static int cHiFalse = 0;
249static int cHiMidstate = 0;
250static int cLoTrue = 0;
251static int cLoFalse = 0;
252static int cLoMidstate = 0;
253static int cDebugThrottle = 0;
Zhikui Rend3da1282020-09-11 17:02:01 -0700254static constexpr int assertLogCount = 10;
Josh Lehan883fb3a2020-02-27 14:41:39 -0800255
Zhikui Ren59b8b9e2020-06-26 18:34:22 -0700256struct ChangeParam
James Feist251c7822018-09-12 12:54:15 -0700257{
Zhikui Ren59b8b9e2020-06-26 18:34:22 -0700258 ChangeParam(Threshold whichThreshold, bool status, double value) :
259 threshold(whichThreshold), asserted(status), assertValue(value)
260 {}
261
262 Threshold threshold;
263 bool asserted;
264 double assertValue;
265};
266
267static std::vector<ChangeParam> checkThresholds(Sensor* sensor, double value)
268{
269 std::vector<ChangeParam> thresholdChanges;
James Feist251c7822018-09-12 12:54:15 -0700270 if (sensor->thresholds.empty())
271 {
James Feist46342ec2019-03-06 14:03:41 -0800272 return thresholdChanges;
James Feist251c7822018-09-12 12:54:15 -0700273 }
James Feist46342ec2019-03-06 14:03:41 -0800274
James Feistd8705872019-02-08 13:26:09 -0800275 for (auto& threshold : sensor->thresholds)
James Feist251c7822018-09-12 12:54:15 -0700276 {
Josh Lehan883fb3a2020-02-27 14:41:39 -0800277 // Use "Schmitt trigger" logic to avoid threshold trigger spam,
278 // if value is noisy while hovering very close to a threshold.
279 // When a threshold is crossed, indicate true immediately,
280 // but require more distance to be crossed the other direction,
281 // before resetting the indicator back to false.
James Feist46342ec2019-03-06 14:03:41 -0800282 if (threshold.direction == thresholds::Direction::HIGH)
James Feistdc6c55f2018-10-31 12:53:20 -0700283 {
James Feist551087a2019-12-09 11:17:12 -0800284 if (value >= threshold.value)
James Feist251c7822018-09-12 12:54:15 -0700285 {
Zhikui Ren59b8b9e2020-06-26 18:34:22 -0700286 thresholdChanges.emplace_back(threshold, true, value);
Zhikui Rend3da1282020-09-11 17:02:01 -0700287 if (++cHiTrue < assertLogCount)
288 {
289 std::cerr << "Sensor " << sensor->name << " high threshold "
290 << threshold.value << " assert: value " << value
291 << " raw data " << sensor->rawValue << "\n";
292 }
Josh Lehan883fb3a2020-02-27 14:41:39 -0800293 }
Rashmica Gupta1e34cec2021-08-31 16:47:39 +1000294 else if (value < (threshold.value - threshold.hysteresis))
Josh Lehan883fb3a2020-02-27 14:41:39 -0800295 {
Zhikui Ren59b8b9e2020-06-26 18:34:22 -0700296 thresholdChanges.emplace_back(threshold, false, value);
Josh Lehan883fb3a2020-02-27 14:41:39 -0800297 ++cHiFalse;
James Feist251c7822018-09-12 12:54:15 -0700298 }
Patrick Venture66235d42019-10-11 08:31:27 -0700299 else
James Feist251c7822018-09-12 12:54:15 -0700300 {
Josh Lehan883fb3a2020-02-27 14:41:39 -0800301 ++cHiMidstate;
James Feist251c7822018-09-12 12:54:15 -0700302 }
303 }
Josh Lehan883fb3a2020-02-27 14:41:39 -0800304 else if (threshold.direction == thresholds::Direction::LOW)
James Feist251c7822018-09-12 12:54:15 -0700305 {
James Feist551087a2019-12-09 11:17:12 -0800306 if (value <= threshold.value)
James Feist251c7822018-09-12 12:54:15 -0700307 {
Zhikui Ren59b8b9e2020-06-26 18:34:22 -0700308 thresholdChanges.emplace_back(threshold, true, value);
Zhikui Rend3da1282020-09-11 17:02:01 -0700309 if (++cLoTrue < assertLogCount)
310 {
311 std::cerr << "Sensor " << sensor->name << " low threshold "
312 << threshold.value << " assert: value "
313 << sensor->value << " raw data "
314 << sensor->rawValue << "\n";
315 }
Josh Lehan883fb3a2020-02-27 14:41:39 -0800316 }
Rashmica Gupta1e34cec2021-08-31 16:47:39 +1000317 else if (value > (threshold.value + threshold.hysteresis))
Josh Lehan883fb3a2020-02-27 14:41:39 -0800318 {
Zhikui Ren59b8b9e2020-06-26 18:34:22 -0700319 thresholdChanges.emplace_back(threshold, false, value);
Josh Lehan883fb3a2020-02-27 14:41:39 -0800320 ++cLoFalse;
James Feist251c7822018-09-12 12:54:15 -0700321 }
Patrick Venture66235d42019-10-11 08:31:27 -0700322 else
James Feist251c7822018-09-12 12:54:15 -0700323 {
Josh Lehan883fb3a2020-02-27 14:41:39 -0800324 ++cLoMidstate;
James Feist251c7822018-09-12 12:54:15 -0700325 }
326 }
Josh Lehan883fb3a2020-02-27 14:41:39 -0800327 else
328 {
329 std::cerr << "Error determining threshold direction\n";
330 }
James Feist251c7822018-09-12 12:54:15 -0700331 }
Josh Lehan883fb3a2020-02-27 14:41:39 -0800332
Ed Tanous8a17c302021-09-02 15:07:11 -0700333 // Throttle debug output, so that it does not continuously spam
334 ++cDebugThrottle;
335 if (cDebugThrottle >= 1000)
Josh Lehan883fb3a2020-02-27 14:41:39 -0800336 {
Ed Tanous8a17c302021-09-02 15:07:11 -0700337 cDebugThrottle = 0;
338 if constexpr (debug)
Josh Lehan883fb3a2020-02-27 14:41:39 -0800339 {
Josh Lehan883fb3a2020-02-27 14:41:39 -0800340 std::cerr << "checkThresholds: High T=" << cHiTrue
341 << " F=" << cHiFalse << " M=" << cHiMidstate
342 << ", Low T=" << cLoTrue << " F=" << cLoFalse
343 << " M=" << cLoMidstate << "\n";
344 }
345 }
346
James Feist46342ec2019-03-06 14:03:41 -0800347 return thresholdChanges;
348}
349
Zhikui Ren12c2c0e2021-04-28 17:21:21 -0700350void ThresholdTimer::startTimer(const std::weak_ptr<Sensor>& weakSensor,
351 const Threshold& threshold, bool assert,
Jeff Lind9cd7042020-11-20 15:49:28 +0800352 double assertValue)
353{
354 struct TimerUsed timerUsed = {};
355 constexpr const size_t waitTime = 5;
356 TimerPair* pair = nullptr;
357
358 for (TimerPair& timer : timers)
359 {
360 if (!timer.first.used)
361 {
362 pair = &timer;
363 break;
364 }
365 }
366 if (pair == nullptr)
367 {
368 pair = &timers.emplace_back(timerUsed, boost::asio::deadline_timer(io));
369 }
370
371 pair->first.used = true;
372 pair->first.level = threshold.level;
373 pair->first.direction = threshold.direction;
374 pair->first.assert = assert;
375 pair->second.expires_from_now(boost::posix_time::seconds(waitTime));
Zhikui Ren12c2c0e2021-04-28 17:21:21 -0700376 pair->second.async_wait([weakSensor, pair, threshold, assert,
Jeff Lind9cd7042020-11-20 15:49:28 +0800377 assertValue](boost::system::error_code ec) {
Zhikui Ren12c2c0e2021-04-28 17:21:21 -0700378 auto sensorPtr = weakSensor.lock();
379 if (!sensorPtr)
380 {
381 return; // owner sensor has been destructed
382 }
383 // pair is valid as long as sensor is valid
Jeff Lind9cd7042020-11-20 15:49:28 +0800384 pair->first.used = false;
385
386 if (ec == boost::asio::error::operation_aborted)
387 {
388 return; // we're being canceled
389 }
390 if (ec)
391 {
392 std::cerr << "timer error: " << ec.message() << "\n";
393 return;
394 }
Zhikui Ren12c2c0e2021-04-28 17:21:21 -0700395 if (sensorPtr->readingStateGood())
Jeff Lind9cd7042020-11-20 15:49:28 +0800396 {
Zhikui Ren12c2c0e2021-04-28 17:21:21 -0700397 assertThresholds(sensorPtr.get(), assertValue, threshold.level,
Jeff Lind9cd7042020-11-20 15:49:28 +0800398 threshold.direction, assert);
399 }
400 });
401}
402
James Feist46342ec2019-03-06 14:03:41 -0800403bool checkThresholds(Sensor* sensor)
404{
James Feist7b18b1e2019-05-14 13:42:09 -0700405 bool status = true;
Zhikui Ren59b8b9e2020-06-26 18:34:22 -0700406 std::vector<ChangeParam> changes = checkThresholds(sensor, sensor->value);
407 for (const auto& change : changes)
James Feist46342ec2019-03-06 14:03:41 -0800408 {
Zhikui Ren59b8b9e2020-06-26 18:34:22 -0700409 assertThresholds(sensor, change.assertValue, change.threshold.level,
410 change.threshold.direction, change.asserted);
411 if (change.threshold.level == thresholds::Level::CRITICAL &&
412 change.asserted)
James Feist46342ec2019-03-06 14:03:41 -0800413 {
James Feist7b18b1e2019-05-14 13:42:09 -0700414 status = false;
James Feist46342ec2019-03-06 14:03:41 -0800415 }
416 }
417
James Feistdc6c55f2018-10-31 12:53:20 -0700418 return status;
James Feist251c7822018-09-12 12:54:15 -0700419}
420
Zhikui Ren12c2c0e2021-04-28 17:21:21 -0700421void checkThresholdsPowerDelay(const std::weak_ptr<Sensor>& weakSensor,
422 ThresholdTimer& thresholdTimer)
James Feist46342ec2019-03-06 14:03:41 -0800423{
Zhikui Ren12c2c0e2021-04-28 17:21:21 -0700424 auto sensorPtr = weakSensor.lock();
425 if (!sensorPtr)
426 {
427 return; // sensor is destructed, should never be here
428 }
James Feist46342ec2019-03-06 14:03:41 -0800429
Zhikui Ren12c2c0e2021-04-28 17:21:21 -0700430 Sensor* sensor = sensorPtr.get();
Zhikui Ren59b8b9e2020-06-26 18:34:22 -0700431 std::vector<ChangeParam> changes = checkThresholds(sensor, sensor->value);
432 for (const auto& change : changes)
James Feist46342ec2019-03-06 14:03:41 -0800433 {
Zhikui Renbf7cbc82020-07-02 08:44:00 -0700434 // When CPU is powered off, some volatges are expected to
435 // go below low thresholds. Filter these events with thresholdTimer.
436 // 1. always delay the assertion of low events to see if they are
437 // caused by power off event.
438 // 2. conditional delay the de-assertion of low events if there is
439 // an existing timer for assertion.
440 // 3. no delays for de-assert of low events if there is an existing
441 // de-assert for low event. This means 2nd de-assert would happen
442 // first and when timer expires for the previous one, no additional
443 // signal will be logged.
444 // 4. no delays for all high events.
445 if (change.threshold.direction == thresholds::Direction::LOW)
James Feist46342ec2019-03-06 14:03:41 -0800446 {
Zhikui Renbf7cbc82020-07-02 08:44:00 -0700447 if (change.asserted || thresholdTimer.hasActiveTimer(
448 change.threshold, !change.asserted))
449 {
Zhikui Ren12c2c0e2021-04-28 17:21:21 -0700450 thresholdTimer.startTimer(weakSensor, change.threshold,
451 change.asserted, change.assertValue);
Zhikui Renbf7cbc82020-07-02 08:44:00 -0700452 continue;
453 }
James Feist46342ec2019-03-06 14:03:41 -0800454 }
Zhikui Renbf7cbc82020-07-02 08:44:00 -0700455 assertThresholds(sensor, change.assertValue, change.threshold.level,
456 change.threshold.direction, change.asserted);
James Feist46342ec2019-03-06 14:03:41 -0800457 }
458}
459
Zhikui Ren59b8b9e2020-06-26 18:34:22 -0700460void assertThresholds(Sensor* sensor, double assertValue,
461 thresholds::Level level, thresholds::Direction direction,
462 bool assert)
James Feist251c7822018-09-12 12:54:15 -0700463{
Jayashree Dhanapal56678082022-01-04 17:27:20 +0530464 if (!findOrder(level, direction))
James Feist251c7822018-09-12 12:54:15 -0700465 {
James Feist251c7822018-09-12 12:54:15 -0700466 return;
467 }
Jayashree Dhanapal56678082022-01-04 17:27:20 +0530468
469 std::shared_ptr<sdbusplus::asio::dbus_interface> interface =
470 sensor->getThresholdInterface(level);
471
James Feist251c7822018-09-12 12:54:15 -0700472 if (!interface)
473 {
474 std::cout << "trying to set uninitialized interface\n";
475 return;
476 }
Zhikui Ren59b8b9e2020-06-26 18:34:22 -0700477
Jayashree Dhanapal45f27022021-12-07 12:56:35 +0530478 std::string property = sensor->propertyAlarm(level, direction);
479 if (property.empty())
480 {
481 std::cout << "Alarm property is empty \n";
482 return;
483 }
Zhikui Ren59b8b9e2020-06-26 18:34:22 -0700484 if (interface->set_property<bool, true>(property, assert))
485 {
486 try
487 {
488 // msg.get_path() is interface->get_object_path()
489 sdbusplus::message::message msg =
490 interface->new_signal("ThresholdAsserted");
491
492 msg.append(sensor->name, interface->get_interface_name(), property,
493 assert, assertValue);
494 msg.signal_send();
495 }
496 catch (const sdbusplus::exception::exception& e)
497 {
498 std::cerr
499 << "Failed to send thresholdAsserted signal with assertValue\n";
500 }
501 }
James Feist251c7822018-09-12 12:54:15 -0700502}
503
Jae Hyun Yoo9ced0a32018-10-25 10:42:39 -0700504bool parseThresholdsFromAttr(
James Feistd8705872019-02-08 13:26:09 -0800505 std::vector<thresholds::Threshold>& thresholdVector,
Vijay Khemka86dea2b2019-06-06 11:14:37 -0700506 const std::string& inputPath, const double& scaleFactor,
507 const double& offset)
James Feist6714a252018-09-10 15:26:18 -0700508{
Zbigniew Kurzynski0a4c4802020-04-01 11:22:27 +0200509 const boost::container::flat_map<
510 std::string, std::vector<std::tuple<const char*, thresholds::Level,
511 thresholds::Direction, double>>>
512 map = {
513 {"average",
514 {
515 std::make_tuple("average_min", Level::WARNING, Direction::LOW,
516 0.0),
517 std::make_tuple("average_max", Level::WARNING, Direction::HIGH,
518 0.0),
519 }},
520 {"input",
521 {
522 std::make_tuple("min", Level::WARNING, Direction::LOW, 0.0),
523 std::make_tuple("max", Level::WARNING, Direction::HIGH, 0.0),
524 std::make_tuple("lcrit", Level::CRITICAL, Direction::LOW, 0.0),
525 std::make_tuple("crit", Level::CRITICAL, Direction::HIGH,
526 offset),
527 }},
528 };
529
530 if (auto fileParts = splitFileName(inputPath))
James Feist6714a252018-09-10 15:26:18 -0700531 {
Zbigniew Kurzynskidbfd4662020-09-28 18:06:00 +0200532 auto& [type, nr, item] = *fileParts;
Zbigniew Kurzynski0a4c4802020-04-01 11:22:27 +0200533 if (map.count(item) != 0)
Jae Hyun Yoo9ced0a32018-10-25 10:42:39 -0700534 {
Zbigniew Kurzynski0a4c4802020-04-01 11:22:27 +0200535 for (const auto& t : map.at(item))
536 {
Zbigniew Kurzynskidbfd4662020-09-28 18:06:00 +0200537 auto& [suffix, level, direction, offset] = t;
Zbigniew Kurzynski0a4c4802020-04-01 11:22:27 +0200538 auto attrPath =
539 boost::replace_all_copy(inputPath, item, suffix);
540 if (auto val = readFile(attrPath, scaleFactor))
541 {
542 *val += offset;
Ed Tanous8a57ec02020-10-09 12:46:52 -0700543 if (debug)
Zbigniew Kurzynski0a4c4802020-04-01 11:22:27 +0200544 {
545 std::cout << "Threshold: " << attrPath << ": " << *val
546 << "\n";
547 }
548 thresholdVector.emplace_back(level, direction, *val);
549 }
550 }
Jae Hyun Yoo9ced0a32018-10-25 10:42:39 -0700551 }
James Feist6714a252018-09-10 15:26:18 -0700552 }
James Feist6714a252018-09-10 15:26:18 -0700553 return true;
554}
555
Jayashree Dhanapal56678082022-01-04 17:27:20 +0530556std::string getInterface(const Level thresholdLevel)
James Feist6714a252018-09-10 15:26:18 -0700557{
Jayashree Dhanapal56678082022-01-04 17:27:20 +0530558 std::string level;
559 switch (thresholdLevel)
James Feist6714a252018-09-10 15:26:18 -0700560 {
Jayashree Dhanapal56678082022-01-04 17:27:20 +0530561 case Level::WARNING:
562 level = "Warning";
563 break;
564 case Level::CRITICAL:
565 level = "Critical";
566 break;
567 case Level::ERROR:
568 level = "Error";
569 break;
James Feist6714a252018-09-10 15:26:18 -0700570 }
Jayashree Dhanapal56678082022-01-04 17:27:20 +0530571 std::string interface = "xyz.openbmc_project.Sensor.Threshold." + level;
572 return interface;
James Feist6714a252018-09-10 15:26:18 -0700573}
574} // namespace thresholds