blob: b9b10fbd2069e1edcacf0f30c310fc7b30c3fafb [file] [log] [blame]
/*
* Copyright 2010, Intel Corporation
*
* This file is part of PowerTOP
*
* This program file is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; version 2 of the License.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program in a file named COPYING; if not, write to the
* Free Software Foundation, Inc,
* 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301 USA
* or just google for it.
*
* Authors:
* Arjan van de Ven <arjan@linux.intel.com>
*/
#include "measurement.h"
#include "acpi.h"
#include <iostream>
#include <fstream>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
using namespace std;
acpi_power_meter::acpi_power_meter(const char *acpi_name)
{
rate = 0.0;
capacity = 0.0;
voltage = 0.0;
strncpy(battery_name, acpi_name, sizeof(battery_name));
}
/*
present: yes
capacity state: ok
charging state: discharging
present rate: 8580 mW
remaining capacity: 34110 mWh
present voltage: 12001 mV
*/
void acpi_power_meter::measure(void)
{
char filename[4096];
char line[4096];
ifstream file;
double _rate = 0;
double _capacity = 0;
double _voltage = 0;
char rate_units[16];
char capacity_units[16];
char voltage_units[16];
rate_units[0] = 0;
capacity_units[0] = 0;
voltage_units[0] = 0;
rate = 0;
voltage = 0;
capacity = 0;
sprintf(filename, "/proc/acpi/battery/%s/state", battery_name);
file.open(filename, ios::in);
if (!file)
return;
while (file) {
char *c;
file.getline(line, 4096);
if (strstr(line, "present:") && (strstr(line, "yes") == NULL)) {
return;
}
if (strstr(line, "charging state:") && (strstr(line, "discharging") == NULL)) {
return; /* not discharging */
}
if (strstr(line, "present rate:")) {
c = strchr(line, ':');
c++;
while (*c == ' ') c++;
_rate = strtoull(c, NULL, 10);
c = strchr(c, ' ');
if (c) {
c++;
strcpy(rate_units, c);
} else {
_rate = 0;
strcpy(rate_units, "Unknown");
}
}
if (strstr(line, "remaining capacity:")) {
c = strchr(line, ':');
c++;
while (*c == ' ') c++;
_capacity = strtoull(c, NULL, 10);
c = strchr(c, ' ');
if (c) {
c++;
strcpy(capacity_units, c);
} else {
_capacity = 0;
strcpy(capacity_units, "Unknown");
}
}
if (strstr(line, "present voltage:")) {
c = strchr(line, ':');
c++;
while (*c == ' ') c++;
_voltage = strtoull(c, NULL, 10);
c = strchr(c, ' ');
if (c) {
c++;
strcpy(voltage_units, c);
} else {
_voltage = 0;
strcpy(voltage_units, "Unknown");
}
}
}
file.close();
/* BIOS report random crack-inspired units. Lets try to get to the Si-system units */
if (strcmp(voltage_units, "mV") == 0) {
_voltage = _voltage / 1000.0;
strcpy(voltage_units, "V");
}
if (strcmp(rate_units, "mW") == 0) {
_rate = _rate / 1000.0;
strcpy(rate_units, "W");
}
if (strcmp(rate_units, "mA") == 0) {
_rate = _rate / 1000.0;
strcpy(rate_units, "A");
}
if (strcmp(capacity_units, "mAh") == 0) {
_capacity = _capacity / 1000.0;
strcpy(capacity_units, "Ah");
}
if (strcmp(capacity_units, "mWh") == 0) {
_capacity = _capacity / 1000.0;
strcpy(capacity_units, "Wh");
}
if (strcmp(capacity_units, "Wh") == 0) {
_capacity = _capacity * 3600.0;
strcpy(capacity_units, "J");
}
if (strcmp(capacity_units, "Ah") == 0 && strcmp(voltage_units, "V") == 0) {
_capacity = _capacity * 3600.0 * _voltage;
strcpy(capacity_units, "J");
}
if (strcmp(rate_units, "A") == 0 && strcmp(voltage_units, "V")==0 ) {
_rate = _rate * _voltage;
strcpy(rate_units, "W");
}
if (strcmp(capacity_units, "J") == 0)
capacity = _capacity;
else
capacity = 0.0;
if (strcmp(rate_units, "W")==0)
rate = _rate;
else
rate = 0.0;
if (strcmp(voltage_units, "V")==0)
voltage = _voltage;
else
voltage = 0.0;
}
void acpi_power_meter::end_measurement(void)
{
measure();
}
void acpi_power_meter::start_measurement(void)
{
/* ACPI battery state is a lagging indication, lets only measure at the end */
}
double acpi_power_meter::joules_consumed(void)
{
return rate;
}