Support averaging power values
Support new env variables 'AVERAGE_power* = "true"' in hwmon config file.
When this env variable is set, power value is the calculated average value.
Otherwise, power value is from power*_input by default.
The new average of power is calculated since the last time the sensor's
values were changed and read.
average =
(cur_average*cur_average_interval - pre_average*pre_average_interval) /
(cur_average_interval - pre_average_interval)
hwmon config example:
AVERAGE_power2 = "true"
AVERAGE_power3 = "true"
AVERAGE_power4 = "true"
Tested: Set AVERAGE_power* in p0 OCC hwmon conf but not in p1 OCC hwmon conf,
then get power sensor info with restapi to check the values.
1. The values of p0*power are all average values.
2. The values of p1*power are all input values.
Note:
Delete $(CODE_COVERAGE_CPPFLAGS) in AM_CPPFLAGS in test/Makefile.am.
This option will define NDEBUG during configuration, then assert in
code doesn't work.
Resolves: openbmc/openbmc#3187
Signed-off-by: Carol Wang <wangkair@cn.ibm.com>
Change-Id: I8d97a7b2905c79cd4f2c276b32e7f5590ffc0483
diff --git a/mainloop.cpp b/mainloop.cpp
index 05ac623..4abfc02 100644
--- a/mainloop.cpp
+++ b/mainloop.cpp
@@ -27,6 +27,7 @@
#include "sysfs.hpp"
#include "targets.hpp"
#include "thresholds.hpp"
+#include "util.hpp"
#include <cassert>
#include <cstdlib>
@@ -351,6 +352,13 @@
_state[std::move(i.first)] = std::move(value);
}
+
+ // Initialize _averageMap of sensor. e.g. <<power, 1>, <0, 0>>
+ if ((i.first.first == hwmon::type::power) &&
+ (phosphor::utility::isAverageEnvSet(i.first)))
+ {
+ _average.setAverageValue(i.first, std::make_pair(0, 0));
+ }
}
/* If there are no sensors specified by labels, exit. */
@@ -394,11 +402,18 @@
}
// Read value from sensor.
- std::string input = hwmon::entry::cinput;
- if (sensorSysfsType == "pwm")
+ std::string input = hwmon::entry::input;
+ if (sensorSysfsType == hwmon::type::pwm)
{
input = "";
}
+ // If type is power and AVERAGE_power* is true in env, use average
+ // instead of input
+ else if ((sensorSysfsType == hwmon::type::power) &&
+ (phosphor::utility::isAverageEnvSet(sensorSetKey)))
+ {
+ input = hwmon::entry::average;
+ }
int64_t value;
auto& obj = std::get<InterfaceMap>(objInfo);
@@ -437,6 +452,41 @@
statusIface->functional(true);
value = sensor->adjustValue(value);
+
+ if (input == hwmon::entry::average)
+ {
+ // Calculate the values of averageMap based on current
+ // average value, current average_interval value, previous
+ // average value, previous average_interval value
+ int64_t interval =
+ _ioAccess->read(sensorSysfsType, sensorSysfsNum,
+ hwmon::entry::caverage_interval,
+ hwmonio::retries, hwmonio::delay);
+ auto ret = _average.getAverageValue(sensorSetKey);
+ assert(ret);
+
+ const auto& [preAverage, preInterval] = *ret;
+
+ auto calValue = Average::calcAverage(
+ preAverage, preInterval, value, interval);
+ if (calValue)
+ {
+ // Update previous values in averageMap before the
+ // variable value is changed next
+ _average.setAverageValue(
+ sensorSetKey, std::make_pair(value, interval));
+ // Update value to be calculated average
+ value = calValue.value();
+ }
+ else
+ {
+ // the value of
+ // power*_average_interval is not changed yet, use the
+ // previous calculated average instead. So skip dbus
+ // update.
+ continue;
+ }
+ }
}
updateSensorInterfaces(obj, value);
@@ -450,9 +500,8 @@
// as the code may exit before reaching it.
statusIface->functional(false);
#endif
- auto file =
- sysfs::make_sysfs_path(_ioAccess->path(), sensorSysfsType,
- sensorSysfsNum, hwmon::entry::cinput);
+ auto file = sysfs::make_sysfs_path(
+ _ioAccess->path(), sensorSysfsType, sensorSysfsNum, input);
// Check sensorAdjusts for sensor removal RCs
auto& sAdjusts = _sensorObjects[sensorSetKey]->getAdjusts();
@@ -534,10 +583,18 @@
_state[std::move(ssValueType.first)] = std::move(value);
+ std::string input = hwmon::entry::input;
+ // If type is power and AVERAGE_power* is true in env, use
+ // average instead of input
+ if ((it->first.first == hwmon::type::power) &&
+ (phosphor::utility::isAverageEnvSet(it->first)))
+ {
+ input = hwmon::entry::average;
+ }
// Sensor object added, erase entry from removal list
- auto file = sysfs::make_sysfs_path(
- _ioAccess->path(), it->first.first, it->first.second,
- hwmon::entry::cinput);
+ auto file =
+ sysfs::make_sysfs_path(_ioAccess->path(), it->first.first,
+ it->first.second, input);
log<level::INFO>("Added sensor to dbus after successful read",
entry("FILE=%s", file.c_str()));