Implement max charge current setting

This commit is contained in:
Matti Viljanen 2022-12-31 23:46:23 +02:00
parent ebd1e64ef7
commit 7042751703
No known key found for this signature in database
GPG key ID: CF32A1495158F888
11 changed files with 125 additions and 5 deletions

View file

@ -44,6 +44,7 @@ Page {
running: true
onTriggered: {
autoStopCharging.checked = settings.limitEnabled
maxChargeCurrentSlider.value = settings.maxChargeCurrent
highLimitSlider.value = settings.highLimit
lowLimitSlider.value = settings.lowLimit
highAlertSlider.value = settings.highAlert
@ -181,6 +182,24 @@ Page {
smallChange: 1
largeChange: 5
}
SectionHeader {
text: qsTr("Maximum Charge Current")
visible: settings.maxSupportedChargeCurrent > 0
}
MySlider {
id: maxChargeCurrentSlider
visible: settings.maxSupportedChargeCurrent > 0
minimumValue: 500000
maximumValue: settings.maxSupportedChargeCurrent
stepSize: 100000
valueText: (value / 1000) + "mA"
onReleased: save()
function save() {
settings.maxChargeCurrent = value
}
}
}
//////////////////////////////////////////////////

View file

@ -18,6 +18,7 @@
chmod 644 /sys/class/power_supply/battery/input_suspend 2>/dev/null
chmod 644 /sys/class/power_supply/battery/charging_enabled 2>/dev/null
chmod 644 /sys/class/power_supply/battery/constant_charge_current_max 2>/dev/null
chmod 644 /sys/class/power_supply/usb/charger_disable 2>/dev/null
chmod 644 /sys/class/power_supply/dollar_cove_battery/enable_charging 2>/dev/null
exit 0

View file

@ -18,6 +18,7 @@
chmod 666 /sys/class/power_supply/battery/input_suspend 2>/dev/null
chmod 666 /sys/class/power_supply/battery/charging_enabled 2>/dev/null
chmod 666 /sys/class/power_supply/battery/constant_charge_current_max 2>/dev/null
chmod 666 /sys/class/power_supply/usb/charger_disable 2>/dev/null
chmod 666 /sys/class/power_supply/dollar_cove_battery/enable_charging 2>/dev/null
exit 0

View file

@ -225,6 +225,8 @@ int Battery::getCharge(){ return charge; }
int Battery::getCurrent(){ return current; }
int Battery::getMaxChargeCurrent() { return maxChargeCurrent; }
QString Battery::getState() { return state; }
QString Battery::getHealth() { return health; }

View file

@ -31,6 +31,7 @@ class Battery : public QObject
Q_OBJECT
Q_PROPERTY(int charge READ getCharge NOTIFY chargeChanged)
Q_PROPERTY(int current READ getCurrent NOTIFY currentChanged)
Q_PROPERTY(int maxChargeCurrent READ getMaxChargeCurrent)
Q_PROPERTY(bool chargerConnected READ getChargerConnected NOTIFY chargerConnectedChanged)
Q_PROPERTY(QString state READ getState NOTIFY stateChanged)
Q_PROPERTY(bool chargingEnabled READ getChargingEnabled NOTIFY chargingEnabledChanged)
@ -44,6 +45,7 @@ public:
int getCharge();
int getCurrent();
int getMaxChargeCurrent();
bool getCharging();
bool getChargerConnected();
QString getState();
@ -62,6 +64,7 @@ private:
QFile* chargerConnectedFile = nullptr;
QFile* stateFile = nullptr;
QFile* chargingEnabledFile = nullptr;
QFile* maxChargeCurrentFile = nullptr;
Settings* settings = nullptr;
Logger* logger = nullptr;
@ -74,6 +77,7 @@ private:
bool chargerConnected = false; // Charger plugged in
QString state = "idle"; // dis/charging, idle, unknown
bool chargingEnabled = true; // Only ever disabled manually
int maxChargeCurrent = 0; // Charge current limit in micro amps
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)

View file

