forked from NG-SD-Plugins/PowerTools
Re-add battery stats
This commit is contained in:
parent
db3f4a85c0
commit
26e781df25
10 changed files with 118 additions and 15 deletions
2
backend/Cargo.lock
generated
2
backend/Cargo.lock
generated
|
@ -567,7 +567,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "powertools-rs"
|
name = "powertools-rs"
|
||||||
version = "1.0.0-beta4"
|
version = "1.0.0-rc1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"log",
|
"log",
|
||||||
"serde",
|
"serde",
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "powertools-rs"
|
name = "powertools-rs"
|
||||||
version = "1.0.0-beta4"
|
version = "1.0.0-rc1"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
|
@ -6,7 +6,22 @@ use crate::utility::{unwrap_lock, unwrap_maybe_fatal};
|
||||||
|
|
||||||
/// Current current (ha!) web method
|
/// Current current (ha!) web method
|
||||||
pub fn current_now(_: super::ApiParameterType) -> super::ApiParameterType {
|
pub fn current_now(_: super::ApiParameterType) -> super::ApiParameterType {
|
||||||
super::utility::map_result(crate::settings::Battery::current_now())
|
super::utility::map_result(crate::settings::Battery::read_current_now())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Charge now web method
|
||||||
|
pub fn charge_now(_: super::ApiParameterType) -> super::ApiParameterType {
|
||||||
|
super::utility::map_result(crate::settings::Battery::read_charge_now())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Charge full web method
|
||||||
|
pub fn charge_full(_: super::ApiParameterType) -> super::ApiParameterType {
|
||||||
|
super::utility::map_result(crate::settings::Battery::read_charge_full())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Charge design web method
|
||||||
|
pub fn charge_design(_: super::ApiParameterType) -> super::ApiParameterType {
|
||||||
|
super::utility::map_result(crate::settings::Battery::read_charge_design())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Generate set battery charge rate web method
|
/// Generate set battery charge rate web method
|
||||||
|
|
|
@ -17,11 +17,14 @@ use usdpl_back::core::serdes::Primitive;
|
||||||
use usdpl_back::Instance;
|
use usdpl_back::Instance;
|
||||||
|
|
||||||
fn main() -> Result<(), ()> {
|
fn main() -> Result<(), ()> {
|
||||||
|
#[cfg(debug_assertions)]
|
||||||
let log_filepath = format!("/home/deck/{}.log", PACKAGE_NAME);
|
let log_filepath = format!("/home/deck/{}.log", PACKAGE_NAME);
|
||||||
|
#[cfg(not(debug_assertions))]
|
||||||
|
let log_filepath = format!("/tmp/{}.log", PACKAGE_NAME);
|
||||||
#[cfg(debug_assertions)]
|
#[cfg(debug_assertions)]
|
||||||
{
|
{
|
||||||
if std::path::Path::new(&log_filepath).exists() {
|
if std::path::Path::new(&log_filepath).exists() {
|
||||||
std::fs::copy(&log_filepath, "/home/deck/powertools.log.old").unwrap();
|
std::fs::copy(&log_filepath, format!("/home/deck/{}.log.old", PACKAGE_NAME)).unwrap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
WriteLogger::init(
|
WriteLogger::init(
|
||||||
|
@ -59,6 +62,9 @@ fn main() -> Result<(), ()> {
|
||||||
})
|
})
|
||||||
// battery API functions
|
// battery API functions
|
||||||
.register("BATTERY_current_now", api::battery::current_now)
|
.register("BATTERY_current_now", api::battery::current_now)
|
||||||
|
.register("BATTERY_charge_now", api::battery::charge_now)
|
||||||
|
.register("BATTERY_charge_full", api::battery::charge_full)
|
||||||
|
.register("BATTERY_charge_design", api::battery::charge_design)
|
||||||
.register(
|
.register(
|
||||||
"BATTERY_set_charge_rate",
|
"BATTERY_set_charge_rate",
|
||||||
api::battery::set_charge_rate(loaded_settings.battery.clone(), save_sender.clone()),
|
api::battery::set_charge_rate(loaded_settings.battery.clone(), save_sender.clone()),
|
||||||
|
|
|
@ -9,8 +9,13 @@ pub struct Battery {
|
||||||
state: crate::state::Battery,
|
state: crate::state::Battery,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const BATTERY_VOLTAGE: f64 = 7.7;
|
||||||
|
|
||||||
const BATTERY_CHARGE_RATE_PATH: &str = "/sys/class/hwmon/hwmon5/maximum_battery_charge_rate"; // write-only
|
const BATTERY_CHARGE_RATE_PATH: &str = "/sys/class/hwmon/hwmon5/maximum_battery_charge_rate"; // write-only
|
||||||
const BATTERY_CURRENT_NOW_PATH: &str = "/sys/class/power_supply/BAT1/current_now"; // read-only
|
const BATTERY_CURRENT_NOW_PATH: &str = "/sys/class/power_supply/BAT1/current_now"; // read-only
|
||||||
|
const BATTERY_CHARGE_NOW_PATH: &str = "/sys/class/hwmon/hwmon2/device/charge_now"; // read-only
|
||||||
|
const BATTERY_CHARGE_FULL_PATH: &str = "/sys/class/hwmon/hwmon2/device/charge_full"; // read-only
|
||||||
|
const BATTERY_CHARGE_DESIGN_PATH: &str = "/sys/class/hwmon/hwmon2/device/charge_full_design"; // read-only
|
||||||
|
|
||||||
impl Battery {
|
impl Battery {
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -57,7 +62,7 @@ impl Battery {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn current_now() -> Result<u64, SettingError> {
|
pub fn read_current_now() -> Result<u64, SettingError> {
|
||||||
match usdpl_back::api::files::read_single::<_, u64, _>(BATTERY_CURRENT_NOW_PATH) {
|
match usdpl_back::api::files::read_single::<_, u64, _>(BATTERY_CURRENT_NOW_PATH) {
|
||||||
Err((Some(e), None)) => Err(SettingError {
|
Err((Some(e), None)) => Err(SettingError {
|
||||||
msg: format!("Failed to read from `{}`: {}", BATTERY_CURRENT_NOW_PATH, e),
|
msg: format!("Failed to read from `{}`: {}", BATTERY_CURRENT_NOW_PATH, e),
|
||||||
|
@ -77,6 +82,63 @@ impl Battery {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn read_charge_now() -> Result<f64, SettingError> {
|
||||||
|
match usdpl_back::api::files::read_single::<_, u64, _>(BATTERY_CHARGE_NOW_PATH) {
|
||||||
|
Err((Some(e), None)) => Err(SettingError {
|
||||||
|
msg: format!("Failed to read from `{}`: {}", BATTERY_CHARGE_NOW_PATH, e),
|
||||||
|
setting: super::SettingVariant::Battery,
|
||||||
|
}),
|
||||||
|
Err((None, Some(e))) => Err(SettingError {
|
||||||
|
msg: format!("Failed to read from `{}`: {}", BATTERY_CHARGE_NOW_PATH, e),
|
||||||
|
setting: super::SettingVariant::Battery,
|
||||||
|
}),
|
||||||
|
Err(_) => panic!(
|
||||||
|
"Invalid error while reading from `{}`",
|
||||||
|
BATTERY_CHARGE_NOW_PATH
|
||||||
|
),
|
||||||
|
// convert to Wh
|
||||||
|
Ok(val) => Ok((val as f64) / 1000000.0 * BATTERY_VOLTAGE),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn read_charge_full() -> Result<f64, SettingError> {
|
||||||
|
match usdpl_back::api::files::read_single::<_, u64, _>(BATTERY_CHARGE_FULL_PATH) {
|
||||||
|
Err((Some(e), None)) => Err(SettingError {
|
||||||
|
msg: format!("Failed to read from `{}`: {}", BATTERY_CHARGE_FULL_PATH, e),
|
||||||
|
setting: super::SettingVariant::Battery,
|
||||||
|
}),
|
||||||
|
Err((None, Some(e))) => Err(SettingError {
|
||||||
|
msg: format!("Failed to read from `{}`: {}", BATTERY_CHARGE_FULL_PATH, e),
|
||||||
|
setting: super::SettingVariant::Battery,
|
||||||
|
}),
|
||||||
|
Err(_) => panic!(
|
||||||
|
"Invalid error while reading from `{}`",
|
||||||
|
BATTERY_CHARGE_NOW_PATH
|
||||||
|
),
|
||||||
|
// convert to Wh
|
||||||
|
Ok(val) => Ok((val as f64) / 1000000.0 * BATTERY_VOLTAGE),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn read_charge_design() -> Result<f64, SettingError> {
|
||||||
|
match usdpl_back::api::files::read_single::<_, u64, _>(BATTERY_CHARGE_DESIGN_PATH) {
|
||||||
|
Err((Some(e), None)) => Err(SettingError {
|
||||||
|
msg: format!("Failed to read from `{}`: {}", BATTERY_CHARGE_DESIGN_PATH, e),
|
||||||
|
setting: super::SettingVariant::Battery,
|
||||||
|
}),
|
||||||
|
Err((None, Some(e))) => Err(SettingError {
|
||||||
|
msg: format!("Failed to read from `{}`: {}", BATTERY_CHARGE_DESIGN_PATH, e),
|
||||||
|
setting: super::SettingVariant::Battery,
|
||||||
|
}),
|
||||||
|
Err(_) => panic!(
|
||||||
|
"Invalid error while reading from `{}`",
|
||||||
|
BATTERY_CHARGE_NOW_PATH
|
||||||
|
),
|
||||||
|
// convert to Wh
|
||||||
|
Ok(val) => Ok((val as f64) / 1000000.0 * BATTERY_VOLTAGE),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn system_default() -> Self {
|
pub fn system_default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
charge_rate: None,
|
charge_rate: None,
|
||||||
|
|
2
main.py
2
main.py
|
@ -11,6 +11,6 @@ class Plugin:
|
||||||
# Asyncio-compatible long-running code, executed in a task when the plugin is loaded
|
# Asyncio-compatible long-running code, executed in a task when the plugin is loaded
|
||||||
async def _main(self):
|
async def _main(self):
|
||||||
# startup
|
# startup
|
||||||
#self.backend_proc = subprocess.Popen([PARENT_DIR + "/bin/backend"])
|
self.backend_proc = subprocess.Popen([PARENT_DIR + "/bin/backend"])
|
||||||
while True:
|
while True:
|
||||||
await asyncio.sleep(1)
|
await asyncio.sleep(1)
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "PowerTools",
|
"name": "PowerTools",
|
||||||
"version": "1.0.0-alpha",
|
"version": "1.0.0-rc1",
|
||||||
"description": "Power tweaks for power users",
|
"description": "Power tweaks for power users",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "shx rm -rf dist && rollup -c",
|
"build": "shx rm -rf dist && rollup -c",
|
||||||
|
|
|
@ -36,6 +36,18 @@ export async function getBatteryCurrent(): Promise<number> {
|
||||||
return (await call_backend("BATTERY_current_now", []))[0];
|
return (await call_backend("BATTERY_current_now", []))[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function getBatteryChargeNow(): Promise<number> {
|
||||||
|
return (await call_backend("BATTERY_charge_now", []))[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function getBatteryChargeFull(): Promise<number> {
|
||||||
|
return (await call_backend("BATTERY_charge_full", []))[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function getBatteryChargeDesign(): Promise<number> {
|
||||||
|
return (await call_backend("BATTERY_charge_design", []))[0];
|
||||||
|
}
|
||||||
|
|
||||||
export async function getBatteryChargeRate(): Promise<number> {
|
export async function getBatteryChargeRate(): Promise<number> {
|
||||||
return (await call_backend("BATTERY_get_charge_rate", []))[0];
|
return (await call_backend("BATTERY_get_charge_rate", []))[0];
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,6 +37,9 @@ const BACKEND_INFO = "VINFO";
|
||||||
|
|
||||||
const CURRENT_BATT = "BATTERY_current_now";
|
const CURRENT_BATT = "BATTERY_current_now";
|
||||||
const CHARGE_RATE_BATT = "BATTERY_charge_rate";
|
const CHARGE_RATE_BATT = "BATTERY_charge_rate";
|
||||||
|
const CHARGE_NOW_BATT = "BATTERY_charge_now";
|
||||||
|
const CHARGE_FULL_BATT = "BATTERY_charge_full";
|
||||||
|
const CHARGE_DESIGN_BATT = "BATTERY_charge_design"
|
||||||
|
|
||||||
const TOTAL_CPUS = "CPUs_total";
|
const TOTAL_CPUS = "CPUs_total";
|
||||||
const ONLINE_CPUS = "CPUs_online";
|
const ONLINE_CPUS = "CPUs_online";
|
||||||
|
@ -58,6 +61,9 @@ const reload = function() {
|
||||||
|
|
||||||
backend.resolve(backend.getBatteryCurrent(), (rate: number) => { set_value(CURRENT_BATT, rate) });
|
backend.resolve(backend.getBatteryCurrent(), (rate: number) => { set_value(CURRENT_BATT, rate) });
|
||||||
backend.resolve(backend.getBatteryChargeRate(), (rate: number) => { set_value(CHARGE_RATE_BATT, rate) });
|
backend.resolve(backend.getBatteryChargeRate(), (rate: number) => { set_value(CHARGE_RATE_BATT, rate) });
|
||||||
|
backend.resolve(backend.getBatteryChargeNow(), (rate: number) => { set_value(CHARGE_NOW_BATT, rate) });
|
||||||
|
backend.resolve(backend.getBatteryChargeFull(), (rate: number) => { set_value(CHARGE_FULL_BATT, rate) });
|
||||||
|
backend.resolve(backend.getBatteryChargeDesign(), (rate: number) => { set_value(CHARGE_DESIGN_BATT, rate) });
|
||||||
|
|
||||||
backend.resolve(backend.getCpuCount(), (count: number) => { set_value(TOTAL_CPUS, count)});
|
backend.resolve(backend.getCpuCount(), (count: number) => { set_value(TOTAL_CPUS, count)});
|
||||||
backend.resolve(backend.getCpusOnline(), (statii: boolean[]) => {
|
backend.resolve(backend.getCpusOnline(), (statii: boolean[]) => {
|
||||||
|
@ -130,6 +136,8 @@ const reload = function() {
|
||||||
|
|
||||||
const periodicals = function() {
|
const periodicals = function() {
|
||||||
backend.resolve(backend.getBatteryCurrent(), (rate: number) => { set_value(CURRENT_BATT, rate) });
|
backend.resolve(backend.getBatteryCurrent(), (rate: number) => { set_value(CURRENT_BATT, rate) });
|
||||||
|
backend.resolve(backend.getBatteryChargeNow(), (rate: number) => { set_value(CHARGE_NOW_BATT, rate) });
|
||||||
|
backend.resolve(backend.getBatteryChargeFull(), (rate: number) => { set_value(CHARGE_FULL_BATT, rate) });
|
||||||
|
|
||||||
backend.resolve(backend.getGeneralPersistent(), (value: boolean) => { set_value(PERSISTENT_GEN, value) });
|
backend.resolve(backend.getGeneralPersistent(), (value: boolean) => { set_value(PERSISTENT_GEN, value) });
|
||||||
backend.resolve(backend.getGeneralSettingsName(), (name: string) => {
|
backend.resolve(backend.getGeneralSettingsName(), (name: string) => {
|
||||||
|
@ -457,30 +465,30 @@ const Content: VFC<{ serverAPI: ServerAPI }> = ({}) => {
|
||||||
<div className={staticClasses.PanelSectionTitle}>
|
<div className={staticClasses.PanelSectionTitle}>
|
||||||
Battery
|
Battery
|
||||||
</div>
|
</div>
|
||||||
{ false && <PanelSectionRow>
|
<PanelSectionRow>
|
||||||
<div className={FieldWithSeparator}>
|
<div className={FieldWithSeparator}>
|
||||||
<div className={gamepadDialogClasses.FieldLabelRow}>
|
<div className={gamepadDialogClasses.FieldLabelRow}>
|
||||||
<div className={gamepadDialogClasses.FieldLabel}>
|
<div className={gamepadDialogClasses.FieldLabel}>
|
||||||
Now (Charge)
|
Now (Charge)
|
||||||
</div>
|
</div>
|
||||||
<div className={gamepadDialogClasses.FieldChildren}>
|
<div className={gamepadDialogClasses.FieldChildren}>
|
||||||
{/* TODO: (7.7 * chargeNowGlobal / 1000000).toFixed(1).toString() + " Wh (" + (100 * chargeNowGlobal / chargeFullGlobal).toFixed(1).toString() + "%)"*/}
|
{get_value(CHARGE_NOW_BATT).toFixed(1)} Wh ({(100 * get_value(CHARGE_NOW_BATT) / get_value(CHARGE_FULL_BATT)).toFixed(1)}%)
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</PanelSectionRow>}
|
</PanelSectionRow>
|
||||||
{ false && <PanelSectionRow>
|
<PanelSectionRow>
|
||||||
<div className={FieldWithSeparator}>
|
<div className={FieldWithSeparator}>
|
||||||
<div className={gamepadDialogClasses.FieldLabelRow}>
|
<div className={gamepadDialogClasses.FieldLabelRow}>
|
||||||
<div className={gamepadDialogClasses.FieldLabel}>
|
<div className={gamepadDialogClasses.FieldLabel}>
|
||||||
Max (Design)
|
Max (Design)
|
||||||
</div>
|
</div>
|
||||||
<div className={gamepadDialogClasses.FieldChildren}>
|
<div className={gamepadDialogClasses.FieldChildren}>
|
||||||
{/* TODO: (7.7 * chargeFullGlobal / 1000000).toFixed(1).toString() + " Wh (" + (100 * chargeFullGlobal / chargeDesignGlobal).toFixed(1).toString() + "%)"*/}
|
{get_value(CHARGE_FULL_BATT).toFixed(1)} Wh ({(100 * get_value(CHARGE_FULL_BATT) / get_value(CHARGE_DESIGN_BATT)).toFixed(1)}%)
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</PanelSectionRow>}
|
</PanelSectionRow>
|
||||||
<PanelSectionRow>
|
<PanelSectionRow>
|
||||||
<ToggleField
|
<ToggleField
|
||||||
checked={get_value(CHARGE_RATE_BATT) != null}
|
checked={get_value(CHARGE_RATE_BATT) != null}
|
||||||
|
@ -553,7 +561,7 @@ const Content: VFC<{ serverAPI: ServerAPI }> = ({}) => {
|
||||||
<div className={FieldWithSeparator}>
|
<div className={FieldWithSeparator}>
|
||||||
<div className={gamepadDialogClasses.FieldLabelRow}>
|
<div className={gamepadDialogClasses.FieldLabelRow}>
|
||||||
<div className={gamepadDialogClasses.FieldLabel}>
|
<div className={gamepadDialogClasses.FieldLabel}>
|
||||||
Now Playing
|
Profile
|
||||||
</div>
|
</div>
|
||||||
<div className={gamepadDialogClasses.FieldChildren}>
|
<div className={gamepadDialogClasses.FieldChildren}>
|
||||||
{get_value(NAME_GEN)}
|
{get_value(NAME_GEN)}
|
||||||
|
|
Loading…
Reference in a new issue