You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
174 lines
3.5 KiB
174 lines
3.5 KiB
#define _POSIX_C_SOURCE 200809L
|
|
|
|
#include <sys/types.h>
|
|
#include <sys/stat.h>
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <fcntl.h>
|
|
#include <dirent.h>
|
|
#include <errno.h>
|
|
#include <string.h>
|
|
#include <unistd.h>
|
|
#include <signal.h>
|
|
#include <time.h>
|
|
#include <limits.h>
|
|
|
|
// TODO: handle multiple batteries
|
|
const char *CAPACITY_PATH = "/sys/class/power_supply/BAT1/capacity";
|
|
const char *STATUS_PATH = "/sys/class/power_supply/BAT1/status";
|
|
const char *POWER_PATH = "/sys/class/power_supply/BAT1/power_now";
|
|
int dead = 0;
|
|
|
|
void usage (void)
|
|
{
|
|
printf("usage: bmon [-wuh] [-f file] [-t interval]\n"
|
|
"-w\tDisplay power draw from battery\n"
|
|
"-u\tPrint seconds as epoch\n"
|
|
"-h\tPrint this message\n"
|
|
"-f\tWrite output to file\n"
|
|
"-t\tSet the update interval in seconds\n");
|
|
}
|
|
|
|
void int_handler (int signum)
|
|
{
|
|
(void)signum;
|
|
dead = 1;
|
|
}
|
|
|
|
int read_int (FILE *fp)
|
|
{
|
|
int x;
|
|
freopen(NULL, "r", fp);
|
|
fscanf(fp, "%d", &x);
|
|
return x;
|
|
}
|
|
|
|
int main (int argc, char *argv[])
|
|
{
|
|
/* Handle SIGINT */
|
|
dead = 0;
|
|
struct sigaction action;
|
|
memset(&action, 0, sizeof(action));
|
|
action.sa_handler = int_handler;
|
|
sigaction(SIGINT, &action, NULL);
|
|
|
|
int wflag = 0;
|
|
int wait_time = 10;
|
|
int fflag = 0;
|
|
int uflag = 0;
|
|
char ofile_path[256];
|
|
|
|
int opc;
|
|
while ((opc = getopt(argc, argv, "uhwf:t:")) != -1) {
|
|
switch (opc) {
|
|
case 'w':
|
|
wflag = 1;
|
|
break;
|
|
case 'f':
|
|
fflag = 1;
|
|
strncpy(ofile_path, optarg, 255);
|
|
break;
|
|
case 't':
|
|
wait_time = atoi(optarg);
|
|
if (wait_time < 1) {
|
|
usage();
|
|
exit(1);
|
|
}
|
|
break;
|
|
case 'u':
|
|
uflag = 1;
|
|
break;
|
|
case 'h':
|
|
default: /* '?' */
|
|
usage();
|
|
exit(1);
|
|
break;
|
|
}
|
|
|
|
}
|
|
|
|
FILE *capacity_fp = NULL, *status_fp = NULL, *power_fp = NULL;
|
|
capacity_fp = fopen(CAPACITY_PATH, "r");
|
|
if (capacity_fp == NULL) {
|
|
fprintf(stderr, "Error opening %s: %s\n", CAPACITY_PATH, strerror(errno));
|
|
exit(1);
|
|
}
|
|
|
|
if (wflag) {
|
|
power_fp = fopen(POWER_PATH, "r");
|
|
if (power_fp == NULL) {
|
|
fprintf(stderr, "Error opening %s: %s\n", POWER_PATH, strerror(errno));
|
|
exit(1);
|
|
}
|
|
status_fp = fopen(STATUS_PATH, "r");
|
|
if (status_fp == NULL) {
|
|
fprintf(stderr, "Error opening %s: %s\n", STATUS_PATH, strerror(errno));
|
|
exit(1);
|
|
}
|
|
}
|
|
|
|
|
|
FILE *output_fp = stdout;
|
|
if (fflag) {
|
|
if ((output_fp = fopen(ofile_path, "w")) == NULL) {
|
|
fprintf(stderr, "Error opening %s: %s\n", ofile_path, strerror(errno));
|
|
exit(1);
|
|
}
|
|
}
|
|
|
|
long int elapsed_time = 0;
|
|
fprintf(output_fp, "TIME\t");
|
|
fprintf(output_fp, "CAP\t");
|
|
if (wflag) fprintf(output_fp, "WATTS");
|
|
fprintf(output_fp, "\n");
|
|
while (!dead) {
|
|
int capacity = read_int(capacity_fp);
|
|
float power = 0;
|
|
if (capacity < 0) {
|
|
fprintf(stderr, "Error reading capacity: %s\n", strerror(errno));
|
|
break;
|
|
}
|
|
if (wflag) {
|
|
power = read_int(power_fp);
|
|
if (power < 0) {
|
|
fprintf(stderr, "Error reading power: %s\n", strerror(errno));
|
|
break;
|
|
}
|
|
static char b[128] = {0};
|
|
freopen(NULL, "r", status_fp);
|
|
if (fgets(b, sizeof(b), status_fp) == NULL) {
|
|
fprintf(stderr, "Error reading status: %s\n", strerror(errno));
|
|
}
|
|
if (strncmp(b, "Discharging\n", sizeof(b)) == 0) {
|
|
power *= -1;
|
|
}
|
|
|
|
// power is in microwatts
|
|
power /= 1e6;
|
|
}
|
|
|
|
fprintf(output_fp, "%ld\t", uflag ? time(NULL) : elapsed_time);
|
|
fprintf(output_fp, "%d\t", capacity);
|
|
if (wflag) fprintf(output_fp, "%.2f", power);
|
|
fprintf(output_fp, "\n");
|
|
|
|
sleep(wait_time);
|
|
elapsed_time += wait_time;
|
|
}
|
|
|
|
if (fflag) {
|
|
fclose(output_fp);
|
|
}
|
|
if (capacity_fp) {
|
|
fclose(capacity_fp);
|
|
}
|
|
if (status_fp) {
|
|
fclose(status_fp);
|
|
}
|
|
if (power_fp) {
|
|
fclose(power_fp);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|