feat(battery): Estimated time remaining
Adds a new token %time% that will display an estimate of the remaining time until fully charged/discharged
This commit is contained in:
parent
30c1cb3d50
commit
38f9ba81cd
@ -59,27 +59,35 @@ option(ENABLE_DAMAGE_EXT "Enable Damage X extension" OFF)
|
||||
|
||||
set(SETTING_ALSA_SOUNDCARD "default"
|
||||
CACHE STRING "Name of the ALSA soundcard driver")
|
||||
set(SETTING_CONNECTION_TEST_IP "8.8.8.8"
|
||||
CACHE STRING "Address to ping when testing network connection")
|
||||
set(SETTING_PATH_BACKLIGHT_VAL "/sys/class/backlight/%card%/brightness"
|
||||
CACHE STRING "Path to file containing the current backlight value")
|
||||
set(SETTING_PATH_BACKLIGHT_MAX "/sys/class/backlight/%card%/max_brightness"
|
||||
CACHE STRING "Path to file containing the maximum backlight value")
|
||||
set(SETTING_PATH_BATTERY_CAPACITY "/sys/class/power_supply/%battery%/capacity"
|
||||
CACHE STRING "Path to file containing the current battery capacity")
|
||||
set(SETTING_PATH_ADAPTER_STATUS "/sys/class/power_supply/%adapter%/online"
|
||||
CACHE STRING "Path to file containing the current adapter status")
|
||||
set(SETTING_BSPWM_SOCKET_PATH "/tmp/bspwm_0_0-socket"
|
||||
CACHE STRING "Path to bspwm socket")
|
||||
set(SETTING_BSPWM_STATUS_PREFIX "W"
|
||||
CACHE STRING "Prefix prepended to the bspwm status line")
|
||||
set(SETTING_CONNECTION_TEST_IP "8.8.8.8"
|
||||
CACHE STRING "Address to ping when testing network connection")
|
||||
set(SETTING_PATH_ADAPTER_STATUS "/sys/class/power_supply/%adapter%/online"
|
||||
CACHE STRING "Path to file containing the current adapter status")
|
||||
set(SETTING_PATH_BACKLIGHT_MAX "/sys/class/backlight/%card%/max_brightness"
|
||||
CACHE STRING "Path to file containing the maximum backlight value")
|
||||
set(SETTING_PATH_BACKLIGHT_VAL "/sys/class/backlight/%card%/brightness"
|
||||
CACHE STRING "Path to file containing the current backlight value")
|
||||
set(SETTING_PATH_BATTERY_CAPACITY "/sys/class/power_supply/%battery%/charge_now"
|
||||
CACHE STRING "Path to file containing the current battery capacity")
|
||||
set(SETTING_PATH_BATTERY_CAPACITY_MAX "/sys/class/power_supply/%battery%/charge_full"
|
||||
CACHE STRING "Path to file containing the current battery capacity")
|
||||
set(SETTING_PATH_BATTERY_CAPACITY_PERC "/sys/class/power_supply/%battery%/capacity"
|
||||
CACHE STRING "Path to file containing the current battery capacity in percentage")
|
||||
set(SETTING_PATH_BATTERY_RATE "/sys/class/power_supply/%battery%/current_now"
|
||||
CACHE STRING "Path to file containing the current battery rate")
|
||||
set(SETTING_PATH_BATTERY_VOLTAGE "/sys/class/power_supply/%battery%/voltage_now"
|
||||
CACHE STRING "Path to file containing the current battery voltage")
|
||||
set(SETTING_PATH_CPU_INFO "/proc/stat"
|
||||
CACHE STRING "Path to file containing cpu info")
|
||||
set(SETTING_PATH_MEMORY_INFO "/proc/meminfo"
|
||||
CACHE STRING "Path to file containing memory info")
|
||||
set(SETTING_PATH_TEMPERATURE_INFO "/sys/class/thermal/thermal_zone%zone%/temp"
|
||||
CACHE STRING "Path to file containing the current temperature")
|
||||
set(SETTING_PATH_MESSAGING_FIFO "/tmp/polybar_mqueue.%pid%"
|
||||
CACHE STRING "Path to file containing the current temperature")
|
||||
set(SETTING_PATH_TEMPERATURE_INFO "/sys/class/thermal/thermal_zone%zone%/temp"
|
||||
CACHE STRING "Path to file containing the current temperature")
|
||||
|
||||
# }}}
|
||||
|
@ -32,18 +32,35 @@ else()
|
||||
message(STATUS " Linking C++ library: system default")
|
||||
endif()
|
||||
|
||||
message(STATUS "---------------------------")
|
||||
message(STATUS " Build testsuite ${BUILD_TESTS}")
|
||||
message(STATUS " Enable debug logger ${DEBUG_LOGGER}")
|
||||
message(STATUS " Enable extra tracing ${VERBOSE_TRACELOG}")
|
||||
message(STATUS " Enable ccache support ${ENABLE_CCACHE}")
|
||||
message(STATUS "---------------------------")
|
||||
message(STATUS " Enable alsa support ${ENABLE_ALSA}")
|
||||
message(STATUS " Enable i3 support ${ENABLE_I3}")
|
||||
message(STATUS " Enable mpd support ${ENABLE_MPD}")
|
||||
message(STATUS " Enable network support ${ENABLE_NETWORK}")
|
||||
message(STATUS "---------------------------")
|
||||
message(STATUS " Enable X RandR ${ENABLE_RANDR_EXT}")
|
||||
message(STATUS " Enable X Render ${ENABLE_RENDER_EXT}")
|
||||
message(STATUS " Enable X Damage ${ENABLE_DAMAGE_EXT}")
|
||||
message(STATUS "---------------------------")
|
||||
message(STATUS "--------------------------------------------")
|
||||
message(STATUS " Build testsuite ${BUILD_TESTS}")
|
||||
message(STATUS " Enable debug logger ${DEBUG_LOGGER}")
|
||||
message(STATUS " Enable extra tracing ${VERBOSE_TRACELOG}")
|
||||
message(STATUS " Enable ccache support ${ENABLE_CCACHE}")
|
||||
message(STATUS "--------------------------------------------")
|
||||
message(STATUS " Enable alsa support ${ENABLE_ALSA}")
|
||||
message(STATUS " Enable i3 support ${ENABLE_I3}")
|
||||
message(STATUS " Enable mpd support ${ENABLE_MPD}")
|
||||
message(STATUS " Enable network support ${ENABLE_NETWORK}")
|
||||
message(STATUS "--------------------------------------------")
|
||||
message(STATUS " Enable X RandR ${ENABLE_RANDR_EXT}")
|
||||
message(STATUS " Enable X Render ${ENABLE_RENDER_EXT}")
|
||||
message(STATUS " Enable X Damage ${ENABLE_DAMAGE_EXT}")
|
||||
message(STATUS "--------------------------------------------")
|
||||
message(STATUS " ALSA_SOUNDCARD ${SETTING_ALSA_SOUNDCARD}")
|
||||
message(STATUS " BSPWM_SOCKET_PATH ${SETTING_BSPWM_SOCKET_PATH}")
|
||||
message(STATUS " BSPWM_STATUS_PREFIX ${SETTING_BSPWM_STATUS_PREFIX}")
|
||||
message(STATUS " CONNECTION_TEST_IP ${SETTING_CONNECTION_TEST_IP}")
|
||||
message(STATUS " PATH_ADAPTER_STATUS ${SETTING_PATH_ADAPTER_STATUS}")
|
||||
message(STATUS " PATH_BACKLIGHT_VAL ${SETTING_PATH_BACKLIGHT_VAL}")
|
||||
message(STATUS " PATH_BACKLIGHT_MAX ${SETTING_PATH_BACKLIGHT_MAX}")
|
||||
message(STATUS " PATH_BATTERY_CAPACITY ${SETTING_PATH_BATTERY_CAPACITY}")
|
||||
message(STATUS " PATH_BATTERY_CAPACITY_MAX ${SETTING_PATH_BATTERY_CAPACITY_MAX}")
|
||||
message(STATUS " PATH_BATTERY_CAPACITY_PERC ${SETTING_PATH_BATTERY_CAPACITY_PERC}")
|
||||
message(STATUS " PATH_BATTERY_VOLTAGE ${SETTING_PATH_BATTERY_VOLTAGE}")
|
||||
message(STATUS " PATH_BATTERY_RATE ${SETTING_PATH_BATTERY_RATE}")
|
||||
message(STATUS " PATH_CPU_INFO ${SETTING_PATH_CPU_INFO}")
|
||||
message(STATUS " PATH_MEMORY_INFO ${SETTING_PATH_MEMORY_INFO}")
|
||||
message(STATUS " PATH_MESSAGING_FIFO ${SETTING_PATH_MESSAGING_FIFO}")
|
||||
message(STATUS " PATH_TEMPERATURE_INFO ${SETTING_PATH_TEMPERATURE_INFO}")
|
||||
message(STATUS "--------------------------------------------")
|
||||
|
@ -28,18 +28,23 @@
|
||||
#endif
|
||||
|
||||
#define BUILDER_SPACE_TOKEN "%__"
|
||||
|
||||
#define ALSA_SOUNDCARD "@SETTING_ALSA_SOUNDCARD@"
|
||||
#define CONNECTION_TEST_IP "@SETTING_CONNECTION_TEST_IP@"
|
||||
#define PATH_BACKLIGHT_VAL "@SETTING_PATH_BACKLIGHT_VAL@"
|
||||
#define PATH_BACKLIGHT_MAX "@SETTING_PATH_BACKLIGHT_MAX@"
|
||||
#define PATH_BATTERY_CAPACITY "@SETTING_PATH_BATTERY_CAPACITY@"
|
||||
#define PATH_ADAPTER_STATUS "@SETTING_PATH_ADAPTER_STATUS@"
|
||||
#define BSPWM_SOCKET_PATH "@SETTING_BSPWM_SOCKET_PATH@"
|
||||
#define BSPWM_STATUS_PREFIX "@SETTING_BSPWM_STATUS_PREFIX@"
|
||||
#define CONNECTION_TEST_IP "@SETTING_CONNECTION_TEST_IP@"
|
||||
#define PATH_ADAPTER_STATUS "@SETTING_PATH_ADAPTER_STATUS@"
|
||||
#define PATH_BACKLIGHT_MAX "@SETTING_PATH_BACKLIGHT_MAX@"
|
||||
#define PATH_BACKLIGHT_VAL "@SETTING_PATH_BACKLIGHT_VAL@"
|
||||
#define PATH_BATTERY_CAPACITY "@SETTING_PATH_BATTERY_CAPACITY@"
|
||||
#define PATH_BATTERY_CAPACITY_MAX "@SETTING_PATH_BATTERY_CAPACITY_MAX@"
|
||||
#define PATH_BATTERY_CAPACITY_PERC "@SETTING_PATH_BATTERY_CAPACITY_PERC@"
|
||||
#define PATH_BATTERY_RATE "@SETTING_PATH_BATTERY_RATE@"
|
||||
#define PATH_BATTERY_VOLTAGE "@SETTING_PATH_BATTERY_VOLTAGE@"
|
||||
#define PATH_CPU_INFO "@SETTING_PATH_CPU_INFO@"
|
||||
#define PATH_MEMORY_INFO "@SETTING_PATH_MEMORY_INFO@"
|
||||
#define PATH_TEMPERATURE_INFO "@SETTING_PATH_TEMPERATURE_INFO@"
|
||||
#define PATH_MESSAGING_FIFO "@SETTING_PATH_MESSAGING_FIFO@"
|
||||
#define PATH_TEMPERATURE_INFO "@SETTING_PATH_TEMPERATURE_INFO@"
|
||||
|
||||
auto print_build_info = []() {
|
||||
// clang-format off
|
||||
@ -51,18 +56,23 @@ auto print_build_info = []() {
|
||||
<< (ENABLE_MPD ? "+" : "-") << "mpd "
|
||||
<< (ENABLE_NETWORK ? "+" : "-") << "network "
|
||||
<< "\n\n"
|
||||
<< "ALSA_SOUNDCARD " << ALSA_SOUNDCARD << "\n"
|
||||
<< "BSPWM_SOCKET_PATH " << BSPWM_SOCKET_PATH << "\n"
|
||||
<< "BSPWM_STATUS_PREFIX " << BSPWM_STATUS_PREFIX << "\n"
|
||||
<< "BUILDER_SPACE_TOKEN " << BUILDER_SPACE_TOKEN << "\n"
|
||||
<< "CONNECTION_TEST_IP " << CONNECTION_TEST_IP << "\n"
|
||||
<< "PATH_ADAPTER_STATUS " << PATH_ADAPTER_STATUS << "\n"
|
||||
<< "PATH_BACKLIGHT_MAX " << PATH_BACKLIGHT_MAX << "\n"
|
||||
<< "PATH_BACKLIGHT_VAL " << PATH_BACKLIGHT_VAL << "\n"
|
||||
<< "PATH_BATTERY_CAPACITY " << PATH_BATTERY_CAPACITY << "\n"
|
||||
<< "PATH_CPU_INFO " << PATH_CPU_INFO << "\n"
|
||||
<< "PATH_MEMORY_INFO " << PATH_MEMORY_INFO << "\n"
|
||||
<< "PATH_TEMPERATURE_INFO " << PATH_TEMPERATURE_INFO << "\n";
|
||||
<< "ALSA_SOUNDCARD " << ALSA_SOUNDCARD << "\n"
|
||||
<< "BSPWM_SOCKET_PATH " << BSPWM_SOCKET_PATH << "\n"
|
||||
<< "BSPWM_STATUS_PREFIX " << BSPWM_STATUS_PREFIX << "\n"
|
||||
<< "BUILDER_SPACE_TOKEN " << BUILDER_SPACE_TOKEN << "\n"
|
||||
<< "CONNECTION_TEST_IP " << CONNECTION_TEST_IP << "\n"
|
||||
<< "PATH_ADAPTER_STATUS " << PATH_ADAPTER_STATUS << "\n"
|
||||
<< "PATH_BACKLIGHT_MAX " << PATH_BACKLIGHT_MAX << "\n"
|
||||
<< "PATH_BACKLIGHT_VAL " << PATH_BACKLIGHT_VAL << "\n"
|
||||
<< "PATH_BATTERY_CAPACITY " << PATH_BATTERY_CAPACITY << "\n"
|
||||
<< "PATH_BATTERY_CAPACITY " << PATH_BATTERY_CAPACITY << "\n"
|
||||
<< "PATH_BATTERY_CAPACITY_MAX " << PATH_BATTERY_CAPACITY_MAX << "\n"
|
||||
<< "PATH_BATTERY_CAPACITY_PERC " << PATH_BATTERY_CAPACITY_PERC << "\n"
|
||||
<< "PATH_BATTERY_RATE " << PATH_BATTERY_RATE << "\n"
|
||||
<< "PATH_BATTERY_VOLTAGE " << PATH_BATTERY_VOLTAGE << "\n"
|
||||
<< "PATH_CPU_INFO " << PATH_CPU_INFO << "\n"
|
||||
<< "PATH_MEMORY_INFO " << PATH_MEMORY_INFO << "\n"
|
||||
<< "PATH_TEMPERATURE_INFO " << PATH_TEMPERATURE_INFO << "\n";
|
||||
// clang-format on
|
||||
};
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "common.hpp"
|
||||
#include "config.hpp"
|
||||
#include "drawtypes/animation.hpp"
|
||||
#include "drawtypes/label.hpp"
|
||||
@ -13,7 +14,23 @@
|
||||
POLYBAR_NS
|
||||
|
||||
namespace modules {
|
||||
enum class battery_state { NONE = 0, UNKNOWN, CHARGING, DISCHARGING, FULL };
|
||||
enum class battery_state {
|
||||
NONE = 0,
|
||||
CHARGING,
|
||||
DISCHARGING,
|
||||
FULL,
|
||||
};
|
||||
|
||||
enum class battery_value {
|
||||
NONE = 0,
|
||||
ADAPTER,
|
||||
CAPACITY,
|
||||
CAPACITY_MAX,
|
||||
CAPACITY_PERC,
|
||||
VOLTAGE,
|
||||
RATE,
|
||||
};
|
||||
|
||||
class battery_module : public inotify_module<battery_module> {
|
||||
public:
|
||||
using inotify_module::inotify_module;
|
||||
@ -29,6 +46,7 @@ namespace modules {
|
||||
protected:
|
||||
int current_percentage();
|
||||
battery_state current_state();
|
||||
string current_time();
|
||||
void subthread();
|
||||
|
||||
private:
|
||||
@ -43,6 +61,8 @@ namespace modules {
|
||||
static constexpr auto TAG_LABEL_DISCHARGING = "<label-discharging>";
|
||||
static constexpr auto TAG_LABEL_FULL = "<label-full>";
|
||||
|
||||
static const int SKIP_N_UNCHANGED{3};
|
||||
|
||||
animation_t m_animation_charging;
|
||||
ramp_t m_ramp_capacity;
|
||||
progressbar_t m_bar_capacity;
|
||||
@ -50,18 +70,14 @@ namespace modules {
|
||||
label_t m_label_discharging;
|
||||
label_t m_label_full;
|
||||
|
||||
string m_battery;
|
||||
string m_adapter;
|
||||
string m_path_capacity;
|
||||
string m_path_adapter;
|
||||
|
||||
battery_state m_state = battery_state::UNKNOWN;
|
||||
std::atomic_int m_percentage{0};
|
||||
|
||||
battery_state m_state{battery_state::DISCHARGING};
|
||||
map<battery_value, string> m_valuepath;
|
||||
std::atomic<int> m_percentage{0};
|
||||
int m_fullat{100};
|
||||
interval_t m_interval;
|
||||
chrono::system_clock::time_point m_lastpoll;
|
||||
|
||||
int m_fullat = 100;
|
||||
string m_timeformat;
|
||||
int m_unchanged{SKIP_N_UNCHANGED};
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -4,41 +4,40 @@
|
||||
POLYBAR_NS
|
||||
|
||||
namespace modules {
|
||||
/**
|
||||
* Bootstrap module by setting up required components
|
||||
*/
|
||||
void battery_module::setup() {
|
||||
// Load configuration values {{{
|
||||
// Load configuration values
|
||||
auto battery = m_conf.get<string>(name(), "battery", "BAT0");
|
||||
auto adapter = m_conf.get<string>(name(), "adapter", "ADP1");
|
||||
|
||||
m_valuepath[battery_value::ADAPTER] = string_util::replace(PATH_ADAPTER_STATUS, "%adapter%", adapter);
|
||||
m_valuepath[battery_value::CAPACITY] = string_util::replace(PATH_BATTERY_CAPACITY, "%battery%", battery);
|
||||
m_valuepath[battery_value::CAPACITY_MAX] = string_util::replace(PATH_BATTERY_CAPACITY_MAX, "%battery%", battery);
|
||||
m_valuepath[battery_value::CAPACITY_PERC] = string_util::replace(PATH_BATTERY_CAPACITY_PERC, "%battery%", battery);
|
||||
m_valuepath[battery_value::VOLTAGE] = string_util::replace(PATH_BATTERY_VOLTAGE, "%battery%", battery);
|
||||
m_valuepath[battery_value::RATE] = string_util::replace(PATH_BATTERY_RATE, "%battery%", battery);
|
||||
|
||||
for (auto&& file : m_valuepath) {
|
||||
if (!file_util::exists(file.second))
|
||||
throw module_error("The file '" + file.second + "' does not exist");
|
||||
}
|
||||
|
||||
m_battery = m_conf.get<string>(name(), "battery", "BAT0");
|
||||
m_adapter = m_conf.get<string>(name(), "adapter", "ADP1");
|
||||
m_fullat = m_conf.get<int>(name(), "full-at", 100);
|
||||
m_interval = interval_t{m_conf.get<float>(name(), "poll-interval", 5.0f)};
|
||||
m_lastpoll = chrono::system_clock::now();
|
||||
|
||||
m_path_capacity = string_util::replace(PATH_BATTERY_CAPACITY, "%battery%", m_battery);
|
||||
m_path_adapter = string_util::replace(PATH_ADAPTER_STATUS, "%adapter%", m_adapter);
|
||||
|
||||
// }}}
|
||||
// Validate paths {{{
|
||||
|
||||
if (!file_util::exists(m_path_capacity))
|
||||
throw module_error("The file '" + m_path_capacity + "' does not exist");
|
||||
if (!file_util::exists(m_path_adapter))
|
||||
throw module_error("The file '" + m_path_adapter + "' does not exist");
|
||||
|
||||
// }}}
|
||||
// Load state and capacity level {{{
|
||||
|
||||
// Load state and capacity level
|
||||
m_percentage = current_percentage();
|
||||
m_state = current_state();
|
||||
|
||||
// }}}
|
||||
// Add formats and elements {{{
|
||||
|
||||
// Add formats and elements
|
||||
m_formatter->add(FORMAT_CHARGING, TAG_LABEL_CHARGING,
|
||||
{TAG_BAR_CAPACITY, TAG_RAMP_CAPACITY, TAG_ANIMATION_CHARGING, TAG_LABEL_CHARGING});
|
||||
m_formatter->add(FORMAT_DISCHARGING, TAG_LABEL_DISCHARGING,
|
||||
{TAG_BAR_CAPACITY, TAG_RAMP_CAPACITY, TAG_LABEL_DISCHARGING});
|
||||
m_formatter->add(
|
||||
FORMAT_FULL, TAG_LABEL_FULL, {TAG_BAR_CAPACITY, TAG_RAMP_CAPACITY, TAG_LABEL_FULL});
|
||||
FORMAT_DISCHARGING, TAG_LABEL_DISCHARGING, {TAG_BAR_CAPACITY, TAG_RAMP_CAPACITY, TAG_LABEL_DISCHARGING});
|
||||
m_formatter->add(FORMAT_FULL, TAG_LABEL_FULL, {TAG_BAR_CAPACITY, TAG_RAMP_CAPACITY, TAG_LABEL_FULL});
|
||||
|
||||
if (m_formatter->has(TAG_ANIMATION_CHARGING, FORMAT_CHARGING))
|
||||
m_animation_charging = load_animation(m_conf, name(), TAG_ANIMATION_CHARGING);
|
||||
@ -46,51 +45,67 @@ namespace modules {
|
||||
m_bar_capacity = load_progressbar(m_bar, m_conf, name(), TAG_BAR_CAPACITY);
|
||||
if (m_formatter->has(TAG_RAMP_CAPACITY))
|
||||
m_ramp_capacity = load_ramp(m_conf, name(), TAG_RAMP_CAPACITY);
|
||||
if (m_formatter->has(TAG_LABEL_CHARGING, FORMAT_CHARGING)) {
|
||||
if (m_formatter->has(TAG_LABEL_CHARGING, FORMAT_CHARGING))
|
||||
m_label_charging = load_optional_label(m_conf, name(), TAG_LABEL_CHARGING, "%percentage%");
|
||||
}
|
||||
if (m_formatter->has(TAG_LABEL_DISCHARGING, FORMAT_DISCHARGING)) {
|
||||
m_label_discharging =
|
||||
load_optional_label(m_conf, name(), TAG_LABEL_DISCHARGING, "%percentage%");
|
||||
}
|
||||
if (m_formatter->has(TAG_LABEL_FULL, FORMAT_FULL)) {
|
||||
if (m_formatter->has(TAG_LABEL_DISCHARGING, FORMAT_DISCHARGING))
|
||||
m_label_discharging = load_optional_label(m_conf, name(), TAG_LABEL_DISCHARGING, "%percentage%");
|
||||
if (m_formatter->has(TAG_LABEL_FULL, FORMAT_FULL))
|
||||
m_label_full = load_optional_label(m_conf, name(), TAG_LABEL_FULL, "%percentage%");
|
||||
|
||||
// Create inotify watches
|
||||
watch(m_valuepath[battery_value::CAPACITY_PERC], IN_ACCESS);
|
||||
watch(m_valuepath[battery_value::ADAPTER], IN_ACCESS);
|
||||
|
||||
// Setup time if token is used
|
||||
if (m_label_charging->has_token("%time%") || m_label_discharging->has_token("%time%")) {
|
||||
if (!m_bar.locale.empty())
|
||||
setlocale(LC_TIME, m_bar.locale.c_str());
|
||||
m_timeformat = m_conf.get<string>(name(), "time-format", "%H:%M:%S");
|
||||
}
|
||||
|
||||
// }}}
|
||||
// Create inotify watches {{{
|
||||
|
||||
watch(m_path_capacity, IN_ACCESS);
|
||||
watch(m_path_adapter, IN_ACCESS);
|
||||
|
||||
// }}}
|
||||
}
|
||||
|
||||
/**
|
||||
* Dispatch the subthread used to update the
|
||||
* charging animation when the module is started
|
||||
*/
|
||||
void battery_module::start() {
|
||||
inotify_module::start();
|
||||
m_threads.emplace_back(thread(&battery_module::subthread, this));
|
||||
}
|
||||
|
||||
/**
|
||||
* Release wake lock when stopping the module
|
||||
*/
|
||||
void battery_module::teardown() {
|
||||
wakeup();
|
||||
}
|
||||
|
||||
/**
|
||||
* Idle between polling inotify watches for events.
|
||||
*
|
||||
* If the defined interval has been reached, trigger a manual
|
||||
* poll in case the inotify events aren't fired.
|
||||
*
|
||||
* This fallback is needed because some systems won't
|
||||
* report inotify events for files on sysfs.
|
||||
*/
|
||||
void battery_module::idle() {
|
||||
// Manually poll values as a fallback for systems that
|
||||
// doesn't report inotify events for files on sysfs
|
||||
if (m_interval.count() > 0) {
|
||||
auto now = chrono::system_clock::now();
|
||||
|
||||
if (chrono::duration_cast<decltype(m_interval)>(now - m_lastpoll) > m_interval) {
|
||||
m_lastpoll = now;
|
||||
m_log.info("%s: Polling values (inotify fallback)", name());
|
||||
file_util::get_contents(m_path_capacity);
|
||||
file_util::get_contents(m_valuepath[battery_value::CAPACITY_PERC]);
|
||||
}
|
||||
}
|
||||
|
||||
inotify_module::idle();
|
||||
}
|
||||
|
||||
/**
|
||||
* Update values when tracked files have changed
|
||||
*/
|
||||
bool battery_module::on_event(inotify_event* event) {
|
||||
if (event != nullptr) {
|
||||
m_log.trace("%s: Inotify event reported for %s", name(), event->filename);
|
||||
@ -106,45 +121,29 @@ namespace modules {
|
||||
percentage = current_percentage();
|
||||
}
|
||||
|
||||
// Ignore unchanged state
|
||||
if (event != nullptr && m_state == state && m_percentage == percentage) {
|
||||
if (event != nullptr && state == m_state && percentage == m_percentage && m_unchanged--) {
|
||||
return false;
|
||||
}
|
||||
|
||||
m_percentage = percentage;
|
||||
m_state = state;
|
||||
m_unchanged = SKIP_N_UNCHANGED;
|
||||
|
||||
string time_remaining;
|
||||
auto rate = strtoul(file_util::get_contents("/sys/class/power_supply/BAT0/current_now").c_str(), nullptr, 10) / 1000;
|
||||
// int rate{atoi(file_util::get_contents("/sys/class/power_supply/BAT0/current_now").c_str()) / 1000};
|
||||
// time_remaining = to_string(rate);
|
||||
auto capacity = strtoul(file_util::get_contents("/sys/class/power_supply/BAT0/charge_now").c_str(), nullptr, 10) / 1000;
|
||||
auto voltage = strtoul(file_util::get_contents("/sys/class/power_supply/BAT0/voltage_now").c_str(), nullptr, 10) / 1000;
|
||||
capacity = capacity * 1000 / voltage;
|
||||
rate = rate * 1000 / voltage;
|
||||
printf("rate=%lu cap=%lu volt=%lu\n", rate, capacity, voltage);
|
||||
int seconds = 3600 * capacity / rate;
|
||||
|
||||
int hours = seconds / 3600;
|
||||
seconds -= 3600 * hours;
|
||||
int minutes = seconds / 60;
|
||||
seconds -= 60 * minutes;
|
||||
char buffer[9]{0};
|
||||
snprintf(buffer, sizeof(buffer), "%02d:%02d:%02d", hours, minutes, seconds);
|
||||
time_remaining = buffer;
|
||||
|
||||
|
||||
if (m_label_charging) {
|
||||
if (m_state == battery_state::CHARGING && m_label_charging) {
|
||||
if (!m_timeformat.empty())
|
||||
time_remaining = current_time();
|
||||
m_label_charging->reset_tokens();
|
||||
m_label_charging->replace_token("%percentage%", to_string(m_percentage) + "%");
|
||||
m_label_charging->replace_token("%time%", time_remaining);
|
||||
}
|
||||
if (m_label_discharging) {
|
||||
} else if (m_state == battery_state::DISCHARGING && m_label_discharging) {
|
||||
if (!m_timeformat.empty())
|
||||
time_remaining = current_time();
|
||||
m_label_discharging->reset_tokens();
|
||||
m_label_discharging->replace_token("%percentage%", to_string(m_percentage) + "%");
|
||||
m_label_discharging->replace_token("%time%", time_remaining);
|
||||
}
|
||||
if (m_label_full) {
|
||||
} else if (m_state == battery_state::FULL && m_label_full) {
|
||||
m_label_full->reset_tokens();
|
||||
m_label_full->replace_token("%percentage%", to_string(m_percentage) + "%");
|
||||
}
|
||||
@ -152,6 +151,9 @@ namespace modules {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the output format based on state
|
||||
*/
|
||||
string battery_module::get_format() const {
|
||||
if (m_state == battery_state::FULL)
|
||||
return FORMAT_FULL;
|
||||
@ -161,6 +163,9 @@ namespace modules {
|
||||
return FORMAT_DISCHARGING;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate the module output using defined drawtypes
|
||||
*/
|
||||
bool battery_module::build(builder* builder, string tag) const {
|
||||
if (tag == TAG_ANIMATION_CHARGING)
|
||||
builder->node(m_animation_charging->get());
|
||||
@ -179,15 +184,18 @@ namespace modules {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current battery state
|
||||
*/
|
||||
battery_state battery_module::current_state() {
|
||||
auto adapter_status = file_util::get_contents(m_path_adapter);
|
||||
auto adapter_status = file_util::get_contents(m_valuepath[battery_value::ADAPTER]);
|
||||
|
||||
if (adapter_status.empty()) {
|
||||
return battery_state::UNKNOWN;
|
||||
return battery_state::DISCHARGING;
|
||||
} else if (adapter_status[0] == '0') {
|
||||
return battery_state::DISCHARGING;
|
||||
} else if (adapter_status[0] != '1') {
|
||||
return battery_state::UNKNOWN;
|
||||
return battery_state::DISCHARGING;
|
||||
} else if (m_percentage < m_fullat) {
|
||||
return battery_state::CHARGING;
|
||||
} else {
|
||||
@ -199,7 +207,7 @@ namespace modules {
|
||||
* Get the current capacity level
|
||||
*/
|
||||
int battery_module::current_percentage() {
|
||||
auto capacity = file_util::get_contents(m_path_capacity);
|
||||
auto capacity = file_util::get_contents(m_valuepath[battery_value::CAPACITY_PERC]);
|
||||
auto value = math_util::cap<int>(std::atof(capacity.c_str()), 0, 100);
|
||||
|
||||
if (value >= m_fullat) {
|
||||
@ -209,6 +217,57 @@ namespace modules {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get estimate of remaining time until fully dis-/charged
|
||||
*/
|
||||
string battery_module::current_time() {
|
||||
if (m_state == battery_state::FULL) {
|
||||
return "";
|
||||
}
|
||||
|
||||
int rate{atoi(file_util::get_contents(m_valuepath[battery_value::RATE]).c_str()) / 1000};
|
||||
int volt{atoi(file_util::get_contents(m_valuepath[battery_value::VOLTAGE]).c_str()) / 1000};
|
||||
int now{atoi(file_util::get_contents(m_valuepath[battery_value::CAPACITY]).c_str()) / 1000};
|
||||
int max{atoi(file_util::get_contents(m_valuepath[battery_value::CAPACITY_MAX]).c_str()) / 1000};
|
||||
int cap{0};
|
||||
|
||||
if (m_state == battery_state::CHARGING) {
|
||||
cap = max - now;
|
||||
} else if (m_state == battery_state::DISCHARGING) {
|
||||
cap = now;
|
||||
}
|
||||
|
||||
struct tm t {
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
||||
};
|
||||
|
||||
if (rate && volt && cap) {
|
||||
cap = cap * 1000 / volt;
|
||||
rate = rate * 1000 / volt;
|
||||
|
||||
if (!rate)
|
||||
rate = -1;
|
||||
|
||||
chrono::seconds sec{3600 * cap / rate};
|
||||
|
||||
m_log.trace("%s: sec=%d %d%% cap=%lu rate=%lu volt=%lu", name(), sec.count(), static_cast<int>(m_percentage), cap,
|
||||
rate, volt);
|
||||
|
||||
if (sec.count() > 0) {
|
||||
t.tm_hour = chrono::duration_cast<chrono::hours>(sec).count();
|
||||
sec -= chrono::seconds{3600 * t.tm_hour};
|
||||
t.tm_min = chrono::duration_cast<chrono::minutes>(sec).count();
|
||||
sec -= chrono::seconds{60 * t.tm_min};
|
||||
t.tm_sec = chrono::duration_cast<chrono::seconds>(sec).count();
|
||||
}
|
||||
}
|
||||
|
||||
char buffer[256]{0};
|
||||
strftime(buffer, sizeof(buffer), m_timeformat.c_str(), &t);
|
||||
|
||||
return {buffer};
|
||||
}
|
||||
|
||||
/**
|
||||
* Subthread runner that emit update events
|
||||
* to refresh <animation-charging> in case it is used.
|
||||
|
Loading…
Reference in New Issue
Block a user