diff --git a/application/qml/pages/MainPage.qml b/application/qml/pages/MainPage.qml
index d6cf582..deff4be 100644
--- a/application/qml/pages/MainPage.qml
+++ b/application/qml/pages/MainPage.qml
@@ -31,6 +31,14 @@ Page {
"empty": qsTr("empty", "Battery fully depleted"),
"unknown": qsTr("unknown", "Battery not detected, or faulty, or something")
}
+ property variant healthText: {
+ "good": qsTr("Good", "Battery is OK"),
+ "warm": qsTr("Warm", "Battery is warm"),
+ "overheat": qsTr("Overheated", "Battery is very hot"),
+ "cool": qsTr("Cool", "Battery is cool"),
+ "cold": qsTr("Cold", "Battery is very cold"),
+ "unknown": qsTr("unknown", "Battery not detected, or faulty, or something")
+ }
property bool serviceRunning: true
Timer {
@@ -166,6 +174,23 @@ Page {
label: qsTr("State:")
value: statusText[battery.state]
}
+ MyDetailItem {
+ label: qsTr("Health:")
+ value: healthText[battery.health]
+ visible: value !== "unknown"
+ }
+ MyDetailItem {
+ label: qsTr("Temperature:")
+ value: battery.temperature === 0x7FFFFFFF ? healthText["unknown"] : formatTemperature(battery.temperature)
+ visible: battery.temperature !== 0x7FFFFFFF
+
+ function formatTemperature(temp) {
+ if(Qt.locale().measurementSystem === Locale.ImperialUSSystem) {
+ return Math.floor((battery.temperature / 10) * 1.8 + 32) + " °F"
+ }
+ return Math.floor(battery.temperature / 10) + " °C"
+ }
+ }
}
}
Column {
diff --git a/application/qml/pages/SettingsPage.qml b/application/qml/pages/SettingsPage.qml
index 3c9b06c..a47fd00 100644
--- a/application/qml/pages/SettingsPage.qml
+++ b/application/qml/pages/SettingsPage.qml
@@ -43,9 +43,11 @@ Page {
highLimitSlider.value = settings.highLimit
lowLimitSlider.value = settings.lowLimit
highAlertSlider.value = settings.highAlert
+ healthSelector.currentIndex = settings.healthAlert
lowAlertSlider.value = settings.lowAlert
highIntervalSlider.value = settings.highNotificationsInterval
lowIntervalSlider.value = settings.lowNotificationsInterval
+ healthIntervalSlider.value = settings.healthNotificationsInterval
if(logger.debug) logger.log("SettingsPage values updated")
daemonCheck.start()
}
@@ -365,6 +367,70 @@ Page {
smallChange: 10
largeChange: 60
}
+
+ Label {
+ x: Theme.paddingLarge
+ text: qsTr("Health notification settings")
+ color: Theme.highlightColor
+ }
+ Label {
+ text: qsTr("Display visual and audible notifications when the battery status exceeds safe values.
This usually means high (or low) temperature but can include other parameters depending on the hardware.")
+ anchors {
+ left: parent.left
+ right: parent.right
+ leftMargin: Theme.horizontalPageMargin*2
+ rightMargin: Theme.horizontalPageMargin
+ }
+ color: Theme.primaryColor
+ font.pixelSize: Theme.fontSizeExtraSmall
+ wrapMode: Text.Wrap
+ }
+
+ SectionHeader { text: qsTr("Battery health notification") }
+
+ ComboBox {
+ id: healthSelector
+ width: parent.width
+ label: qsTr("Notification treshold")
+ currentIndex: settings.healthAlert
+ menu: ContextMenu {
+ MenuItem { text: qsTr("Never") }
+ MenuItem { text: qsTr("Warning") }
+ MenuItem { text: qsTr("Critical") }
+ }
+ onValueChanged: save()
+ function save() {
+ settings.healthAlert = healthSelector.currentIndex
+ }
+ }
+
+ SectionHeader { text: qsTr("Health notification interval") }
+
+ MySlider {
+ id: healthIntervalSlider
+ minimumValue: 50
+ maximumValue: 610
+ stepSize: 10
+ valueText: updateValueText()
+ onValueChanged: updateValueText()
+ function updateValueText() {
+ if(value == 50)
+ return qsTr("Once")
+ if(value == 610)
+ return qsTr("Never")
+ return Math.floor(value / 60) + (value % 60 < 10 ? ":0" + value % 60 : ":" + value % 60)
+ }
+ onReleased: save()
+ function save() {
+ settings.healthNotificationsInterval = value
+ }
+ }
+
+ AdjustmentButtons {
+ targetSlider: healthIntervalSlider
+ smallChange: 10
+ largeChange: 60
+ }
}
}
}
diff --git a/application/src/battery.cpp b/application/src/battery.cpp
index 06baa98..9aa86ad 100644
--- a/application/src/battery.cpp
+++ b/application/src/battery.cpp
@@ -40,6 +40,18 @@ Battery::Battery(Settings* newSettings, Logger* newLogger, QObject* parent) : QO
QString filename;
+ // Number: temperature
+ filename = "/sys/class/power_supply/battery/temp";
+ if(!temperatureFile && QFile::exists(filename)) {
+ temperatureFile = new QFile(filename, this);
+ }
+
+ // String: health state
+ filename = "/sys/class/power_supply/battery/health";
+ if(!healthFile && QFile::exists(filename)) {
+ healthFile = new QFile(filename, this);
+ }
+
// e.g. for Sony Xperia XA2
filename = "/sys/class/power_supply/battery/input_suspend";
if(!chargingEnabledFile && QFile::exists(filename)) {
diff --git a/application/src/battery.h b/application/src/battery.h
index b059d86..526af7a 100644
--- a/application/src/battery.h
+++ b/application/src/battery.h
@@ -67,6 +67,10 @@ private:
QString state = "idle"; // dis/charging, idle, unknown
bool chargingEnabled = true; // Only ever disabled manually
+
+ QString health = "unknown"; // Good, warm, overheat. Might have Cold or Overvoltage depending on driver
+ int temperature = 0x7FFFFFFF; // This value means "unknown" (32-bit INT_MAX)
+
int enableChargingValue = 1;
int disableChargingValue = 0;
bool chargerIsEnabled = true;
diff --git a/application/src/settings.cpp b/application/src/settings.cpp
index 04ef177..ebf9e42 100644
--- a/application/src/settings.cpp
+++ b/application/src/settings.cpp
@@ -31,8 +31,10 @@ Settings::Settings(Logger *newLogger, QObject *parent) : QObject(parent)
// Read in the values
loadInteger(sLowAlert, lowAlert, 5, 99);
loadInteger(sHighAlert, highAlert, 6, 100);
+ loadInteger(sHealthAlert, healthAlert, 0, 2);
loadInteger(sHighNotificationsInterval, highNotificationsInterval, 50, 610);
loadInteger(sLowNotificationsInterval, lowNotificationsInterval, 50, 610);
+ loadInteger(sHealthNotificationsInterval, healthNotificationsInterval, 50, 610);
loadInteger(sLimitEnabled, limitEnabled, 0, 1);
loadInteger(sLowLimit, lowLimit, 5, 99);
loadInteger(sHighLimit, highLimit, 6, 100);
@@ -43,10 +45,16 @@ Settings::Settings(Logger *newLogger, QObject *parent) : QObject(parent)
loadString(sNotificationTitle, notificationTitle);
loadString(sNotificationLowText, notificationLowText);
loadString(sNotificationHighText, notificationHighText);
+ loadString(sNotificationHealthTitle, notificationHealthTitle);
+ loadString(sNotificationHealthWarnText, notificationHealthWarnText);
+ loadString(sNotificationHealthCritText, notificationHealthCritText);
saveString(sNotificationTitle, tr("Battery charge %1%"), notificationTitle);
saveString(sNotificationLowText, tr("Please connect the charger."), notificationLowText);
saveString(sNotificationHighText, tr("Please disconnect the charger."), notificationHighText);
+ saveString(sNotificationHealthTitle, tr("Battery health %1"), notificationHealthTitle);
+ saveString(sNotificationHealthWarnText, tr("Battery health is not good"), notificationHealthWarnText);
+ saveString(sNotificationHealthCritText, tr("Battery health is critical"), notificationHealthCritText);
}
Settings::~Settings()
@@ -56,20 +64,26 @@ Settings::~Settings()
}
// Getters condensed.
-int Settings::getLowAlert() { return lowAlert; }
-int Settings::getHighAlert() { return highAlert; }
-int Settings::getHighNotificationsInterval() { return highNotificationsInterval; }
-int Settings::getLowNotificationsInterval() { return lowNotificationsInterval; }
-int Settings::getLowLimit() { return lowLimit; }
-int Settings::getHighLimit() { return highLimit; }
-bool Settings::getLimitEnabled() { return limitEnabled == 1; }
-QString Settings::getLowAlertFile() { return lowAlertFile; }
-QString Settings::getHighAlertFile() { return highAlertFile; }
-QString Settings::getLogFilename() { return logFilename; }
-QString Settings::getNotificationTitle() { return notificationTitle; }
-QString Settings::getNotificationLowText() { return notificationLowText; }
-QString Settings::getNotificationHighText() { return notificationHighText; }
-int Settings::getLogLevel() { return logLevel; }
+int Settings::getLowAlert() { return lowAlert; }
+int Settings::getHighAlert() { return highAlert; }
+int Settings::getHealthAlert() { return healthAlert; }
+int Settings::getHighNotificationsInterval() { return highNotificationsInterval; }
+int Settings::getLowNotificationsInterval() { return lowNotificationsInterval; }
+int Settings::getHealthNotificationsInterval() { return healthNotificationsInterval; }
+int Settings::getLowLimit() { return lowLimit; }
+int Settings::getHighLimit() { return highLimit; }
+bool Settings::getLimitEnabled() { return limitEnabled == 1; }
+QString Settings::getLowAlertFile() { return lowAlertFile; }
+QString Settings::getHighAlertFile() { return highAlertFile; }
+QString Settings::getHealthAlertFile() { return healthAlertFile; }
+QString Settings::getLogFilename() { return logFilename; }
+QString Settings::getNotificationTitle() { return notificationTitle; }
+QString Settings::getNotificationLowText() { return notificationLowText; }
+QString Settings::getNotificationHighText() { return notificationHighText; }
+QString Settings::getNotificationHealthTitle() { return notificationHealthTitle; }
+QString Settings::getNotificationHealthWarnText() { return notificationHealthWarnText; }
+QString Settings::getNotificationHealthCritText() { return notificationHealthCritText; }
+int Settings::getLogLevel() { return logLevel; }
void Settings::setLowAlert(const int newLimit) {
if(saveInteger(sLowAlert, newLimit, lowAlert)) {
@@ -83,6 +97,12 @@ void Settings::setHighAlert(const int newLimit) {
}
}
+void Settings::setHealthAlert(const int newLimit) {
+ if(saveInteger(sHealthAlert, newLimit, healthAlert)) {
+ emit healthAlertChanged(healthAlert);
+ }
+}
+
void Settings::setHighNotificationsInterval(const int newInterval) {
if(saveInteger(sHighNotificationsInterval, newInterval, highNotificationsInterval)) {
emit highNotificationsIntervalChanged(highNotificationsInterval);
@@ -95,6 +115,12 @@ void Settings::setLowNotificationsInterval(const int newInterval) {
}
}
+void Settings::setHealthNotificationsInterval(const int newInterval) {
+ if(saveInteger(sHealthNotificationsInterval, newInterval, healthNotificationsInterval)) {
+ emit healthNotificationsIntervalChanged(healthNotificationsInterval);
+ }
+}
+
void Settings::setLowLimit(const int newLimit) {
if(saveInteger(sLowLimit, newLimit, lowLimit)) {
emit lowLimitChanged(lowLimit);
@@ -126,6 +152,21 @@ void Settings::setNotificationHighText(const QString newText) {
emit notificationHighTextChanged(notificationHighText);
}
+void Settings::setNotificationHealthTitle(const QString newText) {
+ if(saveString(sNotificationHealthTitle, newText, notificationTitle))
+ emit notificationHealthTitleChanged(notificationTitle);
+}
+
+void Settings::setNotificationHealthWarnText(const QString newText) {
+ if(saveString(sNotificationHealthWarnText, newText, notificationHealthWarnText))
+ emit notificationHealthWarnTextChanged(notificationHealthWarnText);
+}
+
+void Settings::setNotificationHealthCritText(const QString newText) {
+ if(saveString(sNotificationHealthCritText, newText, notificationHealthCritText))
+ emit notificationHealthCritTextChanged(notificationHealthCritText);
+}
+
void Settings::setLogLevel(const int newLogLevel) {
if(saveInteger(sLogLevel, newLogLevel, logLevel))
emit logLevelChanged(logLevel);
diff --git a/application/src/settings.h b/application/src/settings.h
index eecc6a0..b30fc7d 100644
--- a/application/src/settings.h
+++ b/application/src/settings.h
@@ -27,16 +27,22 @@ class Settings : public QObject
Q_OBJECT
Q_PROPERTY(int highAlert READ getHighAlert WRITE setHighAlert NOTIFY highAlertChanged)
Q_PROPERTY(int lowAlert READ getLowAlert WRITE setLowAlert NOTIFY lowAlertChanged)
+ Q_PROPERTY(int healthAlert READ getHealthAlert WRITE setHealthAlert NOTIFY healthAlertChanged)
Q_PROPERTY(int highNotificationsInterval READ getHighNotificationsInterval WRITE setHighNotificationsInterval NOTIFY highNotificationsIntervalChanged)
Q_PROPERTY(int lowNotificationsInterval READ getLowNotificationsInterval WRITE setLowNotificationsInterval NOTIFY lowNotificationsIntervalChanged)
+ Q_PROPERTY(int healthNotificationsInterval READ getHealthNotificationsInterval WRITE setHealthNotificationsInterval NOTIFY healthNotificationsIntervalChanged)
Q_PROPERTY(int highLimit READ getHighLimit WRITE setHighLimit NOTIFY highLimitChanged)
Q_PROPERTY(int lowLimit READ getLowLimit WRITE setLowLimit NOTIFY lowLimitChanged)
Q_PROPERTY(bool limitEnabled READ getLimitEnabled WRITE setLimitEnabled NOTIFY limitEnabledChanged)
Q_PROPERTY(QString highAlertFile READ getHighAlertFile NOTIFY highAlertFileChanged)
Q_PROPERTY(QString lowAlertFile READ getLowAlertFile NOTIFY lowAlertFileChanged)
+ Q_PROPERTY(QString healthAlertFile READ getHealthAlertFile NOTIFY healthAlertFileChanged)
Q_PROPERTY(QString notificationTitle READ getNotificationTitle WRITE setNotificationTitle NOTIFY notificationTitleChanged)
Q_PROPERTY(QString notificationLowText READ getNotificationLowText WRITE setNotificationLowText NOTIFY notificationLowTextChanged)
Q_PROPERTY(QString notificationHighText READ getNotificationHighText WRITE setNotificationHighText NOTIFY notificationHighTextChanged)
+ Q_PROPERTY(QString notificationHealthTitle READ getNotificationHealthTitle WRITE setNotificationHealthTitle NOTIFY notificationHealthTitleChanged)
+ Q_PROPERTY(QString notificationHealthWarnText READ getNotificationHealthWarnText WRITE setNotificationHealthWarnText NOTIFY notificationHealthWarnTextChanged)
+ Q_PROPERTY(QString notificationHealthCritText READ getNotificationHealthCritText WRITE setNotificationHealthCritText NOTIFY notificationHealthCritTextChanged)
Q_PROPERTY(QString logFilename READ getLogFilename NOTIFY logFilenameChanged)
Q_PROPERTY(int logLevel READ getLogLevel WRITE setLogLevel NOTIFY logLevelChanged)
@@ -46,29 +52,40 @@ public:
int getLowAlert();
int getHighAlert();
+ int getHealthAlert();
int getHighNotificationsInterval();
int getLowNotificationsInterval();
+ int getHealthNotificationsInterval();
int getLowLimit();
int getHighLimit();
bool getLimitEnabled();
QString getLowAlertFile();
QString getHighAlertFile();
+ QString getHealthAlertFile();
QString getNotificationTitle();
QString getNotificationLowText();
QString getNotificationHighText();
+ QString getNotificationHealthTitle();
+ QString getNotificationHealthWarnText();
+ QString getNotificationHealthCritText();
QString getLogFilename();
int getLogLevel();
void setLowAlert(const int newLimit);
void setHighAlert(const int newLimit);
+ void setHealthAlert(const int newLimit);
void setHighNotificationsInterval(const int newInterval);
void setLowNotificationsInterval(const int newInterval);
+ void setHealthNotificationsInterval(const int newInterval);
void setLowLimit(const int newLimit);
void setHighLimit(const int newLimit);
void setLimitEnabled(const bool newEnabled);
void setNotificationTitle(const QString newText);
void setNotificationLowText(const QString newText);
void setNotificationHighText(const QString newText);
+ void setNotificationHealthTitle(const QString newText);
+ void setNotificationHealthWarnText(const QString newText);
+ void setNotificationHealthCritText(const QString newText);
void setLogLevel(const int newLogLevel);
private:
@@ -79,32 +96,44 @@ private:
// Default values
int lowAlert = 25;
int highAlert = 75;
+ int healthAlert = 1; // warn
int highNotificationsInterval = 60;
int lowNotificationsInterval = 60;
+ int healthNotificationsInterval = 60;
int limitEnabled = 1; // Converted to boolean for QML
int lowLimit = 65;
int highLimit = 70;
QString lowAlertFile = "/usr/share/sounds/jolla-ambient/stereo/general_warning.wav";
QString highAlertFile = "/usr/share/sounds/jolla-ambient/stereo/positive_confirmation.wav";
+ QString healthAlertFile = lowAlertFile;
QString notificationTitle;
QString notificationLowText;
QString notificationHighText;
+ QString notificationHealthTitle;
+ QString notificationHealthWarnText;
+ QString notificationHealthCritText;
QString logFilename;
int logLevel;
// To avoid repeating the same string over and over and over...
const char* sLowAlert = "lowAlert";
const char* sHighAlert = "highAlert";
+ const char* sHealthAlert = "healthAlert";
const char* sHighNotificationsInterval = "highNotificationsInterval";
const char* sLowNotificationsInterval = "lowNotificationsInterval";
+ const char* sHealthNotificationsInterval = "healthNotificationsInterval";
const char* sLimitEnabled = "limitEnabled";
const char* sLowLimit = "lowLimit";
const char* sHighLimit = "highLimit";
const char* sLowAlertFile = "lowAlertFile";
const char* sHighAlertFile = "highAlertFile";
+ const char* sHealthAlertFile = "healthAlertFile";
const char* sNotificationTitle = "notificationTitle";
const char* sNotificationLowText = "notificationLowText";
const char* sNotificationHighText = "notificationHighText";
+ const char* sNotificationHealthTitle = "notificationHealthTitle";
+ const char* sNotificationHealthWarnText = "notificationHealthWarnText";
+ const char* sNotificationHealthCritText = "notificationHealthCritText";
const char* sLogFilename = "logFilename";
const char* sLogLevel = "logLevel";
@@ -117,16 +146,22 @@ private:
signals:
void lowAlertChanged(int);
void highAlertChanged(int);
+ void healthAlertChanged(int);
void highNotificationsIntervalChanged(int);
void lowNotificationsIntervalChanged(int);
+ void healthNotificationsIntervalChanged(int);
void limitEnabledChanged(bool);
void lowLimitChanged(int);
void highLimitChanged(int);
void lowAlertFileChanged(QString);
void highAlertFileChanged(QString);
+ void healthAlertFileChanged(QString);
void notificationTitleChanged(QString);
void notificationLowTextChanged(QString);
void notificationHighTextChanged(QString);
+ void notificationHealthTitleChanged(QString);
+ void notificationHealthWarnTextChanged(QString);
+ void notificationHealthCritTextChanged(QString);
void logFilenameChanged(QString);
void logLevelChanged(int);
};
diff --git a/application/translations/harbour-batterybuddy-de_DE.ts b/application/translations/harbour-batterybuddy-de_DE.ts
index a0bf919..df7968d 100644
--- a/application/translations/harbour-batterybuddy-de_DE.ts
+++ b/application/translations/harbour-batterybuddy-de_DE.ts
@@ -156,34 +156,34 @@
LogPage
-
+ Logdatei ansehen
-
+ Aktualisieren
-
+ Kopieren
-
+ Log Level
Low log setting
-
+ Still
Medium log setting
-
+ Mittel
High log setting
-
+ Debug
@@ -275,6 +275,39 @@
Strom:
+
+
+ Battery is OK
+ die Batterie ist OK
+
+
+
+ Battery is warm
+ die Batterie ist warm
+
+
+
+ Battery is very hot
+ die Batterie ist sehr heiss
+
+
+
+ Zustand:
+
+
+
+ Temperatur:
+
+
+
+ Battery is cool
+ der Batterie ist kalt
+
+
+
+ Battery is very cold
+ der Batterie ist sehr kalt
+
Settings
@@ -290,6 +323,18 @@
Bitte Ladegerät trennen.
+
+
+
+
+
+
+
+
+
+
+
+
SettingsPage
@@ -364,6 +409,34 @@
+ Logdatei ansehen
+
+
+
+ Zustandsbenachrichtigung
+
+
+
+ Warnung
+
+
+
+ Kritisch
+
+
+
+ Zustandsbenachrichtigungsintervall
+
+
+
+ Visuelle und akustische Benachrichtigungen anzeigen, wenn gewissen Schwellwerte erreicht werden. Meistens gilt das fuer die Temperatur, aber je nach Hardware koennen auch andere Faktoren zu einer Meldung fuehren.
+
+
+
+
+
+
+
diff --git a/application/translations/harbour-batterybuddy-fi.ts b/application/translations/harbour-batterybuddy-fi.ts
index 2a36e3a..fdcdae0 100644
--- a/application/translations/harbour-batterybuddy-fi.ts
+++ b/application/translations/harbour-batterybuddy-fi.ts
@@ -273,6 +273,39 @@
Virta:
+
+
+ Battery is OK
+ Hyvä
+
+
+
+ Battery is warm
+ Lämmin
+
+
+
+ Battery is very hot
+ Ylikuumentunut
+
+
+
+ Battery is cool
+ Viileä
+
+
+
+ Battery is very cold
+ Kylmä
+
+
+
+ Kunto:
+
+
+
+ Lämpötila:
+
Settings
@@ -288,6 +321,18 @@
Ole hyvä ja irrota laturi.
+
+
+ Akun kunto: %1
+
+
+
+ Akun tila ei ole normaali
+
+
+
+ Akun tila on kriittinen
+
SettingsPage
@@ -364,5 +409,33 @@
Näytä loki
+
+
+ Näytä ilmoitukset ja toista hälytysääni, kun akun kunto ylittää normaalit rahat.<br />Yleensä tämä tarkoittaa liian korkeaa (tai matalaa) lämpötilaa, mutta syitä voi olla muitakin, laitteistosta riippuen.
+
+
+
+ Varoitus
+
+
+
+ Kriittinen
+
+
+
+ Akun kuntoilmoitusten aikaväli
+
+
+
+ Akun kunnon ilmoitukset
+
+
+
+ Akun tilan ilmoitusten aikaväli
+
+
+
+ Ilmoitusten taso
+
diff --git a/application/translations/harbour-batterybuddy-fr.ts b/application/translations/harbour-batterybuddy-fr.ts
index 57bf644..d1056c1 100644
--- a/application/translations/harbour-batterybuddy-fr.ts
+++ b/application/translations/harbour-batterybuddy-fr.ts
@@ -273,6 +273,39 @@
Courant:
+
+
+ Battery is OK
+
+
+
+
+ Battery is warm
+
+
+
+
+ Battery is very hot
+
+
+
+
+ Battery is cool
+
+
+
+
+ Battery is very cold
+
+
+
+
+
+
+
+
+
+
Settings
@@ -288,6 +321,18 @@
Merci de débrancher le chargeur.
+
+
+
+
+
+
+
+
+
+
+
+
SettingsPage
@@ -364,5 +409,33 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/application/translations/harbour-batterybuddy-hu.ts b/application/translations/harbour-batterybuddy-hu.ts
index 037d5d8..386decc 100644
--- a/application/translations/harbour-batterybuddy-hu.ts
+++ b/application/translations/harbour-batterybuddy-hu.ts
@@ -273,6 +273,39 @@
Jelenleg:
+
+
+ Battery is OK
+
+
+
+
+ Battery is warm
+
+
+
+
+ Battery is very hot
+
+
+
+
+ Battery is cool
+
+
+
+
+ Battery is very cold
+
+
+
+
+
+
+
+
+
+
Settings
@@ -288,6 +321,18 @@
Kérlek húzd ki a töltőt.
+
+
+
+
+
+
+
+
+
+
+
+
SettingsPage
@@ -364,5 +409,33 @@
Napló megtekintése
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/application/translations/harbour-batterybuddy-pl.ts b/application/translations/harbour-batterybuddy-pl.ts
index 78b9273..6e0af67 100644
--- a/application/translations/harbour-batterybuddy-pl.ts
+++ b/application/translations/harbour-batterybuddy-pl.ts
@@ -273,6 +273,39 @@
Prąd:
+
+
+ Battery is OK
+
+
+
+
+ Battery is warm
+
+
+
+
+ Battery is very hot
+
+
+
+
+ Battery is cool
+
+
+
+
+ Battery is very cold
+
+
+
+
+
+
+
+
+
+
Settings
@@ -288,6 +321,18 @@
Odłącz ładowarkę.
+
+
+
+
+
+
+
+
+
+
+
+
SettingsPage
@@ -364,5 +409,33 @@
Pokaż logi
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/application/translations/harbour-batterybuddy-sv.ts b/application/translations/harbour-batterybuddy-sv.ts
index eefd74b..78c0024 100644
--- a/application/translations/harbour-batterybuddy-sv.ts
+++ b/application/translations/harbour-batterybuddy-sv.ts
@@ -273,6 +273,39 @@
Ström:
+
+
+ Battery is OK
+
+
+
+
+ Battery is warm
+
+
+
+
+ Battery is very hot
+
+
+
+
+ Battery is cool
+
+
+
+
+ Battery is very cold
+
+
+
+
+
+
+
+
+
+
Settings
@@ -288,6 +321,18 @@
Koppla ifrån laddaren.
+
+
+
+
+
+
+
+
+
+
+
+
SettingsPage
@@ -364,5 +409,33 @@
Visa logg
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/application/translations/harbour-batterybuddy-zh_CN.ts b/application/translations/harbour-batterybuddy-zh_CN.ts
index 40e5856..1e42a0e 100644
--- a/application/translations/harbour-batterybuddy-zh_CN.ts
+++ b/application/translations/harbour-batterybuddy-zh_CN.ts
@@ -275,6 +275,39 @@
当前状态:
+
+
+ Battery is OK
+
+
+
+
+ Battery is warm
+
+
+
+
+ Battery is very hot
+
+
+
+
+ Battery is cool
+
+
+
+
+ Battery is very cold
+
+
+
+
+
+
+
+
+
+
Settings
@@ -290,6 +323,18 @@
请断开充电器
+
+
+
+
+
+
+
+
+
+
+
+
SettingsPage
@@ -366,5 +411,33 @@
查看日志
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/application/translations/harbour-batterybuddy.ts b/application/translations/harbour-batterybuddy.ts
index e39464c..11aa9f6 100644
--- a/application/translations/harbour-batterybuddy.ts
+++ b/application/translations/harbour-batterybuddy.ts
@@ -273,6 +273,39 @@
+
+
+ Battery is OK
+
+
+
+
+ Battery is warm
+
+
+
+
+ Battery is very hot
+
+
+
+
+ Battery is cool
+
+
+
+
+ Battery is very cold
+
+
+
+
+
+
+
+
+
+
Settings
@@ -288,6 +321,18 @@
+
+
+
+
+
+
+
+
+
+
+
+
SettingsPage
@@ -364,5 +409,33 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/service/src/battery.cpp b/service/src/battery.cpp
index 5078293..88799f6 100644
--- a/service/src/battery.cpp
+++ b/service/src/battery.cpp
@@ -33,23 +33,38 @@ Battery::Battery(Logger* newLogger, bool loglevelSet, QObject *parent) : QObject
updateTimer = new QTimer(this);
highNotifyTimer = new QTimer(this);
lowNotifyTimer = new QTimer(this);
- notification = new MyNotification(this);
+ healthNotifyTimer = new QTimer(this);
+ chargeNotification = new MyNotification(this);
+ healthNotification = new MyNotification(this);
// Number: charge percentage, e.g. 42
chargeFile = new QFile("/sys/class/power_supply/battery/capacity", this);
- logE("Capacity file: " + chargeFile->fileName());
+ logE("Capacity file: " + chargeFile->fileName() + (chargeFile->exists() ? " OK" : " doesn't exist"));
// String: charging, discharging, full, empty, unknown (others?)
stateFile = new QFile("/sys/class/power_supply/battery/status", this);
- logE("Charge state file: " + stateFile->fileName());
+ logE("Charge state file: " + stateFile->fileName() + (stateFile->exists() ? " OK" : " doesn't exist"));
// Number: 0 or 1
chargerConnectedFile = new QFile("/sys/class/power_supply/usb/present", this);
- logE("Charger status file: " + chargerConnectedFile->fileName());
+ logE("Charger status file: " + chargerConnectedFile->fileName() + (chargerConnectedFile->exists() ? " OK" : " doesn't exist"));
- // ENABLE/DISABLE CHARGING
QString filename;
+ // Number: temperature
+ filename = "/sys/class/power_supply/battery/temp";
+ if(!temperatureFile && QFile::exists(filename)) {
+ temperatureFile = new QFile(filename, this);
+ }
+ logE("Temperature file: " + filename + (QFile::exists(filename) ? " OK" : " doesn't exist"));
+
+ // String: health state
+ filename = "/sys/class/power_supply/battery/health";
+ if(!healthFile && QFile::exists(filename)) {
+ healthFile = new QFile(filename, this);
+ }
+ logE("Battery health file: " + filename + (QFile::exists(filename) ? " OK" : " doesn't exist"));
+
// e.g. for Sony Xperia XA2
filename = "/sys/class/power_supply/battery/input_suspend";
if(!chargingEnabledFile && QFile::exists(filename)) {
@@ -76,7 +91,7 @@ Battery::Battery(Logger* newLogger, bool loglevelSet, QObject *parent) : QObject
// If we found a usable file, check that it is writable
if(chargingEnabledFile) {
- logE("Charger control file: " + chargingEnabledFile->fileName());
+ logE("Charger control file: " + chargingEnabledFile->fileName() + (chargingEnabledFile->exists() ? " OK" : " doesn't exist"));
if(chargingEnabledFile->open(QIODevice::WriteOnly)) {
chargingEnabledFile->close();
}
@@ -97,6 +112,7 @@ Battery::Battery(Logger* newLogger, bool loglevelSet, QObject *parent) : QObject
connect(settings, SIGNAL(resetTimers()), this, SLOT(resetTimers()));
connect(highNotifyTimer, SIGNAL(timeout()), this, SLOT(showHighNotification()));
connect(lowNotifyTimer, SIGNAL(timeout()), this, SLOT(showLowNotification()));
+ connect(healthNotifyTimer, SIGNAL(timeout()), this, SLOT(showHealthNotification()));
updateData();
updateTimer->start(5000);
@@ -105,7 +121,7 @@ Battery::Battery(Logger* newLogger, bool loglevelSet, QObject *parent) : QObject
// aka. "charging" status didn't change
// (or if both times are disabled, actually)
// manually trigger the timer startup.
- if(!highNotifyTimer->isActive() && !lowNotifyTimer->isActive()) {
+ if(!highNotifyTimer->isActive() && !lowNotifyTimer->isActive() && !healthNotifyTimer->isActive()) {
resetTimers();
}
}
@@ -145,6 +161,29 @@ void Battery::updateData()
stateFile->close();
}
+ if(temperatureFile && temperatureFile->open(QIODevice::ReadOnly)) {
+ nextTemperature = temperatureFile->readLine().trimmed().toInt();
+ if(nextTemperature != temperature) {
+ temperature = nextTemperature;
+ emit temperatureChanged(temperature);
+ logV(QString("Temperature: %1°C").arg(temperature / 10));
+ }
+ temperatureFile->close();
+ }
+
+ if(healthFile && healthFile->open(QIODevice::ReadOnly)) {
+ nextHealth = (QString(healthFile->readLine().trimmed().toLower()));
+ if(nextHealth != health) {
+ health = nextHealth;
+ emit healthChanged(health);
+ logV("Health: " + health);
+
+ // Hide/show notification right away
+ resetTimers();
+ }
+ healthFile->close();
+ }
+
if(chargingEnabledFile && settings->getLimitEnabled()) {
if(chargingEnabled && charge >= settings->getHighLimit()) {
logD("Disabling charging...");
@@ -160,8 +199,10 @@ void Battery::updateData()
void Battery::resetTimers() {
highNotifyTimer->stop();
lowNotifyTimer->stop();
+ healthNotifyTimer->stop();
highNotifyTimer->setInterval(settings->getHighNotificationsInterval() * 1000);
lowNotifyTimer->setInterval(settings->getLowNotificationsInterval() * 1000);
+ healthNotifyTimer->setInterval(settings->getHealthNotificationsInterval() * 1000);
if(settings->getHighNotificationsInterval() < 610) {
logD("Starting high battery timer");
@@ -180,13 +221,22 @@ void Battery::resetTimers() {
else {
logD("Low battery timer not started");
}
+
+ if(settings->getHealthNotificationsInterval() < 610) {
+ logD("Start health timer");
+ healthNotifyTimer->start();
+ showHealthNotification();
+ }
+ else {
+ logD("Health timer not started");
+ }
}
void Battery::showHighNotification() {
if(settings->getHighNotificationsInterval() < 610 && (charge >= settings->getHighAlert() && state != "discharging")
&& !(charge == 100 && state == "idle")) {
logV(QString("Notification: %1").arg(settings->getNotificationTitle().arg(charge)));
- notification->send(settings->getNotificationTitle().arg(charge), settings->getNotificationHighText(), settings->getHighAlertFile());
+ chargeNotification->send(settings->getNotificationTitle().arg(charge), settings->getNotificationHighText(), settings->getHighAlertFile());
if(settings->getHighNotificationsInterval() == 50) {
logD("Stop high battery timer");
highNotifyTimer->stop();
@@ -194,14 +244,14 @@ void Battery::showHighNotification() {
}
else if(charge > settings->getLowAlert()) {
logD("Close high battery notification");
- notification->close();
+ chargeNotification->close();
}
}
void Battery::showLowNotification() {
if(settings->getLowNotificationsInterval() < 610 && charge <= settings->getLowAlert() && state != "charging") {
logV(QString("Notification: %1").arg(settings->getNotificationTitle().arg(charge)));
- notification->send(settings->getNotificationTitle().arg(charge), settings->getNotificationLowText(), settings->getLowAlertFile());
+ chargeNotification->send(settings->getNotificationTitle().arg(charge), settings->getNotificationLowText(), settings->getLowAlertFile());
if(settings->getLowNotificationsInterval() == 50) {
logD("Stop low battery timer");
lowNotifyTimer->stop();
@@ -209,7 +259,52 @@ void Battery::showLowNotification() {
}
else if(charge < settings->getHighAlert()) {
logD("Close low battery notification");
- notification->close();
+ chargeNotification->close();
+ }
+}
+
+void Battery::showHealthNotification() {
+ // set up alert categories
+ // TODO: manage this more globally, use better data types(?), align with QML/Settings part
+ static const QMap HealthThresh {
+ { "ok" , 0},
+ { "warn" , 1},
+ { "crit" , 2},
+ };
+ // map string values from sysfs file to alert category
+ static const QMap HealthState {
+ { "unknown" , HealthThresh["ok"] },
+ { "good" , HealthThresh["ok"] },
+ { "warm" , HealthThresh["warn"] },
+ { "cool" , HealthThresh["warn"] },
+ { "overheat" , HealthThresh["crit"] },
+ { "cold" , HealthThresh["crit"] }
+ };
+ if(settings->getHealthNotificationsInterval() < 610 && temperature != 0x7FFFFFFF && ( HealthState[health] != HealthThresh["ok"] && HealthState[health] >= settings->getHealthAlert() ) ) {
+ QString displayTemp = QString::number(temperature / 10.0);
+ if (QLocale().measurementSystem() == QLocale::ImperialUSSystem)
+ displayTemp = QString::number((temperature / 10) * 1.8 + 32) + " F";
+
+ QString titleArgs;
+ titleArgs = health + " (" + displayTemp + "), " + state; // might show other things in the future
+
+ // show different test depending on severity
+ QString notificationText = "";
+ if (HealthState[health] == HealthThresh["warn"]) {
+ notificationText = settings->getNotificationHealthWarnText();
+ } else if (HealthState[health] == HealthThresh["crit"]) {
+ notificationText = settings->getNotificationHealthCritText();
+ }
+ logD(QString("Notification: %1").arg(settings->getNotificationHealthTitle().arg(titleArgs)));
+ healthNotification->send(settings->getNotificationHealthTitle().arg(titleArgs), notificationText, settings->getHealthAlertFile());
+ if(settings->getHealthNotificationsInterval() == 50) {
+ logD("Stop health timer");
+ healthNotifyTimer->stop();
+ }
+ }
+ else if(HealthState[health] == HealthThresh["ok"] || HealthState[health] < settings->getHealthAlert()) {
+ logD("Close health notification");
+ healthNotification->close();
}
}
@@ -217,6 +312,10 @@ int Battery::getCharge() { return charge; }
QString Battery::getState() { return state; }
+int Battery::getTemperature() { return temperature; }
+
+QString Battery::getHealth() { return health; }
+
bool Battery::getChargingEnabled() { return chargingEnabled; }
bool Battery::setChargingEnabled(const bool isEnabled) {
@@ -253,7 +352,7 @@ bool Battery::getChargerConnected() {
void Battery::shutdown() {
logV("Shutting down...");
- notification->close();
+ chargeNotification->close();
blockSignals(true);
if(updateTimer) {
updateTimer->stop();
@@ -267,6 +366,10 @@ void Battery::shutdown() {
lowNotifyTimer->stop();
logD("Low battery notification stopped");
}
+ if(healthNotifyTimer) {
+ healthNotifyTimer->stop();
+ logD("Health notification stopped");
+ }
// ENABLE/DISABLE CHARGING
if(!setChargingEnabled(true) && !QHostInfo::localHostName().contains("SailfishEmul")) {
logE("ERROR! Could not restore charger status! Your device "
diff --git a/service/src/battery.h b/service/src/battery.h
index 33533c7..cb45d2f 100644
--- a/service/src/battery.h
+++ b/service/src/battery.h
@@ -24,6 +24,7 @@
#include
#include
#include
+#include
#include "settings.h"
#include "mynotification.h"
#include "logger.h"
@@ -44,6 +45,9 @@ public:
bool getChargingEnabled();
bool setChargingEnabled(const bool isEnabled);
+ int getTemperature();
+ QString getHealth();
+
public slots:
void updateData();
void shutdown();
@@ -54,11 +58,16 @@ private:
QFile *chargerConnectedFile = nullptr;
QFile *stateFile = nullptr;
QFile *chargingEnabledFile = nullptr;
+ QFile *temperatureFile = nullptr;
+ QFile *healthFile = nullptr;
Settings *settings = nullptr;
QTimer *updateTimer = nullptr;
QTimer *highNotifyTimer = nullptr;
QTimer *lowNotifyTimer = nullptr;
- MyNotification *notification = nullptr;
+ QTimer *healthNotifyTimer = nullptr;
+ MyNotification *chargeNotification = nullptr;
+ MyNotification *healthNotification = nullptr;
+
// Default values:
int charge = 100; // 100% full
@@ -66,6 +75,9 @@ private:
QString state = "idle"; // dis/charging, idle, unknown
bool chargingEnabled = true; // Only ever disabled manually
+ QString health = "unknown"; // Good, warm, overheat. Might have Cold or Overvoltage depending on driver
+ int temperature = 0x7FFFFFFF; // This value means "unknown" (32-bit INT_MAX)
+
int enableChargingValue = 1;
int disableChargingValue = 0;
bool chargerIsEnabled = true;
@@ -74,6 +86,8 @@ private:
bool nextChargerConnected = chargerConnected;
QString nextState = state;
bool nextChargingEnabled = chargingEnabled;
+ int nextTemperature = temperature;
+ QString nextHealth = health;
QFileDevice::Permissions originalPerms; // Updated in constructor
QFileDevice::Permissions customPerms = static_cast(0x0666);
@@ -83,11 +97,14 @@ signals:
void stateChanged(QString);
void chargingEnabledChanged(bool);
void chargerConnectedChanged(bool);
+ void temperatureChanged(int);
+ void healthChanged(QString);
public slots:
void resetTimers();
void showHighNotification();
void showLowNotification();
+ void showHealthNotification();
};
#endif // BATTERY_H
diff --git a/service/src/settings.cpp b/service/src/settings.cpp
index 6f6d990..ac206c0 100644
--- a/service/src/settings.cpp
+++ b/service/src/settings.cpp
@@ -92,6 +92,9 @@ Settings::Settings(Logger* newLogger, QObject *parent) : QObject(parent)
notificationTitle = "Battery charge %1%";
notificationLowText = "Please connect the charger.";
notificationHighText = "Please disconnect the charger.";
+ notificationHealthTitle = "Battery health %1";
+ notificationHealthWarnText = "Battery health is not good";
+ notificationHealthCritText = "Battery health is critical";
// Do this here, because...
watcher = new QFileSystemWatcher(QStringList(mySettings->fileName()), this);
@@ -129,8 +132,10 @@ void Settings::updateConfig(const QString path) {
loadInteger(sLowAlert, lowAlert, 5, 99);
loadInteger(sHighAlert, highAlert, 6, 100);
+ loadInteger(sHealthAlert, healthAlert, 0, 2);
restartTimers |= loadInteger(sHighNotificationsInterval, highNotificationsInterval, 50, 610);
restartTimers |= loadInteger(sLowNotificationsInterval, lowNotificationsInterval, 50, 610);
+ restartTimers |= loadInteger(sHealthNotificationsInterval, healthNotificationsInterval, 50, 610);
loadInteger(sLimitEnabled, limitEnabled, 0, 1);
loadInteger(sLowLimit, lowLimit, 5, 99);
loadInteger(sHighLimit, highLimit, 6, 100);
@@ -139,6 +144,11 @@ void Settings::updateConfig(const QString path) {
notificationLowText = mySettings->value(sNotificationLowText, notificationLowText).toString();
notificationHighText = mySettings->value(sNotificationHighText, notificationHighText).toString();
+ notificationHealthTitle = mySettings->value(sNotificationHealthTitle, notificationHealthTitle).toString();
+ notificationHealthWarnText = mySettings->value(sNotificationHealthWarnText, notificationHealthWarnText).toString();
+ notificationHealthCritText = mySettings->value(sNotificationHealthCritText, notificationHealthCritText).toString();
+
+
// Update log level
int oldLogLevel = logLevel;
loadInteger(sLogLevel, logLevel, 0, 2);
@@ -168,16 +178,22 @@ void Settings::updateConfig(const QString path) {
}
// Getters condensed
-int Settings::getLowAlert() { return lowAlert; }
-int Settings::getHighAlert() { return highAlert; }
-int Settings::getHighNotificationsInterval() { return highNotificationsInterval; }
-int Settings::getLowNotificationsInterval() { return lowNotificationsInterval; }
-int Settings::getLowLimit() { return lowLimit; }
-int Settings::getHighLimit() { return highLimit; }
-bool Settings::getLimitEnabled() { return limitEnabled == 1; }
-QString Settings::getLowAlertFile() { return lowAlertFile; }
-QString Settings::getHighAlertFile() { return highAlertFile; }
-QString Settings::getNotificationTitle() { return notificationTitle; }
-QString Settings::getNotificationLowText() { return notificationLowText; }
-QString Settings::getNotificationHighText() { return notificationHighText; }
-int Settings::getLogLevel() { return logLevel; }
+int Settings::getLowAlert() { return lowAlert; }
+int Settings::getHighAlert() { return highAlert; }
+int Settings::getHealthAlert() { return healthAlert; }
+int Settings::getHighNotificationsInterval() { return highNotificationsInterval; }
+int Settings::getLowNotificationsInterval() { return lowNotificationsInterval; }
+int Settings::getHealthNotificationsInterval() { return healthNotificationsInterval; }
+int Settings::getLowLimit() { return lowLimit; }
+int Settings::getHighLimit() { return highLimit; }
+bool Settings::getLimitEnabled() { return limitEnabled == 1; }
+QString Settings::getLowAlertFile() { return lowAlertFile; }
+QString Settings::getHighAlertFile() { return highAlertFile; }
+QString Settings::getHealthAlertFile() { return healthAlertFile; }
+QString Settings::getNotificationTitle() { return notificationTitle; }
+QString Settings::getNotificationLowText() { return notificationLowText; }
+QString Settings::getNotificationHighText() { return notificationHighText; }
+QString Settings::getNotificationHealthTitle() { return notificationHealthTitle; }
+QString Settings::getNotificationHealthWarnText() { return notificationHealthWarnText; }
+QString Settings::getNotificationHealthCritText() { return notificationHealthCritText; }
+int Settings::getLogLevel() { return logLevel; }
diff --git a/service/src/settings.h b/service/src/settings.h
index a7e4320..55c39f3 100644
--- a/service/src/settings.h
+++ b/service/src/settings.h
@@ -36,17 +36,24 @@ public:
int getHighAlert();
int getHighNotificationsInterval();
int getLowNotificationsInterval();
+ int getHealthAlert();
+ int getHealthNotificationsInterval();
int getLowLimit();
int getHighLimit();
int getLogLevel();
bool getLimitEnabled();
bool getHighNotificationsEnabled();
bool getLowNotificationsEnabled();
+ bool getHealthNotificationsEnabled();
QString getLowAlertFile();
QString getHighAlertFile();
+ QString getHealthAlertFile();
QString getNotificationTitle();
QString getNotificationLowText();
QString getNotificationHighText();
+ QString getNotificationHealthTitle();
+ QString getNotificationHealthWarnText();
+ QString getNotificationHealthCritText();
private:
Logger* logger;
@@ -63,8 +70,10 @@ private:
// Default values
int lowAlert = 25;
int highAlert = 75;
+ int healthAlert = 1; // 0=off, 1=warn, 2=crit
int highNotificationsInterval = 60;
int lowNotificationsInterval = 60;
+ int healthNotificationsInterval = 60;
// Converted to boolean for QML
int limitEnabled = 1;
@@ -74,23 +83,33 @@ private:
int highLimit = 70;
QString lowAlertFile = "/usr/share/sounds/jolla-ambient/stereo/general_warning.wav";
QString highAlertFile = "/usr/share/sounds/jolla-ambient/stereo/positive_confirmation.wav";
+ QString healthAlertFile = "/usr/share/sounds/jolla-ambient/stereo/battery_low.wav";
QString notificationTitle;
QString notificationLowText;
QString notificationHighText;
+ QString notificationHealthTitle;
+ QString notificationHealthWarnText;
+ QString notificationHealthCritText;
// To avoid repeating the same string over and over and over...
const char* sLowAlert = "lowAlert";
const char* sHighAlert = "highAlert";
+ const char* sHealthAlert = "healthAlert";
const char* sHighNotificationsInterval = "highNotificationsInterval";
const char* sLowNotificationsInterval = "lowNotificationsInterval";
+ const char* sHealthNotificationsInterval = "healthNotificationsInterval";
const char* sLimitEnabled = "limitEnabled";
const char* sLowLimit = "lowLimit";
const char* sHighLimit = "highLimit";
const char* sLowAlertFile = "lowAlertFile";
const char* sHighAlertFile = "highAlertFile";
+ const char* sHealthAlertFile = "healthAlertFile";
const char* sNotificationTitle = "notificationTitle";
const char* sNotificationLowText = "notificationLowText";
const char* sNotificationHighText = "notificationHighText";
+ const char* sNotificationHealthTitle = "notificationHealthTitle";
+ const char* sNotificationHealthWarnText = "notificationHealthWarnText";
+ const char* sNotificationHealthCritText = "notificationHealthCritText";
const char* sLogFilename = "logFilename";
const char* sLogLevel = "logLevel";