// https://www.kernel.org/doc/Documentation/hwmon/sysfs-interface
/*
gcc hwmn.c -o hwmn `pkg-config --cflags --libs eina ecore ecore-file`
 */
#include <Eina.h>
#include <Ecore.h>
#include <Ecore_File.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>

typedef enum
{
   TEMP_UNKNOWN,
   TEMP_CPU, // CPU embedded diode
   TEMP_TRANSISTOR, // 3904 transistor
   TEMP_THERMAL, // thermal diode
   TEMP_THERMISTOR, // thermistor
   TEMP_AMD_AMDSI, // AMD AMDSI
   TEMP_INTEL_PECI // Intel PECI
} Temp_Type;

typedef enum
{
   PWM_OFF, // full speed
   PWM_ON, // enabled
   PWM_AUTO // automatic mode
} Pwm_Mode;

typedef struct
{
   Temp_Type type;
   const char *path;
   const char *name;
   const char *label;
   int enable;
   int fault;
   double temp;
   double min;
   double max;
   double crit;
   double emergency;
   double offset;
} Temp;

typedef struct
{
   const char *path;
   const char *name;
   const char *label;
   int enable;
   int fault;
   int rpm;
   int min;
   int max;
   int target;
} Fan;

typedef struct
{
   const char *path;
   const char *name;
   Pwm_Mode mode;
   double val;
   double min;
   double max;
} Pwm;

typedef struct
{
   const char *path;
   const char *name;
   const char *label;
   double mhz;
} Freq;

typedef struct
{
   const char *path;
   const char *name;
   int enable;
   double watts;
   double min;
   double max;
   double cap;
   double cap_min;
   double cap_max;
   double crit;
} Power;

typedef struct
{
   const char *path;
   const char *name;
   const char *label;
   int enable;
   double volts;
   double min;
   double max;
   double crit_min;
   double crit;
} Volt;

typedef struct
{
   const char *path;
   const char *name;
   int enable;
   double amps;
   double min;
   double max;
   double crit_min;
   double crit;
} Amp;

typedef struct
{
   const char *path;
   const char *name;
   int enable;
   double joules;
} Energy;

typedef struct
{
   const char *path;
   const char *name;
   int enable;
   double percent;
} Humid;

typedef struct
{
   const char *path;
   const char *name;
   int alarm;
} Intrusion;

typedef struct
{
   const char *path;
   const char *name;
   const char *label;
   Eina_List *temps;
   Eina_List *fans;
   Eina_List *pwms;
   Eina_List *freqs;
   Eina_List *powers;
   Eina_List *volts;
   Eina_List *amps;
   Eina_List *energies;
   Eina_List *humids;
   Eina_List *intrusions;
} Mon;

static Eina_List *mons = NULL;

static char *
_file_str_get(const char *path)
{
   int fd = open(path, O_RDONLY);
   char buf[4096], *str = NULL, *s;
   ssize_t sz;

   if (fd < 0) return NULL;
   sz = read(fd, buf, sizeof(buf) - 1);
   if (sz < 1) goto err;
   buf[sz] = '\0';
   for (s = buf; s[0] != '\0'; s++)
     {
        if ((s[0] == '\n') || (s[0] == '\r'))
          {
             s[0] = '\0';
             break;
          }
     }
   str = strdup(buf);
err:
   close(fd);
   return str;
}

#define NOVAL -999999999

static int
_file_int_get(const char *path)
{
   char *str = _file_str_get(path);
   if (!str) return NOVAL;
   int val = atoi(str);
   free(str);
   return val;
}

#define GETVAL_STR(_base, _name, _field) do { char *_s; char _b[4096]; \
   snprintf(_b, sizeof(_b), "%s_%s", _base, _name); \
   if ((_s = _file_str_get(_b))) { \
      _field = eina_stringshare_add(_s); \
      free(_s); \
   } \
} while (0)
#define GETVAL_INT(_base, _name, _field) do { int _v; char _b[4096]; \
   snprintf(_b, sizeof(_b), "%s_%s", _base, _name); \
   if ((_v = _file_int_get(_b)) >= 0) _field = _v; \
} while (0)
#define GETVAL_DBL(_base, _name, _field, _div) do { int _v; char _b[4096]; \
   snprintf(_b, sizeof(_b), "%s_%s", _base, _name); \
   if ((_v = _file_int_get(_b)) >= 0) _field = (double)_v / (_div); \
} while (0)

