Skip to content

Commit

Permalink
Add support for multiple batteries and chargers. Make wifi handling s…
Browse files Browse the repository at this point in the history
…marter
  • Loading branch information
Eeems committed Sep 11, 2020
1 parent 204ed29 commit fb1ac1c
Show file tree
Hide file tree
Showing 6 changed files with 118 additions and 22 deletions.
20 changes: 14 additions & 6 deletions applications/launcher/controller.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,14 +51,24 @@ class Controller : public QObject
qFatal("Power API was not available");
}
powerApi = new Power(OXIDE_SERVICE, path, bus);
connect(powerApi, &Power::batteryAlert, this, &Controller::batteryAlert);
// Connect to signals
connect(powerApi, &Power::batteryLevelChanged, this, &Controller::batteryLevelChanged);
connect(powerApi, &Power::batteryStateChanged, this, &Controller::batteryStateChanged);
connect(powerApi, &Power::batteryTemperatureChanged, this, &Controller::batteryTemperatureChanged);
connect(powerApi, &Power::batteryWarning, this, &Controller::batteryWarning);
connect(powerApi, &Power::chargerStateChanged, this, &Controller::chargerStateChanged);
connect(powerApi, &Power::chargerWarning, this, &Controller::chargerWarning);
connect(powerApi, &Power::stateChanged, this, &Controller::stateChanged);
connect(powerApi, &Power::batteryAlert, this, &Controller::batteryAlert);
connect(powerApi, &Power::batteryWarning, this, &Controller::batteryWarning);
connect(powerApi, &Power::chargerWarning, this, &Controller::chargerWarning);
QTimer::singleShot(1000, [=](){
// Get initial values when UI is ready
batteryLevelChanged(powerApi->batteryLevel());
batteryStateChanged(powerApi->batteryState());
batteryTemperatureChanged(powerApi->batteryTemperature());
chargerStateChanged(powerApi->chargerState());
stateChanged(powerApi->state());
});

}
Q_INVOKABLE bool turnOnWifi(){
wifiState = "up";
Expand Down Expand Up @@ -90,9 +100,7 @@ class Controller : public QObject
}
return true;
};
Q_INVOKABLE bool wifiOn(){
return WifiManager::singleton() != nullptr;
};
Q_INVOKABLE bool wifiOn(){ return WifiManager::wifiOn(); };
Q_INVOKABLE void loadSettings();
Q_INVOKABLE void saveSettings();
Q_INVOKABLE QList<QObject*> getApps();
Expand Down
2 changes: 1 addition & 1 deletion applications/launcher/main.qml
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ ApplicationWindow {
property bool alert: false
property bool warning: false
property bool charging: false
property bool present: false
property bool present: true
property int level: 0
property int temperature: 0
source: {
Expand Down
19 changes: 17 additions & 2 deletions applications/launcher/wifimanager.h
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,13 @@ class WifiManager : public DBusInterface
static WifiManager* singleton(){
if(instance() == nullptr){
xochitlSettings()->sync();
if(xochitlSettings()->value("wifion").toBool() && !turnOnWifi()){
if(xochitlSettings()->value("wifion").toBool()){
qDebug() << "Wifi should be enabled";
if(!turnOnWifi()){
turnOffWifi();
}
}else{
qDebug() << "Wifi should not be enabled";
turnOffWifi();
}
}
Expand Down Expand Up @@ -154,6 +160,7 @@ class WifiManager : public DBusInterface
xochitlSettings()->sync();
qDebug() << "Loading networks...";
instance()->loadNetworks();
instance()->Reconnect();
return true;
}
static void turnOffWifi(){
Expand All @@ -166,6 +173,7 @@ class WifiManager : public DBusInterface
}
system("ifconfig wlan0 down");
}
static bool wifiOn(){ return !system("ip addr show wlan0 | grep UP > /dev/null"); }
static bool ensureService(){
QDBusConnection bus = QDBusConnection::systemBus();
if(!bus.isConnected()){
Expand All @@ -175,8 +183,12 @@ class WifiManager : public DBusInterface
// Connect to service
QStringList serviceNames = bus.interface()->registeredServiceNames();
if (!serviceNames.contains(SERVICE)){
if(!system("systemctl --quiet is-active wpa_supplicant")){
qCritical() << "wpa_supplicant is running, but not active?";
return false;
}
qDebug() << "Starting wpa_supplicant...";
if(!system("systemctl --quiet is-active wpa_supplicant") && !system("systemctl --quiet start wpa_supplicant")){
if(system("systemctl --quiet start wpa_supplicant")){
qCritical() << "Failed to start wpa_supplicant";
return false;
}
Expand Down Expand Up @@ -361,9 +373,12 @@ class WifiManager : public DBusInterface
return instance;
}
if(instance != nullptr){
qDebug() << "Removing old WifiManager instance";
delete instance;
instance = nullptr;
}
if(path != "/"){
qDebug() << ("Creating new WifiManager instance on " + path).toStdString().c_str();
instance = new WifiManager(path, QDBusConnection::systemBus());
}
return instance;
Expand Down
2 changes: 1 addition & 1 deletion applications/system-service/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ void onExit(){
auto procs = ButtonHandler::split_string_by_newline(ButtonHandler::exec((
"grep -Erl /proc/*/status --regexp='PPid:\\s+" + oxidepid + "' | awk '{print substr($1, 7, length($1) - 13)}'"
).toStdString().c_str()));
qDebug() << "Pausing child tasks...";
qDebug() << "Killing child tasks...";
for(auto pid : procs){
string cmd = "cat /proc/" + pid + "/status | grep PPid: | awk '{print$2}'";
if(my_pid != pid && ButtonHandler::is_uint(pid) && ButtonHandler::exec(cmd.c_str()) == oxidepid.toStdString() + "\n"){
Expand Down
95 changes: 83 additions & 12 deletions applications/system-service/powerapi.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include <QTimer>
#include <QException>
#include <QCoreApplication>
#include <QDir>

#include "dbussettings.h"
#include "sysobject.h"
Expand All @@ -21,8 +22,31 @@ class PowerAPI : public QObject {
Q_PROPERTY(int chargerState READ chargerState NOTIFY chargerStateChanged)
public:
PowerAPI(QObject* parent)
: QObject(parent),
battery("/sys/class/power_supply/bq27441-0") {
: QObject(parent), batteries(), chargers(){
QDir dir("/sys/class/power_supply");
qDebug() << "Looking for batteries and chargers...";
for(auto path : dir.entryList(QDir::Dirs | QDir::NoDotAndDotDot | QDir::Readable)){
qDebug() << (" Checking " + path + "...").toStdString().c_str();
SysObject item(dir.path() + "/" + path);
if(!item.hasProperty("type")){
qDebug() << " Missing type property";
continue;
}
if(item.hasProperty("present") && !item.intProperty("present")){
qDebug() << " Either missing present property, or battery is not present";
break;
}
if(item.strProperty("type") == "Battery"){
qDebug() << " Found Battery!";
batteries.append(item);
}else if(item.strProperty("type") == "USB"){
qDebug() << " Found Charger!";
chargers.append(item);
}else{
qDebug() << " Unknown type";
}
}
update();
timer = new QTimer(this);
timer->setSingleShot(false);
timer->setInterval(3 * 1000); // 3 seconds
Expand Down Expand Up @@ -84,7 +108,8 @@ class PowerAPI : public QObject {

private:
QTimer* timer;
SysObject battery;
QList<SysObject> batteries;
QList<SysObject> chargers;
int m_state = Normal;
int m_batteryState = BatteryUnknown;
int m_batteryLevel;
Expand All @@ -93,17 +118,64 @@ class PowerAPI : public QObject {
bool m_batteryWarning = false;
bool m_batteryAlert = false;

int batteryInt(QString property){
int result = 0;
for(auto battery : batteries){
result += battery.intProperty(property.toStdString());
}
return result;
}
int batteryIntMax(QString property){
int result = 0;
for(auto battery : batteries){
int value = battery.intProperty(property.toStdString());
if(value > result){
result = value;
}
}
return result;
}
int calcBatteryLevel(){
return batteryInt("capacity") / batteries.length();
}
std::array<bool, 3> getBatteryStates(){
bool alert = false;
bool warning = false;
bool charging = false;
for(auto battery : batteries){
auto capacityLevel = battery.strProperty("capacity_level");
auto status = battery.strProperty("status");
if(!charging && status == "Charging"){
charging = true;
}
if(capacityLevel == "Critical" || capacityLevel == ""){
alert = true;
}
if(status == "Unknown" || status == "" || capacityLevel == "Unknown"){
warning = true;
}
if(alert && warning && charging){
break;
}
}
std::array<bool, 3> state;
state[0] = charging;
state[1] = warning;
state[2] = alert;
return state;
}

private slots:
void update(){
if(!battery.exists()){
if(!batteries.length()){
if(!m_batteryWarning){
qWarning() << "Can't find battery information";
m_batteryWarning = true;
emit batteryWarning();
}
return;
}
if(!battery.intProperty("present")){
if(!batteryInt("present")){
qWarning() << "Battery is somehow not in the device?";
if(!m_batteryWarning){
qWarning() << "Can't find battery information";
Expand All @@ -112,33 +184,32 @@ private slots:
}
return;
}
int battery_level = battery.intProperty("capacity");
int battery_level = calcBatteryLevel();
if(batteryLevel() != battery_level){
setBatteryLevel(battery_level);
}
std::string status = battery.strProperty("status");
auto charging = status == "Charging";
auto states = getBatteryStates();
bool charging = states[0];
bool warning = states[1];
bool alert = states[2];
if(charging && batteryState() != BatteryCharging){
setBatteryState(BatteryCharging);
}else if(!charging && batteryState() != BatteryDischarging){
setBatteryState(BatteryDischarging);
}
std::string capacityLevel = battery.strProperty("capacity_level");
auto alert = capacityLevel == "Critical" || capacityLevel == "";
if(m_batteryAlert != alert){
m_batteryAlert = alert;
if(alert){
emit batteryAlert();
}
}
auto warning = status == "Unknown" || status == "" || capacityLevel == "Unknown";
if(m_batteryWarning != warning){
if(warning){
emit batteryWarning();
}
m_batteryWarning = warning;
}
int temperature = battery.intProperty("temp") / 10;
int temperature = batteryIntMax("temp") / 10;
if(batteryTemperature() != temperature){
setBatteryTemperature(temperature);
}
Expand Down
2 changes: 2 additions & 0 deletions applications/system-service/sysobject.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,13 @@
#define SYSOBJECT_H

#include <string>
#include <QString>

class SysObject
{
public:
explicit SysObject(std::string path) : m_path(path){};
explicit SysObject(QString path) : m_path(path.toStdString()){};
bool exists();
bool hasProperty(std::string name);
std::string strProperty(std::string name);
Expand Down

0 comments on commit fb1ac1c

Please sign in to comment.