Implement charger control and charger plugged in boolean

This commit is contained in:
Matti Viljanen 2020-03-20 17:26:29 +02:00
parent b429c474c6
commit c67a33a4b7
No known key found for this signature in database
GPG key ID: CF32A1495158F888
9 changed files with 302 additions and 91 deletions

1
.gitignore vendored
View file

@ -1,5 +1,6 @@
*.old
*.bak
*.tmp
*.pro.user
*.pro.user.*
*.qm

View file

@ -22,7 +22,7 @@ Item {
id: batteryGraph
property real borderSize: width * 0.15
property real charge: battery.charge
property bool charging: battery.charging
property bool chargerConnected: battery.chargerConnected
height: 1.75 * width
Rectangle {

View file

@ -22,27 +22,33 @@ import "../components"
CoverBackground {
id: coverPage
onStatusChanged: batteryGraph.updateView()
BatteryGraph {
id: batteryGraph
x: coverPage.width * 0.3
y: coverPage.width * 0.25
width: 0.4 * coverPage.width
onStateChanged: { updateView() }
onChargingChanged: { updateView() }
onChargeChanged: { updateView() }
Component.onCompleted: updateView()
onStateChanged: updateView()
onChargerConnectedChanged: updateView()
onChargeChanged: updateView()
function updateView() {
if(charge <= settings.lowerLimit && battery.state === "discharging") {
coverText.text = qsTr("Connect\ncharger")
}
else if(battery.charge >= settings.upperLimit &&
((battery.state === "charging" && battery.charging === true) || (battery.state === "idle" && battery.charging === false))) {
(battery.state === "charging" || battery.state === "idle")) {
coverText.text = qsTr("Disconnect\ncharger")
}
else if(battery.charging) {
coverText.text = qsTr("Charging...")
else if(battery.chargerConnected && battery.state === "charging") {
coverText.text = qsTr("Charging")
}
else {
else if(battery.chargerConnected && battery.state === "discharging") {
coverText.text = qsTr("Not charging")
}
else { // Discharging
coverText.text = qsTr("Battery\nBuddy")
}
}

View file

@ -94,8 +94,8 @@ Page {
value: battery.charge + "%"
}
MyDetailItem {
label: qsTr("Charging:")
value: battery.charging ? qsTr("yes") : qsTr("no")
label: qsTr("Charger connected:")
value: battery.chargerConnected ? qsTr("yes") : qsTr("no")
}
MyDetailItem {
label: qsTr("State:")

View file

@ -20,61 +20,171 @@ import Sailfish.Silica 1.0
Page {
id: settingsPage
anchors.fill: parent
PageHeader {
id: header
title: qsTr("Settings")
}
SilicaFlickable {
anchors.fill: parent
contentHeight: header.height + settingsColumn.height + Theme.horizontalPageMargin
Column {
anchors.top: header.bottom
width: parent.width
spacing: Theme.paddingMedium
PageHeader {
id: header
title: qsTr("Settings")
}
Label {
x: Theme.paddingLarge
text: qsTr("Alert settings")
color: Theme.highlightColor
}
Label {
x: Theme.paddingLarge*2
width: parent.width - x*2;
wrapMode: Text.Wrap
text: qsTr("Set the maximum and minimum target charge levels.")
color: Theme.primaryColor
font.pixelSize: Theme.fontSizeSmall
}
Slider {
width: parent.width
label: qsTr("Charging limit")
minimumValue: 60
maximumValue: 99
stepSize: 1
value: settings.upperLimit
valueText: value + "%"
onValueChanged: settings.upperLimit = value
}
Slider {
width: parent.width
label: qsTr("Discharging limit")
minimumValue: 10
maximumValue: 40
stepSize: 1
value: settings.lowerLimit
valueText: value + "%"
onValueChanged: settings.lowerLimit = value
}
Slider {
width: parent.width
label: qsTr("Alert interval")
minimumValue: 60
maximumValue: 600
stepSize: 10
value: settings.interval
valueText: Math.floor(value / 60) + (value % 60 < 10 ? ":0" + value % 60 : ":" + value % 60)
onValueChanged: settings.interval = value
Column {
id: settingsColumn
anchors {
top: header.bottom
left: parent.left
right: parent.right
}
spacing: Theme.paddingMedium
Label {
x: Theme.paddingLarge
text: qsTr("Alert settings")
color: Theme.highlightColor
}
Slider {
width: parent.width
label: qsTr("Alert interval")
minimumValue: 60
maximumValue: 600
stepSize: 10
value: settings.interval
valueText: Math.floor(value / 60) + (value % 60 < 10 ? ":0" + value % 60 : ":" + value % 60)
onValueChanged: settings.interval = value
}
Label {
x: Theme.paddingLarge*2
width: parent.width - x*2;
wrapMode: Text.Wrap
text: qsTr("Set the maximum and minimum target charge levels.")
color: Theme.primaryColor
font.pixelSize: Theme.fontSizeSmall
}
Slider {
id: upperChargeLimit
width: parent.width
label: qsTr("Charging limit")
minimumValue: 60
maximumValue: 99
stepSize: 1
value: settings.upperLimit
valueText: value + "%"
onValueChanged: {
settings.upperLimit = value
if((value - 2) < continueChargeLimit.value)
continueChargeLimit.value = value - 2
}
}
Slider {
width: parent.width
label: qsTr("Discharging limit")
minimumValue: 10
maximumValue: 40
stepSize: 1
value: settings.lowerLimit
valueText: value + "%"
onValueChanged: settings.lowerLimit = value
}
TextSwitch {
id: autoStopCharging
text: qsTr("Stop charging when limit reached")
description: qsTr("This option stops charging when battery has reached the percentage set in Charging limit value, and resumes charging when charge has decreased below Continue charge limit value. Generally a value close to the Charging limit value is recommened, such as 80% and 75%.")
checked: settings.limitEnabled
onCheckedChanged: settings.limitEnabled = checked
}
Slider {
id: continueChargeLimit
handleVisible: enabled
width: parent.width
label: qsTr("Resume charging limit")
minimumValue: 50
maximumValue: upperChargeLimit.value - 2
stepSize: 1
value: settings.chargeLimit
valueText: value + "%"
onValueChanged: settings.chargeLimit = value
}
Label {
x: Theme.paddingLarge*2
width: parent.width - x*2;
wrapMode: Text.Wrap
text: qsTr("You can also independently stop and resume charging.")
color: Theme.primaryColor
font.pixelSize: Theme.fontSizeSmall
}
Row {
anchors {
left: parent.left
right: parent.right
}
height: button.height
Column {
width: parent.width / 2
Button {
id: button
anchors.horizontalCenter: parent.horizontalCenter
text: qsTr("Enable")
onClicked: battery.chargingEnabled = true
}
}
Column {
width: parent.width / 2
Button {
anchors.horizontalCenter: parent.horizontalCenter
text: qsTr("Disable")
onClicked: battery.chargingEnabled = false
}
}
}
Label {
x: Theme.paddingLarge
text: qsTr("Alert tests")
color: Theme.highlightColor
}
Label {
x: Theme.paddingLarge*2
width: parent.width - x*2;
wrapMode: Text.Wrap
text: qsTr("Click the buttons to test the sound and notification.")
color: Theme.primaryColor
font.pixelSize: Theme.fontSizeSmall
}
Row {
anchors {
left: parent.left
right: parent.right
}
height: button.height
Column {
width: parent.width / 2
Button {
anchors.horizontalCenter: parent.horizontalCenter
text: qsTr("Charged")
onClicked: {
alertHigh.play()
notification.republishTest()
}
}
}
Column {
width: parent.width / 2
Button {
anchors.horizontalCenter: parent.horizontalCenter
text: qsTr("Discharged")
onClicked: {
alertLow.play()
notification.republishTest()
}
}
}
}
}
}
}

View file

@ -20,11 +20,36 @@
Battery::Battery(QObject* parent) : QObject(parent)
{
// Number: meaning percentage, e.g. 42
chargeFile = new QFile("/run/state/namespaces/Battery/ChargePercentage", this);
// Number: 0 or 1
chargingFile = new QFile("/run/state/namespaces/Battery/IsCharging", this);
chargeFile = new QFile("/sys/class/power_supply/battery/capacity", this);
// String: charging, discharging, (empty), unknown (others?)
stateFile = new QFile("/run/state/namespaces/Battery/ChargingState", this);
stateFile = new QFile("/sys/class/power_supply/battery/status", this);
// Number: 0 or 1
chargerConnectedFile = new QFile("/sys/class/power_supply/usb/present");
// ENABLE/DISABLE CHARGING
// e.g. for Sony Xperia XA2
if(QFile::exists(QString("/sys/class/power_supply/battery/input_suspend"))) {
chargingEnabledFile = new QFile("/sys/class/power_supply/battery/input_suspend");
enableChargingValue = 0;
disableChargingValue = 1;
}
// e.g. for Sony Xperia Z3 Compact Tablet
else if(QFile::exists(QString("/sys/class/power_supply/battery/charging_enabled"))) {
chargingEnabledFile = new QFile("/sys/class/power_supply/battery/charging_enabled");
enableChargingValue = 1;
disableChargingValue = 0;
}
// e.g. for Jolla Phone
else if(QFile::exists(QString("/sys/class/power_supply/usb/charger_disable"))) {
chargingEnabledFile = new QFile("/sys/class/power_supply/usb/charger_disable");
enableChargingValue = 0;
disableChargingValue = 1;
}
else
chargingEnabledFile = Q_NULLPTR;
// TODO
// Implement DBus mechanism for reading battery status
@ -37,33 +62,58 @@ Battery::~Battery() { }
void Battery::updateData()
{
if(chargeFile->open(QIODevice::ReadOnly)) {
nextCharge = chargeFile->readAll().toInt();
nextCharge = chargeFile->readLine().trimmed().toInt();
if(nextCharge != charge) {
charge = nextCharge;
emit chargeChanged();
}
chargeFile->close();
}
if(chargingFile->open(QIODevice::ReadOnly)) {
nextCharging = (chargingFile->readAll().toInt() == 0 ? false : true);
if(nextCharging != charging) {
charging = nextCharging;
emit chargingChanged();
if(chargerConnectedFile->open(QIODevice::ReadOnly)) {
nextChargerConnected = chargerConnectedFile->readLine().trimmed().toInt();
if(nextChargerConnected != chargerConnected) {
chargerConnected = nextChargerConnected;
emit chargerConnectedChanged();
}
chargingFile->close();
chargerConnectedFile->close();
}
if(stateFile->open(QIODevice::ReadOnly)) {
nextState = (QString(stateFile->readAll()));
nextState = (QString(stateFile->readLine().trimmed().toLower()));
if(nextState != state) {
state = nextState;
emit stateChanged();
}
stateFile->close();
}
// This can't be used, because on Jolla Phone the file always reads "0" :(
// It doesn't matter that much anyway, because the value changes only when we change it.
// if(chargingEnabledFile && chargingEnabledFile->open(QIODevice::ReadOnly)) {
// nextChargingEnabled = chargingEnabledFile->readLine().trimmed().toInt() == enableChargingValue;
// if(nextChargingEnabled != chargingEnabled) {
// chargingEnabled = nextChargingEnabled;
// emit chargingEnabledChanged();
// }
// chargingEnabledFile->close();
// }
}
int Battery::getCharge(){ return charge; }
bool Battery::getCharging() { return charging; }
QString Battery::getState() { return state; }
bool Battery::getChargingEnabled() { return chargingEnabled; }
void Battery::setChargingEnabled(bool isEnabled) {
if(chargingEnabledFile && chargingEnabledFile->open(QIODevice::WriteOnly)) {
if(chargingEnabledFile->write(QString("%1").arg(isEnabled ? enableChargingValue : disableChargingValue).toLatin1())) {
chargingEnabled = isEnabled;
emit chargingEnabledChanged();
}
chargingEnabledFile->close();
}
}
bool Battery::getChargerConnected() {
return chargerConnected;
}

View file

@ -25,9 +25,10 @@
class Battery : public QObject
{
Q_OBJECT
Q_PROPERTY(int charge READ getCharge NOTIFY chargeChanged )
Q_PROPERTY(bool charging READ getCharging NOTIFY chargingChanged)
Q_PROPERTY(QString state READ getState NOTIFY stateChanged)
Q_PROPERTY(int charge READ getCharge NOTIFY chargeChanged)
Q_PROPERTY(bool chargerConnected READ getChargerConnected NOTIFY chargerConnectedChanged)
Q_PROPERTY(QString state READ getState NOTIFY stateChanged)
Q_PROPERTY(bool chargingEnabled READ getChargingEnabled WRITE setChargingEnabled NOTIFY chargingEnabledChanged)
public:
Battery(QObject* parent = nullptr);
@ -35,29 +36,40 @@ public:
int getCharge();
bool getCharging();
bool getChargerConnected();
QString getState();
bool getChargingEnabled();
void setChargingEnabled(bool);
public slots:
void updateData();
private:
QFile* chargeFile;
QFile* chargingFile;
QFile* chargerConnectedFile;
QFile* stateFile;
QFile* chargingEnabledFile;
// Default values:
int charge = 100; // 100% full
bool charging = true; // Charger plugged in
QString state = "idle"; // dis/charging, idle, unknown
int charge = 100; // 100% full
bool chargerConnected = false; // Charger plugged in
QString state = "idle"; // dis/charging, idle, unknown
bool chargingEnabled = true; // Only ever disabled manually
int nextCharge = charge;
bool nextCharging = charging;
int enableChargingValue = 1;
int disableChargingValue = 0;
int nextCharge = charge;
bool nextChargerConnected = chargerConnected;
QString nextState = state;
bool nextChargingEnabled = chargingEnabled;
signals:
int chargeChanged();
bool chargingChanged();
QString stateChanged();
bool chargingEnabledChanged();
bool chargerConnectedChanged();
};
#endif // BATTERY_H

View file

@ -41,13 +41,27 @@ Settings::Settings(QObject *parent) : QObject(parent)
emit intervalChanged();
}
}
if(mySettings.contains("limitEnabled")) {
limitEnabled = (mySettings.value("limitEnabled").toInt() == 1);
emit limitEnabledChanged();
}
if(mySettings.contains("chargeLimit")) {
tempValue = mySettings.value("chargeLimit").toInt();
if(tempValue >= 50 && tempValue <= (upperLimit - 2)) {
chargeLimit = tempValue;
emit chargeLimitChanged();
}
}
}
Settings::~Settings()
{
int limitValue = limitEnabled ? 1 : 0;
mySettings.setValue("lowerLimit", QByteArray::number(lowerLimit));
mySettings.setValue("upperLimit", QByteArray::number(upperLimit));
mySettings.setValue("interval", QByteArray::number(interval));
mySettings.setValue("limitEnabled", QByteArray::number(limitValue));
mySettings.setValue("chargeLimit", QByteArray::number(chargeLimit));
}
int Settings::getLowerLimit() { return lowerLimit; }
@ -60,8 +74,16 @@ QString Settings::getLowAlert() { return lowAlertFile; }
QString Settings::getHighAlert() { return highAlertFile; }
bool Settings::getLimitEnabled() { return limitEnabled; }
int Settings::getChargeLimit() { return chargeLimit; }
void Settings::setLowerLimit(int newLimit) { lowerLimit = newLimit; }
void Settings::setUpperLimit(int newLimit) { upperLimit = newLimit; }
void Settings::setInterval(int newInterval) { interval = newInterval; }
void Settings::setLimitEnabled(bool newEnabled) { limitEnabled = newEnabled; }
void Settings::setChargeLimit(int newLimit) { chargeLimit = newLimit; }

View file

@ -24,11 +24,13 @@
class Settings : public QObject
{
Q_OBJECT
Q_PROPERTY(int lowerLimit READ getLowerLimit WRITE setLowerLimit NOTIFY lowerLimitChanged)
Q_PROPERTY(int upperLimit READ getUpperLimit WRITE setUpperLimit NOTIFY upperLimitChanged)
Q_PROPERTY(int interval READ getInterval WRITE setInterval NOTIFY intervalChanged)
Q_PROPERTY(QString lowAlertFile READ getLowAlert NOTIFY lowAlertChanged)
Q_PROPERTY(QString highAlertFile READ getHighAlert NOTIFY highAlertChanged)
Q_PROPERTY(int lowerLimit READ getLowerLimit WRITE setLowerLimit NOTIFY lowerLimitChanged)
Q_PROPERTY(int upperLimit READ getUpperLimit WRITE setUpperLimit NOTIFY upperLimitChanged)
Q_PROPERTY(int interval READ getInterval WRITE setInterval NOTIFY intervalChanged)
Q_PROPERTY(bool limitEnabled READ getLimitEnabled WRITE setLimitEnabled NOTIFY limitEnabledChanged)
Q_PROPERTY(int chargeLimit READ getChargeLimit WRITE setChargeLimit NOTIFY chargeLimitChanged)
Q_PROPERTY(QString lowAlertFile READ getLowAlert NOTIFY lowAlertChanged)
Q_PROPERTY(QString highAlertFile READ getHighAlert NOTIFY highAlertChanged)
public:
Settings(QObject* parent = nullptr);
@ -38,11 +40,15 @@ public:
int getLowerLimit();
int getUpperLimit();
int getInterval();
bool getLimitEnabled();
int getChargeLimit();
QString getLowAlert();
QString getHighAlert();
void setLowerLimit(int newLimit);
void setUpperLimit(int newLimit);
void setInterval(int newInterval);
void setLimitEnabled(bool newEnabled);
void setChargeLimit(int newLimit);
private:
QSettings mySettings;
@ -51,6 +57,8 @@ private:
int lowerLimit = 25;
int upperLimit = 75;
int interval = 60;
bool limitEnabled = false;
int chargeLimit = 70;
QString lowAlertFile = "/usr/share/sounds/jolla-ambient/stereo/general_warning.wav";
QString highAlertFile = "/usr/share/sounds/jolla-ambient/stereo/positive_confirmation.wav";
@ -58,6 +66,8 @@ signals:
int lowerLimitChanged();
int upperLimitChanged();
int intervalChanged();
bool limitEnabledChanged();
int chargeLimitChanged();
QString lowAlertChanged();
QString highAlertChanged();
};