static void
_hwmon_init(void)
{
   Eina_List *list;
   char *s, *str, buf[4096], buf2[4096];
   int i, x;

   list = ecore_file_ls("/sys/class/hwmon");
   EINA_LIST_FREE(list, s)
     {
        Mon *mon = calloc(1, sizeof(Mon));
        if (mon)
          {
             snprintf(buf, sizeof(buf), "/sys/class/hwmon/%s", s);
             mon->path = eina_stringshare_add(buf);
             mon->name = eina_stringshare_add(s);
             snprintf(buf, sizeof(buf), "/sys/class/hwmon/%s/name", s);
             str = _file_str_get(buf);
             if (str)
               {
                  mon->label = eina_stringshare_add(str);
                  free(str);
               }
             for (i = 1; ; i++)
               {
                  snprintf(buf,  sizeof(buf),  "/sys/class/hwmon/%s/temp%i", s, i);
                  snprintf(buf2, sizeof(buf2), "%s_%s", buf, "input");
                  x = _file_int_get(buf2);
                  if (x == NOVAL) break;
                  Temp *t = calloc(1, sizeof(Temp));
                  if (t)
                    {
                       t->temp = (double)x / 1000.0;
                       t->path = eina_stringshare_add(buf);
                       snprintf(buf2,  sizeof(buf2),  "temp%i", i);
                       t->name = eina_stringshare_add(buf2);
                       GETVAL_STR(buf, "label", t->label);
                       t->enable = 1;
                       GETVAL_INT(buf, "enable", t->enable);
                       GETVAL_INT(buf, "fault", t->fault);
                       GETVAL_INT(buf, "type", t->type);
                       GETVAL_DBL(buf, "min", t->min, 1000.0);
                       GETVAL_DBL(buf, "max", t->max, 1000.0);
                       GETVAL_DBL(buf, "crit", t->crit, 1000.0);
                       GETVAL_DBL(buf, "emergency", t->emergency, 1000.0);
                       mon->temps = eina_list_append(mon->temps, t);
                    }
               }
             for (i = 1; ; i++)
               {
                  snprintf(buf,  sizeof(buf),  "/sys/class/hwmon/%s/fan%i", s, i);
                  snprintf(buf2, sizeof(buf2), "%s_%s", buf, "input");
                  x = _file_int_get(buf2);
                  if (x == NOVAL) break;
                  Fan *f = calloc(1, sizeof(Fan));
                  if (f)
                    {
                       f->rpm = x;
                       f->path = eina_stringshare_add(buf);
                       snprintf(buf2,  sizeof(buf2),  "fan%i", i);
                       f->name = eina_stringshare_add(buf2);
                       GETVAL_STR(buf, "label", f->label);
                       f->enable = 1;
                       GETVAL_INT(buf, "enable", f->enable);
                       GETVAL_INT(buf, "fault", f->fault);
                       GETVAL_INT(buf, "min", f->min);
                       GETVAL_INT(buf, "max", f->max);
                       GETVAL_INT(buf, "target", f->target);
                       mon->fans = eina_list_append(mon->fans, f);
                    }
               }
             for (i = 1; ; i++)
               {
                  snprintf(buf,  sizeof(buf),  "/sys/class/hwmon/%s/pwm%i", s, i);
                  x = _file_int_get(buf);
                  if (x == NOVAL) break;
                  Pwm *p = calloc(1, sizeof(Pwm));
                  if (p)
                    {
                       p->val = (double)x / 255.0;
                       p->path = eina_stringshare_add(buf);
                       snprintf(buf2,  sizeof(buf2),  "pwm%i", i);
                       p->name = eina_stringshare_add(buf2);
                       GETVAL_INT(buf, "enable", p->mode);
                       GETVAL_DBL(buf, "min", p->min, 255.0);
                       GETVAL_DBL(buf, "max", p->max, 255.0);
                       mon->pwms = eina_list_append(mon->pwms, p);
                    }
               }
             for (i = 1; ; i++)
               {
                  snprintf(buf,  sizeof(buf),  "/sys/class/hwmon/%s/freq%i", s, i);
                  snprintf(buf2, sizeof(buf2), "%s_%s", buf, "input");
                  x = _file_int_get(buf2);
                  if (x == NOVAL) break;
                  Freq *f = calloc(1, sizeof(Freq));
                  if (f)
                    {
                       f->mhz = (double)x / 1000000.0;
                       f->path = eina_stringshare_add(buf);
                       snprintf(buf2,  sizeof(buf2),  "freq%i", i);
                       f->name = eina_stringshare_add(buf2);
                       GETVAL_STR(buf, "label", f->label);
                       mon->freqs = eina_list_append(mon->freqs, f);
                    }
               }
             for (i = 1; ; i++)
               {
                  snprintf(buf,  sizeof(buf),  "/sys/class/hwmon/%s/power%i", s, i);
                  snprintf(buf2, sizeof(buf2), "%s_%s", buf, "input");
                  x = _file_int_get(buf2);
                  if (x < 0)
                    {
                       snprintf(buf2, sizeof(buf2), "%s_%s", buf, "average");
                       x = _file_int_get(buf2);
                    }
                  if (x == NOVAL) break;
                  Power *p = calloc(1, sizeof(Power));
                  if (p)
                    {
                       p->watts = (double)x / 1000000.0;
                       p->path = eina_stringshare_add(buf);
                       snprintf(buf2,  sizeof(buf2),  "power%i", i);
                       p->name = eina_stringshare_add(buf2);
                       p->enable = 1;
                       GETVAL_INT(buf, "enable", p->enable);
                       GETVAL_DBL(buf, "min", p->min, 1000000.0);
                       GETVAL_DBL(buf, "max", p->max, 1000000.0);
                       if (p->min <= 0.0)
                         GETVAL_DBL(buf, "average_min", p->min, 1000000.0);
                       if (p->max <= 0.0)
                         GETVAL_DBL(buf, "average_max", p->max, 1000000.0);
                       GETVAL_DBL(buf, "cap", p->cap, 1000000.0);
                       GETVAL_DBL(buf, "cap_min", p->cap_min, 1000000.0);
                       GETVAL_DBL(buf, "cap_max", p->cap_max, 1000000.0);
                       GETVAL_DBL(buf, "crit", p->crit, 1000000.0);
                       mon->powers = eina_list_append(mon->powers, p);
                    }
               }
             for (i = 0; ; i++)
               {
                  snprintf(buf,  sizeof(buf),  "/sys/class/hwmon/%s/in%i", s, i);
                  snprintf(buf2, sizeof(buf2), "%s_%s", buf, "input");
                  x = _file_int_get(buf2);
                  if (x < 0)
                    {
                       snprintf(buf2, sizeof(buf2), "%s_%s", buf, "average");
                       x = _file_int_get(buf2);
                    }
                  if (x == NOVAL) break;
                  Volt *v = calloc(1, sizeof(Volt));
                  if (v)
                    {
                       v->volts = (double)x / 1000.0;
                       v->path = eina_stringshare_add(buf);
                       snprintf(buf2,  sizeof(buf2),  "in%i", i);
                       v->name = eina_stringshare_add(buf2);
                       GETVAL_STR(buf, "label", v->label);
                       v->enable = 1;
                       GETVAL_INT(buf, "enable", v->enable);
                       GETVAL_DBL(buf, "min", v->min, 1000.0);
                       GETVAL_DBL(buf, "max", v->max, 1000.0);
                       GETVAL_DBL(buf, "lcrit", v->crit_min, 1000.0);
                       GETVAL_DBL(buf, "crit", v->crit, 1000.0);
                       mon->volts = eina_list_append(mon->volts, v);
                    }
               }
             for (i = 1; ; i++)
               {
                  snprintf(buf,  sizeof(buf),  "/sys/class/hwmon/%s/curr%i", s, i);
                  snprintf(buf2, sizeof(buf2), "%s_%s", buf, "input");
                  x = _file_int_get(buf2);
                  if (x < 0)
                    {
                       snprintf(buf2, sizeof(buf2), "%s_%s", buf, "average");
                       x = _file_int_get(buf2);
                    }
                  if (x == NOVAL) break;
                  Amp *a = calloc(1, sizeof(Amp));
                  if (a)
                    {
                       a->amps = (double)x / 1000.0;
                       a->path = eina_stringshare_add(buf);
                       snprintf(buf2,  sizeof(buf2),  "curr%i", i);
                       a->name = eina_stringshare_add(buf2);
                       a->enable = 1;
                       GETVAL_INT(buf, "enable", a->enable);
                       GETVAL_DBL(buf, "min", a->min, 1000.0);
                       GETVAL_DBL(buf, "max", a->max, 1000.0);
                       GETVAL_DBL(buf, "lcrit", a->crit_min, 1000.0);
                       GETVAL_DBL(buf, "crit", a->crit, 1000.0);
                       mon->amps = eina_list_append(mon->amps, a);
                    }
               }
             for (i = 1; ; i++)
               {
                  snprintf(buf,  sizeof(buf),  "/sys/class/hwmon/%s/energy%i", s, i);
                  snprintf(buf2, sizeof(buf2), "%s_%s", buf, "input");
                  x = _file_int_get(buf2);
                  if (x == NOVAL) break;
                  Energy *e = calloc(1, sizeof(Energy));
                  if (e)
                    {
                       e->joules = (double)x / 1000000.0;
                       e->path = eina_stringshare_add(buf);
                       snprintf(buf2,  sizeof(buf2),  "energy%i", i);
                       e->name = eina_stringshare_add(buf2);
                       e->enable = 1;
                       GETVAL_INT(buf, "enable", e->enable);
                       mon->energies = eina_list_append(mon->energies, e);
                    }
               }
             for (i = 1; ; i++)
               {
                  snprintf(buf,  sizeof(buf),  "/sys/class/hwmon/%s/humidity%i", s, i);
                  snprintf(buf2, sizeof(buf2), "%s_%s", buf, "input");
                  x = _file_int_get(buf2);
                  if (x == NOVAL) break;
                  Humid *h = calloc(1, sizeof(Humid));
                  if (h)
                    {
                       h->percent = (double)x / 1000.0;
                       h->path = eina_stringshare_add(buf);
                       snprintf(buf2,  sizeof(buf2),  "humidity%i", i);
                       h->name = eina_stringshare_add(buf2);
                       h->enable = 1;
                       GETVAL_INT(buf, "enable", h->enable);
                       mon->humids = eina_list_append(mon->humids, h);
                    }
               }
             for (i = 0; ; i++)
               {
                  snprintf(buf,  sizeof(buf),  "/sys/class/hwmon/%s/intrusion%i", s, i);
                  snprintf(buf2, sizeof(buf2), "%s_%s", buf, "alarm");
                  x = _file_int_get(buf2);
                  if (x == NOVAL) break;
                  Intrusion *n = calloc(1, sizeof(Intrusion));
                  if (n)
                    {
                       n->alarm = x;
                       n->path = eina_stringshare_add(buf);
                       snprintf(buf2,  sizeof(buf2),  "intrusion%i", i);
                       n->name = eina_stringshare_add(buf2);
                       mon->intrusions = eina_list_append(mon->intrusions, n);
                    }
               }
             mons = eina_list_append(mons, mon);
          }
        free(s);
     }
}

