/* * Copyright (c) 2011 Anssi Hannula * * 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: * Anssi Hannula */ #include "measurement.h" #include "sysfs.h" #include "../lib.h" #include #include sysfs_power_meter::sysfs_power_meter(const char *power_supply_name) { rate = 0.0; capacity = 0.0; strncpy(name, power_supply_name, sizeof(name)); } bool sysfs_power_meter::get_sysfs_attr(const char *attribute, int *value) { char filename[4096]; bool ok; snprintf(filename, sizeof(filename), "/sys/class/power_supply/%s/%s", name, attribute); *value = read_sysfs(filename, &ok); return ok; } bool sysfs_power_meter::is_present() { int present = 0; if (!get_sysfs_attr("present", &present)) return true; /* assume always present */ return present; } double sysfs_power_meter::get_voltage() { int voltage; if (!get_sysfs_attr("voltage_now", &voltage)) return -1.0; /* µV to V */ return voltage / 1000000.0; } bool sysfs_power_meter::set_rate_from_power() { int power; if (!get_sysfs_attr("power_now", &power)) return false; /* µW to W */ rate = power / 1000000.0; return true; } bool sysfs_power_meter::set_rate_from_current(double voltage) { int current; if (!get_sysfs_attr("current_now", ¤t)) return false; /* current: µA * voltage: V * rate: W */ rate = (current / 1000000.0) * voltage; return true; } bool sysfs_power_meter::set_capacity_from_energy() { int energy; if (!get_sysfs_attr("energy_now", &energy)) return false; /* µWh to J */ capacity = energy / 1000000.0 * 3600.0; return true; } bool sysfs_power_meter::set_capacity_from_charge(double voltage) { int charge; if (!get_sysfs_attr("charge_now", &charge)) return false; /* charge: µAh * voltage: V * capacity: J */ capacity = (charge / 1000000.0) * voltage * 3600.0; return true; } void sysfs_power_meter::measure() { bool got_rate = false; bool got_capacity = false; rate = 0.0; capacity = 0.0; if (!is_present()) return; if (read_sysfs_string("/sys/class/power_supply/%s/status", name) != "Discharging") return; got_rate = set_rate_from_power(); got_capacity = set_capacity_from_energy(); if (!got_rate || !got_capacity) { double voltage = get_voltage(); if (voltage < 0.0) return; if (!got_rate) set_rate_from_current(voltage); if (!got_capacity) set_capacity_from_charge(voltage); } } void sysfs_power_meter::end_measurement(void) { measure(); } void sysfs_power_meter::start_measurement(void) { /* Battery state is generally a lagging indication, lets only measure at the end */ }