updated battery meter code from Ian Hands, slightly tweaked

This commit is contained in:
Hisham Muhammad 2009-04-27 21:48:09 +00:00
parent 510213591b
commit 20bb68824d
1 changed files with 249 additions and 59 deletions

View File

@ -4,7 +4,7 @@
Released under the GNU GPL, see the COPYING file Released under the GNU GPL, see the COPYING file
in the source distribution for its full text. in the source distribution for its full text.
This "Meter" written by Ian P. Hands (iphands@gmail.com). This "Meter" written by Ian P. Hands (iphands@gmail.com, ihands@redhat.com).
*/ */
#include "BatteryMeter.h" #include "BatteryMeter.h"
@ -14,13 +14,39 @@
#include "String.h" #include "String.h"
#include "debug.h" #include "debug.h"
/*{
typedef enum ACPresence_ {
AC_ABSENT,
AC_PRESENT,
AC_ERROR
} ACPresence;
}*/
int BatteryMeter_attributes[] = { int BatteryMeter_attributes[] = {
BATTERY BATTERY
}; };
static unsigned long int parseBatInfo(const char * fileName, const unsigned short int lineNum, const unsigned short int wordNum) { static unsigned long int parseUevent(FILE * file, char *key) {
char line[100];
unsigned long int dValue = 0;
while (fgets(line, sizeof line, file)) {
if (strncmp(line, key, strlen(key)) == 0) {
char *value;
value = strtok(line, "=");
value = strtok(NULL, "=");
dValue = atoi(value);
break;
}
}
return dValue;
}
static unsigned long int parseBatInfo(const char *fileName, const unsigned short int lineNum, const unsigned short int wordNum) {
const DIR *batteryDir; const DIR *batteryDir;
const struct dirent *pDirEnt; const struct dirent *dirEntries;
const char batteryPath[] = PROCDIR "/acpi/battery/"; const char batteryPath[] = PROCDIR "/acpi/battery/";
batteryDir = opendir(batteryPath); batteryDir = opendir(batteryPath);
@ -29,8 +55,11 @@ static unsigned long int parseBatInfo(const char * fileName, const unsigned shor
return 0; return 0;
} }
char * string; char *entryName;
typedef struct listLbl { char* content; struct listLbl* next; } list; typedef struct listLbl {
char *content;
struct listLbl *next;
} list;
list *myList = NULL; list *myList = NULL;
list *newEntry; list *newEntry;
@ -39,77 +68,235 @@ static unsigned long int parseBatInfo(const char * fileName, const unsigned shor
Some of this is based off of code found in kismet (they claim it came from gkrellm). Some of this is based off of code found in kismet (they claim it came from gkrellm).
Written for multi battery use... Written for multi battery use...
*/ */
for (pDirEnt= readdir((DIR*)batteryDir); pDirEnt; pDirEnt = readdir((DIR*)batteryDir)) { for (dirEntries = readdir((DIR *) batteryDir); dirEntries; dirEntries = readdir((DIR *) batteryDir)) {
string = (char*)pDirEnt->d_name; entryName = (char *) dirEntries->d_name;
if(!strcmp(string, ".") || !strcmp(string, ".."))
if (strncmp(entryName, "BAT", 3))
continue; continue;
newEntry = calloc(1, sizeof(list)); newEntry = calloc(1, sizeof(list));
newEntry->next = myList; newEntry->next = myList;
newEntry->content = string; newEntry->content = entryName;
myList = newEntry; myList = newEntry;
} }
unsigned long int total = 0; unsigned long int total = 0;
for (newEntry = myList; newEntry; newEntry = newEntry->next) { for (newEntry = myList; newEntry; newEntry = newEntry->next) {
const char infoPath[30]; const char infoPath[30];
const FILE * file; const FILE *file;
char line[50]; char line[50];
sprintf((char*)infoPath, "%s%s/%s", batteryPath, newEntry->content, fileName); sprintf((char *) infoPath, "%s%s/%s", batteryPath, newEntry->content, fileName);
if ((file = fopen(infoPath, "r")) == NULL) { if ((file = fopen(infoPath, "r")) == NULL) {
return 0; return 0;
} }
for (unsigned short int i = 0; i < lineNum; i++){ for (unsigned short int i = 0; i < lineNum; i++) {
fgets(line, sizeof line, (FILE*)file); fgets(line, sizeof line, (FILE *) file);
} }
fclose((FILE*)file); fclose((FILE *) file);
const char * foundNumTmp = String_getToken(line, wordNum); const char *foundNumTmp = String_getToken(line, wordNum);
const unsigned long int foundNum = atoi(foundNumTmp); const unsigned long int foundNum = atoi(foundNumTmp);
free((char*)foundNumTmp); free((char *) foundNumTmp);
total += foundNum; total += foundNum;
} }
free(myList); free(myList);
free(newEntry); free(newEntry);
closedir((DIR*)batteryDir); closedir((DIR *) batteryDir);
return total; return total;
} }
static void BatteryMeter_setValues(Meter* this, char* buffer, int len) { static ACPresence chkIsOnline() {
FILE* file = fopen(PROCDIR "/acpi/ac_adapter/AC/state", "r"); FILE *file = NULL;
if (!file) ACPresence isOn = AC_ERROR;
file = fopen(PROCDIR "/acpi/ac_adapter/ADP1/state", "r");
if (access(PROCDIR "/acpi/ac_adapter", F_OK) == 0) {
const struct dirent *dirEntries;
char *power_supplyPath = PROCDIR "/acpi/ac_adapter";
DIR *power_supplyDir = opendir(power_supplyPath);
char *entryName;
if (!power_supplyDir) {
closedir(power_supplyDir);
return AC_ERROR;
}
for (dirEntries = readdir((DIR *) power_supplyDir); dirEntries; dirEntries = readdir((DIR *) power_supplyDir)) {
entryName = (char *) dirEntries->d_name;
if (strncmp(entryName, "A", 1)) {
continue;
}
char statePath[50];
sprintf((char *) statePath, "%s/%s/state", power_supplyPath, entryName);
file = fopen(statePath, "r");
if (!file) { if (!file) {
isOn = AC_ERROR;
continue;
}
char line[100];
fgets(line, sizeof line, file);
line[sizeof(line) - 1] = '\0';
if (file) {
fclose(file);
file = NULL;
}
const char *isOnline = String_getToken(line, 2);
if (strcmp(isOnline, "on-line") == 0) {
free((char *) isOnline);
isOn = AC_PRESENT;
// If any AC adapter is being used then stop
break;
} else {
isOn = AC_ABSENT;
}
free((char *) isOnline);
}
if (power_supplyDir)
closedir(power_supplyDir);
} else {
char *power_supplyPath = "/sys/class/power_supply";
if (access("/sys/class/power_supply", F_OK) == 0) {
const struct dirent *dirEntries;
DIR *power_supplyDir = opendir(power_supplyPath);
char *entryName;
if (!power_supplyDir) {
return AC_ERROR;
}
for (dirEntries = readdir((DIR *) power_supplyDir); dirEntries; dirEntries = readdir((DIR *) power_supplyDir)) {
entryName = (char *) dirEntries->d_name;
if (strncmp(entryName, "A", 1)) {
continue;
}
char onlinePath[50];
sprintf((char *) onlinePath, "%s/%s/online", power_supplyPath, entryName);
file = fopen(onlinePath, "r");
if (!file) {
isOn = AC_ERROR;
continue;
}
isOn = (fgetc(file) - '0');
if (file) {
fclose(file);
file = NULL;
}
if (isOn == AC_PRESENT) {
// If any AC adapter is being used then stop
break;
} else {
continue;
}
}
if (power_supplyDir)
closedir(power_supplyDir);
}
}
// Just in case :-)
if (file)
fclose(file);
return isOn;
}
static double getProcBatData() {
const unsigned long int totalFull = parseBatInfo("info", 3, 4);
if (totalFull == 0)
return 0;
const unsigned long int totalRemain = parseBatInfo("state", 5, 3);
if (totalRemain == 0)
return 0;
double percent = totalFull > 0 ? ((double) totalRemain * 100) / (double) totalFull : 0;
return percent;
}
static double getSysBatData() {
const struct dirent *dirEntries;
char *power_supplyPath = "/sys/class/power_supply/";
DIR *power_supplyDir = opendir(power_supplyPath);
if (!power_supplyDir) {
closedir(power_supplyDir);
return 0;
}
char *entryName;
unsigned long int totalFull = 0;
unsigned long int totalRemain = 0;
for (dirEntries = readdir((DIR *) power_supplyDir); dirEntries; dirEntries = readdir((DIR *) power_supplyDir)) {
entryName = (char *) dirEntries->d_name;
if (strncmp(entryName, "BAT", 3)) {
continue;
}
const char ueventPath[50];
sprintf((char *) ueventPath, "%s%s/uevent", power_supplyPath, entryName);
FILE *file;
if ((file = fopen(ueventPath, "r")) == NULL) {
closedir(power_supplyDir);
return 0;
}
totalFull += parseUevent(file, "POWER_SUPPLY_ENERGY_FULL=");
totalRemain += parseUevent(file, "POWER_SUPPLY_ENERGY_NOW=");
fclose(file);
}
const double percent = totalFull > 0 ? ((double) totalRemain * 100) / (double) totalFull : 0;
closedir(power_supplyDir);
return percent;
}
static void BatteryMeter_setValues(Meter * this, char *buffer, int len) {
double percent = getProcBatData();
if (percent == 0) {
percent = getSysBatData();
if (percent == 0) {
snprintf(buffer, len, "n/a"); snprintf(buffer, len, "n/a");
return; return;
} }
char line [100];
fgets(line, sizeof line, file);
line[sizeof(line) - 1] = '\0';
fclose(file);
const unsigned long int totalFull = parseBatInfo("info", 3, 4);
const unsigned long int totalRemain = parseBatInfo("state", 5, 3);
const double percent = totalFull > 0 ? ((double)totalRemain * 100) / (double)totalFull : 0;
if (totalFull == 0) {
snprintf(buffer, len, "n/a");
return;
} }
this->values[0] = percent; this->values[0] = percent;
const char* isOnline = String_getToken(line, 2); char *onAcText, *onBatteryText, *unknownText;
char *onAcText, *onBatteryText;
unknownText = "%.1f%%";
if (this->mode == TEXT_METERMODE) { if (this->mode == TEXT_METERMODE) {
onAcText = "%.1f%% (Running on A/C)"; onAcText = "%.1f%% (Running on A/C)";
onBatteryText = "%.1f%% (Running on battery)"; onBatteryText = "%.1f%% (Running on battery)";
@ -118,13 +305,16 @@ static void BatteryMeter_setValues(Meter* this, char* buffer, int len) {
onBatteryText = "%.1f%%(bat)"; onBatteryText = "%.1f%%(bat)";
} }
if (strcmp(String_getToken(line, 2),"on-line") == 0) { ACPresence isOnLine = chkIsOnline();
if (isOnLine == AC_PRESENT) {
snprintf(buffer, len, onAcText, percent); snprintf(buffer, len, onAcText, percent);
} else { } else if (isOnLine == AC_ABSENT) {
snprintf(buffer, len, onBatteryText, percent); snprintf(buffer, len, onBatteryText, percent);
} else {
snprintf(buffer, len, unknownText, percent);
} }
free((char*)isOnline);
return; return;
} }