blob: 404b261609fc9b9c112f352a912b6981647756a1 [file] [log] [blame]
James Feist8fd8a582018-11-16 11:10:46 -08001#pragma once
Bruce Lee1263c3d2021-06-04 15:16:33 +08002#include "dbus-sensor_config.h"
James Feist8fd8a582018-11-16 11:10:46 -08003
Ed Tanous6cb732a2021-02-18 15:33:51 -08004#include <SensorPaths.hpp>
Ed Tanous8a57ec02020-10-09 12:46:52 -07005#include <Thresholds.hpp>
6#include <Utils.hpp>
James Feist38fb5982020-05-28 10:09:54 -07007#include <sdbusplus/asio/object_server.hpp>
8
Patrick Venturefd6ba732019-10-31 14:27:39 -07009#include <limits>
10#include <memory>
Patrick Venturefd6ba732019-10-31 14:27:39 -070011#include <string>
12#include <vector>
James Feist8fd8a582018-11-16 11:10:46 -080013
James Feist1169eb42018-10-31 10:08:47 -070014constexpr size_t sensorFailedPollTimeMs = 5000;
James Feista5e58722019-04-22 14:43:11 -070015
Josh Lehan3bcd8232020-10-29 00:22:12 -070016// Enable useful logging with sensor instrumentation
17// This is intentionally not DEBUG, avoid clash with usage in .cpp files
18constexpr bool enableInstrumentation = false;
19
James Feista5e58722019-04-22 14:43:11 -070020constexpr const char* sensorValueInterface = "xyz.openbmc_project.Sensor.Value";
Jie Yang3291b9c2021-07-29 14:46:51 -070021constexpr const char* valueMutabilityInterfaceName =
22 "xyz.openbmc_project.Sensor.ValueMutability";
James Feist67601bd2020-06-16 17:14:44 -070023constexpr const char* availableInterfaceName =
24 "xyz.openbmc_project.State.Decorator.Availability";
James Feist961bf092020-07-01 16:38:12 -070025constexpr const char* operationalInterfaceName =
26 "xyz.openbmc_project.State.Decorator.OperationalStatus";
27constexpr const size_t errorThreshold = 5;
28
Josh Lehan3bcd8232020-10-29 00:22:12 -070029struct SensorInstrumentation
30{
31 // These are for instrumentation for debugging
32 int numCollectsGood = 0;
33 int numCollectsMiss = 0;
34 int numStreakGreats = 0;
35 int numStreakMisses = 0;
36 double minCollected = 0.0;
37 double maxCollected = 0.0;
38};
39
James Feist8fd8a582018-11-16 11:10:46 -080040struct Sensor
41{
James Feist930fcde2019-05-28 12:58:43 -070042 Sensor(const std::string& name,
James Feistd8705872019-02-08 13:26:09 -080043 std::vector<thresholds::Threshold>&& thresholdData,
44 const std::string& configurationPath, const std::string& objectType,
Jie Yang3291b9c2021-07-29 14:46:51 -070045 bool isSettable, bool isMutable, const double max, const double min,
James Feiste3338522020-09-15 15:40:30 -070046 std::shared_ptr<sdbusplus::asio::connection>& conn,
James Feist961bf092020-07-01 16:38:12 -070047 PowerState readState = PowerState::always) :
Ed Tanous6cb732a2021-02-18 15:33:51 -080048 name(sensor_paths::escapePathForDbus(name)),
James Feist930fcde2019-05-28 12:58:43 -070049 configurationPath(configurationPath), objectType(objectType),
Jie Yang3291b9c2021-07-29 14:46:51 -070050 isSensorSettable(isSettable), isValueMutable(isMutable), maxValue(max),
51 minValue(min), thresholds(std::move(thresholdData)),
Josh Lehan883fb3a2020-02-27 14:41:39 -080052 hysteresisTrigger((max - min) * 0.01),
James Feiste3338522020-09-15 15:40:30 -070053 hysteresisPublish((max - min) * 0.0001), dbusConnection(conn),
Josh Lehan3bcd8232020-10-29 00:22:12 -070054 readState(readState), errCount(0),
55 instrumentation(enableInstrumentation
56 ? std::make_unique<SensorInstrumentation>()
57 : nullptr)
James Feist38fb5982020-05-28 10:09:54 -070058 {}
James Feist8fd8a582018-11-16 11:10:46 -080059 virtual ~Sensor() = default;
James Feistce3fca42018-11-21 12:58:24 -080060 virtual void checkThresholds(void) = 0;
James Feistdc6c55f2018-10-31 12:53:20 -070061 std::string name;
James Feistce3fca42018-11-21 12:58:24 -080062 std::string configurationPath;
63 std::string objectType;
Bruce Lee1263c3d2021-06-04 15:16:33 +080064 bool isSensorSettable;
Jie Yang3291b9c2021-07-29 14:46:51 -070065
66 /* A flag indicates if properties of xyz.openbmc_project.Sensor.Value
67 * interface are mutable. If mutable, then
68 * xyz.openbmc_project.Sensor.ValueMutability interface will be
69 * instantiated.
70 */
71 bool isValueMutable;
James Feistce3fca42018-11-21 12:58:24 -080072 double maxValue;
73 double minValue;
James Feist8fd8a582018-11-16 11:10:46 -080074 std::vector<thresholds::Threshold> thresholds;
75 std::shared_ptr<sdbusplus::asio::dbus_interface> sensorInterface;
James Feist078f2322019-03-08 11:09:05 -080076 std::shared_ptr<sdbusplus::asio::dbus_interface> association;
James Feist67601bd2020-06-16 17:14:44 -070077 std::shared_ptr<sdbusplus::asio::dbus_interface> availableInterface;
James Feist961bf092020-07-01 16:38:12 -070078 std::shared_ptr<sdbusplus::asio::dbus_interface> operationalInterface;
Jie Yang3291b9c2021-07-29 14:46:51 -070079 std::shared_ptr<sdbusplus::asio::dbus_interface> valueMutabilityInterface;
James Feist8fd8a582018-11-16 11:10:46 -080080 double value = std::numeric_limits<double>::quiet_NaN();
Zhikui Rend3da1282020-09-11 17:02:01 -070081 double rawValue = std::numeric_limits<double>::quiet_NaN();
Richard Marian Thomaiyarc0ca7ee2019-04-24 21:22:52 +053082 bool overriddenState = false;
Richard Marian Thomaiyar87219222018-11-06 20:25:38 +053083 bool internalSet = false;
Josh Lehan883fb3a2020-02-27 14:41:39 -080084 double hysteresisTrigger;
85 double hysteresisPublish;
James Feiste3338522020-09-15 15:40:30 -070086 std::shared_ptr<sdbusplus::asio::connection> dbusConnection;
James Feist961bf092020-07-01 16:38:12 -070087 PowerState readState;
88 size_t errCount;
Josh Lehan3bcd8232020-10-29 00:22:12 -070089 std::unique_ptr<SensorInstrumentation> instrumentation;
90
Josh Lehanffe18342021-03-17 13:29:51 -070091 // This member variable provides a hook that can be used to receive
92 // notification whenever this Sensor's value is externally set via D-Bus.
93 // If interested, assign your own lambda to this variable, during
94 // construction of your Sensor subclass. See ExternalSensor for example.
95 std::function<void()> externalSetHook;
96
Ed Tanousc8fed202022-01-12 14:24:45 -080097 using Level = thresholds::Level;
98 using Direction = thresholds::Direction;
Jayashree Dhanapal45f27022021-12-07 12:56:35 +053099
Ed Tanousc8fed202022-01-12 14:24:45 -0800100 std::array<std::shared_ptr<sdbusplus::asio::dbus_interface>,
101 thresholds::thresProp.size()>
Jayashree Dhanapal56678082022-01-04 17:27:20 +0530102 thresholdInterfaces;
103
104 std::shared_ptr<sdbusplus::asio::dbus_interface>
Ed Tanousc8fed202022-01-12 14:24:45 -0800105 getThresholdInterface(Level lev)
Jayashree Dhanapal56678082022-01-04 17:27:20 +0530106 {
107 size_t index = static_cast<size_t>(lev);
108 if (index >= thresholdInterfaces.size())
109 {
110 std::cout << "Unknown threshold level \n";
111 return nullptr;
112 }
113 std::shared_ptr<sdbusplus::asio::dbus_interface> interface =
114 thresholdInterfaces[index];
115 return interface;
116 }
117
Josh Lehan3bcd8232020-10-29 00:22:12 -0700118 void updateInstrumentation(double readValue)
119 {
120 // Do nothing if this feature is not enabled
121 if constexpr (!enableInstrumentation)
122 {
123 return;
124 }
125 if (!instrumentation)
126 {
127 return;
128 }
129
130 // Save some typing
131 auto& inst = *instrumentation;
132
133 // Show constants if first reading (even if unsuccessful)
134 if ((inst.numCollectsGood == 0) && (inst.numCollectsMiss == 0))
135 {
136 std::cerr << "Sensor " << name << ": Configuration min=" << minValue
137 << ", max=" << maxValue << ", type=" << objectType
138 << ", path=" << configurationPath << "\n";
139 }
140
141 // Sensors can use "nan" to indicate unavailable reading
142 if (!std::isfinite(readValue))
143 {
144 // Only show this if beginning a new streak
145 if (inst.numStreakMisses == 0)
146 {
147 std::cerr << "Sensor " << name
148 << ": Missing reading, Reading counts good="
149 << inst.numCollectsGood
150 << ", miss=" << inst.numCollectsMiss
151 << ", Prior good streak=" << inst.numStreakGreats
152 << "\n";
153 }
154
155 inst.numStreakGreats = 0;
156 ++(inst.numCollectsMiss);
157 ++(inst.numStreakMisses);
158
159 return;
160 }
161
162 // Only show this if beginning a new streak and not the first time
163 if ((inst.numStreakGreats == 0) && (inst.numCollectsGood != 0))
164 {
165 std::cerr << "Sensor " << name
166 << ": Recovered reading, Reading counts good="
167 << inst.numCollectsGood
168 << ", miss=" << inst.numCollectsMiss
169 << ", Prior miss streak=" << inst.numStreakMisses << "\n";
170 }
171
172 // Initialize min/max if the first successful reading
173 if (inst.numCollectsGood == 0)
174 {
175 std::cerr << "Sensor " << name << ": First reading=" << readValue
176 << "\n";
177
178 inst.minCollected = readValue;
179 inst.maxCollected = readValue;
180 }
181
182 inst.numStreakMisses = 0;
183 ++(inst.numCollectsGood);
184 ++(inst.numStreakGreats);
185
186 // Only provide subsequent output if new min/max established
187 if (readValue < inst.minCollected)
188 {
189 std::cerr << "Sensor " << name << ": Lowest reading=" << readValue
190 << "\n";
191
192 inst.minCollected = readValue;
193 }
194
195 if (readValue > inst.maxCollected)
196 {
197 std::cerr << "Sensor " << name << ": Highest reading=" << readValue
198 << "\n";
199
200 inst.maxCollected = readValue;
201 }
202 }
James Feistce3fca42018-11-21 12:58:24 -0800203
James Feistd8705872019-02-08 13:26:09 -0800204 int setSensorValue(const double& newValue, double& oldValue)
Richard Marian Thomaiyar87219222018-11-06 20:25:38 +0530205 {
Richard Marian Thomaiyaraf6b87c2019-04-03 23:54:28 +0530206 if (!internalSet)
Richard Marian Thomaiyar87219222018-11-06 20:25:38 +0530207 {
Ed Tanous74cffa82022-01-25 13:00:28 -0800208 if (insecureSensorOverride == 0)
Bruce Lee1263c3d2021-06-04 15:16:33 +0800209 { // insecure sesnor override.
210 if (isSensorSettable == false)
211 { // sensor is not settable.
212 if (getManufacturingMode() == false)
213 { // manufacture mode is not enable.
Patrick Williams379b1132021-09-02 05:42:25 -0500214 std::cerr << "Sensor " << name
215 << ": Not allowed to set property value.\n";
216 return -EACCES;
Bruce Lee1263c3d2021-06-04 15:16:33 +0800217 }
218 }
219 }
220
Richard Marian Thomaiyar87219222018-11-06 20:25:38 +0530221 oldValue = newValue;
Richard Marian Thomaiyarc0ca7ee2019-04-24 21:22:52 +0530222 overriddenState = true;
223 // check thresholds for external set
224 value = newValue;
225 checkThresholds();
Josh Lehanffe18342021-03-17 13:29:51 -0700226
227 // Trigger the hook, as an external set has just happened
228 if (externalSetHook)
229 {
230 externalSetHook();
231 }
Richard Marian Thomaiyar87219222018-11-06 20:25:38 +0530232 }
Richard Marian Thomaiyarc0ca7ee2019-04-24 21:22:52 +0530233 else if (!overriddenState)
Richard Marian Thomaiyaraf6b87c2019-04-03 23:54:28 +0530234 {
235 oldValue = newValue;
236 }
Richard Marian Thomaiyar87219222018-11-06 20:25:38 +0530237 return 1;
238 }
James Feistce3fca42018-11-21 12:58:24 -0800239
Andrei Kartashev39287412022-02-04 16:04:47 +0300240 void setInitialProperties(const std::string& unit,
241 const std::string& label = std::string(),
242 size_t thresholdSize = 0)
James Feistce3fca42018-11-21 12:58:24 -0800243 {
James Feist961bf092020-07-01 16:38:12 -0700244 if (readState == PowerState::on || readState == PowerState::biosPost)
245 {
Andrei Kartashev39287412022-02-04 16:04:47 +0300246 setupPowerMatch(dbusConnection);
James Feist961bf092020-07-01 16:38:12 -0700247 }
248
James Feist82bac4c2019-03-11 11:16:53 -0700249 createAssociation(association, configurationPath);
AppaRao Pulic82213c2020-02-27 01:24:58 +0530250
Zev Weiss6b6891c2021-04-22 02:46:21 -0500251 sensorInterface->register_property("Unit", unit);
James Feistce3fca42018-11-21 12:58:24 -0800252 sensorInterface->register_property("MaxValue", maxValue);
253 sensorInterface->register_property("MinValue", minValue);
254 sensorInterface->register_property(
James Feistd8705872019-02-08 13:26:09 -0800255 "Value", value, [&](const double& newValue, double& oldValue) {
James Feistce3fca42018-11-21 12:58:24 -0800256 return setSensorValue(newValue, oldValue);
257 });
Konstantin Aladyshev75872ef2021-05-13 11:17:58 +0300258
259 fillMissingThresholds();
260
James Feistd8705872019-02-08 13:26:09 -0800261 for (auto& threshold : thresholds)
James Feistce3fca42018-11-21 12:58:24 -0800262 {
Rashmica Gupta1e34cec2021-08-31 16:47:39 +1000263 if (std::isnan(threshold.hysteresis))
264 {
265 threshold.hysteresis = hysteresisTrigger;
266 }
Ed Tanous17551b82022-01-26 16:47:17 -0800267
Jayashree Dhanapal56678082022-01-04 17:27:20 +0530268 std::shared_ptr<sdbusplus::asio::dbus_interface> iface =
269 getThresholdInterface(threshold.level);
270
James Feistce3fca42018-11-21 12:58:24 -0800271 if (!iface)
272 {
273 std::cout << "trying to set uninitialized interface\n";
274 continue;
275 }
Cheng C Yang6b1247a2020-03-09 23:48:39 +0800276
Jayashree Dhanapal45f27022021-12-07 12:56:35 +0530277 std::string level =
278 propertyLevel(threshold.level, threshold.direction);
279 std::string alarm =
280 propertyAlarm(threshold.level, threshold.direction);
281
282 if ((level.empty()) || (alarm.empty()))
283 {
284 continue;
285 }
Cheng C Yang6b1247a2020-03-09 23:48:39 +0800286 size_t thresSize =
287 label.empty() ? thresholds.size() : thresholdSize;
James Feistce3fca42018-11-21 12:58:24 -0800288 iface->register_property(
289 level, threshold.value,
Cheng C Yang6b1247a2020-03-09 23:48:39 +0800290 [&, label, thresSize](const double& request, double& oldValue) {
Ed Tanousbb679322022-05-16 16:10:00 -0700291 oldValue = request; // todo, just let the config do this?
292 threshold.value = request;
293 thresholds::persistThreshold(configurationPath, objectType,
294 threshold, dbusConnection,
295 thresSize, label);
296 // Invalidate previously remembered value,
297 // so new thresholds will be checked during next update,
298 // even if sensor reading remains unchanged.
299 value = std::numeric_limits<double>::quiet_NaN();
Josh Lehan883fb3a2020-02-27 14:41:39 -0800300
Ed Tanousbb679322022-05-16 16:10:00 -0700301 // Although tempting, don't call checkThresholds() from here
302 // directly. Let the regular sensor monitor call the same
303 // using updateValue(), which can check conditions like
304 // poweron, etc., before raising any event.
305 return 1;
James Feistce3fca42018-11-21 12:58:24 -0800306 });
307 iface->register_property(alarm, false);
308 }
309 if (!sensorInterface->initialize())
310 {
311 std::cerr << "error initializing value interface\n";
312 }
James Feistce3fca42018-11-21 12:58:24 -0800313
Jayashree Dhanapal56678082022-01-04 17:27:20 +0530314 for (auto& thresIface : thresholdInterfaces)
James Feistce3fca42018-11-21 12:58:24 -0800315 {
Jayashree Dhanapal56678082022-01-04 17:27:20 +0530316 if (thresIface)
317 {
318 if (!thresIface->initialize(true))
319 {
320 std::cerr << "Error initializing threshold interface \n";
321 }
322 }
James Feistce3fca42018-11-21 12:58:24 -0800323 }
James Feist67601bd2020-06-16 17:14:44 -0700324
Jie Yang3291b9c2021-07-29 14:46:51 -0700325 if (isValueMutable)
326 {
327 valueMutabilityInterface =
328 std::make_shared<sdbusplus::asio::dbus_interface>(
Andrei Kartashev39287412022-02-04 16:04:47 +0300329 dbusConnection, sensorInterface->get_object_path(),
Jie Yang3291b9c2021-07-29 14:46:51 -0700330 valueMutabilityInterfaceName);
331 valueMutabilityInterface->register_property("Mutable", true);
332 if (!valueMutabilityInterface->initialize())
333 {
334 std::cerr
335 << "error initializing sensor value mutability interface\n";
336 valueMutabilityInterface = nullptr;
337 }
338 }
339
James Feist67601bd2020-06-16 17:14:44 -0700340 if (!availableInterface)
341 {
342 availableInterface =
343 std::make_shared<sdbusplus::asio::dbus_interface>(
Andrei Kartashev39287412022-02-04 16:04:47 +0300344 dbusConnection, sensorInterface->get_object_path(),
James Feist67601bd2020-06-16 17:14:44 -0700345 availableInterfaceName);
346 availableInterface->register_property(
347 "Available", true, [this](const bool propIn, bool& old) {
348 if (propIn == old)
349 {
350 return 1;
351 }
James Feist961bf092020-07-01 16:38:12 -0700352 old = propIn;
James Feist67601bd2020-06-16 17:14:44 -0700353 if (!propIn)
354 {
355 updateValue(std::numeric_limits<double>::quiet_NaN());
356 }
James Feist67601bd2020-06-16 17:14:44 -0700357 return 1;
358 });
359 availableInterface->initialize();
360 }
James Feist961bf092020-07-01 16:38:12 -0700361 if (!operationalInterface)
362 {
363 operationalInterface =
364 std::make_shared<sdbusplus::asio::dbus_interface>(
Andrei Kartashev39287412022-02-04 16:04:47 +0300365 dbusConnection, sensorInterface->get_object_path(),
James Feist961bf092020-07-01 16:38:12 -0700366 operationalInterfaceName);
367 operationalInterface->register_property("Functional", true);
368 operationalInterface->initialize();
369 }
370 }
371
Ed Tanousc8fed202022-01-12 14:24:45 -0800372 std::string propertyLevel(const Level lev, const Direction dir)
Jayashree Dhanapal45f27022021-12-07 12:56:35 +0530373 {
Ed Tanousc8fed202022-01-12 14:24:45 -0800374 for (const thresholds::ThresholdDefinition& prop :
375 thresholds::thresProp)
Jayashree Dhanapal45f27022021-12-07 12:56:35 +0530376 {
Ed Tanousc8fed202022-01-12 14:24:45 -0800377 if (prop.level == lev)
Jayashree Dhanapal45f27022021-12-07 12:56:35 +0530378 {
Ed Tanousc8fed202022-01-12 14:24:45 -0800379 if (dir == Direction::HIGH)
380 {
381 return std::string(prop.levelName) + "High";
382 }
383 if (dir == Direction::LOW)
384 {
385 return std::string(prop.levelName) + "Low";
386 }
Jayashree Dhanapal45f27022021-12-07 12:56:35 +0530387 }
388 }
389 return "";
390 }
391
Ed Tanousc8fed202022-01-12 14:24:45 -0800392 std::string propertyAlarm(const Level lev, const Direction dir)
Jayashree Dhanapal45f27022021-12-07 12:56:35 +0530393 {
Ed Tanousc8fed202022-01-12 14:24:45 -0800394 for (const thresholds::ThresholdDefinition& prop :
395 thresholds::thresProp)
Jayashree Dhanapal45f27022021-12-07 12:56:35 +0530396 {
Ed Tanousc8fed202022-01-12 14:24:45 -0800397 if (prop.level == lev)
Jayashree Dhanapal45f27022021-12-07 12:56:35 +0530398 {
Ed Tanousc8fed202022-01-12 14:24:45 -0800399 if (dir == Direction::HIGH)
400 {
401 return std::string(prop.levelName) + "AlarmHigh";
402 }
403 if (dir == Direction::LOW)
404 {
405 return std::string(prop.levelName) + "AlarmLow";
406 }
Jayashree Dhanapal45f27022021-12-07 12:56:35 +0530407 }
408 }
409 return "";
410 }
411
James Feist961bf092020-07-01 16:38:12 -0700412 bool readingStateGood()
413 {
414 if (readState == PowerState::on && !isPowerOn())
415 {
416 return false;
417 }
418 if (readState == PowerState::biosPost &&
419 (!hasBiosPost() || !isPowerOn()))
420 {
421 return false;
422 }
423
424 return true;
425 }
426
427 void markFunctional(bool isFunctional)
428 {
429 if (operationalInterface)
430 {
431 operationalInterface->set_property("Functional", isFunctional);
432 }
433 if (isFunctional)
434 {
435 errCount = 0;
436 }
437 else
438 {
439 updateValue(std::numeric_limits<double>::quiet_NaN());
440 }
441 }
442
443 void markAvailable(bool isAvailable)
444 {
445 if (availableInterface)
446 {
447 availableInterface->set_property("Available", isAvailable);
448 errCount = 0;
449 }
450 }
451
452 void incrementError()
453 {
454 if (!readingStateGood())
455 {
456 markAvailable(false);
457 return;
458 }
459
460 if (errCount >= errorThreshold)
461 {
462 return;
463 }
464
465 errCount++;
466 if (errCount == errorThreshold)
467 {
468 std::cerr << "Sensor " << name << " reading error!\n";
469 markFunctional(false);
470 }
James Feistce3fca42018-11-21 12:58:24 -0800471 }
472
Andrew Jefferyfad36052022-03-15 21:44:44 +1030473 bool inError()
474 {
475 return errCount >= errorThreshold;
476 }
477
James Feistd8705872019-02-08 13:26:09 -0800478 void updateValue(const double& newValue)
James Feistce3fca42018-11-21 12:58:24 -0800479 {
Richard Marian Thomaiyarc0ca7ee2019-04-24 21:22:52 +0530480 // Ignore if overriding is enabled
James Feist961bf092020-07-01 16:38:12 -0700481 if (overriddenState)
Richard Marian Thomaiyarc0ca7ee2019-04-24 21:22:52 +0530482 {
Josh Lehan883fb3a2020-02-27 14:41:39 -0800483 return;
Richard Marian Thomaiyarc0ca7ee2019-04-24 21:22:52 +0530484 }
Josh Lehan883fb3a2020-02-27 14:41:39 -0800485
James Feist961bf092020-07-01 16:38:12 -0700486 if (!readingStateGood())
487 {
488 markAvailable(false);
Adrian Ambrożewicz623723b2020-07-29 12:53:54 +0200489 updateValueProperty(std::numeric_limits<double>::quiet_NaN());
James Feist961bf092020-07-01 16:38:12 -0700490 return;
491 }
492
Adrian Ambrożewicz623723b2020-07-29 12:53:54 +0200493 updateValueProperty(newValue);
Josh Lehan3bcd8232020-10-29 00:22:12 -0700494 updateInstrumentation(newValue);
Josh Lehan883fb3a2020-02-27 14:41:39 -0800495
496 // Always check thresholds after changing the value,
497 // as the test against hysteresisTrigger now takes place in
498 // the thresholds::checkThresholds() method,
499 // which is called by checkThresholds() below,
500 // in all current implementations of sensors that have thresholds.
501 checkThresholds();
James Feist961bf092020-07-01 16:38:12 -0700502 if (!std::isnan(newValue))
503 {
504 markFunctional(true);
505 markAvailable(true);
506 }
James Feistce3fca42018-11-21 12:58:24 -0800507 }
Zbigniew Kurzynski4f45e422020-06-09 12:42:15 +0200508
509 void updateProperty(
510 std::shared_ptr<sdbusplus::asio::dbus_interface>& interface,
511 double& oldValue, const double& newValue, const char* dbusPropertyName)
512 {
513 if (requiresUpdate(oldValue, newValue))
514 {
515 oldValue = newValue;
Jae Hyun Yoo1a540b82020-07-30 23:33:18 -0700516 if (interface &&
517 !(interface->set_property(dbusPropertyName, newValue)))
Zbigniew Kurzynski4f45e422020-06-09 12:42:15 +0200518 {
519 std::cerr << "error setting property " << dbusPropertyName
520 << " to " << newValue << "\n";
521 }
522 }
523 }
524
525 bool requiresUpdate(const double& lVal, const double& rVal)
526 {
527 if (std::isnan(lVal) || std::isnan(rVal))
528 {
529 return true;
530 }
531 double diff = std::abs(lVal - rVal);
532 if (diff > hysteresisPublish)
533 {
534 return true;
535 }
536 return false;
537 }
Adrian Ambrożewicz623723b2020-07-29 12:53:54 +0200538
539 private:
Konstantin Aladyshev75872ef2021-05-13 11:17:58 +0300540 // If one of the thresholds for a dbus interface is provided
541 // we have to set the other one as dbus properties are never
542 // optional.
543 void fillMissingThresholds()
544 {
545 for (thresholds::Threshold& thisThreshold : thresholds)
546 {
547 bool foundOpposite = false;
548 thresholds::Direction opposite = thresholds::Direction::HIGH;
549 if (thisThreshold.direction == thresholds::Direction::HIGH)
550 {
551 opposite = thresholds::Direction::LOW;
552 }
553 for (thresholds::Threshold& otherThreshold : thresholds)
554 {
555 if (thisThreshold.level != otherThreshold.level)
556 {
557 continue;
558 }
559 if (otherThreshold.direction != opposite)
560 {
561 continue;
562 }
563 foundOpposite = true;
564 break;
565 }
566 if (foundOpposite)
567 {
568 continue;
569 }
570 thresholds.emplace_back(thisThreshold.level, opposite,
571 std::numeric_limits<double>::quiet_NaN());
572 }
573 }
574
Adrian Ambrożewicz623723b2020-07-29 12:53:54 +0200575 void updateValueProperty(const double& newValue)
576 {
577 // Indicate that it is internal set call, not an external overwrite
578 internalSet = true;
579 updateProperty(sensorInterface, value, newValue, "Value");
580 internalSet = false;
581 }
Richard Marian Thomaiyarc0ca7ee2019-04-24 21:22:52 +0530582};