static void
_hwmon_update(void)
{
   Eina_List *l, *ll;
   Mon *mon;
   Temp *temp;
   Fan *fan;
   Pwm *pwm;
   Freq *freq;
   Power *power;
   Volt *volt;
   Amp *amp;
   Energy *energy;
   Humid *humid;
   Intrusion *intrusion;
   int x;
   char buf[4096];

   EINA_LIST_FOREACH(mons, l, mon)
     {
        EINA_LIST_FOREACH(mon->temps, ll, temp)
          {
             snprintf(buf, sizeof(buf), "%s_input", temp->path);
             temp->temp = (double)_file_int_get(buf) / 1000.0;
             snprintf(buf, sizeof(buf), "%s_enable", temp->path);
             x = _file_int_get(buf);
             if (x != NOVAL) temp->enable = x;
             snprintf(buf, sizeof(buf), "%s_fault", temp->path);
             temp->fault = _file_int_get(buf);
          }
        EINA_LIST_FOREACH(mon->fans, ll, fan)
          {
             snprintf(buf, sizeof(buf), "%s_input", fan->path);
             fan->rpm = _file_int_get(buf);
             snprintf(buf, sizeof(buf), "%s_target", fan->path);
             fan->target = _file_int_get(buf);
             snprintf(buf, sizeof(buf), "%s_enable", fan->path);
             x = _file_int_get(buf);
             if (x != NOVAL) fan->enable = x;
             snprintf(buf, sizeof(buf), "%s_fault", fan->path);
             fan->fault = _file_int_get(buf);
          }
        EINA_LIST_FOREACH(mon->pwms, ll, pwm)
          {
             snprintf(buf, sizeof(buf), "%s", pwm->path);
             pwm->val = (double)_file_int_get(buf) / 255.0;
             snprintf(buf, sizeof(buf), "%s_enable", pwm->path);
             x = _file_int_get(buf);
             if (x != NOVAL) pwm->mode = x;
          }
        EINA_LIST_FOREACH(mon->freqs, ll, freq)
          {
             snprintf(buf, sizeof(buf), "%s_input", freq->path);
             freq->mhz = (double)_file_int_get(buf) / 1000000.0;
          }
        EINA_LIST_FOREACH(mon->powers, ll, power)
          {
             snprintf(buf, sizeof(buf), "%s_input", power->path);
             x = _file_int_get(buf);
             if (x == NOVAL)
               {
                  snprintf(buf, sizeof(buf), "%s_average", power->path);
                  x = _file_int_get(buf);
               }
             power->watts = (double)x / 1000000.0;
             snprintf(buf, sizeof(buf), "%s_enable", power->path);
             x = _file_int_get(buf);
             if (x != NOVAL) power->enable = x;
          }
        EINA_LIST_FOREACH(mon->volts, ll, volt)
          {
             snprintf(buf, sizeof(buf), "%s_input", volt->path);
             x = _file_int_get(buf);
             if (x == NOVAL)
               {
                  snprintf(buf, sizeof(buf), "%s_average", volt->path);
                  x = _file_int_get(buf);
               }
             volt->volts = (double)x / 1000.0;
             snprintf(buf, sizeof(buf), "%s_enable", volt->path);
             x = _file_int_get(buf);
             if (x != NOVAL) volt->enable = x;
          }
        EINA_LIST_FOREACH(mon->amps, ll, amp)
          {
             snprintf(buf, sizeof(buf), "%s_input", amp->path);
             x = _file_int_get(buf);
             if (x == NOVAL)
               {
                  snprintf(buf, sizeof(buf), "%s_average", amp->path);
                  x = _file_int_get(buf);
               }
             amp->amps = (double)x / 1000.0;
             snprintf(buf, sizeof(buf), "%s_enable", amp->path);
             x = _file_int_get(buf);
             if (x != NOVAL) amp->enable = x;
          }
        EINA_LIST_FOREACH(mon->energies, ll, energy)
          {
             snprintf(buf, sizeof(buf), "%s_input", energy->path);
             energy->joules = (double)_file_int_get(buf) / 1000000.0;
             snprintf(buf, sizeof(buf), "%s_enable", energy->path);
             x = _file_int_get(buf);
             if (x != NOVAL) energy->enable = x;
         }
        EINA_LIST_FOREACH(mon->humids, ll, humid)
          {
             snprintf(buf, sizeof(buf), "%s_input", humid->path);
             humid->percent = (double)_file_int_get(buf) / 1000.0;
             snprintf(buf, sizeof(buf), "%s_enable", humid->path);
             x = _file_int_get(buf);
             if (x != NOVAL) humid->enable = x;
          }
        EINA_LIST_FOREACH(mon->intrusions, ll, intrusion)
          {
             snprintf(buf, sizeof(buf), "%s_alarm", intrusion->path);
             intrusion->alarm = _file_int_get(buf);
          }
     }
}