@ -38,6 +38,8 @@ Settings::Settings(Logger *newLogger, QObject *parent) : QObject(parent)
loadInteger(sLimitEnabled, limitEnabled, 0, 1);
loadInteger(sLowLimit, lowLimit, 5, 99);
loadInteger(sHighLimit, highLimit, 6, 100);
loadInteger(sMaxSupportedChargeCurrent, maxSupportedChargeCurrent, 0, 5000000);
loadInteger(sMaxChargeCurrent, maxChargeCurrent, 0, maxSupportedChargeCurrent);
loadInteger(sLogLevel, logLevel, 0, 2);
loadString(sLogFilename, logFilename);
@ -72,6 +74,8 @@ int Settings::getLowNotificationsInterval() { return lowNotificationsInte
int Settings::getHealthNotificationsInterval() { return healthNotificationsInterval; }
int Settings::getLowLimit() { return lowLimit; }
int Settings::getHighLimit() { return highLimit; }
int Settings::getMaxChargeCurrent() { return maxChargeCurrent; }
int Settings::getMaxSupportedChargeCurrent() { return maxSupportedChargeCurrent; }
bool Settings::getLimitEnabled() { return limitEnabled == 1; }
QString Settings::getLowAlertFile() { return lowAlertFile; }
QString Settings::getHighAlertFile() { return highAlertFile; }
@ -132,6 +136,11 @@ void Settings::setHighLimit(const int newLimit) {
emit highLimitChanged(highLimit);
}
void Settings::setMaxChargeCurrent(const int newCurrent) {
if(saveInteger(sMaxChargeCurrent, newCurrent, maxChargeCurrent))
emit maxChargeCurrentChanged(maxChargeCurrent);
}
void Settings::setLimitEnabled(const bool newEnabled) {
if(saveInteger(sLimitEnabled, (newEnabled ? 1 : 0), limitEnabled))
emit limitEnabledChanged(limitEnabled);

View file

@ -33,6 +33,8 @@ class Settings : public QObject
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(int maxChargeCurrent READ getMaxChargeCurrent WRITE setMaxChargeCurrent NOTIFY maxChargeCurrentChanged)
Q_PROPERTY(int maxSupportedChargeCurrent READ getMaxSupportedChargeCurrent NOTIFY maxSupportedChargeCurrentChanged)
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)
@ -58,6 +60,8 @@ public:
int getHealthNotificationsInterval();
int getLowLimit();
int getHighLimit();
int getMaxChargeCurrent();
int getMaxSupportedChargeCurrent();
bool getLimitEnabled();
QString getLowAlertFile();
QString getHighAlertFile();
@ -79,6 +83,7 @@ public:
void setHealthNotificationsInterval(const int newInterval);
void setLowLimit(const int newLimit);
void setHighLimit(const int newLimit);
void setMaxChargeCurrent(const int newCurrent);
void setLimitEnabled(const bool newEnabled);
void setNotificationTitle(const QString newText);
void setNotificationLowText(const QString newText);
@ -103,6 +108,8 @@ private:
int limitEnabled = 1; // Converted to boolean for QML
int lowLimit = 65;
int highLimit = 70;
int maxChargeCurrent = 0; // micro amps
int maxSupportedChargeCurrent = 0; // micro amps
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;
@ -125,6 +132,8 @@ private:
const char* sLimitEnabled = "limitEnabled";
const char* sLowLimit = "lowLimit";
const char* sHighLimit = "highLimit";
const char* sMaxSupportedChargeCurrent = "maxSupportedChargeCurrent";
const char* sMaxChargeCurrent = "maxChargeCurrent";
const char* sLowAlertFile = "lowAlertFile";
const char* sHighAlertFile = "highAlertFile";
const char* sHealthAlertFile = "healthAlertFile";
@ -153,6 +162,8 @@ signals:
void limitEnabledChanged(bool);
void lowLimitChanged(int);
void highLimitChanged(int);
void maxChargeCurrentChanged(int);
void maxSupportedChargeCurrentChanged(int);
void lowAlertFileChanged(QString);
void highAlertFileChanged(QString);
void healthAlertFileChanged(QString);

View file

@ -63,6 +63,38 @@ Battery::Battery(Logger* newLogger, bool loglevelSet, QCoreApplication *app, QOb
if(currentFile) logL("Charging/discharging current file: " + currentFile->fileName());
else logL("Charging/discharging current file: not found!");
// Maximum charge current in microamps, e.g. 3500000 (3500mA)
filenames.clear();
filenames << "/sys/class/power_supply/battery/constant_charge_current_max";
foreach(const QString& file, filenames) {
if(!maxChargeCurrentFile && QFile::exists(file)) {
maxChargeCurrentFile = new QFile(file, this);
break;
}
}
if(maxChargeCurrentFile) {
logL("Max charge current file: " + maxChargeCurrentFile->fileName());
if(maxChargeCurrentFile->open(QIODevice::WriteOnly)) {
maxChargeCurrentFile->close();
if(maxChargeCurrentFile->open(QIODevice::ReadOnly)) {
maxSupportedChargeCurrent = maxChargeCurrentFile->readLine().trimmed().toInt();
logL(QString("Maximum supported charge current: %1mA").arg(maxSupportedChargeCurrent / 1000));
maxChargeCurrentFile->close();
}
}
else {
logL("Max charge current file is not writable - feature disabled");
delete maxChargeCurrentFile;
maxChargeCurrentFile = Q_NULLPTR;
}
}
else {
logL("Max charge current file: not found!");
}
settings->setMaxSupportedChargeCurrent(maxSupportedChargeCurrent);
// Battery/charging status: charging, discharging, full, empty, unknown (others?)
filenames.clear();
filenames << "/sys/class/power_supply/battery/status"
@ -161,6 +193,7 @@ Battery::Battery(Logger* newLogger, bool loglevelSet, QCoreApplication *app, QOb
else logL("Charger control file: not found!");
connect(settings, SIGNAL(resetTimers()), this, SLOT(resetTimers()));
connect(settings, SIGNAL(setMaxChargeCurrent(int)), this, SLOT(setMaxChargeCurrent(int)));
updateTimer = new BackgroundActivity(app);
highNotifyTimer = new BackgroundActivity(app);
@ -192,6 +225,8 @@ Battery::Battery(Logger* newLogger, bool loglevelSet, QCoreApplication *app, QOb
}
Battery::~Battery() {
this->setMaxChargeCurrent(maxSupportedChargeCurrent);
updateTimer->stop();
highNotifyTimer->stop();
lowNotifyTimer->stop();
@ -447,6 +482,25 @@ bool Battery::setChargingEnabled(const bool isEnabled) {
return success;
}
void Battery::setMaxChargeCurrent(int newCurrent) {
if(maxChargeCurrentFile) {
logM(QString("Setting max charging current to %1...").arg(newCurrent / 1000));
if(newCurrent > maxSupportedChargeCurrent) {
newCurrent = maxSupportedChargeCurrent;
}
if(maxChargeCurrentFile->open(QIODevice::WriteOnly)) {
QString data = QString("%1").arg(newCurrent);
if(!maxChargeCurrentFile->write(data.toLocal8Bit())) {
logM("Could not write to max charging current file");
}
}
else {
logM("Could not open max charging current file");
}
maxChargeCurrentFile->close();
}
}
bool Battery::getChargerConnected() {
return chargerConnected;
}

View file

@ -81,6 +81,7 @@ private:
QFile *currentFile = nullptr;
QFile *stateFile = nullptr;
QFile *chargingEnabledFile = nullptr;
QFile *maxChargeCurrentFile = nullptr;
QFile *temperatureFile = nullptr;
QFile *healthFile = nullptr;
Settings *settings = nullptr;
@ -98,6 +99,8 @@ private:
bool chargerConnected = false; // Charger plugged in
QString state = "idle"; // dis/charging, idle, unknown
bool chargingEnabled = true; // Only ever disabled manually
int maxChargeCurrent = 0;
int maxSupportedChargeCurrent = 0;
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)
@ -124,6 +127,7 @@ public slots:
void showHighNotification();
void showLowNotification();
void showHealthNotification();
void setMaxChargeCurrent(int newCurrent);
};
#endif // BATTERY_H

View file

@ -96,11 +96,12 @@ Settings::Settings(Logger* newLogger, QObject *parent) : QObject(parent)
notificationHealthWarnText = "Battery health is not good";
notificationHealthCritText = "Battery health is critical";
// Do this here, because...
watcher = new QFileSystemWatcher(QStringList(mySettings->fileName()), this);
connect(watcher, SIGNAL(fileChanged(QString)), this, SLOT(updateConfig(QString)));
// ...calling this deletes mySettings!
// To trigger setting the initial config value
maxChargeCurrent = 0;
updateConfig(mySettings->fileName());
}
@ -123,6 +124,8 @@ void Settings::updateConfig(const QString path) {
// Use the same file location as GUI for data exchange
if(!mySettings) {
mySettings = new QSettings(appName, appName, this);
} else {
mySettings->sync();
}
logH("Updating configuration...");
@ -139,6 +142,9 @@ void Settings::updateConfig(const QString path) {
loadInteger(sLimitEnabled, limitEnabled, 0, 1);
loadInteger(sLowLimit, lowLimit, 5, 99);
loadInteger(sHighLimit, highLimit, 6, 100);
if(loadInteger(sMaxChargeCurrent, maxChargeCurrent, 0, 5000000)) {
emit setMaxChargeCurrent(maxChargeCurrent);
}
notificationTitle = mySettings->value(sNotificationTitle, notificationTitle).toString();
notificationLowText = mySettings->value(sNotificationLowText, notificationLowText).toString();
@ -158,9 +164,6 @@ void Settings::updateConfig(const QString path) {
logL(QString("Log level set to %1").arg((logLevel == 0 ? "low" : (logLevel == 1 ? "medium" : "high"))));
}
delete mySettings;
mySettings = nullptr;
// Let the file system settle...
QThread::msleep(100);
@ -180,6 +183,7 @@ void Settings::updateConfig(const QString path) {
// Getters condensed
int Settings::getLowAlert() { return lowAlert; }
int Settings::getHighAlert() { return highAlert; }
int Settings::getMaxChargeCurrent() { return maxChargeCurrent; }
int Settings::getHealthAlert() { return healthAlert; }
int Settings::getHighNotificationsInterval() { return highNotificationsInterval; }
int Settings::getLowNotificationsInterval() { return lowNotificationsInterval; }
@ -197,3 +201,7 @@ QString Settings::getNotificationHealthTitle() { return notificationHealthTi
QString Settings::getNotificationHealthWarnText() { return notificationHealthWarnText; }
QString Settings::getNotificationHealthCritText() { return notificationHealthCritText; }
int Settings::getLogLevel() { return logLevel; }
void Settings::setMaxSupportedChargeCurrent(int newCurrent) {
mySettings->setValue(sMaxSupportedChargeCurrent, QByteArray::number(newCurrent));
}

View file

@ -34,6 +34,7 @@ public:
int getLowAlert();
int getHighAlert();
int getMaxChargeCurrent();
int getHighNotificationsInterval();
int getLowNotificationsInterval();
int getHealthAlert();
@ -55,6 +56,8 @@ public:
QString getNotificationHealthWarnText();
QString getNotificationHealthCritText();
void setMaxSupportedChargeCurrent(int newCurrent);
private:
Logger* logger;
QSettings* mySettings = nullptr;
@ -70,6 +73,7 @@ private:
// Default values
int lowAlert = 25;
int highAlert = 75;
int maxChargeCurrent = 0;
int healthAlert = 1; // 0=off, 1=warn, 2=crit
int highNotificationsInterval = 60;
int lowNotificationsInterval = 60;
@ -101,6 +105,8 @@ private:
const char* sLimitEnabled = "limitEnabled";
const char* sLowLimit = "lowLimit";
const char* sHighLimit = "highLimit";
const char* sMaxChargeCurrent = "maxChargeCurrent";
const char* sMaxSupportedChargeCurrent = "maxSupportedChargeCurrent";
const char* sLowAlertFile = "lowAlertFile";
const char* sHighAlertFile = "highAlertFile";
const char* sHealthAlertFile = "healthAlertFile";
@ -120,6 +126,7 @@ private slots:
signals:
void resetTimers();
void setMaxChargeCurrent(int newCurrent);
};
#endif // SETTINGS_H