Add charge mode setting for SD, move static battery readings into driver

This commit is contained in:
NGnius (Graham) 2022-11-21 20:58:35 -05:00
parent 1466c4647b
commit 2b2a6eaf9d
9 changed files with 201 additions and 56 deletions

View file

@ -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

View file

@ -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()),
}
}
}

View file

@ -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()),

View file

@ -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() {

View file

@ -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
}
}
}
}

View file

@ -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>;
}

View file

@ -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 }
}

View file

@ -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];
}

View file

@ -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"