forked from NG-SD-Plugins/PowerTools
Add charge mode setting for SD, move static battery readings into driver
This commit is contained in:
parent
1466c4647b
commit
2b2a6eaf9d
9 changed files with 201 additions and 56 deletions
|
@ -1,27 +1,101 @@
|
|||
use std::sync::mpsc::{Sender, self};
|
||||
use std::sync::Mutex;
|
||||
use std::sync::{Arc, Mutex};
|
||||
use usdpl_back::core::serdes::Primitive;
|
||||
use usdpl_back::AsyncCallable;
|
||||
|
||||
use super::handler::{ApiMessage, BatteryMessage};
|
||||
|
||||
/// Current current (ha!) web method
|
||||
pub fn current_now(_: super::ApiParameterType) -> super::ApiParameterType {
|
||||
super::utility::map_optional_result(crate::settings::driver::read_current_now())
|
||||
pub fn current_now(
|
||||
sender: Sender<ApiMessage>,
|
||||
) -> impl AsyncCallable {
|
||||
let sender = Arc::new(Mutex::new(sender)); // Sender is not Sync; this is required for safety
|
||||
let getter = move || {
|
||||
let sender2 = sender.clone();
|
||||
move || {
|
||||
let (tx, rx) = mpsc::channel();
|
||||
let callback = move |val: Option<f64>| tx.send(val).expect("current_now callback send failed");
|
||||
sender2.lock().unwrap().send(ApiMessage::Battery(BatteryMessage::ReadCurrentNow(Box::new(callback)))).expect("current_now send failed");
|
||||
rx.recv().expect("current_now callback recv failed")
|
||||
}
|
||||
};
|
||||
super::async_utils::AsyncIshGetter {
|
||||
set_get: getter,
|
||||
trans_getter: |result| {
|
||||
super::utility::map_optional_result(Ok(result))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Current current (ha!) web method
|
||||
/*pub fn current_now(_: super::ApiParameterType) -> super::ApiParameterType {
|
||||
super::utility::map_optional_result(crate::settings::driver::read_current_now())
|
||||
}*/
|
||||
|
||||
/// Charge now web method
|
||||
pub fn charge_now(_: super::ApiParameterType) -> super::ApiParameterType {
|
||||
super::utility::map_optional_result(crate::settings::driver::read_charge_now())
|
||||
pub fn charge_now(
|
||||
sender: Sender<ApiMessage>,
|
||||
) -> impl AsyncCallable {
|
||||
let sender = Arc::new(Mutex::new(sender)); // Sender is not Sync; this is required for safety
|
||||
let getter = move || {
|
||||
let sender2 = sender.clone();
|
||||
move || {
|
||||
let (tx, rx) = mpsc::channel();
|
||||
let callback = move |val: Option<f64>| tx.send(val).expect("charge_now callback send failed");
|
||||
sender2.lock().unwrap().send(ApiMessage::Battery(BatteryMessage::ReadChargeNow(Box::new(callback)))).expect("charge_now send failed");
|
||||
rx.recv().expect("charge_now callback recv failed")
|
||||
}
|
||||
};
|
||||
super::async_utils::AsyncIshGetter {
|
||||
set_get: getter,
|
||||
trans_getter: |result| {
|
||||
super::utility::map_optional_result(Ok(result))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Charge full web method
|
||||
pub fn charge_full(_: super::ApiParameterType) -> super::ApiParameterType {
|
||||
super::utility::map_optional_result(crate::settings::driver::read_charge_full())
|
||||
pub fn charge_full(
|
||||
sender: Sender<ApiMessage>,
|
||||
) -> impl AsyncCallable {
|
||||
let sender = Arc::new(Mutex::new(sender)); // Sender is not Sync; this is required for safety
|
||||
let getter = move || {
|
||||
let sender2 = sender.clone();
|
||||
move || {
|
||||
let (tx, rx) = mpsc::channel();
|
||||
let callback = move |val: Option<f64>| tx.send(val).expect("charge_full callback send failed");
|
||||
sender2.lock().unwrap().send(ApiMessage::Battery(BatteryMessage::ReadChargeFull(Box::new(callback)))).expect("charge_full send failed");
|
||||
rx.recv().expect("charge_full callback recv failed")
|
||||
}
|
||||
};
|
||||
super::async_utils::AsyncIshGetter {
|
||||
set_get: getter,
|
||||
trans_getter: |result| {
|
||||
super::utility::map_optional_result(Ok(result))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Charge design web method
|
||||
pub fn charge_design(_: super::ApiParameterType) -> super::ApiParameterType {
|
||||
super::utility::map_optional_result(crate::settings::driver::read_charge_design())
|
||||
pub fn charge_design(
|
||||
sender: Sender<ApiMessage>,
|
||||
) -> impl AsyncCallable {
|
||||
let sender = Arc::new(Mutex::new(sender)); // Sender is not Sync; this is required for safety
|
||||
let getter = move || {
|
||||
let sender2 = sender.clone();
|
||||
move || {
|
||||
let (tx, rx) = mpsc::channel();
|
||||
let callback = move |val: Option<f64>| tx.send(val).expect("charge_design callback send failed");
|
||||
sender2.lock().unwrap().send(ApiMessage::Battery(BatteryMessage::ReadChargeDesign(Box::new(callback)))).expect("charge_design send failed");
|
||||
rx.recv().expect("charge_design callback recv failed")
|
||||
}
|
||||
};
|
||||
super::async_utils::AsyncIshGetter {
|
||||
set_get: getter,
|
||||
trans_getter: |result| {
|
||||
super::utility::map_optional_result(Ok(result))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Generate set battery charge rate web method
|
||||
|
|
|
@ -24,6 +24,10 @@ pub enum BatteryMessage {
|
|||
GetChargeRate(Callback<Option<u64>>),
|
||||
SetChargeMode(Option<String>),
|
||||
GetChargeMode(Callback<Option<String>>),
|
||||
ReadChargeFull(Callback<Option<f64>>),
|
||||
ReadChargeNow(Callback<Option<f64>>),
|
||||
ReadChargeDesign(Callback<Option<f64>>),
|
||||
ReadCurrentNow(Callback<Option<f64>>),
|
||||
}
|
||||
|
||||
impl BatteryMessage {
|
||||
|
@ -33,6 +37,10 @@ impl BatteryMessage {
|
|||
Self::GetChargeRate(cb) => cb(settings.get_charge_rate()),
|
||||
Self::SetChargeMode(mode) => settings.charge_mode(mode),
|
||||
Self::GetChargeMode(cb) => cb(settings.get_charge_mode()),
|
||||
Self::ReadChargeFull(cb) => cb(settings.read_charge_full()),
|
||||
Self::ReadChargeNow(cb) => cb(settings.read_charge_now()),
|
||||
Self::ReadChargeDesign(cb) => cb(settings.read_charge_design()),
|
||||
Self::ReadCurrentNow(cb) => cb(settings.read_current_now()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -66,10 +66,10 @@ fn main() -> Result<(), ()> {
|
|||
vec![format!("{} v{}", PACKAGE_NAME, PACKAGE_VERSION).into()]
|
||||
})
|
||||
// battery API functions
|
||||
.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_async("BATTERY_current_now", api::battery::current_now(api_sender.clone()))
|
||||
.register_async("BATTERY_charge_now", api::battery::charge_now(api_sender.clone()))
|
||||
.register_async("BATTERY_charge_full", api::battery::charge_full(api_sender.clone()))
|
||||
.register_async("BATTERY_charge_design", api::battery::charge_design(api_sender.clone()))
|
||||
.register(
|
||||
"BATTERY_set_charge_rate",
|
||||
api::battery::set_charge_rate(api_sender.clone()),
|
||||
|
|
|
@ -142,44 +142,7 @@ impl Driver {
|
|||
}
|
||||
}
|
||||
|
||||
// static battery calls
|
||||
|
||||
#[inline]
|
||||
pub fn read_current_now() -> Result<Option<u64>, SettingError> {
|
||||
match auto_detect() {
|
||||
DriverJson::SteamDeck => super::steam_deck::Battery::read_current_now().map(|x| Some(x)),
|
||||
DriverJson::SteamDeckAdvance => super::steam_deck::Battery::read_current_now().map(|x| Some(x)),
|
||||
DriverJson::Unknown => Ok(None),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn read_charge_now() -> Result<Option<f64>, SettingError> {
|
||||
match auto_detect() {
|
||||
DriverJson::SteamDeck => super::steam_deck::Battery::read_charge_now().map(|x| Some(x)),
|
||||
DriverJson::SteamDeckAdvance => super::steam_deck::Battery::read_charge_now().map(|x| Some(x)),
|
||||
DriverJson::Unknown => Ok(None),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn read_charge_full() -> Result<Option<f64>, SettingError> {
|
||||
match auto_detect() {
|
||||
DriverJson::SteamDeck => super::steam_deck::Battery::read_charge_full().map(|x| Some(x)),
|
||||
DriverJson::SteamDeckAdvance => super::steam_deck::Battery::read_charge_full().map(|x| Some(x)),
|
||||
DriverJson::Unknown => Ok(None),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn read_charge_design() -> Result<Option<f64>, SettingError> {
|
||||
match auto_detect() {
|
||||
DriverJson::SteamDeck => super::steam_deck::Battery::read_charge_design().map(|x| Some(x)),
|
||||
DriverJson::SteamDeckAdvance => super::steam_deck::Battery::read_charge_design().map(|x| Some(x)),
|
||||
DriverJson::Unknown => Ok(None),
|
||||
}
|
||||
}
|
||||
|
||||
// sshhhh, this function isn't here ;)
|
||||
#[inline]
|
||||
pub fn maybe_do_button() {
|
||||
match auto_detect() {
|
||||
|
|
|
@ -242,7 +242,7 @@ impl TBattery for Battery {
|
|||
max: max.charge_rate.unwrap(),
|
||||
}),
|
||||
charge_current_step: 50,
|
||||
charge_modes: vec!["discharge".to_owned(), "idle".to_owned(), "normal".to_owned()],
|
||||
charge_modes: vec!["normal".to_owned(), "discharge".to_owned(), "idle".to_owned()],
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -265,4 +265,44 @@ impl TBattery for Battery {
|
|||
fn get_charge_mode(&self) -> Option<String> {
|
||||
self.charge_mode.map(Self::charge_mode_to_str)
|
||||
}
|
||||
|
||||
fn read_charge_full(&self) -> Option<f64> {
|
||||
match Self::read_charge_full() {
|
||||
Ok(x) => Some(x),
|
||||
Err(e) => {
|
||||
log::warn!("read_charge_full err: {}", e.msg);
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn read_charge_now(&self) -> Option<f64> {
|
||||
match Self::read_charge_now() {
|
||||
Ok(x) => Some(x),
|
||||
Err(e) => {
|
||||
log::warn!("read_charge_now err: {}", e.msg);
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn read_charge_design(&self) -> Option<f64> {
|
||||
match Self::read_charge_design() {
|
||||
Ok(x) => Some(x),
|
||||
Err(e) => {
|
||||
log::warn!("read_charge_design err: {}", e.msg);
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn read_current_now(&self) -> Option<f64> {
|
||||
match Self::read_current_now() {
|
||||
Ok(x) => Some(x as f64),
|
||||
Err(e) => {
|
||||
log::warn!("read_current_now err: {}", e.msg);
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -83,4 +83,12 @@ pub trait TBattery: OnResume + OnSet + Debug + Send {
|
|||
fn charge_mode(&mut self, mode: Option<String>);
|
||||
|
||||
fn get_charge_mode(&self) -> Option<String>;
|
||||
|
||||
fn read_charge_full(&self) -> Option<f64>;
|
||||
|
||||
fn read_charge_now(&self) -> Option<f64>;
|
||||
|
||||
fn read_charge_design(&self) -> Option<f64>;
|
||||
|
||||
fn read_current_now(&self) -> Option<f64>;
|
||||
}
|
||||
|
|
|
@ -55,4 +55,12 @@ impl TBattery for Battery {
|
|||
fn get_charge_mode(&self) -> Option<String> {
|
||||
None
|
||||
}
|
||||
|
||||
fn read_charge_full(&self) -> Option<f64> { None }
|
||||
|
||||
fn read_charge_now(&self) -> Option<f64> { None }
|
||||
|
||||
fn read_charge_design(&self) -> Option<f64> { None }
|
||||
|
||||
fn read_current_now(&self) -> Option<f64> { None }
|
||||
}
|
||||
|
|
|
@ -41,7 +41,7 @@ export type SettingsLimits = {
|
|||
export type BatteryLimits = {
|
||||
charge_current: RangeLimit | null;
|
||||
charge_current_step: number;
|
||||
charge_modes: number;
|
||||
charge_modes: string[];
|
||||
};
|
||||
|
||||
export type CpuLimits = {
|
||||
|
@ -105,11 +105,11 @@ export async function unsetBatteryChargeRate(): Promise<any[]> {
|
|||
return await call_backend("BATTERY_unset_charge_rate", []);
|
||||
}
|
||||
|
||||
export async function getBatteryChargeMode(): Promise<number> {
|
||||
export async function getBatteryChargeMode(): Promise<string> {
|
||||
return (await call_backend("BATTERY_get_charge_mode", []))[0];
|
||||
}
|
||||
|
||||
export async function setBatteryChargeMode(val: number): Promise<number> {
|
||||
export async function setBatteryChargeMode(val: string): Promise<string> {
|
||||
return (await call_backend("BATTERY_set_charge_mode", [val]))[0];
|
||||
}
|
||||
|
||||
|
|
|
@ -51,6 +51,7 @@ const LIMITS_INFO = "LIMITS_all";
|
|||
|
||||
const CURRENT_BATT = "BATTERY_current_now";
|
||||
const CHARGE_RATE_BATT = "BATTERY_charge_rate";
|
||||
const CHARGE_MODE_BATT = "BATTERY_charge_mode";
|
||||
const CHARGE_NOW_BATT = "BATTERY_charge_now";
|
||||
const CHARGE_FULL_BATT = "BATTERY_charge_full";
|
||||
const CHARGE_DESIGN_BATT = "BATTERY_charge_design"
|
||||
|
@ -107,6 +108,7 @@ const reload = function() {
|
|||
|
||||
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.getBatteryChargeMode(), (mode: string) => { set_value(CHARGE_MODE_BATT, mode) });
|
||||
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) });
|
||||
|
@ -218,6 +220,11 @@ const Content: VFC<{ serverAPI: ServerAPI }> = ({}) => {
|
|||
label: <span>{elem}</span>,
|
||||
};});
|
||||
|
||||
const chargeModeOptions: SingleDropdownOption[] = (get_value(LIMITS_INFO) as backend.SettingsLimits).battery.charge_modes.map((elem) => {return {
|
||||
data: elem,
|
||||
label: <span>{elem}</span>,
|
||||
};});
|
||||
|
||||
return (
|
||||
<PanelSection>
|
||||
{/* CPU */}
|
||||
|
@ -494,7 +501,7 @@ const Content: VFC<{ serverAPI: ServerAPI }> = ({}) => {
|
|||
}}
|
||||
/>}
|
||||
</PanelSectionRow>}
|
||||
{advancedMode && (get_value(LIMITS_INFO) as backend.SettingsLimits).cpu.cpus[advancedCpuIndex].governors.length != 0 && <PanelSectionRow>
|
||||
{advancedMode && governorOptions.length != 0 && <PanelSectionRow>
|
||||
<Field
|
||||
label="Governor"
|
||||
>
|
||||
|
@ -739,6 +746,43 @@ const Content: VFC<{ serverAPI: ServerAPI }> = ({}) => {
|
|||
}}
|
||||
/>}
|
||||
</PanelSectionRow>}
|
||||
{chargeModeOptions.length != 0 && <PanelSectionRow>
|
||||
<ToggleField
|
||||
checked={get_value(CHARGE_MODE_BATT) != null}
|
||||
label="Charge Mode"
|
||||
description="Force battery charge mode"
|
||||
onChange={(value: boolean) => {
|
||||
if (value) {
|
||||
set_value(CHARGE_MODE_BATT, chargeModeOptions[0].data as string);
|
||||
reloadGUI("BATTChargeModeToggle");
|
||||
} else {
|
||||
set_value(CHARGE_MODE_BATT, null);
|
||||
backend.resolve(backend.unsetBatteryChargeMode(), (_: any[]) => {
|
||||
reloadGUI("BATTUnsetChargeMode");
|
||||
});
|
||||
}
|
||||
}}
|
||||
/>
|
||||
{get_value(CHARGE_MODE_BATT) != null && <Field
|
||||
label="Mode"
|
||||
>
|
||||
<Dropdown
|
||||
menuLabel="Charge Mode"
|
||||
rgOptions={chargeModeOptions}
|
||||
selectedOption={chargeModeOptions.find((val: SingleDropdownOption, _index, _arr) => {
|
||||
return val.data == get_value(CHARGE_MODE_BATT);
|
||||
})}
|
||||
strDefaultLabel={get_value(CHARGE_MODE_BATT)}
|
||||
onChange={(elem: SingleDropdownOption) => {
|
||||
console.debug("Charge mode dropdown selected", elem);
|
||||
backend.resolve(backend.setBatteryChargeMode(elem.data as string), (mode: string) => {
|
||||
set_value(CHARGE_MODE_BATT, mode);
|
||||
reloadGUI("BATTChargeMode");
|
||||
});
|
||||
}}
|
||||
/>
|
||||
</Field>}
|
||||
</PanelSectionRow>}
|
||||
<PanelSectionRow>
|
||||
<Field
|
||||
label="Current"
|
||||
|
|
Loading…
Reference in a new issue