static void
_hwmon_print(void)
{
   Eina_List *l, *ll;
   Mon *mon;
   Temp *temp;
   Fan *fan;
   Pwm *pwm;
   Freq *freq;
   Power *power;
   Volt *volt;
   Amp *amp;
   Energy *energy;
   Humid *humid;
   Intrusion *intrusion;

   EINA_LIST_FOREACH(mons, l, mon)
     {
        printf("%s\n", mon->label ? mon->label : mon->name);
        EINA_LIST_FOREACH(mon->temps, ll, temp)
          {
             static const char *types[] = {
                "unknown",
                "CPU embedded diode",
                "3904 transistor",
                "thermal diode",
                "thermistor",
                "AMD AMDSI",
                "Intel PECI"
             };
             printf("  %20s: %3.1fc [%20s]", temp->label ? temp->label : temp->name, temp->temp, types[temp->type]);
             if (temp->enable         ) printf(" on");
             else                       printf(" off");
             if (temp->min       > 0.0) printf(" min=%3.1fc", temp->min);
             if (temp->max       > 0.0) printf(" max=%3.1fc", temp->max);
             if (temp->crit      > 0.0) printf(" cri=%3.1fc", temp->crit);
             if (temp->emergency > 0.0) printf(" emr=%3.1fc", temp->emergency);
             printf("\n");
          }
        EINA_LIST_FOREACH(mon->fans, ll, fan)
          {
             printf("  %20s: %5irpm", fan->label ? fan->label : fan->name, fan->rpm);
             if (fan->enable    ) printf(" on");
             else                 printf(" off");
             if (fan->min    > 0) printf(" min=%irpm", fan->min);
             if (fan->max    > 0) printf(" max=%irpm", fan->max);
             if (fan->target > 0) printf(" tgt=%irpm", fan->target);
             printf("\n");
          }
        EINA_LIST_FOREACH(mon->pwms, ll, pwm)
          {
             static const char *modes[] = {
                "off",
                "on",
                "auto"
             };
             printf("  %20s: %3.0f%% %s", pwm->name, pwm->val * 100.0, modes[pwm->mode <= 2 ? pwm->mode : 2]);
             if (pwm->min    > 0.0) printf(" min=%3.0f%%", pwm->min * 100.0);
             if (pwm->max    > 0.0) printf(" max=%3.0f%%", pwm->max * 100.0);
             printf("\n");
          }
        EINA_LIST_FOREACH(mon->freqs, ll, freq)
          {
             printf("  %20s: %4.0fmhz", freq->label ? freq->label : freq->name, freq->mhz);
             printf("\n");
          }
        EINA_LIST_FOREACH(mon->powers, ll, power)
          {
             printf("  %20s: %3.1fw", power->name, power->watts);
             if (power->enable        ) printf(" on");
             else                       printf(" off");
             if (power->min      > 0.0) printf(" min=%3.1fw", power->min);
             if (power->max      > 0.0) printf(" min=%3.1fw", power->max);
             if (power->cap      > 0.0) printf(" cap=%3.1fw", power->cap);
             if (power->cap_min  > 0.0) printf(" capmin=%3.1fw", power->cap_min);
             if (power->cap_max  > 0.0) printf(" capmax=%3.1fw", power->cap_max);
             if (power->crit     > 0.0) printf(" cri=%3.1fw", power->crit);
             printf("\n");
          }
        EINA_LIST_FOREACH(mon->volts, ll, volt)
          {
             printf("  %20s: %2.2fv", volt->label ? volt->label : volt->name, volt->volts);
             if (volt->enable         ) printf(" on");
             else                       printf(" off");
             if (volt->min       > 0.0) printf(" min=%2.2fv", volt->min);
             if (volt->max       > 0.0) printf(" max=%2.2fv", volt->max);
             if (volt->crit_min  > 0.0) printf(" crimin=%2.2fv", volt->crit_min);
             if (volt->crit      > 0.0) printf(" cri=%2.2fv", volt->crit_min);
             printf("\n");
          }
        EINA_LIST_FOREACH(mon->amps, ll, amp)
          {
             printf("  %20s: %2.2fa", amp->name, amp->amps);
             if (amp->enable         ) printf(" on");
             else                      printf(" off");
             if (amp->min       > 0.0) printf(" min=%2.2fv", amp->min);
             if (amp->max       > 0.0) printf(" max=%2.2fv", amp->max);
             if (amp->crit_min  > 0.0) printf(" crimin=%2.2fv", amp->crit_min);
             if (amp->crit      > 0.0) printf(" cri=%2.2fv", amp->crit_min);
             printf("\n");
          }
        EINA_LIST_FOREACH(mon->energies, ll, energy)
          {
             printf("  %20s: %2.2fj", energy->name, energy->joules);
             if (energy->enable         ) printf(" on");
             else                         printf(" off");
             printf("\n");
          }
        EINA_LIST_FOREACH(mon->humids, ll, humid)
          {
             printf("  %20s: %3.1f%%", humid->name, humid->percent);
             if (energy->enable         ) printf(" on");
             else                         printf(" off");
             printf("\n");
          }
        EINA_LIST_FOREACH(mon->intrusions, ll, intrusion)
          {
             printf("  %20s: %s", intrusion->name, intrusion->alarm ? "on" : "off");
             printf("\n");
          }
     }
}

int
main(int argc, char **argv)
{
   ecore_file_init();
   _hwmon_init();
   for (;;)
     {
        _hwmon_print();
        sleep(1);
        _hwmon_update();
     }
   ecore_file_shutdown();
   return 0;
}
