parent
14958bdd23
commit
ad0af86a7b
@ -282,7 +282,7 @@ class config {
|
||||
string filename{move(var)};
|
||||
|
||||
if (file_util::exists(filename)) {
|
||||
return convert<T>(string_util::trim(file_util::get_contents(filename), '\n'));
|
||||
return convert<T>(string_util::trim(file_util::contents(filename), '\n'));
|
||||
}
|
||||
|
||||
return fallback;
|
||||
|
@ -1,7 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "common.hpp"
|
||||
#include "config.hpp"
|
||||
#include "modules/meta/inotify_module.hpp"
|
||||
|
||||
POLYBAR_NS
|
||||
@ -25,6 +24,25 @@ namespace modules {
|
||||
RATE,
|
||||
};
|
||||
|
||||
template <typename ReturnType>
|
||||
struct value_reader {
|
||||
using return_type = ReturnType;
|
||||
|
||||
explicit value_reader() = default;
|
||||
explicit value_reader(function<ReturnType()>&& fn) : m_fn(forward<decltype(fn)>(fn)) {}
|
||||
|
||||
ReturnType read() const {
|
||||
return m_fn();
|
||||
}
|
||||
|
||||
private:
|
||||
const function<ReturnType()> m_fn;
|
||||
};
|
||||
|
||||
using state_reader = mutex_wrapper<value_reader<bool /* is_charging */>>;
|
||||
using capacity_reader = mutex_wrapper<value_reader<int /* percentage */>>;
|
||||
using rate_reader = mutex_wrapper<value_reader<unsigned long /* seconds */>>;
|
||||
|
||||
public:
|
||||
explicit battery_module(const bar_settings&, string);
|
||||
|
||||
@ -36,40 +54,51 @@ namespace modules {
|
||||
bool build(builder* builder, const string& tag) const;
|
||||
|
||||
protected:
|
||||
int current_percentage();
|
||||
battery_module::state current_state();
|
||||
state current_state();
|
||||
int current_percentage(state state);
|
||||
string current_time();
|
||||
void subthread();
|
||||
|
||||
private:
|
||||
static constexpr auto FORMAT_CHARGING = "format-charging";
|
||||
static constexpr auto FORMAT_DISCHARGING = "format-discharging";
|
||||
static constexpr auto FORMAT_FULL = "format-full";
|
||||
static constexpr const char* FORMAT_CHARGING{"format-charging"};
|
||||
static constexpr const char* FORMAT_DISCHARGING{"format-discharging"};
|
||||
static constexpr const char* FORMAT_FULL{"format-full"};
|
||||
|
||||
static constexpr auto TAG_ANIMATION_CHARGING = "<animation-charging>";
|
||||
static constexpr auto TAG_BAR_CAPACITY = "<bar-capacity>";
|
||||
static constexpr auto TAG_RAMP_CAPACITY = "<ramp-capacity>";
|
||||
static constexpr auto TAG_LABEL_CHARGING = "<label-charging>";
|
||||
static constexpr auto TAG_LABEL_DISCHARGING = "<label-discharging>";
|
||||
static constexpr auto TAG_LABEL_FULL = "<label-full>";
|
||||
static constexpr const char* TAG_ANIMATION_CHARGING{"<animation-charging>"};
|
||||
static constexpr const char* TAG_BAR_CAPACITY{"<bar-capacity>"};
|
||||
static constexpr const char* TAG_RAMP_CAPACITY{"<ramp-capacity>"};
|
||||
static constexpr const char* TAG_LABEL_CHARGING{"<label-charging>"};
|
||||
static constexpr const char* TAG_LABEL_DISCHARGING{"<label-discharging>"};
|
||||
static constexpr const char* TAG_LABEL_FULL{"<label-full>"};
|
||||
|
||||
static const int SKIP_N_UNCHANGED{3};
|
||||
static const size_t SKIP_N_UNCHANGED{3_z};
|
||||
|
||||
unique_ptr<state_reader> m_state_reader;
|
||||
unique_ptr<capacity_reader> m_capacity_reader;
|
||||
unique_ptr<rate_reader> m_rate_reader;
|
||||
|
||||
animation_t m_animation_charging;
|
||||
ramp_t m_ramp_capacity;
|
||||
progressbar_t m_bar_capacity;
|
||||
label_t m_label_charging;
|
||||
label_t m_label_discharging;
|
||||
label_t m_label_full;
|
||||
animation_t m_animation_charging;
|
||||
progressbar_t m_bar_capacity;
|
||||
ramp_t m_ramp_capacity;
|
||||
|
||||
string m_fstate;
|
||||
string m_fcapnow;
|
||||
string m_fcapfull;
|
||||
string m_frate;
|
||||
string m_fvoltage;
|
||||
|
||||
state m_state{state::DISCHARGING};
|
||||
int m_percentage{0};
|
||||
|
||||
battery_module::state m_state{battery_module::state::DISCHARGING};
|
||||
map<value, string> m_valuepath;
|
||||
std::atomic<int> m_percentage{0};
|
||||
int m_fullat{100};
|
||||
string m_timeformat;
|
||||
size_t m_unchanged{SKIP_N_UNCHANGED};
|
||||
chrono::duration<double> m_interval{};
|
||||
chrono::system_clock::time_point m_lastpoll;
|
||||
string m_timeformat;
|
||||
int m_unchanged{SKIP_N_UNCHANGED};
|
||||
thread m_subthread;
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -23,6 +23,7 @@ namespace modules {
|
||||
CAST_MOD(Impl)->broadcast();
|
||||
|
||||
while (this->running()) {
|
||||
std::lock_guard<std::mutex> guard(this->m_updatelock);
|
||||
CAST_MOD(Impl)->poll_events();
|
||||
}
|
||||
} catch (const module_error& err) {
|
||||
@ -57,8 +58,6 @@ namespace modules {
|
||||
}
|
||||
|
||||
while (this->running()) {
|
||||
std::unique_lock<std::mutex> guard(this->m_updatelock);
|
||||
|
||||
for (auto&& w : watches) {
|
||||
this->m_log.trace_x("%s: Poll inotify watch %s", this->name(), w->path());
|
||||
|
||||
@ -66,11 +65,7 @@ namespace modules {
|
||||
auto event = w->get_event();
|
||||
|
||||
for (auto&& w : watches) {
|
||||
try {
|
||||
w->remove();
|
||||
} catch (const system_error&) {
|
||||
// ignore
|
||||
}
|
||||
w->remove(true);
|
||||
}
|
||||
|
||||
if (CAST_MOD(Impl)->on_event(event.get())) {
|
||||
@ -83,8 +78,6 @@ namespace modules {
|
||||
if (!this->running())
|
||||
break;
|
||||
}
|
||||
|
||||
guard.unlock();
|
||||
CAST_MOD(Impl)->idle();
|
||||
}
|
||||
}
|
||||
|
@ -93,7 +93,8 @@ class fd_stream : public StreamType {
|
||||
|
||||
namespace file_util {
|
||||
bool exists(const string& filename);
|
||||
string get_contents(const string& filename);
|
||||
string pick(const vector<string>& filenames);
|
||||
string contents(const string& filename);
|
||||
bool is_fifo(string filename);
|
||||
|
||||
template <typename... Args>
|
||||
|
@ -182,8 +182,7 @@ namespace net {
|
||||
* Test if the network interface is in a valid state
|
||||
*/
|
||||
bool network::test_interface() const {
|
||||
auto operstate = file_util::get_contents("/sys/class/net/" + m_interface + "/operstate");
|
||||
return operstate.compare(0, 2, "up") == 0;
|
||||
return file_util::contents("/sys/class/net/" + m_interface + "/operstate").compare(0, 2, "up") == 0;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -20,7 +20,7 @@ namespace modules {
|
||||
}
|
||||
|
||||
float backlight_module::brightness_handle::read() const {
|
||||
return std::strtof(file_util::get_contents(m_path).c_str(), nullptr);
|
||||
return std::strtof(file_util::contents(m_path).c_str(), nullptr);
|
||||
}
|
||||
|
||||
backlight_module::backlight_module(const bar_settings& bar, string name_)
|
||||
|
@ -1,10 +1,8 @@
|
||||
#include "modules/battery.hpp"
|
||||
|
||||
#include "drawtypes/animation.hpp"
|
||||
#include "drawtypes/label.hpp"
|
||||
#include "drawtypes/progressbar.hpp"
|
||||
#include "drawtypes/ramp.hpp"
|
||||
|
||||
#include "utils/file.hpp"
|
||||
#include "utils/math.hpp"
|
||||
|
||||
@ -15,60 +13,71 @@ POLYBAR_NS
|
||||
namespace modules {
|
||||
template class module<battery_module>;
|
||||
|
||||
template <typename ValueReader>
|
||||
typename ValueReader::return_type read(ValueReader& reader) {
|
||||
std::lock_guard<ValueReader> guard(reader);
|
||||
return reader.read();
|
||||
}
|
||||
|
||||
/**
|
||||
* Bootstrap module by setting up required components
|
||||
*/
|
||||
battery_module::battery_module(const bar_settings& bar, string name_)
|
||||
: inotify_module<battery_module>(bar, move(name_)) {
|
||||
auto battery = m_conf.get(name(), "battery", "BAT0"s);
|
||||
auto adapter = m_conf.get(name(), "adapter", "ADP1"s);
|
||||
|
||||
auto path_adapter = string_util::replace(PATH_ADAPTER, "%adapter%", adapter) + "/";
|
||||
auto path_battery = string_util::replace(PATH_BATTERY, "%battery%", battery) + "/";
|
||||
|
||||
if (!file_util::exists(path_adapter + "online")) {
|
||||
throw module_error("The file '" + path_adapter + "online' does not exist");
|
||||
}
|
||||
m_valuepath[battery_module::value::ADAPTER] = path_adapter + "online";
|
||||
|
||||
if (!file_util::exists(path_battery + "voltage_now")) {
|
||||
throw module_error("The file '" + path_battery + "voltage_now' does not exist");
|
||||
}
|
||||
m_valuepath[battery_module::value::VOLTAGE] = path_battery + "voltage_now";
|
||||
|
||||
for (auto&& file : vector<string>{"charge", "energy"}) {
|
||||
if (file_util::exists(path_battery + file + "_now")) {
|
||||
m_valuepath[battery_module::value::CAPACITY] = path_battery + file + "_now";
|
||||
}
|
||||
if (file_util::exists(path_battery + file + "_full")) {
|
||||
m_valuepath[battery_module::value::CAPACITY_MAX] = path_battery + file + "_full";
|
||||
}
|
||||
}
|
||||
|
||||
if (m_valuepath[battery_module::value::CAPACITY].empty()) {
|
||||
throw module_error("The file '" + path_battery + "[charge|energy]_now' does not exist");
|
||||
}
|
||||
if (m_valuepath[battery_module::value::CAPACITY_MAX].empty()) {
|
||||
throw module_error("The file '" + path_battery + "[charge|energy]_full' does not exist");
|
||||
}
|
||||
|
||||
for (auto&& file : vector<string>{"current", "power"}) {
|
||||
if (file_util::exists(path_battery + file + "_now")) {
|
||||
m_valuepath[battery_module::value::RATE] = path_battery + file + "_now";
|
||||
}
|
||||
}
|
||||
|
||||
if (m_valuepath[battery_module::value::RATE].empty()) {
|
||||
throw module_error("The file '" + path_battery + "[current|power]_now' does not exist");
|
||||
}
|
||||
|
||||
m_fullat = m_conf.get(name(), "full-at", 100);
|
||||
m_interval = m_conf.get(name(), "poll-interval", 5s);
|
||||
// Load configuration values
|
||||
m_fullat = m_conf.get(name(), "full-at", m_fullat);
|
||||
m_interval = m_conf.get<decltype(m_interval)>(name(), "poll-interval", 5s);
|
||||
m_lastpoll = chrono::system_clock::now();
|
||||
|
||||
auto path_adapter = string_util::replace(PATH_ADAPTER, "%adapter%", m_conf.get(name(), "adapter", "ADP1"s)) + "/";
|
||||
auto path_battery = string_util::replace(PATH_BATTERY, "%battery%", m_conf.get(name(), "battery", "BAT0"s)) + "/";
|
||||
|
||||
// Make state reader
|
||||
if (file_util::exists((m_fstate = path_adapter + "online"))) {
|
||||
m_state_reader = make_unique<state_reader>([=] { return file_util::contents(m_fstate).erase(1) == "1"; });
|
||||
} else if (file_util::exists((m_fstate = path_battery + "status"))) {
|
||||
m_state_reader = make_unique<state_reader>([=] { return file_util::contents(m_fstate).erase(8) == "Charging"; });
|
||||
} else {
|
||||
throw module_error("No suitable way to get current charge state");
|
||||
}
|
||||
|
||||
// Make capacity reader
|
||||
if ((m_fcapnow = file_util::pick({path_battery + "charge_now", path_battery + "energy_now"})).empty()) {
|
||||
throw module_error("No suitable way to get current capacity value");
|
||||
} else if ((m_fcapfull = file_util::pick({path_battery + "charge_full", path_battery + "energy_full"})).empty()) {
|
||||
throw module_error("No suitable way to get max capacity value");
|
||||
}
|
||||
|
||||
m_capacity_reader = make_unique<capacity_reader>([=] {
|
||||
auto cap_now = std::strtoul(file_util::contents(m_fcapnow).c_str(), nullptr, 10);
|
||||
auto cap_max = std::strtoul(file_util::contents(m_fcapfull).c_str(), nullptr, 10);
|
||||
return math_util::percentage(cap_now, 0UL, cap_max);
|
||||
});
|
||||
|
||||
// Make rate reader
|
||||
if ((m_fvoltage = file_util::pick({path_battery + "voltage_now"})).empty()) {
|
||||
throw module_error("No suitable way to get current voltage value");
|
||||
} else if ((m_frate = file_util::pick({path_battery + "current_now", path_battery + "power_now"})).empty()) {
|
||||
throw module_error("No suitable way to get current charge rate value");
|
||||
}
|
||||
|
||||
m_rate_reader = make_unique<rate_reader>([this] {
|
||||
unsigned long rate{std::strtoul(file_util::contents(m_frate).c_str(), nullptr, 10) / 1000UL};
|
||||
unsigned long volt{std::strtoul(file_util::contents(m_fvoltage).c_str(), nullptr, 10) / 1000UL};
|
||||
unsigned long now{std::strtoul(file_util::contents(m_fcapnow).c_str(), nullptr, 10) / 1000UL};
|
||||
unsigned long max{std::strtoul(file_util::contents(m_fcapfull).c_str(), nullptr, 10) / 1000UL};
|
||||
unsigned long cap{read(*m_state_reader) ? max - now : now};
|
||||
|
||||
if (rate && volt && cap) {
|
||||
return 3600UL * (cap * 1000UL / volt) / (rate * 1000UL / volt);
|
||||
} else {
|
||||
return 0UL;
|
||||
}
|
||||
});
|
||||
|
||||
// Load state and capacity level
|
||||
m_percentage = current_percentage();
|
||||
m_state = current_state();
|
||||
m_percentage = current_percentage(m_state);
|
||||
|
||||
// Add formats and elements
|
||||
m_formatter->add(FORMAT_CHARGING, TAG_LABEL_CHARGING,
|
||||
@ -97,11 +106,12 @@ namespace modules {
|
||||
}
|
||||
|
||||
// Create inotify watches
|
||||
watch(m_valuepath[battery_module::value::CAPACITY], IN_ACCESS);
|
||||
watch(m_valuepath[battery_module::value::ADAPTER], IN_ACCESS);
|
||||
watch(m_fcapnow, IN_ACCESS);
|
||||
watch(m_fstate, IN_ACCESS);
|
||||
|
||||
// Setup time if token is used
|
||||
if ((m_label_charging && m_label_charging->has_token("%time%")) || (m_label_discharging && m_label_discharging->has_token("%time%"))) {
|
||||
if ((m_label_charging && m_label_charging->has_token("%time%")) ||
|
||||
(m_label_discharging && m_label_discharging->has_token("%time%"))) {
|
||||
if (!m_bar.locale.empty()) {
|
||||
setlocale(LC_TIME, m_bar.locale.c_str());
|
||||
}
|
||||
@ -115,14 +125,16 @@ namespace modules {
|
||||
*/
|
||||
void battery_module::start() {
|
||||
this->inotify_module::start();
|
||||
m_threads.emplace_back(thread(&battery_module::subthread, this));
|
||||
m_subthread = thread(&battery_module::subthread, this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Release wake lock when stopping the module
|
||||
*/
|
||||
void battery_module::teardown() {
|
||||
wakeup();
|
||||
if (m_subthread.joinable()) {
|
||||
m_subthread.join();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -137,11 +149,10 @@ namespace modules {
|
||||
void battery_module::idle() {
|
||||
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_valuepath[battery_module::value::CAPACITY]);
|
||||
read(*m_capacity_reader);
|
||||
}
|
||||
}
|
||||
|
||||
@ -152,47 +163,40 @@ namespace modules {
|
||||
* 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);
|
||||
}
|
||||
auto state = current_state();
|
||||
auto percentage = current_percentage(state);
|
||||
|
||||
// Reset timer to avoid unnecessary polling
|
||||
m_lastpoll = chrono::system_clock::now();
|
||||
|
||||
auto state = current_state();
|
||||
int percentage = m_percentage;
|
||||
if (event != nullptr) {
|
||||
m_log.trace("%s: Inotify event reported for %s", name(), event->filename);
|
||||
|
||||
if (state != battery_module::state::FULL) {
|
||||
percentage = current_percentage();
|
||||
if (state == m_state && percentage == m_percentage && m_unchanged--) {
|
||||
return false;
|
||||
}
|
||||
|
||||
m_unchanged = SKIP_N_UNCHANGED;
|
||||
}
|
||||
|
||||
if (event != nullptr && state == m_state && percentage == m_percentage && m_unchanged--) {
|
||||
return false;
|
||||
}
|
||||
|
||||
m_percentage = percentage;
|
||||
m_state = state;
|
||||
m_unchanged = SKIP_N_UNCHANGED;
|
||||
m_percentage = percentage;
|
||||
|
||||
string time_remaining;
|
||||
const auto label = [this] {
|
||||
if (m_state == state::FULL) {
|
||||
return m_label_full;
|
||||
} else if (m_state == state::DISCHARGING) {
|
||||
return m_label_discharging;
|
||||
} else {
|
||||
return m_label_charging;
|
||||
}
|
||||
}();
|
||||
|
||||
if (m_state == battery_module::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);
|
||||
} else if (m_state == battery_module::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);
|
||||
} else if (m_state == battery_module::state::FULL && m_label_full) {
|
||||
m_label_full->reset_tokens();
|
||||
m_label_full->replace_token("%percentage%", to_string(m_percentage) + "%");
|
||||
label->reset_tokens();
|
||||
label->replace_token("%percentage%", to_string(m_percentage) + "%");
|
||||
|
||||
if (m_state != state::FULL && !m_timeformat.empty()) {
|
||||
label->replace_token("%time%", current_time());
|
||||
}
|
||||
|
||||
return true;
|
||||
@ -202,17 +206,17 @@ namespace modules {
|
||||
* Get the output format based on state
|
||||
*/
|
||||
string battery_module::get_format() const {
|
||||
if (m_state == battery_module::state::FULL) {
|
||||
return FORMAT_FULL;
|
||||
} else if (m_state == battery_module::state::CHARGING) {
|
||||
if (m_state == state::CHARGING) {
|
||||
return FORMAT_CHARGING;
|
||||
} else {
|
||||
} else if (m_state == state::DISCHARGING) {
|
||||
return FORMAT_DISCHARGING;
|
||||
} else {
|
||||
return FORMAT_FULL;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate the module output using defined drawtypes
|
||||
* Generate module output using defined drawtypes
|
||||
*/
|
||||
bool battery_module::build(builder* builder, const string& tag) const {
|
||||
if (tag == TAG_ANIMATION_CHARGING) {
|
||||
@ -230,6 +234,7 @@ namespace modules {
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -237,83 +242,45 @@ namespace modules {
|
||||
* Get the current battery state
|
||||
*/
|
||||
battery_module::state battery_module::current_state() {
|
||||
auto adapter_status = file_util::get_contents(m_valuepath[battery_module::value::ADAPTER]);
|
||||
|
||||
if (adapter_status.empty()) {
|
||||
return battery_module::state::DISCHARGING;
|
||||
} else if (adapter_status[0] == '0') {
|
||||
return battery_module::state::DISCHARGING;
|
||||
} else if (adapter_status[0] != '1') {
|
||||
return battery_module::state::DISCHARGING;
|
||||
} else if (m_percentage < m_fullat) {
|
||||
return battery_module::state::CHARGING;
|
||||
if (!read(*m_state_reader)) {
|
||||
return state::DISCHARGING;
|
||||
} else if (read(*m_capacity_reader) < m_fullat) {
|
||||
return state::CHARGING;
|
||||
} else {
|
||||
return battery_module::state::FULL;
|
||||
return state::FULL;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current capacity level
|
||||
*/
|
||||
int battery_module::current_percentage() {
|
||||
auto capacity_now =
|
||||
std::strtoul(file_util::get_contents(m_valuepath[battery_module::value::CAPACITY]).c_str(), nullptr, 10);
|
||||
auto capacity_max =
|
||||
std::strtoul(file_util::get_contents(m_valuepath[battery_module::value::CAPACITY_MAX]).c_str(), nullptr, 10);
|
||||
auto percentage = math_util::percentage(capacity_now, 0UL, capacity_max);
|
||||
|
||||
return percentage < m_fullat ? percentage : 100;
|
||||
int battery_module::current_percentage(state state) {
|
||||
int percentage{read(*m_capacity_reader)};
|
||||
if (state == state::FULL && percentage >= m_fullat) {
|
||||
percentage = 100;
|
||||
}
|
||||
return percentage;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get estimate of remaining time until fully dis-/charged
|
||||
*/
|
||||
string battery_module::current_time() {
|
||||
if (m_state == battery_module::state::FULL) {
|
||||
return "";
|
||||
}
|
||||
|
||||
int rate{atoi(file_util::get_contents(m_valuepath[battery_module::value::RATE]).c_str()) / 1000};
|
||||
int volt{atoi(file_util::get_contents(m_valuepath[battery_module::value::VOLTAGE]).c_str()) / 1000};
|
||||
int now{atoi(file_util::get_contents(m_valuepath[battery_module::value::CAPACITY]).c_str()) / 1000};
|
||||
int max{atoi(file_util::get_contents(m_valuepath[battery_module::value::CAPACITY_MAX]).c_str()) / 1000};
|
||||
int cap{0};
|
||||
|
||||
if (m_state == battery_module::state::CHARGING) {
|
||||
cap = max - now;
|
||||
} else if (m_state == battery_module::state::DISCHARGING) {
|
||||
cap = now;
|
||||
}
|
||||
|
||||
struct tm t {
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, nullptr
|
||||
};
|
||||
|
||||
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();
|
||||
}
|
||||
chrono::seconds sec{read(*m_rate_reader)};
|
||||
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};
|
||||
}
|
||||
|
||||
@ -322,18 +289,19 @@ namespace modules {
|
||||
* to refresh <animation-charging> in case it is used.
|
||||
*/
|
||||
void battery_module::subthread() {
|
||||
chrono::duration<double> dur = 1s;
|
||||
chrono::duration<double> dur{0.0};
|
||||
|
||||
if (m_animation_charging) {
|
||||
dur = chrono::duration<double>(float(m_animation_charging->framerate()) / 1000.0f);
|
||||
dur += chrono::milliseconds{m_animation_charging->framerate()};
|
||||
} else {
|
||||
dur += 1s;
|
||||
}
|
||||
|
||||
while (running()) {
|
||||
for (int i = 0; running() && i < dur.count(); ++i) {
|
||||
if (m_state == battery_module::state::CHARGING) {
|
||||
if (m_state == state::CHARGING) {
|
||||
broadcast();
|
||||
}
|
||||
|
||||
sleep(dur);
|
||||
}
|
||||
}
|
||||
|
@ -39,7 +39,7 @@ namespace modules {
|
||||
}
|
||||
|
||||
bool temperature_module::update() {
|
||||
m_temp = std::atoi(file_util::get_contents(m_path).c_str()) / 1000.0f + 0.5f;
|
||||
m_temp = std::atoi(file_util::contents(m_path).c_str()) / 1000.0f + 0.5f;
|
||||
m_perc = math_util::cap(math_util::percentage(m_temp, 0, m_tempwarn), 0, 100);
|
||||
|
||||
const auto replace_tokens = [&](label_t& label) {
|
||||
|
@ -169,14 +169,25 @@ namespace file_util {
|
||||
return stat(filename.c_str(), &buffer) == 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Picks the first existing file out of given entries
|
||||
*/
|
||||
string pick(const vector<string>& filenames) {
|
||||
for (auto&& f : filenames) {
|
||||
if (exists(f)) {
|
||||
return f;
|
||||
}
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the contents of the given file
|
||||
*/
|
||||
string get_contents(const string& filename) {
|
||||
string contents(const string& filename) {
|
||||
try {
|
||||
std::ifstream ifs(filename);
|
||||
string contents((std::istreambuf_iterator<char>(ifs)), (std::istreambuf_iterator<char>()));
|
||||
return contents;
|
||||
return string((std::istreambuf_iterator<char>(ifs)), (std::istreambuf_iterator<char>()));
|
||||
} catch (std::ios_base::failure& e) {
|
||||
return "";
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user