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"
|
set(SETTING_ALSA_SOUNDCARD "default"
|
||||||
CACHE STRING "Name of the ALSA soundcard driver")
|
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"
|
set(SETTING_BSPWM_SOCKET_PATH "/tmp/bspwm_0_0-socket"
|
||||||
CACHE STRING "Path to bspwm socket")
|
CACHE STRING "Path to bspwm socket")
|
||||||
set(SETTING_BSPWM_STATUS_PREFIX "W"
|
set(SETTING_BSPWM_STATUS_PREFIX "W"
|
||||||
CACHE STRING "Prefix prepended to the bspwm status line")
|
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"
|
set(SETTING_PATH_CPU_INFO "/proc/stat"
|
||||||
CACHE STRING "Path to file containing cpu info")
|
CACHE STRING "Path to file containing cpu info")
|
||||||
set(SETTING_PATH_MEMORY_INFO "/proc/meminfo"
|
set(SETTING_PATH_MEMORY_INFO "/proc/meminfo"
|
||||||
CACHE STRING "Path to file containing memory info")
|
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%"
|
set(SETTING_PATH_MESSAGING_FIFO "/tmp/polybar_mqueue.%pid%"
|
||||||
CACHE STRING "Path to file containing the current temperature")
|
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")
|
message(STATUS " Linking C++ library: system default")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
message(STATUS "---------------------------")
|
message(STATUS "--------------------------------------------")
|
||||||
message(STATUS " Build testsuite ${BUILD_TESTS}")
|
message(STATUS " Build testsuite ${BUILD_TESTS}")
|
||||||
message(STATUS " Enable debug logger ${DEBUG_LOGGER}")
|
message(STATUS " Enable debug logger ${DEBUG_LOGGER}")
|
||||||
message(STATUS " Enable extra tracing ${VERBOSE_TRACELOG}")
|
message(STATUS " Enable extra tracing ${VERBOSE_TRACELOG}")
|
||||||
message(STATUS " Enable ccache support ${ENABLE_CCACHE}")
|
message(STATUS " Enable ccache support ${ENABLE_CCACHE}")
|
||||||
message(STATUS "---------------------------")
|
message(STATUS "--------------------------------------------")
|
||||||
message(STATUS " Enable alsa support ${ENABLE_ALSA}")
|
message(STATUS " Enable alsa support ${ENABLE_ALSA}")
|
||||||
message(STATUS " Enable i3 support ${ENABLE_I3}")
|
message(STATUS " Enable i3 support ${ENABLE_I3}")
|
||||||
message(STATUS " Enable mpd support ${ENABLE_MPD}")
|
message(STATUS " Enable mpd support ${ENABLE_MPD}")
|
||||||
message(STATUS " Enable network support ${ENABLE_NETWORK}")
|
message(STATUS " Enable network support ${ENABLE_NETWORK}")
|
||||||
message(STATUS "---------------------------")
|
message(STATUS "--------------------------------------------")
|
||||||
message(STATUS " Enable X RandR ${ENABLE_RANDR_EXT}")
|
message(STATUS " Enable X RandR ${ENABLE_RANDR_EXT}")
|
||||||
message(STATUS " Enable X Render ${ENABLE_RENDER_EXT}")
|
message(STATUS " Enable X Render ${ENABLE_RENDER_EXT}")
|
||||||
message(STATUS " Enable X Damage ${ENABLE_DAMAGE_EXT}")
|
message(STATUS " Enable X Damage ${ENABLE_DAMAGE_EXT}")
|
||||||
message(STATUS "---------------------------")
|
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
|
#endif
|
||||||
|
|
||||||
#define BUILDER_SPACE_TOKEN "%__"
|
#define BUILDER_SPACE_TOKEN "%__"
|
||||||
|
|
||||||
#define ALSA_SOUNDCARD "@SETTING_ALSA_SOUNDCARD@"
|
#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_SOCKET_PATH "@SETTING_BSPWM_SOCKET_PATH@"
|
||||||
#define BSPWM_STATUS_PREFIX "@SETTING_BSPWM_STATUS_PREFIX@"
|
#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_CPU_INFO "@SETTING_PATH_CPU_INFO@"
|
||||||
#define PATH_MEMORY_INFO "@SETTING_PATH_MEMORY_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_MESSAGING_FIFO "@SETTING_PATH_MESSAGING_FIFO@"
|
||||||
|
#define PATH_TEMPERATURE_INFO "@SETTING_PATH_TEMPERATURE_INFO@"
|
||||||
|
|
||||||
auto print_build_info = []() {
|
auto print_build_info = []() {
|
||||||
// clang-format off
|
// clang-format off
|
||||||
@ -60,6 +65,11 @@ auto print_build_info = []() {
|
|||||||
<< "PATH_BACKLIGHT_MAX " << PATH_BACKLIGHT_MAX << "\n"
|
<< "PATH_BACKLIGHT_MAX " << PATH_BACKLIGHT_MAX << "\n"
|
||||||
<< "PATH_BACKLIGHT_VAL " << PATH_BACKLIGHT_VAL << "\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 " << 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_CPU_INFO " << PATH_CPU_INFO << "\n"
|
||||||
<< "PATH_MEMORY_INFO " << PATH_MEMORY_INFO << "\n"
|
<< "PATH_MEMORY_INFO " << PATH_MEMORY_INFO << "\n"
|
||||||
<< "PATH_TEMPERATURE_INFO " << PATH_TEMPERATURE_INFO << "\n";
|
<< "PATH_TEMPERATURE_INFO " << PATH_TEMPERATURE_INFO << "\n";
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "common.hpp"
|
||||||
#include "config.hpp"
|
#include "config.hpp"
|
||||||
#include "drawtypes/animation.hpp"
|
#include "drawtypes/animation.hpp"
|
||||||
#include "drawtypes/label.hpp"
|
#include "drawtypes/label.hpp"
|
||||||
@ -13,7 +14,23 @@
|
|||||||
POLYBAR_NS
|
POLYBAR_NS
|
||||||
|
|
||||||
namespace modules {
|
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> {
|
class battery_module : public inotify_module<battery_module> {
|
||||||
public:
|
public:
|
||||||
using inotify_module::inotify_module;
|
using inotify_module::inotify_module;
|
||||||
@ -29,6 +46,7 @@ namespace modules {
|
|||||||
protected:
|
protected:
|
||||||
int current_percentage();
|
int current_percentage();
|
||||||
battery_state current_state();
|
battery_state current_state();
|
||||||
|
string current_time();
|
||||||
void subthread();
|
void subthread();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -43,6 +61,8 @@ namespace modules {
|
|||||||
static constexpr auto TAG_LABEL_DISCHARGING = "<label-discharging>";
|
static constexpr auto TAG_LABEL_DISCHARGING = "<label-discharging>";
|
||||||
static constexpr auto TAG_LABEL_FULL = "<label-full>";
|
static constexpr auto TAG_LABEL_FULL = "<label-full>";
|
||||||
|
|
||||||
|
static const int SKIP_N_UNCHANGED{3};
|
||||||
|
|
||||||
animation_t m_animation_charging;
|
animation_t m_animation_charging;
|
||||||
ramp_t m_ramp_capacity;
|
ramp_t m_ramp_capacity;
|
||||||
progressbar_t m_bar_capacity;
|
progressbar_t m_bar_capacity;
|
||||||
@ -50,18 +70,14 @@ namespace modules {
|
|||||||
label_t m_label_discharging;
|
label_t m_label_discharging;
|
||||||
label_t m_label_full;
|
label_t m_label_full;
|
||||||
|
|
||||||
string m_battery;
|
battery_state m_state{battery_state::DISCHARGING};
|
||||||
string m_adapter;
|
map<battery_value, string> m_valuepath;
|
||||||
string m_path_capacity;
|
std::atomic<int> m_percentage{0};
|
||||||
string m_path_adapter;
|
int m_fullat{100};
|
||||||
|
|
||||||
battery_state m_state = battery_state::UNKNOWN;
|
|
||||||
std::atomic_int m_percentage{0};
|
|
||||||
|
|
||||||
interval_t m_interval;
|
interval_t m_interval;
|
||||||
chrono::system_clock::time_point m_lastpoll;
|
chrono::system_clock::time_point m_lastpoll;
|
||||||
|
string m_timeformat;
|
||||||
int m_fullat = 100;
|
int m_unchanged{SKIP_N_UNCHANGED};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,41 +4,40 @@
|
|||||||
POLYBAR_NS
|
POLYBAR_NS
|
||||||
|
|
||||||
namespace modules {
|
namespace modules {
|
||||||
|
/**
|
||||||
|
* Bootstrap module by setting up required components
|
||||||
|
*/
|
||||||
void battery_module::setup() {
|
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_fullat = m_conf.get<int>(name(), "full-at", 100);
|
||||||
m_interval = interval_t{m_conf.get<float>(name(), "poll-interval", 5.0f)};
|
m_interval = interval_t{m_conf.get<float>(name(), "poll-interval", 5.0f)};
|
||||||
m_lastpoll = chrono::system_clock::now();
|
m_lastpoll = chrono::system_clock::now();
|
||||||
|
|
||||||
m_path_capacity = string_util::replace(PATH_BATTERY_CAPACITY, "%battery%", m_battery);
|
// Load state and capacity level
|
||||||
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 {{{
|
|
||||||
|
|
||||||
m_percentage = current_percentage();
|
m_percentage = current_percentage();
|
||||||
m_state = current_state();
|
m_state = current_state();
|
||||||
|
|
||||||
// }}}
|
// Add formats and elements
|
||||||
// Add formats and elements {{{
|
|
||||||
|
|
||||||
m_formatter->add(FORMAT_CHARGING, TAG_LABEL_CHARGING,
|
m_formatter->add(FORMAT_CHARGING, TAG_LABEL_CHARGING,
|
||||||
{TAG_BAR_CAPACITY, TAG_RAMP_CAPACITY, TAG_ANIMATION_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(
|
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))
|
if (m_formatter->has(TAG_ANIMATION_CHARGING, FORMAT_CHARGING))
|
||||||
m_animation_charging = load_animation(m_conf, name(), TAG_ANIMATION_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);
|
m_bar_capacity = load_progressbar(m_bar, m_conf, name(), TAG_BAR_CAPACITY);
|
||||||
if (m_formatter->has(TAG_RAMP_CAPACITY))
|
if (m_formatter->has(TAG_RAMP_CAPACITY))
|
||||||
m_ramp_capacity = load_ramp(m_conf, name(), 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%");
|
m_label_charging = load_optional_label(m_conf, name(), TAG_LABEL_CHARGING, "%percentage%");
|
||||||
}
|
if (m_formatter->has(TAG_LABEL_DISCHARGING, FORMAT_DISCHARGING))
|
||||||
if (m_formatter->has(TAG_LABEL_DISCHARGING, FORMAT_DISCHARGING)) {
|
m_label_discharging = load_optional_label(m_conf, name(), TAG_LABEL_DISCHARGING, "%percentage%");
|
||||||
m_label_discharging =
|
if (m_formatter->has(TAG_LABEL_FULL, FORMAT_FULL))
|
||||||
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%");
|
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 {{{
|
* Dispatch the subthread used to update the
|
||||||
|
* charging animation when the module is started
|
||||||
watch(m_path_capacity, IN_ACCESS);
|
*/
|
||||||
watch(m_path_adapter, IN_ACCESS);
|
|
||||||
|
|
||||||
// }}}
|
|
||||||
}
|
|
||||||
|
|
||||||
void battery_module::start() {
|
void battery_module::start() {
|
||||||
inotify_module::start();
|
inotify_module::start();
|
||||||
m_threads.emplace_back(thread(&battery_module::subthread, this));
|
m_threads.emplace_back(thread(&battery_module::subthread, this));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Release wake lock when stopping the module
|
||||||
|
*/
|
||||||
void battery_module::teardown() {
|
void battery_module::teardown() {
|
||||||
wakeup();
|
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() {
|
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) {
|
if (m_interval.count() > 0) {
|
||||||
auto now = chrono::system_clock::now();
|
auto now = chrono::system_clock::now();
|
||||||
|
|
||||||
if (chrono::duration_cast<decltype(m_interval)>(now - m_lastpoll) > m_interval) {
|
if (chrono::duration_cast<decltype(m_interval)>(now - m_lastpoll) > m_interval) {
|
||||||
m_lastpoll = now;
|
m_lastpoll = now;
|
||||||
m_log.info("%s: Polling values (inotify fallback)", name());
|
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();
|
inotify_module::idle();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update values when tracked files have changed
|
||||||
|
*/
|
||||||
bool battery_module::on_event(inotify_event* event) {
|
bool battery_module::on_event(inotify_event* event) {
|
||||||
if (event != nullptr) {
|
if (event != nullptr) {
|
||||||
m_log.trace("%s: Inotify event reported for %s", name(), event->filename);
|
m_log.trace("%s: Inotify event reported for %s", name(), event->filename);
|
||||||
@ -106,45 +121,29 @@ namespace modules {
|
|||||||
percentage = current_percentage();
|
percentage = current_percentage();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ignore unchanged state
|
if (event != nullptr && state == m_state && percentage == m_percentage && m_unchanged--) {
|
||||||
if (event != nullptr && m_state == state && m_percentage == percentage) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_percentage = percentage;
|
m_percentage = percentage;
|
||||||
m_state = state;
|
m_state = state;
|
||||||
|
m_unchanged = SKIP_N_UNCHANGED;
|
||||||
|
|
||||||
string time_remaining;
|
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;
|
if (m_state == battery_state::CHARGING && m_label_charging) {
|
||||||
seconds -= 3600 * hours;
|
if (!m_timeformat.empty())
|
||||||
int minutes = seconds / 60;
|
time_remaining = current_time();
|
||||||
seconds -= 60 * minutes;
|
|
||||||
char buffer[9]{0};
|
|
||||||
snprintf(buffer, sizeof(buffer), "%02d:%02d:%02d", hours, minutes, seconds);
|
|
||||||
time_remaining = buffer;
|
|
||||||
|
|
||||||
|
|
||||||
if (m_label_charging) {
|
|
||||||
m_label_charging->reset_tokens();
|
m_label_charging->reset_tokens();
|
||||||
m_label_charging->replace_token("%percentage%", to_string(m_percentage) + "%");
|
m_label_charging->replace_token("%percentage%", to_string(m_percentage) + "%");
|
||||||
m_label_charging->replace_token("%time%", time_remaining);
|
m_label_charging->replace_token("%time%", time_remaining);
|
||||||
}
|
} else if (m_state == battery_state::DISCHARGING && m_label_discharging) {
|
||||||
if (m_label_discharging) {
|
if (!m_timeformat.empty())
|
||||||
|
time_remaining = current_time();
|
||||||
m_label_discharging->reset_tokens();
|
m_label_discharging->reset_tokens();
|
||||||
m_label_discharging->replace_token("%percentage%", to_string(m_percentage) + "%");
|
m_label_discharging->replace_token("%percentage%", to_string(m_percentage) + "%");
|
||||||
m_label_discharging->replace_token("%time%", time_remaining);
|
m_label_discharging->replace_token("%time%", time_remaining);
|
||||||
}
|
} else if (m_state == battery_state::FULL && m_label_full) {
|
||||||
if (m_label_full) {
|
|
||||||
m_label_full->reset_tokens();
|
m_label_full->reset_tokens();
|
||||||
m_label_full->replace_token("%percentage%", to_string(m_percentage) + "%");
|
m_label_full->replace_token("%percentage%", to_string(m_percentage) + "%");
|
||||||
}
|
}
|
||||||
@ -152,6 +151,9 @@ namespace modules {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the output format based on state
|
||||||
|
*/
|
||||||
string battery_module::get_format() const {
|
string battery_module::get_format() const {
|
||||||
if (m_state == battery_state::FULL)
|
if (m_state == battery_state::FULL)
|
||||||
return FORMAT_FULL;
|
return FORMAT_FULL;
|
||||||
@ -161,6 +163,9 @@ namespace modules {
|
|||||||
return FORMAT_DISCHARGING;
|
return FORMAT_DISCHARGING;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate the module output using defined drawtypes
|
||||||
|
*/
|
||||||
bool battery_module::build(builder* builder, string tag) const {
|
bool battery_module::build(builder* builder, string tag) const {
|
||||||
if (tag == TAG_ANIMATION_CHARGING)
|
if (tag == TAG_ANIMATION_CHARGING)
|
||||||
builder->node(m_animation_charging->get());
|
builder->node(m_animation_charging->get());
|
||||||
@ -179,15 +184,18 @@ namespace modules {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the current battery state
|
||||||
|
*/
|
||||||
battery_state battery_module::current_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()) {
|
if (adapter_status.empty()) {
|
||||||
return battery_state::UNKNOWN;
|
return battery_state::DISCHARGING;
|
||||||
} else if (adapter_status[0] == '0') {
|
} else if (adapter_status[0] == '0') {
|
||||||
return battery_state::DISCHARGING;
|
return battery_state::DISCHARGING;
|
||||||
} else if (adapter_status[0] != '1') {
|
} else if (adapter_status[0] != '1') {
|
||||||
return battery_state::UNKNOWN;
|
return battery_state::DISCHARGING;
|
||||||
} else if (m_percentage < m_fullat) {
|
} else if (m_percentage < m_fullat) {
|
||||||
return battery_state::CHARGING;
|
return battery_state::CHARGING;
|
||||||
} else {
|
} else {
|
||||||
@ -199,7 +207,7 @@ namespace modules {
|
|||||||
* Get the current capacity level
|
* Get the current capacity level
|
||||||
*/
|
*/
|
||||||
int battery_module::current_percentage() {
|
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);
|
auto value = math_util::cap<int>(std::atof(capacity.c_str()), 0, 100);
|
||||||
|
|
||||||
if (value >= m_fullat) {
|
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
|
* Subthread runner that emit update events
|
||||||
* to refresh <animation-charging> in case it is used.
|
* to refresh <animation-charging> in case it is used.
|
||||||
|
Loading…
Reference in New Issue
Block a user