use MSD for battery calculations, fix segfault

This commit is contained in:
Evgenii Alekseev 2017-08-25 06:11:18 +03:00
parent ea5d73d8fd
commit 2d7d4c55a2
5 changed files with 68 additions and 41 deletions

View File

@ -106,7 +106,9 @@ QStringList AWDataEngineMapper::registerSource(const QString &_source,
QString key = _source;
key.remove("battery/");
m_map[_source] = key;
m_formatter[key] = AWKeysAggregator::FormatterType::IntegerThree;
m_formatter[key] = _source.contains("rate")
? AWKeysAggregator::FormatterType::Float
: AWKeysAggregator::FormatterType::IntegerThree;
} else if (_source == "cpu/system/TotalLoad") {
// cpu
m_map[_source] = "cpu";

View File

@ -136,8 +136,13 @@ QStringList AWKeyOperations::dictKeys() const
= QDir("/sys/class/power_supply")
.entryList(QStringList({"BAT*"}),
QDir::Dirs | QDir::NoDotAndDotDot, QDir::Name);
for (int i = 0; i < allBatteryDevices.count(); i++)
for (int i = 0; i < allBatteryDevices.count(); i++) {
allKeys.append(QString("bat%1").arg(i));
allKeys.append(QString("batleft%1").arg(i));
allKeys.append(QString("batnow%1").arg(i));
allKeys.append(QString("batrate%1").arg(i));
allKeys.append(QString("battotal%1").arg(i));
}
// package manager
for (auto &item : m_extUpgrade->activeItems())
allKeys.append(item->tag("pkgcount"));

View File

@ -20,6 +20,8 @@
#include <QDir>
#include <cmath>
#include "awdebug.h"
@ -31,7 +33,6 @@ BatterySource::BatterySource(QObject *_parent, const QStringList &_args)
m_acpiPath = _args.at(0);
m_sources = getSources();
m_timestamp = QDateTime::currentDateTimeUtc();
}
@ -50,12 +51,14 @@ QStringList BatterySource::getSources()
sources.append("battery/batnow");
sources.append("battery/batrate");
sources.append("battery/battotal");
m_batteriesCount
= QDir(m_acpiPath)
.entryList(QStringList({"BAT*"}),
QDir::Dirs | QDir::NoDotAndDotDot, QDir::Name)
.count();
qCInfo(LOG_ESS) << "Init batteries count as" << m_batteriesCount;
for (int i = 0; i < m_batteriesCount; i++) {
sources.append(QString("battery/bat%1").arg(i));
sources.append(QString("battery/batleft%1").arg(i));
@ -159,9 +162,6 @@ QVariantMap BatterySource::initialData(const QString &_source) const
void BatterySource::run()
{
// swap data
m_previousValues.swap(m_values);
// adaptor
QFile acFile(QString("%1/AC/online").arg(m_acpiPath));
if (acFile.open(QIODevice::ReadOnly | QIODevice::Text))
@ -175,9 +175,11 @@ void BatterySource::run()
// current level
QFile currentLevelFile(
QString("%1/BAT%2/energy_now").arg(m_acpiPath).arg(i));
if (currentLevelFile.open(QIODevice::ReadOnly | QIODevice::Text))
m_values[QString("battery/batnow%1").arg(i)]
= QString(currentLevelFile.readLine()).toInt();
if (currentLevelFile.open(QIODevice::ReadOnly | QIODevice::Text)) {
auto value = QString(currentLevelFile.readLine()).toInt();
m_trend[i + 1].append(value);
m_values[QString("battery/batnow%1").arg(i)] = value;
}
currentLevelFile.close();
// total
QFile fullLevelFile(
@ -196,6 +198,7 @@ void BatterySource::run()
}
// total
m_trend[0].append(static_cast<int>(currentLevel));
m_values["battery/batnow"] = static_cast<int>(currentLevel);
m_values["battery/battotal"] = static_cast<int>(fullLevel);
m_values["battery/bat"] = static_cast<int>(100 * currentLevel / fullLevel);
@ -210,42 +213,56 @@ QStringList BatterySource::sources() const
}
double BatterySource::approximate(const QList<int> &_trend)
{
qCDebug(LOG_ESS) << "Approximate by MSD" << _trend;
auto count = _trend.count();
auto sumxy = 0;
for (int i = 0; i < count; i++)
sumxy += _trend.at(i) * (i + 1);
auto sumx = count * (count + 1) / 2;
auto sumy = std::accumulate(_trend.cbegin(), _trend.cend(), 0);
auto sumx2 = count * (count + 1) * (2 * count + 1) / 6;
return (count * sumxy - sumx * sumy) / (count * sumx2 - std::pow(sumx, 2));
}
void BatterySource::calculateRates()
{
// we are using moving average to get good numbers
// check time interval
auto now = QDateTime::currentDateTimeUtc();
auto interval
= 1000 * (now.toMSecsSinceEpoch() - m_timestamp.toMSecsSinceEpoch());
m_timestamp.swap(now);
// check time
if (m_previousValues.empty()) {
qCInfo(LOG_ESS) << "No historical data found for charges, exit";
// check if it is first run
if (!m_timestamp.isValid()) {
m_timestamp = QDateTime::currentDateTimeUtc();
return;
}
// per battery
// check time interval
auto now = QDateTime::currentDateTimeUtc();
auto interval
= (now.toMSecsSinceEpoch() - m_timestamp.toMSecsSinceEpoch()) / 1000.0f;
m_timestamp.swap(now);
for (int i = 0; i < m_batteriesCount; i++) {
auto rate
= (m_values[QString("battery/batnow%1").arg(i)].toInt()
- m_previousValues[QString("battery/batnow%1").arg(i)].toInt())
/ interval;
m_values[QString("battery/batrate%1").arg(i)]
= (m_previousValues[QString("battery/batrate%1").arg(i)].toInt()
+ rate)
/ 2;
auto approx = approximate(m_trend[i + 1]);
m_values[QString("battery/batrate%1").arg(i)] = approx / interval;
m_values[QString("battery/batleft%1").arg(i)]
= m_values[QString("battery/batnow%1").arg(i)].toInt()
/ m_values[QString("battery/batrate%1").arg(i)].toInt();
= interval * m_values[QString("battery/batnow%1").arg(i)].toFloat()
/ approx;
}
// total
auto totalRate = (m_values["battery/batnow"].toInt()
- m_previousValues["battery/batnow"].toInt())
/ interval;
m_values["battery/batrate"]
= (totalRate + m_previousValues["battery/batrate"].toInt()) / 2;
m_values["battery/batleft"] = m_values["battery/batnow"].toInt()
/ m_values["battery/batrate"].toInt();
auto approx = approximate(m_trend[0]);
m_values["battery/batrate"] = approx / interval;
m_values["battery/batleft"]
= interval * m_values["battery/batnow"].toFloat() / approx;
// old data cleanup
for (auto &trend : m_trend.keys()) {
if (m_trend[trend].count() <= TREND_LIMIT)
continue;
m_trend[trend].removeFirst();
}
}

View File

@ -29,6 +29,8 @@ class BatterySource : public AbstractExtSysMonSource
Q_OBJECT
public:
const int TREND_LIMIT = 20;
explicit BatterySource(QObject *_parent, const QStringList &_args);
virtual ~BatterySource();
QStringList getSources();
@ -38,14 +40,15 @@ public:
QStringList sources() const;
private:
double approximate(const QList<int> &_trend);
void calculateRates();
// configuration and values
int m_batteriesCount = 0;
QString m_acpiPath;
QStringList m_sources;
QDateTime m_timestamp;
QHash<int, QList<int>> m_trend;
QVariantHash m_values;
QVariantHash m_previousValues;
};

View File

@ -59,9 +59,9 @@ const char STATIC_KEYS[]
"gputemp,gpu,memmb,memgb,memfreemb,memfreegb,memtotmb,memtotgb,memusedmb,"
"memusedgb,mem,swapmb,swapgb,swapfreemb,swapfreegb,swaptotmb,swaptotgb,"
"swap,downunits,upunits,downkb,downtotkb,downtot,down,uptotkb,uptot,upkb,"
"up,netdev,ac,bat,album,artist,duration,progress,title,dalbum,dartist,"
"dtitle,salbum,sartist,stitle,pscount,pstot,ps,desktop,ndesktop,"
"tdesktops,la15,la5,la1";
"up,netdev,ac,bat,batleft,batnow,batrate,battotal,album,artist,duration,"
"progress,title,dalbum,dartist,dtitle,salbum,sartist,stitle,pscount,pstot"
",ps,desktop,ndesktop,tdesktops,la15,la5,la1";
#cmakedefine BUILD_FUTURE
#cmakedefine BUILD_LOAD
#cmakedefine BUILD_TESTING