Add health and temperature support to service

Preparing and cleaning up for PR:

reword, update German
fix log output units
printf debugging
fix loading config
imperial measurement in notification

for some reason notification does not work on pre-Koli:

  /usr/bin/harbour-batterybuddy-daemon: symbol lookup error: /usr/bin/harbour-batterybuddy-daemon: undefined symbol: _ZN12Notification8setSoundERK7QString
This commit is contained in:
Peter G. (nephros) 2021-05-02 21:14:29 +02:00
parent c9281ccabd
commit 343f0b73c8
7 changed files with 177 additions and 16 deletions

View file

@ -35,6 +35,8 @@ Page {
"good": qsTr("Good", "Battery is OK"), "good": qsTr("Good", "Battery is OK"),
"warm": qsTr("Warm", "Battery is warm"), "warm": qsTr("Warm", "Battery is warm"),
"overheat": qsTr("Overheated", "Battery is very hot"), "overheat": qsTr("Overheated", "Battery is very hot"),
"cool": qsTr("Cool", "Battery is cool"),
"cold": qsTr("Cold", "Battery is very cold"),
} }
property bool serviceRunning: true property bool serviceRunning: true

View file

@ -374,7 +374,7 @@ Page {
color: Theme.highlightColor color: Theme.highlightColor
} }
Label { Label {
text: qsTr("Display visual and audible notifications about battery health, when the battery status exceeds safe values.<br />This usually means high temperature but can be affected by other factors depending on the hardware.") text: qsTr("Display visual and audible notifications when the battery status exceeds safe values.<br />This usually means high (or low) temperature but can include other parameters depending on the hardware.")
anchors { anchors {
left: parent.left left: parent.left
right: parent.right right: parent.right

View file

@ -298,6 +298,16 @@
<source>Temperature:</source> <source>Temperature:</source>
<translation>Temperatur:</translation> <translation>Temperatur:</translation>
</message> </message>
<message>
<source>Cool</source>
<comment>Battery is cool</comment>
<translation>der Batterie ist kalt</translation>
</message>
<message>
<source>Cold</source>
<comment>Battery is very cold</comment>
<translation>der Batterie ist sehr kalt</translation>
</message>
</context> </context>
<context> <context>
<name>Settings</name> <name>Settings</name>
@ -423,7 +433,7 @@
</message> </message>
<message> <message>
<source>Display visual and audible notifications about battery health, when the battery status exceeds safe values.&lt;br /&gt;This usually means high temperature but can be affected by other factors depending on the hardware.</source> <source>Display visual and audible notifications about battery health, when the battery status exceeds safe values.&lt;br /&gt;This usually means high temperature but can be affected by other factors depending on the hardware.</source>
<translation>Visuelle und akustische Benachrichtigungen zum Batteriezustand anzeigen, sobald gewisse Schwellwerte erreicht werden.&lt;br /&gt;Das betrifft meist die Temperatur, kann aber je nach Hardware auch andere Faktoren beinhalten.</translation> <translation type="vanished">Visuelle und akustische Benachrichtigungen zum Batteriezustand anzeigen, sobald gewisse Schwellwerte erreicht werden.&lt;br /&gt;Das betrifft meist die Temperatur, kann aber je nach Hardware auch andere Faktoren beinhalten.</translation>
</message> </message>
<message> <message>
<source>Health notification</source> <source>Health notification</source>
@ -437,5 +447,9 @@
<source>Health notification interval</source> <source>Health notification interval</source>
<translation>Zustandsbenachrichtigungsintervall</translation> <translation>Zustandsbenachrichtigungsintervall</translation>
</message> </message>
<message>
<source>Display visual and audible notifications when the battery status exceeds safe values.&lt;br /&gt;This usually means high (or low) temperature but can include other parameters depending on the hardware.</source>
<translation type="vanished">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.</translation>
</message>
</context> </context>
</TS> </TS>

View file

@ -33,6 +33,7 @@ Battery::Battery(Logger* newLogger, bool loglevelSet, QObject *parent) : QObject
updateTimer = new QTimer(this); updateTimer = new QTimer(this);
highNotifyTimer = new QTimer(this); highNotifyTimer = new QTimer(this);
lowNotifyTimer = new QTimer(this); lowNotifyTimer = new QTimer(this);
healthNotifyTimer = new QTimer(this);
notification = new MyNotification(this); notification = new MyNotification(this);
// Number: charge percentage, e.g. 42 // Number: charge percentage, e.g. 42
@ -47,6 +48,14 @@ Battery::Battery(Logger* newLogger, bool loglevelSet, QObject *parent) : QObject
chargerConnectedFile = new QFile("/sys/class/power_supply/usb/present", this); chargerConnectedFile = new QFile("/sys/class/power_supply/usb/present", this);
logE("Charger status file: " + chargerConnectedFile->fileName()); logE("Charger status file: " + chargerConnectedFile->fileName());
// Number: temperature
temperatureFile = new QFile("/sys/class/power_supply/battery/temp", this);
logE("Temperature file: " + temperatureFile->fileName());
// String: Good, Warm, Overheat, (others?)
healthFile = new QFile("/sys/class/power_supply/battery/health", this);
logE("Health state file: " + healthFile->fileName());
// ENABLE/DISABLE CHARGING // ENABLE/DISABLE CHARGING
QString filename; QString filename;
@ -97,6 +106,7 @@ Battery::Battery(Logger* newLogger, bool loglevelSet, QObject *parent) : QObject
connect(settings, SIGNAL(resetTimers()), this, SLOT(resetTimers())); connect(settings, SIGNAL(resetTimers()), this, SLOT(resetTimers()));
connect(highNotifyTimer, SIGNAL(timeout()), this, SLOT(showHighNotification())); connect(highNotifyTimer, SIGNAL(timeout()), this, SLOT(showHighNotification()));
connect(lowNotifyTimer, SIGNAL(timeout()), this, SLOT(showLowNotification())); connect(lowNotifyTimer, SIGNAL(timeout()), this, SLOT(showLowNotification()));
connect(healthNotifyTimer, SIGNAL(timeout()), this, SLOT(showHealthNotification()));
updateData(); updateData();
updateTimer->start(5000); updateTimer->start(5000);
@ -105,7 +115,7 @@ Battery::Battery(Logger* newLogger, bool loglevelSet, QObject *parent) : QObject
// aka. "charging" status didn't change // aka. "charging" status didn't change
// (or if both times are disabled, actually) // (or if both times are disabled, actually)
// manually trigger the timer startup. // manually trigger the timer startup.
if(!highNotifyTimer->isActive() && !lowNotifyTimer->isActive()) { if(!highNotifyTimer->isActive() && !lowNotifyTimer->isActive() && !healthNotifyTimer->isActive()) {
resetTimers(); resetTimers();
} }
} }
@ -145,6 +155,28 @@ void Battery::updateData()
stateFile->close(); stateFile->close();
} }
if(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->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(chargingEnabledFile && settings->getLimitEnabled()) {
if(chargingEnabled && charge >= settings->getHighLimit()) { if(chargingEnabled && charge >= settings->getHighLimit()) {
logD("Disabling charging..."); logD("Disabling charging...");
@ -160,8 +192,10 @@ void Battery::updateData()
void Battery::resetTimers() { void Battery::resetTimers() {
highNotifyTimer->stop(); highNotifyTimer->stop();
lowNotifyTimer->stop(); lowNotifyTimer->stop();
healthNotifyTimer->stop();
highNotifyTimer->setInterval(settings->getHighNotificationsInterval() * 1000); highNotifyTimer->setInterval(settings->getHighNotificationsInterval() * 1000);
lowNotifyTimer->setInterval(settings->getLowNotificationsInterval() * 1000); lowNotifyTimer->setInterval(settings->getLowNotificationsInterval() * 1000);
healthNotifyTimer->setInterval(settings->getHealthNotificationsInterval() * 1000);
if(settings->getHighNotificationsInterval() < 610) { if(settings->getHighNotificationsInterval() < 610) {
logD("Starting high battery timer"); logD("Starting high battery timer");
@ -180,6 +214,15 @@ void Battery::resetTimers() {
else { else {
logD("Low battery timer not started"); 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() { void Battery::showHighNotification() {
@ -213,10 +256,58 @@ void Battery::showLowNotification() {
} }
} }
void Battery::showHealthNotification() {
// set up alert categories
// TODO: manage this more globally, use better data types(?), align with QML/Settings part
static const QMap<QString, int> HealthThresh {
{ "ok" , 0},
{ "warn" , 1},
{ "crit" , 2},
};
// map string values from sysfs file to alert category
static const QMap<QString, int> HealthState {
{ "good" , HealthThresh["ok"] },
{ "warm" , HealthThresh["warn"] },
{ "cool" , HealthThresh["warn"] },
{ "overheat" , HealthThresh["crit"] },
{ "cold" , HealthThresh["crit"] }
};
if(settings->getHealthNotificationsInterval() < 610 && ( 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)));
notification->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");
notification->close();
}
}
int Battery::getCharge() { return charge; } int Battery::getCharge() { return charge; }
QString Battery::getState() { return state; } QString Battery::getState() { return state; }
int Battery::getTemperature() { return temperature; }
QString Battery::getHealth() { return health; }
bool Battery::getChargingEnabled() { return chargingEnabled; } bool Battery::getChargingEnabled() { return chargingEnabled; }
bool Battery::setChargingEnabled(const bool isEnabled) { bool Battery::setChargingEnabled(const bool isEnabled) {
@ -267,6 +358,10 @@ void Battery::shutdown() {
lowNotifyTimer->stop(); lowNotifyTimer->stop();
logD("Low battery notification stopped"); logD("Low battery notification stopped");
} }
if(healthNotifyTimer) {
healthNotifyTimer->stop();
logD("Health notification stopped");
}
// ENABLE/DISABLE CHARGING // ENABLE/DISABLE CHARGING
if(!setChargingEnabled(true) && !QHostInfo::localHostName().contains("SailfishEmul")) { if(!setChargingEnabled(true) && !QHostInfo::localHostName().contains("SailfishEmul")) {
logE("ERROR! Could not restore charger status! Your device " logE("ERROR! Could not restore charger status! Your device "

View file

@ -24,6 +24,7 @@
#include <QFile> #include <QFile>
#include <QStandardPaths> #include <QStandardPaths>
#include <QHostInfo> #include <QHostInfo>
#include <QLocale>
#include "settings.h" #include "settings.h"
#include "mynotification.h" #include "mynotification.h"
#include "logger.h" #include "logger.h"
@ -44,6 +45,9 @@ public:
bool getChargingEnabled(); bool getChargingEnabled();
bool setChargingEnabled(const bool isEnabled); bool setChargingEnabled(const bool isEnabled);
int getTemperature();
QString getHealth();
public slots: public slots:
void updateData(); void updateData();
void shutdown(); void shutdown();
@ -54,17 +58,23 @@ private:
QFile *chargerConnectedFile = nullptr; QFile *chargerConnectedFile = nullptr;
QFile *stateFile = nullptr; QFile *stateFile = nullptr;
QFile *chargingEnabledFile = nullptr; QFile *chargingEnabledFile = nullptr;
QFile *temperatureFile = nullptr;
QFile *healthFile = nullptr;
Settings *settings = nullptr; Settings *settings = nullptr;
QTimer *updateTimer = nullptr; QTimer *updateTimer = nullptr;
QTimer *highNotifyTimer = nullptr; QTimer *highNotifyTimer = nullptr;
QTimer *lowNotifyTimer = nullptr; QTimer *lowNotifyTimer = nullptr;
QTimer *healthNotifyTimer = nullptr;
MyNotification *notification = nullptr; MyNotification *notification = nullptr;
// Default values: // Default values:
int charge = 100; // 100% full int charge = 100; // 100% full
bool chargerConnected = false; // Charger plugged in bool chargerConnected = false; // Charger plugged in
QString state = "idle"; // dis/charging, idle, unknown QString state = "idle"; // dis/charging, idle, unknown
bool chargingEnabled = true; // Only ever disabled manually bool chargingEnabled = true; // Only ever disabled manually
int temperature = 0; // freezing
QString health = "Good"; // good, warm, overheat, possibly more
int enableChargingValue = 1; int enableChargingValue = 1;
int disableChargingValue = 0; int disableChargingValue = 0;
@ -74,6 +84,8 @@ private:
bool nextChargerConnected = chargerConnected; bool nextChargerConnected = chargerConnected;
QString nextState = state; QString nextState = state;
bool nextChargingEnabled = chargingEnabled; bool nextChargingEnabled = chargingEnabled;
int nextTemperature = temperature;
QString nextHealth = health;
QFileDevice::Permissions originalPerms; // Updated in constructor QFileDevice::Permissions originalPerms; // Updated in constructor
QFileDevice::Permissions customPerms = static_cast<QFileDevice::Permissions>(0x0666); QFileDevice::Permissions customPerms = static_cast<QFileDevice::Permissions>(0x0666);
@ -83,11 +95,14 @@ signals:
void stateChanged(QString); void stateChanged(QString);
void chargingEnabledChanged(bool); void chargingEnabledChanged(bool);
void chargerConnectedChanged(bool); void chargerConnectedChanged(bool);
void temperatureChanged(int);
void healthChanged(QString);
public slots: public slots:
void resetTimers(); void resetTimers();
void showHighNotification(); void showHighNotification();
void showLowNotification(); void showLowNotification();
void showHealthNotification();
}; };
#endif // BATTERY_H #endif // BATTERY_H

View file

@ -92,6 +92,9 @@ Settings::Settings(Logger* newLogger, QObject *parent) : QObject(parent)
notificationTitle = "Battery charge %1%"; notificationTitle = "Battery charge %1%";
notificationLowText = "Please connect the charger."; notificationLowText = "Please connect the charger.";
notificationHighText = "Please disconnect 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... // Do this here, because...
watcher = new QFileSystemWatcher(QStringList(mySettings->fileName()), this); watcher = new QFileSystemWatcher(QStringList(mySettings->fileName()), this);
@ -129,8 +132,10 @@ void Settings::updateConfig(const QString path) {
loadInteger(sLowAlert, lowAlert, 5, 99); loadInteger(sLowAlert, lowAlert, 5, 99);
loadInteger(sHighAlert, highAlert, 6, 100); loadInteger(sHighAlert, highAlert, 6, 100);
loadInteger(sHealthAlert, healthAlert, 0, 2);
restartTimers |= loadInteger(sHighNotificationsInterval, highNotificationsInterval, 50, 610); restartTimers |= loadInteger(sHighNotificationsInterval, highNotificationsInterval, 50, 610);
restartTimers |= loadInteger(sLowNotificationsInterval, lowNotificationsInterval, 50, 610); restartTimers |= loadInteger(sLowNotificationsInterval, lowNotificationsInterval, 50, 610);
restartTimers |= loadInteger(sHealthNotificationsInterval, healthNotificationsInterval, 50, 610);
loadInteger(sLimitEnabled, limitEnabled, 0, 1); loadInteger(sLimitEnabled, limitEnabled, 0, 1);
loadInteger(sLowLimit, lowLimit, 5, 99); loadInteger(sLowLimit, lowLimit, 5, 99);
loadInteger(sHighLimit, highLimit, 6, 100); loadInteger(sHighLimit, highLimit, 6, 100);
@ -139,6 +144,11 @@ void Settings::updateConfig(const QString path) {
notificationLowText = mySettings->value(sNotificationLowText, notificationLowText).toString(); notificationLowText = mySettings->value(sNotificationLowText, notificationLowText).toString();
notificationHighText = mySettings->value(sNotificationHighText, notificationHighText).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 // Update log level
int oldLogLevel = logLevel; int oldLogLevel = logLevel;
loadInteger(sLogLevel, logLevel, 0, 2); loadInteger(sLogLevel, logLevel, 0, 2);
@ -168,16 +178,22 @@ void Settings::updateConfig(const QString path) {
} }
// Getters condensed // Getters condensed
int Settings::getLowAlert() { return lowAlert; } int Settings::getLowAlert() { return lowAlert; }
int Settings::getHighAlert() { return highAlert; } int Settings::getHighAlert() { return highAlert; }
int Settings::getHighNotificationsInterval() { return highNotificationsInterval; } int Settings::getHealthAlert() { return healthAlert; }
int Settings::getLowNotificationsInterval() { return lowNotificationsInterval; } int Settings::getHighNotificationsInterval() { return highNotificationsInterval; }
int Settings::getLowLimit() { return lowLimit; } int Settings::getLowNotificationsInterval() { return lowNotificationsInterval; }
int Settings::getHighLimit() { return highLimit; } int Settings::getHealthNotificationsInterval() { return healthNotificationsInterval; }
bool Settings::getLimitEnabled() { return limitEnabled == 1; } int Settings::getLowLimit() { return lowLimit; }
QString Settings::getLowAlertFile() { return lowAlertFile; } int Settings::getHighLimit() { return highLimit; }
QString Settings::getHighAlertFile() { return highAlertFile; } bool Settings::getLimitEnabled() { return limitEnabled == 1; }
QString Settings::getNotificationTitle() { return notificationTitle; } QString Settings::getLowAlertFile() { return lowAlertFile; }
QString Settings::getNotificationLowText() { return notificationLowText; } QString Settings::getHighAlertFile() { return highAlertFile; }
QString Settings::getNotificationHighText() { return notificationHighText; } QString Settings::getHealthAlertFile() { return healthAlertFile; }
int Settings::getLogLevel() { return logLevel; } 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; }

View file

@ -36,17 +36,24 @@ public:
int getHighAlert(); int getHighAlert();
int getHighNotificationsInterval(); int getHighNotificationsInterval();
int getLowNotificationsInterval(); int getLowNotificationsInterval();
int getHealthAlert();
int getHealthNotificationsInterval();
int getLowLimit(); int getLowLimit();
int getHighLimit(); int getHighLimit();
int getLogLevel(); int getLogLevel();
bool getLimitEnabled(); bool getLimitEnabled();
bool getHighNotificationsEnabled(); bool getHighNotificationsEnabled();
bool getLowNotificationsEnabled(); bool getLowNotificationsEnabled();
bool getHealthNotificationsEnabled();
QString getLowAlertFile(); QString getLowAlertFile();
QString getHighAlertFile(); QString getHighAlertFile();
QString getHealthAlertFile();
QString getNotificationTitle(); QString getNotificationTitle();
QString getNotificationLowText(); QString getNotificationLowText();
QString getNotificationHighText(); QString getNotificationHighText();
QString getNotificationHealthTitle();
QString getNotificationHealthWarnText();
QString getNotificationHealthCritText();
private: private:
Logger* logger; Logger* logger;
@ -63,8 +70,10 @@ private:
// Default values // Default values
int lowAlert = 25; int lowAlert = 25;
int highAlert = 75; int highAlert = 75;
int healthAlert = 1; // 0=off, 1=warn, 2=crit
int highNotificationsInterval = 60; int highNotificationsInterval = 60;
int lowNotificationsInterval = 60; int lowNotificationsInterval = 60;
int healthNotificationsInterval = 60;
// Converted to boolean for QML // Converted to boolean for QML
int limitEnabled = 1; int limitEnabled = 1;
@ -74,23 +83,33 @@ private:
int highLimit = 70; int highLimit = 70;
QString lowAlertFile = "/usr/share/sounds/jolla-ambient/stereo/general_warning.wav"; QString lowAlertFile = "/usr/share/sounds/jolla-ambient/stereo/general_warning.wav";
QString highAlertFile = "/usr/share/sounds/jolla-ambient/stereo/positive_confirmation.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 notificationTitle;
QString notificationLowText; QString notificationLowText;
QString notificationHighText; QString notificationHighText;
QString notificationHealthTitle;
QString notificationHealthWarnText;
QString notificationHealthCritText;
// To avoid repeating the same string over and over and over... // To avoid repeating the same string over and over and over...
const char* sLowAlert = "lowAlert"; const char* sLowAlert = "lowAlert";
const char* sHighAlert = "highAlert"; const char* sHighAlert = "highAlert";
const char* sHealthAlert = "healthAlert";
const char* sHighNotificationsInterval = "highNotificationsInterval"; const char* sHighNotificationsInterval = "highNotificationsInterval";
const char* sLowNotificationsInterval = "lowNotificationsInterval"; const char* sLowNotificationsInterval = "lowNotificationsInterval";
const char* sHealthNotificationsInterval = "healthNotificationsInterval";
const char* sLimitEnabled = "limitEnabled"; const char* sLimitEnabled = "limitEnabled";
const char* sLowLimit = "lowLimit"; const char* sLowLimit = "lowLimit";
const char* sHighLimit = "highLimit"; const char* sHighLimit = "highLimit";
const char* sLowAlertFile = "lowAlertFile"; const char* sLowAlertFile = "lowAlertFile";
const char* sHighAlertFile = "highAlertFile"; const char* sHighAlertFile = "highAlertFile";
const char* sHealthAlertFile = "healthAlertFile";
const char* sNotificationTitle = "notificationTitle"; const char* sNotificationTitle = "notificationTitle";
const char* sNotificationLowText = "notificationLowText"; const char* sNotificationLowText = "notificationLowText";
const char* sNotificationHighText = "notificationHighText"; const char* sNotificationHighText = "notificationHighText";
const char* sNotificationHealthTitle = "notificationHealthTitle";
const char* sNotificationHealthWarnText = "notificationHealthWarnText";
const char* sNotificationHealthCritText = "notificationHealthCritText";
const char* sLogFilename = "logFilename"; const char* sLogFilename = "logFilename";
const char* sLogLevel = "logLevel"; const char* sLogLevel = "logLevel";