Initial commit
This commit is contained in:
commit
b7d90b9afe
16245 files changed
+3396666
No files matched your search
Executable
+397
@@ -0,0 +1,397 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* Gui Plugin for Battery Monitor
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
# Created by Mike Wille, NLE, 2019-01-21
|
||||
*/
|
||||
|
||||
#include "bat_gui_plugin.h"
|
||||
|
||||
#include <LtsNotification/lts_notification.h>
|
||||
#include <LtsSession/lts_session.h>
|
||||
#include <NGLLogger/NGLLoggerBootstrap.h>
|
||||
#include <LtsWidgets/lts_message_dialog.h>
|
||||
#include <LtsWidgets/lts_base_layout_widget.h>
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
#include <Windows.h> // windows battery api
|
||||
#include <wlanapi.h>
|
||||
#endif
|
||||
#include <QProcess>
|
||||
#include <math.h>
|
||||
|
||||
|
||||
namespace Battery
|
||||
{
|
||||
|
||||
std::shared_ptr<GuiPluginBase::Interface> GuiPlugin::createGuiInterface(LtsSession::LtsSession *session)
|
||||
{
|
||||
return std::make_shared<InterfaceImpl>(session);
|
||||
}
|
||||
|
||||
|
||||
InterfaceImpl::InterfaceImpl(LtsSession::LtsSession *session)
|
||||
: GuiPluginBase::Interface(session, NGL::NGLLoggerBootstrap::getNGLRootLogger().getNGLLogger("BatteryGui"))
|
||||
, m_noti(nullptr)
|
||||
, m_notiWlan(nullptr)
|
||||
, m_warnedLow(false)
|
||||
, m_warnedCritical(false)
|
||||
, m_issi(QString())
|
||||
, m_signal(0)
|
||||
{
|
||||
connect(m_session, &LtsSession::LtsSession::signalDoneInitializingSession, // workaround to only receive the signal once
|
||||
this, &InterfaceImpl::onInitDone);
|
||||
}
|
||||
|
||||
void InterfaceImpl::onInitDone()
|
||||
{
|
||||
disconnect(m_session, &LtsSession::LtsSession::signalDoneInitializingSession,
|
||||
this, nullptr); // workaround to only receive the signal once
|
||||
checkWlanStatus();
|
||||
}
|
||||
|
||||
QVector<LtsWidgets::PluginData> InterfaceImpl::getActions()
|
||||
{
|
||||
QVector<LtsWidgets::PluginData> ret;
|
||||
|
||||
LtsWidgets::PluginData plData;
|
||||
plData.identifier = QLatin1String("CreateBatteryNoti");
|
||||
plData.createInstant = LtsWidgets::CreateInstantType::CreateInstantAndDiscardAction;
|
||||
plData.directFunc = [this](const LtsWidgets::PluginData &)
|
||||
{
|
||||
m_noti = m_session->createNotification(QStringLiteral("BatteryMonitor"));
|
||||
m_noti->setIcon(QIcon(QStringLiteral("icon:battery-unknown.svg")));
|
||||
m_noti->setAction([this]()
|
||||
{
|
||||
new LtsWidgets::LtsMessageDialogNew(m_session->baseLayout(), m_noti->tooltip(), tr("Current battery status"));
|
||||
});
|
||||
|
||||
slotCheckBatteryStatus();
|
||||
|
||||
QTimer *t = new QTimer(this);
|
||||
t->setInterval(10000);
|
||||
connect(t, &QTimer::timeout,
|
||||
this, &InterfaceImpl::slotCheckBatteryStatus);
|
||||
t->start();
|
||||
};
|
||||
ret.append(plData);
|
||||
|
||||
//Wlan Connection
|
||||
plData.directFunc = [this](const LtsWidgets::PluginData &)
|
||||
{
|
||||
m_notiWlan = m_session->createNotification(QStringLiteral("TabOcWlanConnection"));
|
||||
m_notiWlan->setToolTip(tr("No Wlan Connection"));
|
||||
m_notiWlan->setAction([this]()
|
||||
{
|
||||
LtsWidgets::LtsMessageDialog::showMessage(m_session->baseLayout(), m_notiWlan->tooltip());
|
||||
});
|
||||
};
|
||||
ret.append(plData);
|
||||
|
||||
connect(&m_timer, &QTimer::timeout, this, &InterfaceImpl::checkWlanStatus);
|
||||
m_timer.setInterval(1000);
|
||||
m_timer.start();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
//#define FAKE_CHARGE
|
||||
#ifdef FAKE_CHARGE
|
||||
static int fakeCharge = 100;
|
||||
#endif
|
||||
bool InterfaceImpl::getBatteryStatus(bool &hasAC, uint8_t &charge, int32_t &lifetime)
|
||||
{
|
||||
#ifdef FAKE_CHARGE
|
||||
// substracts 10% battery charge per status update (5 secs) - turns to 100 again after hitting 0
|
||||
|
||||
hasAC = false;
|
||||
charge = fakeCharge;
|
||||
fakeCharge -= 10;
|
||||
|
||||
if (fakeCharge < 0)
|
||||
fakeCharge = 100;
|
||||
|
||||
//lifetime = 9000; // 2 hours & 30 minutes (in secs)
|
||||
lifetime = 1800; // 0 hours & 30 minutes (in secs)
|
||||
|
||||
return true;
|
||||
#else
|
||||
#ifdef Q_OS_WIN
|
||||
SYSTEM_POWER_STATUS status;
|
||||
|
||||
if (!GetSystemPowerStatus(&status))
|
||||
{
|
||||
ERROR_LOG(m_logger) << "GetSystemPowerStatus failed";
|
||||
return false;
|
||||
}
|
||||
|
||||
hasAC = (status.ACLineStatus == 1); // The classic: Microsoft's Boolean is not boolean
|
||||
charge = status.BatteryLifePercent;
|
||||
lifetime = status.BatteryLifeTime;
|
||||
|
||||
if (charge == 255)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
#else // linux
|
||||
// TODO: linux
|
||||
QProcess upower;
|
||||
|
||||
QString text;
|
||||
QString arg;
|
||||
upower.setProgram(QStringLiteral("upower"));
|
||||
upower.setProcessChannelMode(QProcess::MergedChannels);
|
||||
|
||||
QStringList args;
|
||||
// first check for BATTERY NAME
|
||||
args << QStringLiteral("-e");
|
||||
upower.setArguments(args);
|
||||
upower.start();
|
||||
upower.waitForStarted();
|
||||
upower.waitForFinished(1000);
|
||||
while( upower.canReadLine())
|
||||
{
|
||||
QString line = QString::fromUtf8(upower.readLine().trimmed());
|
||||
if (line.contains(QStringLiteral("BAT")))
|
||||
arg = line;
|
||||
}
|
||||
|
||||
if (arg.isEmpty())
|
||||
return false;
|
||||
|
||||
args.clear();
|
||||
args << QStringLiteral("-i");
|
||||
//args << QStringLiteral("/org/freedesktop/UPower/devices/battery_BAT0");
|
||||
args << arg ;
|
||||
upower.setArguments(args);
|
||||
//std::cout << "Try Starting upower " << upower.arguments().join(" ").toStdString()<< std::endl;
|
||||
upower.start();
|
||||
upower.waitForStarted();
|
||||
upower.waitForFinished(1000);
|
||||
if (!upower.canReadLine())
|
||||
return false;
|
||||
while( upower.canReadLine())
|
||||
{
|
||||
|
||||
const QString &line = QString::fromUtf8(upower.readLine().trimmed());
|
||||
// std::cout << "line: " << line.toStdString() <<std::endl;
|
||||
|
||||
if (line.startsWith(QStringLiteral("state")))
|
||||
{
|
||||
QStringList parts = line.split(QLatin1Char(':'));
|
||||
if (parts.size() > 1)
|
||||
{
|
||||
if (parts.at(1).contains(QStringLiteral("discharging")))
|
||||
hasAC = false;
|
||||
else
|
||||
hasAC = true;
|
||||
}
|
||||
}
|
||||
if (line.contains(QStringLiteral(" to ")))
|
||||
{
|
||||
QStringList parts = line.split(QLatin1Char(':'));
|
||||
if (parts.size() > 1)
|
||||
{
|
||||
text = parts.at(1);
|
||||
text = text.trimmed();
|
||||
QStringList time = text.split(QLatin1Char(' '));
|
||||
if (time.size() > 1)
|
||||
{
|
||||
QString timeinX = time.at(0);
|
||||
int p1 = 0;
|
||||
int p2 = 0;
|
||||
QStringList timeSplitt = timeinX.split(QLatin1Char('.'));
|
||||
if (timeSplitt.size() > 1)
|
||||
{
|
||||
p2 = timeSplitt.at(1).toInt();
|
||||
}
|
||||
p1 = timeSplitt.at(0).toInt();
|
||||
|
||||
if (time.at(1).contains(QStringLiteral("minutes")))
|
||||
{
|
||||
p1 *=60;
|
||||
p2 = (60/10*p2);
|
||||
}
|
||||
else
|
||||
{
|
||||
p1 = p1*60*60;
|
||||
p2 = ((60/10)*p2)*60;
|
||||
}
|
||||
lifetime = p1 + p2;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (line.startsWith(QStringLiteral("percentage")))
|
||||
{
|
||||
QStringList parts = line.split(QLatin1Char(':'));
|
||||
if (parts.size() > 1)
|
||||
{
|
||||
QString chargeString = parts.at(1);
|
||||
chargeString.chop(1);
|
||||
charge = chargeString.toInt();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//std::cout << "HAS AC: " << hasAC << " percentage: " << charge << " STATE: " << text.toStdString() << " Lifetime: " << lifetime << std::endl;
|
||||
DEBUG_LOG(m_logger) << "HAS AC: " << hasAC << " percentage: " << charge << " STATE: " << text.toStdString() << " Lifetime: " << lifetime << " seconds";
|
||||
|
||||
return true;
|
||||
#endif // end linux
|
||||
#endif
|
||||
}
|
||||
|
||||
void InterfaceImpl::checkWlanStatus()
|
||||
{
|
||||
bool bConnected = false;
|
||||
#ifdef Q_OS_WIN
|
||||
HANDLE hClient;
|
||||
DWORD NegociationVersion;
|
||||
DWORD dwResult = WlanOpenHandle(WLAN_API_VERSION, nullptr, &NegociationVersion, &hClient);
|
||||
if (dwResult == ERROR_SUCCESS)
|
||||
{
|
||||
PWLAN_INTERFACE_INFO_LIST pIfList = nullptr;
|
||||
dwResult = WlanEnumInterfaces(hClient, NULL, &pIfList);
|
||||
if (dwResult == ERROR_SUCCESS)
|
||||
{
|
||||
for (DWORD i = 0; i < pIfList->dwNumberOfItems; i++)
|
||||
{
|
||||
const auto &ifInfo = pIfList->InterfaceInfo[i];
|
||||
PWLAN_AVAILABLE_NETWORK_LIST pBssList = nullptr;
|
||||
dwResult = WlanGetAvailableNetworkList(hClient, &ifInfo.InterfaceGuid,
|
||||
0, nullptr, &pBssList);
|
||||
if (dwResult == ERROR_SUCCESS)
|
||||
{
|
||||
for (DWORD j = 0; j < pBssList->dwNumberOfItems; j++) {
|
||||
const auto &bssEntry = pBssList->Network[j];
|
||||
if (bssEntry.dwFlags & WLAN_AVAILABLE_NETWORK_CONNECTED)
|
||||
{
|
||||
bConnected = true;
|
||||
m_issi = QString::fromLocal8Bit(reinterpret_cast<const char*>(&bssEntry.dot11Ssid.ucSSID[0]));
|
||||
m_signal = bssEntry.wlanSignalQuality;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
WlanFreeMemory(pBssList);
|
||||
if (bConnected)
|
||||
break;
|
||||
}
|
||||
WlanFreeMemory(pIfList);
|
||||
}
|
||||
WlanCloseHandle(hClient, nullptr);
|
||||
}
|
||||
#endif
|
||||
|
||||
setWlanStatus(bConnected);
|
||||
}
|
||||
|
||||
|
||||
void InterfaceImpl::slotCheckBatteryStatus()
|
||||
{
|
||||
if (m_noti == nullptr)
|
||||
return;
|
||||
|
||||
bool hasAC = false;
|
||||
uint8_t charge = 255;
|
||||
int32_t lifetime = 0;
|
||||
|
||||
bool success = getBatteryStatus(hasAC, charge, lifetime);
|
||||
|
||||
QString statusText;
|
||||
QString filename;
|
||||
|
||||
if (!success)
|
||||
{
|
||||
statusText = tr("unknown");
|
||||
filename = QStringLiteral("icon:battery-unknown.svg");
|
||||
}
|
||||
else
|
||||
{
|
||||
int chargeFile = 0;
|
||||
|
||||
if (charge < 11) // this '11' thing ruins the easy 4-liner I had here first..
|
||||
chargeFile = 0;
|
||||
else if (charge < 21)
|
||||
chargeFile = 20;
|
||||
else if (charge < 41)
|
||||
chargeFile = 40;
|
||||
else if (charge < 61)
|
||||
chargeFile = 60;
|
||||
else if (charge < 81)
|
||||
chargeFile = 80;
|
||||
else
|
||||
chargeFile = 100;
|
||||
|
||||
filename = QStringLiteral("icon:battery-%1-%2.svg")
|
||||
.arg(QString::number(chargeFile),
|
||||
hasAC ? QStringLiteral("charging") : QStringLiteral("discharging"));
|
||||
|
||||
if (hasAC)
|
||||
statusText = tr("Charging");
|
||||
else
|
||||
statusText = tr("Discharging");
|
||||
|
||||
statusText += QStringLiteral(", ");
|
||||
statusText += QString::number(charge);
|
||||
statusText += QStringLiteral("%");
|
||||
statusText += QStringLiteral(" - %1 hour(s) and %2 minute(s) estimated remaining").arg(lifetime / 60 / 60).arg((lifetime / 60) % 60);
|
||||
}
|
||||
|
||||
QString tooltip(tr("Battery status: %1").arg(statusText));
|
||||
|
||||
m_noti->setIcon(QIcon(filename));
|
||||
m_noti->setToolTip(tooltip);
|
||||
|
||||
|
||||
if (!hasAC)
|
||||
{
|
||||
if (charge < 21 && !m_warnedLow)
|
||||
{
|
||||
m_warnedLow = true;
|
||||
new LtsWidgets::LtsMessageDialogNew(m_session->baseLayout(), tr("Battery charge is low, please plug the AC adapter in soon"));
|
||||
}
|
||||
else if (charge < 11 && !m_warnedCritical)
|
||||
{
|
||||
m_warnedCritical = true;
|
||||
new LtsWidgets::LtsMessageDialogNew(m_session->baseLayout(), tr("Battery charge is critical, please plug the AC adapter in now!"));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_warnedLow = false;
|
||||
m_warnedCritical = false;
|
||||
}
|
||||
}
|
||||
|
||||
void InterfaceImpl::setWlanStatus(bool isConnected)
|
||||
{
|
||||
if (!m_notiWlan)
|
||||
return;
|
||||
|
||||
if (isConnected)
|
||||
{
|
||||
m_notiWlan->setToolTip(tr("Connected to Wlan %1 \nSignal strength %2 %").arg(m_issi).arg(m_signal));
|
||||
if (m_signal > 0)
|
||||
{
|
||||
if (m_signal > 85)
|
||||
m_notiWlan->setIcon(QIcon(QStringLiteral("icon:wireless-green.svg")));
|
||||
else if (m_signal > 70)
|
||||
m_notiWlan->setIcon(QIcon(QStringLiteral("icon:wireless-yellow.svg")));
|
||||
else
|
||||
m_notiWlan->setIcon(QIcon(QStringLiteral("icon:wireless-orange.svg")));
|
||||
}
|
||||
else
|
||||
m_notiWlan->setIcon(QIcon(QStringLiteral("icon:wireless-green.svg")));
|
||||
}
|
||||
else
|
||||
{
|
||||
m_notiWlan->setToolTip(tr("No Wlan Connection"));
|
||||
m_notiWlan->setIcon(QIcon(QStringLiteral("icon:wireless-red.svg")));
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Battery
|
||||
Reference in new issue
Block a user