battery.c 2.57 KB
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>

const char *icon[] = {
    "\uf58d",                                         /* 0% */
    "\uf579", "\uf57a", "\uf57b", "\uf57c", "\uf57d", /* 50% */
    "\uf57e", "\uf57f", "\uf580", "\uf581", "\uf578", /* 100% */
};

typedef enum {
  CHARGED = 0,
  DISCHARGING = 1,
  CHARGING = 2,
  DISCONNECTED = 7,
  UNKNOWN = -1
} State;

#if defined(__linux__)
void battery_state(int *nbats, int bat[], State state[]) {
  FILE *fd;
  int i = 0;
  do {
    char filename[50], status[50];

    // get current capacity
    sprintf(filename, "/sys/class/power_supply/BAT%d/capacity", i);
    fd = fopen(filename, "rb");
    if (fd == NULL)
      break;
    fscanf(fd, "%d", &bat[i]);
    fclose(fd);
    // battery status (charging...)
    sprintf(filename, "/sys/class/power_supply/BAT%d/status", i);
    fd = fopen(filename, "rb");
    fgets(status, 50, fd);
    // puts(status);
    fclose(fd);
    if (!strcmp(status, "Not charging\n"))
      state[i] = CHARGED;
    else if (!strcmp(status, "Discharging\n"))
      state[i] = DISCHARGING;
    else if (!strcmp(status, "Charging\n"))
      state[i] = CHARGING;
    else
      state[i] = UNKNOWN;

    // next
    i++;
  } while (1);
  *nbats = i;
}
#elif defined(__FreeBSD__)
#include <sys/sysctl.h>
void battery_state(int *nbats, int bat[], State state[]) {
  size_t len = sizeof(int);
  int status, life = 0;

  *nbats = 1; // FIXME: deal with multiple batteries

  if (sysctlbyname("hw.acpi.battery.state", &status, &len, NULL, 0) ||
      sysctlbyname("hw.acpi.battery.life", &life, &len, NULL, 0)) {
    state[0] = UNKNOWN;
    bat[0] = 0;
  } else {
    bat[0] = life;
    state[0] = status;
  }
}
#endif

int main() {
  char *color;
  int life[2], nbats;
  State state[2];

  battery_state(&nbats, life, state);
  for (int i = 0; i < nbats; i++) {

    if (life[i] >= 50)
      color = "colour028"; /* green */
    else if (life[i] >= 25)
      color = "colour172"; /* yellow */
    else
      color = "colour088"; /* red */

    switch (state[i]) {
    case CHARGED: /* fully charged */
      printf("%s %d%%  ", icon[life[i] / 10], life[i]);
      break;
    case DISCHARGING: /* discharging */
      printf("#[fg=%s]%s#[fg=default] %d%%  ", color, icon[life[i] / 10],
             life[i]);
      break;
    case CHARGING: /* charging */
      printf("#[fg=yellow]\uf583#[fg=default] %d%%\n  ", life[i]);
      break;
    case DISCONNECTED: /* disconnected */
      printf("\uf492  ");
      break;
    default: /* unknown code */
      printf("\uf590  ");
    }
  }

  return EXIT_SUCCESS;
}