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; QString key = _source;
key.remove("battery/"); key.remove("battery/");
m_map[_source] = key; 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") { } else if (_source == "cpu/system/TotalLoad") {
// cpu // cpu
m_map[_source] = "cpu"; m_map[_source] = "cpu";

View File

@ -136,8 +136,13 @@ QStringList AWKeyOperations::dictKeys() const
= QDir("/sys/class/power_supply") = QDir("/sys/class/power_supply")
.entryList(QStringList({"BAT*"}), .entryList(QStringList({"BAT*"}),
QDir::Dirs | QDir::NoDotAndDotDot, QDir::Name); 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("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 // package manager
for (auto &item : m_extUpgrade->activeItems()) for (auto &item : m_extUpgrade->activeItems())
allKeys.append(item->tag("pkgcount")); allKeys.append(item->tag("pkgcount"));

View File

@ -20,6 +20,8 @@
#include <QDir> #include <QDir>
#include <cmath>
#include "awdebug.h" #include "awdebug.h"
@ -31,7 +33,6 @@ BatterySource::BatterySource(QObject *_parent, const QStringList &_args)
m_acpiPath = _args.at(0); m_acpiPath = _args.at(0);
m_sources = getSources(); m_sources = getSources();
m_timestamp = QDateTime::currentDateTimeUtc();
} }
@ -50,12 +51,14 @@ QStringList BatterySource::getSources()
sources.append("battery/batnow"); sources.append("battery/batnow");
sources.append("battery/batrate"); sources.append("battery/batrate");
sources.append("battery/battotal"); sources.append("battery/battotal");
m_batteriesCount m_batteriesCount
= QDir(m_acpiPath) = QDir(m_acpiPath)
.entryList(QStringList({"BAT*"}), .entryList(QStringList({"BAT*"}),
QDir::Dirs | QDir::NoDotAndDotDot, QDir::Name) QDir::Dirs | QDir::NoDotAndDotDot, QDir::Name)
.count(); .count();
qCInfo(LOG_ESS) << "Init batteries count as" << m_batteriesCount; qCInfo(LOG_ESS) << "Init batteries count as" << m_batteriesCount;
for (int i = 0; i < m_batteriesCount; i++) { for (int i = 0; i < m_batteriesCount; i++) {
sources.append(QString("battery/bat%1").arg(i)); sources.append(QString("battery/bat%1").arg(i));
sources.append(QString("battery/batleft%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() void BatterySource::run()
{ {
// swap data
m_previousValues.swap(m_values);
// adaptor // adaptor
QFile acFile(QString("%1/AC/online").arg(m_acpiPath)); QFile acFile(QString("%1/AC/online").arg(m_acpiPath));
if (acFile.open(QIODevice::ReadOnly | QIODevice::Text)) if (acFile.open(QIODevice::ReadOnly | QIODevice::Text))
@ -175,9 +175,11 @@ void BatterySource::run()
// current level // current level
QFile currentLevelFile( QFile currentLevelFile(
QString("%1/BAT%2/energy_now").arg(m_acpiPath).arg(i)); QString("%1/BAT%2/energy_now").arg(m_acpiPath).arg(i));
if (currentLevelFile.open(QIODevice::ReadOnly | QIODevice::Text)) if (currentLevelFile.open(QIODevice::ReadOnly | QIODevice::Text)) {
m_values[QString("battery/batnow%1").arg(i)] auto value = QString(currentLevelFile.readLine()).toInt();
= QString(currentLevelFile.readLine()).toInt(); m_trend[i + 1].append(value);
m_values[QString("battery/batnow%1").arg(i)] = value;
}
currentLevelFile.close(); currentLevelFile.close();
// total // total
QFile fullLevelFile( QFile fullLevelFile(
@ -196,6 +198,7 @@ void BatterySource::run()
} }
// total // total
m_trend[0].append(static_cast<int>(currentLevel));
m_values["battery/batnow"] = static_cast<int>(currentLevel); m_values["battery/batnow"] = static_cast<int>(currentLevel);
m_values["battery/battotal"] = static_cast<int>(fullLevel); m_values["battery/battotal"] = static_cast<int>(fullLevel);
m_values["battery/bat"] = static_cast<int>(100 * currentLevel / 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() void BatterySource::calculateRates()
{ {
// we are using moving average to get good numbers // check if it is first run
// check time interval if (!m_timestamp.isValid()) {
auto now = QDateTime::currentDateTimeUtc(); m_timestamp = 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";
return; 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++) { for (int i = 0; i < m_batteriesCount; i++) {
auto rate auto approx = approximate(m_trend[i + 1]);
= (m_values[QString("battery/batnow%1").arg(i)].toInt() m_values[QString("battery/batrate%1").arg(i)] = approx / interval;
- 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;
m_values[QString("battery/batleft%1").arg(i)] m_values[QString("battery/batleft%1").arg(i)]
= m_values[QString("battery/batnow%1").arg(i)].toInt() = interval * m_values[QString("battery/batnow%1").arg(i)].toFloat()
/ m_values[QString("battery/batrate%1").arg(i)].toInt(); / approx;
} }
// total // total
auto totalRate = (m_values["battery/batnow"].toInt() auto approx = approximate(m_trend[0]);
- m_previousValues["battery/batnow"].toInt()) m_values["battery/batrate"] = approx / interval;
/ interval; m_values["battery/batleft"]
m_values["battery/batrate"] = interval * m_values["battery/batnow"].toFloat() / approx;
= (totalRate + m_previousValues["battery/batrate"].toInt()) / 2;
m_values["battery/batleft"] = m_values["battery/batnow"].toInt() // old data cleanup
/ m_values["battery/batrate"].toInt(); 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 Q_OBJECT
public: public:
const int TREND_LIMIT = 20;
explicit BatterySource(QObject *_parent, const QStringList &_args); explicit BatterySource(QObject *_parent, const QStringList &_args);
virtual ~BatterySource(); virtual ~BatterySource();
QStringList getSources(); QStringList getSources();
@ -38,14 +40,15 @@ public:
QStringList sources() const; QStringList sources() const;
private: private:
double approximate(const QList<int> &_trend);
void calculateRates(); void calculateRates();
// configuration and values // configuration and values
int m_batteriesCount = 0; int m_batteriesCount = 0;
QString m_acpiPath; QString m_acpiPath;
QStringList m_sources; QStringList m_sources;
QDateTime m_timestamp; QDateTime m_timestamp;
QHash<int, QList<int>> m_trend;
QVariantHash m_values; 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," "gputemp,gpu,memmb,memgb,memfreemb,memfreegb,memtotmb,memtotgb,memusedmb,"
"memusedgb,mem,swapmb,swapgb,swapfreemb,swapfreegb,swaptotmb,swaptotgb," "memusedgb,mem,swapmb,swapgb,swapfreemb,swapfreegb,swaptotmb,swaptotgb,"
"swap,downunits,upunits,downkb,downtotkb,downtot,down,uptotkb,uptot,upkb," "swap,downunits,upunits,downkb,downtotkb,downtot,down,uptotkb,uptot,upkb,"
"up,netdev,ac,bat,album,artist,duration,progress,title,dalbum,dartist," "up,netdev,ac,bat,batleft,batnow,batrate,battotal,album,artist,duration,"
"dtitle,salbum,sartist,stitle,pscount,pstot,ps,desktop,ndesktop," "progress,title,dalbum,dartist,dtitle,salbum,sartist,stitle,pscount,pstot"
"tdesktops,la15,la5,la1"; ",ps,desktop,ndesktop,tdesktops,la15,la5,la1";
#cmakedefine BUILD_FUTURE #cmakedefine BUILD_FUTURE
#cmakedefine BUILD_LOAD #cmakedefine BUILD_LOAD
#cmakedefine BUILD_TESTING #cmakedefine BUILD_TESTING