battery.c 2.41 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,
} 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;

    // 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 state = -1, life = 0;

  if (sysctlbyname("hw.acpi.battery.state", &state, &len, NULL, 0) ||
      sysctlbyname("hw.acpi.battery.life", &life, &len, NULL, 0))
    state[0] = UNKNOWN;

  *nbats = 1;
  bat[0] = life;
  state[0] = state;
}
#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;
}