Merge branch 'dev'
This commit is contained in:
commit
733681a6d9
4 changed files with 393 additions and 5 deletions
44
README.md
44
README.md
|
@ -1,14 +1,15 @@
|
|||
# PowerTools
|
||||
|
||||
![plugin_demo](https://raw.githubusercontent.com/NGnius/PowerTools/master/extras/ui.png)
|
||||
![plugin_demo](./extras/ui.png)
|
||||
|
||||
Steam Deck power tweaks for power users.
|
||||
|
||||
This is generated from the template plugin for the [SteamOS Plugin Loader](https://github.com/SteamDeckHomebrew/PluginLoader).
|
||||
You will need that installed for this plugin to work.
|
||||
|
||||
## Cool, whatever
|
||||
## Cool, but that's too much work
|
||||
|
||||
Yeah, that's fair.
|
||||
Fair enough.
|
||||
In case you still want some of the functionality, without the nice GUI, here's some equivalent commands.
|
||||
These should all be run as superuser, i.e. run `sudo su` and then run these commands in that.
|
||||
|
||||
|
@ -32,6 +33,43 @@ Use `cpupower` (usage: `cpupower --help`).
|
|||
This isn't strictly how PowerTools does it, but it's a multi-step process which can involve changing the CPU governor.
|
||||
All that can be done automatically by `cpupower frequency-set --freq {frequency}` where `{frequency}` is `1.7G`, `2.4G` or `2.8G`.
|
||||
|
||||
### Set GPU Power
|
||||
|
||||
Set Slow Powerplay Table (PPT):`echo {microwatts} > /sys/class/hwmon/hwmon4/power1_cap` where `{microwatts}` is a wattage in millionths of a Watt. This doesn't seem to do a lot.
|
||||
|
||||
Set Fast Powerplay Table (PPT): `echo {microwatts} > /sys/class/hwmon/hwmon4/power2_cap` where `{microwatts}` is a wattage in millionths of a Watt.
|
||||
|
||||
Get the entry limits for those two commands with `cat /sys/class/hwmon/hwmon4/power{number}_cap_max` where `{number}` is `1` (slowPPT) or `2` (fastPPT).
|
||||
|
||||
### Set Fan speed
|
||||
|
||||
Enable automatic control: `echo 0 > /sys/class/hwmon/hwmon5/recalculate` enables automatic fan control.
|
||||
|
||||
Disable automatic control: `echo 1 > /sys/class/hwmon/hwmon5/recalculate` disables automatic (temperature-based) fan control and starts using the set fan target instead.
|
||||
|
||||
Set the fan speed: `echo {rpm} > /sys/class/hwmon/hwmon5/fan1_target` where `{rpm}` is the RPM.
|
||||
|
||||
Read the actual fan RPM: `cat /sys/class/hwmon/hwmon5/fan1_input` gives the fan speed.
|
||||
|
||||
NOTE: There's a bug in the fan controller; if you enable automatic fan control it will forget any previously-set target despite it appearing to be set correctly (i.e. `cat /sys/class/hwmon/hwmon5/fan1_target` will display the correct value).
|
||||
When you disable automatic fan control, you will need to set the fan RPM again.
|
||||
|
||||
### Battery stats
|
||||
|
||||
Get the battery charge right now: `cat /sys/class/hwmon/hwmon2/device/charge_now` gives charge in uAh (uAh * 7.7/1000000 = charge in Wh).
|
||||
|
||||
Get the maximum battery capacity: `cat /sys/class/hwmon/hwmon2/device/charge_full` gives charge in uAh.
|
||||
|
||||
Get the design battery capacity: `cat /sys/class/hwmon/hwmon2/device/charge_full_design` gives charge in uAh.
|
||||
|
||||
Get whether the deck is plugged in: `cat /sys/class/hwmon/hwmon5/curr1_input` gives the charger current in mA.
|
||||
|
||||
### Steam Deck kernel patches
|
||||
|
||||
This is how I figured out how the fan stuff works.
|
||||
I've only scratched the surface of what this code allows, I'm sure it has more useful information.
|
||||
https://lkml.org/lkml/2022/2/5/391
|
||||
|
||||
## License
|
||||
|
||||
This is licensed under GNU GPLv3.
|
||||
|
|
BIN
extras/ui.png
BIN
extras/ui.png
Binary file not shown.
Before Width: | Height: | Size: 95 KiB After Width: | Height: | Size: 180 KiB |
74
main.py
74
main.py
|
@ -1,8 +1,19 @@
|
|||
import time
|
||||
#import subprocess
|
||||
|
||||
VERSION = "0.3.0"
|
||||
|
||||
class Plugin:
|
||||
CPU_COUNT = 8
|
||||
SCALING_FREQUENCIES = [1700000, 2400000, 2800000]
|
||||
FAN_SPEEDS = [0, 1000, 2000, 3000, 4000, 5000, 6000]
|
||||
|
||||
auto_fan = True
|
||||
|
||||
async def get_version(self) -> str:
|
||||
return VERSION
|
||||
|
||||
# CPU stuff
|
||||
|
||||
# call from main_view.html with setCPUs(count, smt)
|
||||
async def set_cpus(self, count, smt=True) -> int:
|
||||
|
@ -32,7 +43,10 @@ class Plugin:
|
|||
return online_count
|
||||
|
||||
async def get_smt(self) -> bool:
|
||||
return status_cpu(1) == status_cpu(2) and status_cpu(3) == status_cpu(4)
|
||||
for cpu in range(1, self.CPU_COUNT, 2):
|
||||
if (not status_cpu(cpu)) and status_cpu(cpu+1):
|
||||
return False
|
||||
return True
|
||||
|
||||
async def set_boost(self, enabled: bool) -> bool:
|
||||
write_to_sys("/sys/devices/system/cpu/cpufreq/boost", int(enabled))
|
||||
|
@ -66,6 +80,61 @@ class Plugin:
|
|||
freq = int(freq_maybe)
|
||||
return self.SCALING_FREQUENCIES.index(freq)
|
||||
|
||||
# GPU stuff
|
||||
|
||||
async def set_gpu_power(self, value: int, power_number: int) -> bool:
|
||||
write_to_sys(gpu_power_path(power_number), value)
|
||||
return True
|
||||
|
||||
async def get_gpu_power(self, power_number: int) -> int:
|
||||
return int(read_from_sys(gpu_power_path(power_number), amount=-1).strip())
|
||||
|
||||
# Fan stuff
|
||||
|
||||
async def set_fan_tick(self, tick: int):
|
||||
if tick >= len(self.FAN_SPEEDS):
|
||||
# automatic mode
|
||||
self.auto_fan = True
|
||||
write_to_sys("/sys/class/hwmon/hwmon5/recalculate", 0)
|
||||
write_to_sys("/sys/class/hwmon/hwmon5/fan1_target", 4099) # 4099 is default
|
||||
#subprocess.run(["systemctl", "start", "jupiter-fan-control.service"])
|
||||
else:
|
||||
# manual voltage
|
||||
self.auto_fan = False
|
||||
write_to_sys("/sys/class/hwmon/hwmon5/recalculate", 1)
|
||||
write_to_sys("/sys/class/hwmon/hwmon5/fan1_target", self.FAN_SPEEDS[tick])
|
||||
#subprocess.run(["systemctl", "stop", "jupiter-fan-control.service"])
|
||||
|
||||
async def get_fan_tick(self) -> int:
|
||||
fan_target = int(read_from_sys("/sys/class/hwmon/hwmon5/fan1_target", amount=-1).strip())
|
||||
fan_input = int(read_from_sys("/sys/class/hwmon/hwmon5/fan1_input", amount=-1).strip())
|
||||
fan_target_v = float(fan_target) / 1000
|
||||
fan_input_v = float(fan_input) / 1000
|
||||
if self.auto_fan:
|
||||
return len(self.FAN_SPEEDS)
|
||||
elif fan_target == 4099 or (int(round(fan_target_v)) != int(round(fan_input_v)) and fan_target not in self.FAN_SPEEDS):
|
||||
# cannot read /sys/class/hwmon/hwmon5/recalculate, so guess based on available fan info
|
||||
# NOTE: the fan takes time to ramp up, so fan_target will never approximately equal fan_input
|
||||
# when fan_target was changed recently (hence set voltage caching)
|
||||
return len(self.FAN_SPEEDS)
|
||||
else:
|
||||
# quantize voltage to nearest tick (price is right rules; closest without going over)
|
||||
for i in range(len(self.FAN_SPEEDS)-1):
|
||||
if fan_target <= self.FAN_SPEEDS[i]:
|
||||
return i
|
||||
return len(self.FAN_SPEEDS)-1 # any higher value is considered as highest manual setting
|
||||
|
||||
# Battery stuff
|
||||
|
||||
async def get_charge_now(self) -> int:
|
||||
return int(read_from_sys("/sys/class/hwmon/hwmon2/device/charge_now", amount=-1).strip())
|
||||
|
||||
async def get_charge_full(self) -> int:
|
||||
return int(read_from_sys("/sys/class/hwmon/hwmon2/device/charge_full", amount=-1).strip())
|
||||
|
||||
async def get_charge_design(self) -> int:
|
||||
return int(read_from_sys("/sys/class/hwmon/hwmon2/device/charge_full_design", amount=-1).strip())
|
||||
|
||||
# Asyncio-compatible long-running code, executed in a task when the plugin is loaded
|
||||
async def _main(self):
|
||||
pass
|
||||
|
@ -81,6 +150,9 @@ def cpu_freq_scaling_path(cpu_number: int) -> str:
|
|||
|
||||
def cpu_governor_scaling_path(cpu_number: int) -> str:
|
||||
return f"/sys/devices/system/cpu/cpu{cpu_number}/cpufreq/scaling_governor"
|
||||
|
||||
def gpu_power_path(power_number: int) -> str:
|
||||
return f"/sys/class/hwmon/hwmon4/power{power_number}_cap"
|
||||
|
||||
def write_to_sys(path, value: int):
|
||||
with open(path, mode="w") as f:
|
||||
|
|
280
main_view.html
280
main_view.html
|
@ -6,6 +6,10 @@
|
|||
<script src="/static/library.js"></script>
|
||||
<script>
|
||||
// Python functions
|
||||
function getVersion() {
|
||||
return call_plugin_method("get_version", {});
|
||||
}
|
||||
|
||||
function setCPUs(value, smt) {
|
||||
return call_plugin_method("set_cpus", {"count":value, "smt": smt});
|
||||
}
|
||||
|
@ -33,6 +37,34 @@
|
|||
function getMaxBoost() {
|
||||
return call_plugin_method("get_max_boost", {});
|
||||
}
|
||||
|
||||
function setGPUPower(value, index) {
|
||||
return call_plugin_method("set_gpu_power", {"value": value, "power_number": index});
|
||||
}
|
||||
|
||||
function getGPUPower(index) {
|
||||
return call_plugin_method("get_gpu_power", {"power_number": index});
|
||||
}
|
||||
|
||||
function setFanTick(tick) {
|
||||
return call_plugin_method("set_fan_tick", {"tick": tick});
|
||||
}
|
||||
|
||||
function getFanTick() {
|
||||
return call_plugin_method("get_fan_tick", {});
|
||||
}
|
||||
|
||||
function getChargeNow() {
|
||||
return call_plugin_method("get_charge_now", {});
|
||||
}
|
||||
|
||||
function getChargeFull() {
|
||||
return call_plugin_method("get_charge_full", {});
|
||||
}
|
||||
|
||||
function getChargeDesign() {
|
||||
return call_plugin_method("get_charge_design", {});
|
||||
}
|
||||
|
||||
// other logic
|
||||
|
||||
|
@ -42,6 +74,11 @@
|
|||
setToggleState(document.getElementById("smtToggle"), await getSMT());
|
||||
selectNotch("cpuThreadsNotch", await getCPUs() - 1, 8);
|
||||
selectNotch("frequencyNotch", await getMaxBoost(), 3);
|
||||
await onReadyGPU();
|
||||
selectNotch("fanNotch", await getFanTick(), 8);
|
||||
await updateBatteryStats();
|
||||
// this is unimportant; always do it last
|
||||
await updateVersion();
|
||||
}
|
||||
|
||||
async function setCPUNotch(index) {
|
||||
|
@ -93,6 +130,62 @@
|
|||
selectNotch(ROOT_ID, await getMaxBoost(), 3);
|
||||
}
|
||||
|
||||
async function onSetFanNotch(index) {
|
||||
const ROOT_ID = "fanNotch";
|
||||
await setFanTick(index);
|
||||
selectNotch(ROOT_ID, index, 8);
|
||||
}
|
||||
|
||||
async function onReadyGPU() {
|
||||
let power1_cap = await getGPUPower(1);
|
||||
let power2_cap = await getGPUPower(2);
|
||||
if (power1_cap <= 0) {
|
||||
selectNotch("slowPPTNotch", 0, 3);
|
||||
document.getElementById("slowPPTAutoDefault").innerText = "Default";
|
||||
} else if (power1_cap > 15000000) {
|
||||
selectNotch("slowPPTNotch", 2, 3);
|
||||
document.getElementById("slowPPTAutoDefault").innerText = "Default";
|
||||
} else {
|
||||
selectNotch("slowPPTNotch", 1, 3);
|
||||
}
|
||||
|
||||
if (power2_cap <= 0) {
|
||||
selectNotch("fastPPTNotch", 0, 3);
|
||||
document.getElementById("fastPPTAutoDefault").innerText = "Default";
|
||||
} else if (power2_cap > 15000000) {
|
||||
selectNotch("fastPPTNotch", 2, 3);
|
||||
document.getElementById("fastPPTAutoDefault").innerText = "Default";
|
||||
} else {
|
||||
selectNotch("fastPPTNotch", 1, 3);
|
||||
}
|
||||
}
|
||||
|
||||
async function onSetSlowPPTNotch(index) {
|
||||
const ROOT_ID = "slowPPTNotch";
|
||||
document.getElementById("slowPPTAutoDefault").innerText = "Default";
|
||||
if (index == 0) {
|
||||
await setGPUPower(0, 1);
|
||||
} else if (index == 1) {
|
||||
await setGPUPower(15000000, 1);
|
||||
} else {
|
||||
await setGPUPower(29000000, 1);
|
||||
}
|
||||
selectNotch(ROOT_ID, index, 3);
|
||||
}
|
||||
|
||||
async function onSetFastPPTNotch(index) {
|
||||
const ROOT_ID = "fastPPTNotch";
|
||||
document.getElementById("fastPPTAutoDefault").innerText = "Default";
|
||||
if (index == 0) {
|
||||
await setGPUPower(0, 2);
|
||||
} else if (index == 1) {
|
||||
await setGPUPower(15000000, 2);
|
||||
} else {
|
||||
await setGPUPower(30000000, 2);
|
||||
}
|
||||
selectNotch(ROOT_ID, index, 3);
|
||||
}
|
||||
|
||||
function selectNotch(rootId, index, elements) {
|
||||
// WARNING: this yeets any style in div of slider
|
||||
const ENABLED_CLASS = "gamepadslider_TickActive_j418S";
|
||||
|
@ -108,11 +201,37 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function updateBatteryStats() {
|
||||
//console.log("Updating battery stats");
|
||||
let batCapacityNow = document.getElementById("batCapacityNow");
|
||||
let batCapacityFull = document.getElementById("batCapacityFull");
|
||||
let chargeNow = await getChargeNow();
|
||||
let chargeFull = await getChargeFull();
|
||||
let chargeDesign = await getChargeDesign();
|
||||
batCapacityNow.innerText = (7.7 * chargeNow / 1000000).toFixed(2).toString() + " Wh (" + (100 * chargeNow / chargeFull).toFixed(0).toString() + "%)";
|
||||
batCapacityFull.innerText = (7.7 * chargeFull / 1000000).toFixed(2).toString() + " Wh (" + (100 * chargeFull / chargeDesign).toFixed(0).toString() + "%)";
|
||||
}
|
||||
|
||||
let versionCount = -1;
|
||||
async function updateVersion() {
|
||||
let version = await getVersion();
|
||||
let target = document.getElementById("versionStr");
|
||||
target.innerText = "v" + version;
|
||||
if (versionCount >= 9) {
|
||||
target.innerText += " by NGnius ;) ";
|
||||
versionCount = 0;
|
||||
} else {
|
||||
versionCount += 1;
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
<style type="text/css" media="screen"></style>
|
||||
</head>
|
||||
<body onload="onReady()">
|
||||
<body onload="onReady()" style="/*margin:0px;padding:0px;*/overflow-x:hidden;">
|
||||
<!-- CPU -->
|
||||
|
||||
<!-- SMT toggle switch, roughly copied from https://github.com/SteamDeckHomebrew/ExtraSettingsPlugin/blob/main/main_view.html -->
|
||||
<!-- Due to a bug in MangoHud, this has been hidden for now -->
|
||||
<div class="quickaccessmenu_TabGroupPanel_1QO7b Panel Focusable" style="display:none;">
|
||||
|
@ -130,10 +249,12 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="gamepaddialog_FieldDescription_1W1to">Disables odd-numbered CPUs</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- CPUs selector -->
|
||||
<div class="gamepaddialog_Field_eKmEX gamepaddialog_WithFirstRow_2bDqk gamepaddialog_WithChildrenBelow_37xzV gamepaddialog_InlineWrapShiftsChildrenBelow_3LCXh gamepaddialog_WithBottomSeparator_3YKpU gamepaddialog_ChildrenWidthFixed_ljcbL gamepaddialog_ExtraPaddingOnChildrenBelow_3nLNL gamepaddialog_StandardPadding_xIITX gamepaddialog_HighlightOnFocus_2HFrm Panel Focusable">
|
||||
<div class="gamepaddialog_FieldLabelRow_2VcTl">
|
||||
|
@ -199,10 +320,12 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="gamepaddialog_FieldDescription_1W1to">Allows the CPU to go above max frequency</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Frequency selector -->
|
||||
<div class="gamepaddialog_Field_eKmEX gamepaddialog_WithFirstRow_2bDqk gamepaddialog_WithChildrenBelow_37xzV gamepaddialog_InlineWrapShiftsChildrenBelow_3LCXh gamepaddialog_WithBottomSeparator_3YKpU gamepaddialog_ChildrenWidthFixed_ljcbL gamepaddialog_ExtraPaddingOnChildrenBelow_3nLNL gamepaddialog_StandardPadding_xIITX gamepaddialog_HighlightOnFocus_2HFrm Panel Focusable">
|
||||
<div class="gamepaddialog_FieldLabelRow_2VcTl">
|
||||
|
@ -236,5 +359,160 @@
|
|||
WARNING: This will change the CPU governor.
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- GPU -->
|
||||
|
||||
<!-- SlowPPT power limit (number 1) -->
|
||||
<div class="gamepaddialog_Field_eKmEX gamepaddialog_WithFirstRow_2bDqk gamepaddialog_WithChildrenBelow_37xzV gamepaddialog_InlineWrapShiftsChildrenBelow_3LCXh gamepaddialog_WithBottomSeparator_3YKpU gamepaddialog_ChildrenWidthFixed_ljcbL gamepaddialog_ExtraPaddingOnChildrenBelow_3nLNL gamepaddialog_StandardPadding_xIITX gamepaddialog_HighlightOnFocus_2HFrm Panel Focusable">
|
||||
<div class="gamepaddialog_FieldLabelRow_2VcTl">
|
||||
<div class="gamepaddialog_FieldLabel_3jMlJ">GPU SlowPPT Power</div>
|
||||
</div>
|
||||
<div class="gamepaddialog_FieldChildren_2rhav">
|
||||
<div id="slowPPTNotch" class="gamepadslider_SliderControlAndNotches_23hjX Focusable" tabindex="0" style="--normalized-slider-value:0.33;">
|
||||
<div class="gamepadslider_SliderControl_1udlG">
|
||||
<div class="gamepadslider_SliderTrack_2_vG6 gamepadslider_SliderHasNotches_1Lr71 "></div>
|
||||
<div class="gamepadslider_SliderHandleContainer_8xNY6">
|
||||
<div class="gamepadslider_SliderHandle_11PBf"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="gamepadslider_SliderNotchContainer_2yM7S Panel Focusable">
|
||||
<div class="gamepadslider_SliderNotch_LYPXt">
|
||||
<div id="slowPPTNotch0" class="gamepadslider_SliderNotchTick_u8QEa gamepadslider_TickActive_j418S" onclick='onSetSlowPPTNotch(0)'></div>
|
||||
<div class="gamepadslider_SliderNotchLabel_dbACW">0</div>
|
||||
</div>
|
||||
<div class="gamepadslider_SliderNotch_LYPXt">
|
||||
<div id="slowPPTNotch1" class="gamepadslider_SliderNotchTick_u8QEa gamepadslider_TickActive_j418S" onclick='onSetSlowPPTNotch(1)'></div>
|
||||
<div class="gamepadslider_SliderNotchLabel_dbACW" id="slowPPTAutoDefault">Auto</div>
|
||||
</div>
|
||||
<div class="gamepadslider_SliderNotch_LYPXt">
|
||||
<div id="slowPPTNotch2" class="gamepadslider_SliderNotchTick_u8QEa gamepadslider_TickActive_j418S" onclick='onSetSlowPPTNotch(2)'></div>
|
||||
<div class="gamepadslider_SliderNotchLabel_dbACW">Max</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- FastPPT power limit (number 2) -->
|
||||
<div class="gamepaddialog_Field_eKmEX gamepaddialog_WithFirstRow_2bDqk gamepaddialog_WithChildrenBelow_37xzV gamepaddialog_InlineWrapShiftsChildrenBelow_3LCXh gamepaddialog_WithBottomSeparator_3YKpU gamepaddialog_ChildrenWidthFixed_ljcbL gamepaddialog_ExtraPaddingOnChildrenBelow_3nLNL gamepaddialog_StandardPadding_xIITX gamepaddialog_HighlightOnFocus_2HFrm Panel Focusable">
|
||||
<div class="gamepaddialog_FieldLabelRow_2VcTl">
|
||||
<div class="gamepaddialog_FieldLabel_3jMlJ">GPU FastPPT Power</div>
|
||||
</div>
|
||||
<div class="gamepaddialog_FieldChildren_2rhav">
|
||||
<div id="fastPPTNotch" class="gamepadslider_SliderControlAndNotches_23hjX Focusable" tabindex="0" style="--normalized-slider-value:0.33;">
|
||||
<div class="gamepadslider_SliderControl_1udlG">
|
||||
<div class="gamepadslider_SliderTrack_2_vG6 gamepadslider_SliderHasNotches_1Lr71 "></div>
|
||||
<div class="gamepadslider_SliderHandleContainer_8xNY6">
|
||||
<div class="gamepadslider_SliderHandle_11PBf"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="gamepadslider_SliderNotchContainer_2yM7S Panel Focusable">
|
||||
<div class="gamepadslider_SliderNotch_LYPXt">
|
||||
<div id="fastPPTNotch0" class="gamepadslider_SliderNotchTick_u8QEa gamepadslider_TickActive_j418S" onclick='onSetFastPPTNotch(0)'></div>
|
||||
<div class="gamepadslider_SliderNotchLabel_dbACW">0</div>
|
||||
</div>
|
||||
<div class="gamepadslider_SliderNotch_LYPXt">
|
||||
<div id="fastPPTNotch1" class="gamepadslider_SliderNotchTick_u8QEa gamepadslider_TickActive_j418S" onclick='onSetFastPPTNotch(1)'></div>
|
||||
<div class="gamepadslider_SliderNotchLabel_dbACW" id="fastPPTAutoDefault">Auto</div>
|
||||
</div>
|
||||
<div class="gamepadslider_SliderNotch_LYPXt">
|
||||
<div id="fastPPTNotch2" class="gamepadslider_SliderNotchTick_u8QEa gamepadslider_TickActive_j418S" onclick='onSetFastPPTNotch(2)'></div>
|
||||
<div class="gamepadslider_SliderNotchLabel_dbACW">Max</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Fan RPM selector -->
|
||||
<!-- TODO: Make this non-notched slider when PluginLoader PR#41 is merged -->
|
||||
<div class="gamepaddialog_Field_eKmEX gamepaddialog_WithFirstRow_2bDqk gamepaddialog_WithChildrenBelow_37xzV gamepaddialog_InlineWrapShiftsChildrenBelow_3LCXh gamepaddialog_WithBottomSeparator_3YKpU gamepaddialog_ChildrenWidthFixed_ljcbL gamepaddialog_ExtraPaddingOnChildrenBelow_3nLNL gamepaddialog_StandardPadding_xIITX gamepaddialog_HighlightOnFocus_2HFrm Panel Focusable">
|
||||
<div class="gamepaddialog_FieldLabelRow_2VcTl">
|
||||
<div class="gamepaddialog_FieldLabel_3jMlJ">Fan RPM</div>
|
||||
</div>
|
||||
<div class="gamepaddialog_FieldChildren_2rhav">
|
||||
<div id="fanNotch" class="gamepadslider_SliderControlAndNotches_23hjX Focusable" tabindex="0" style="--normalized-slider-value:0.33;">
|
||||
<div class="gamepadslider_SliderControl_1udlG">
|
||||
<div class="gamepadslider_SliderTrack_2_vG6 gamepadslider_SliderHasNotches_1Lr71 "></div>
|
||||
<div class="gamepadslider_SliderHandleContainer_8xNY6">
|
||||
<div class="gamepadslider_SliderHandle_11PBf"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="gamepadslider_SliderNotchContainer_2yM7S Panel Focusable">
|
||||
<div class="gamepadslider_SliderNotch_LYPXt">
|
||||
<div id="fanNotch0" class="gamepadslider_SliderNotchTick_u8QEa gamepadslider_TickActive_j418S" onclick='onSetFanNotch(0)'></div>
|
||||
<div class="gamepadslider_SliderNotchLabel_dbACW">0</div>
|
||||
</div>
|
||||
<div class="gamepadslider_SliderNotch_LYPXt">
|
||||
<div id="fanNotch1" class="gamepadslider_SliderNotchTick_u8QEa gamepadslider_TickActive_j418S" onclick='onSetFanNotch(1)'></div>
|
||||
<div class="gamepadslider_SliderNotchLabel_dbACW">1K</div>
|
||||
</div>
|
||||
<div class="gamepadslider_SliderNotch_LYPXt">
|
||||
<div id="fanNotch2" class="gamepadslider_SliderNotchTick_u8QEa gamepadslider_TickActive_j418S" onclick='onSetFanNotch(2)'></div>
|
||||
<div class="gamepadslider_SliderNotchLabel_dbACW">2K</div>
|
||||
</div>
|
||||
<div class="gamepadslider_SliderNotch_LYPXt">
|
||||
<div id="fanNotch3" class="gamepadslider_SliderNotchTick_u8QEa gamepadslider_TickActive_j418S" onclick='onSetFanNotch(3)'></div>
|
||||
<div class="gamepadslider_SliderNotchLabel_dbACW">3K</div>
|
||||
</div>
|
||||
<div class="gamepadslider_SliderNotch_LYPXt">
|
||||
<div id="fanNotch4" class="gamepadslider_SliderNotchTick_u8QEa gamepadslider_TickActive_j418S" onclick='onSetFanNotch(4)'></div>
|
||||
<div class="gamepadslider_SliderNotchLabel_dbACW">4K</div>
|
||||
</div>
|
||||
<div class="gamepadslider_SliderNotch_LYPXt">
|
||||
<div id="fanNotch5" class="gamepadslider_SliderNotchTick_u8QEa gamepadslider_TickActive_j418S" onclick='onSetFanNotch(5)'></div>
|
||||
<div class="gamepadslider_SliderNotchLabel_dbACW">5K</div>
|
||||
</div>
|
||||
<div class="gamepadslider_SliderNotch_LYPXt">
|
||||
<div id="fanNotch6" class="gamepadslider_SliderNotchTick_u8QEa gamepadslider_TickActive_j418S" onclick='onSetFanNotch(6)'></div>
|
||||
<div class="gamepadslider_SliderNotchLabel_dbACW">6K</div>
|
||||
</div>
|
||||
<div class="gamepadslider_SliderNotch_LYPXt">
|
||||
<div id="fanNotch7" class="gamepadslider_SliderNotchTick_u8QEa gamepadslider_TickActive_j418S" onclick='onSetFanNotch(7)'></div>
|
||||
<div class="gamepadslider_SliderNotchLabel_dbACW">Auto</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Battery Info -->
|
||||
<div class="quickaccesscontrols_PanelSection_3gY0a" onclick="updateBatteryStats()" style="margin-bottom:0px;">
|
||||
<div class="quickaccesscontrols_PanelSectionTitle_1IigU">
|
||||
<div class="quickaccesscontrols_Text_1cokl">Battery</div>
|
||||
</div>
|
||||
<div class="Panel Focusable" tabindex="0">
|
||||
<div class="quickaccesscontrols_PanelSectionRow_3LM_Z">
|
||||
<div class="gamepaddialog_Field_eKmEX gamepaddialog_WithFirstRow_2bDqk gamepaddialog_InlineWrapShiftsChildrenBelow_3LCXh gamepaddialog_StandardPadding_xIITX gamepaddialog_HighlightOnFocus_2HFrm Panel Focusable" style="--indent-level:0;padding-left:0px;padding-right:0px;">
|
||||
<div class="gamepaddialog_FieldLabelRow_2VcTl">
|
||||
<div class="gamepaddialog_FieldLabel_3jMlJ">Now (Charge%)</div>
|
||||
<div class="gamepaddialog_FieldChildren_2rhav">
|
||||
<div class="gamepaddialog_LabelFieldValue_3pteV" id="batCapacityNow"> :'( (|-_-|) </div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="quickaccesscontrols_PanelSectionRow_3LM_Z">
|
||||
<div class="gamepaddialog_Field_eKmEX gamepaddialog_WithFirstRow_2bDqk gamepaddialog_InlineWrapShiftsChildrenBelow_3LCXh gamepaddialog_WithBottomSeparator_3YKpU gamepaddialog_StandardPadding_xIITX gamepaddialog_HighlightOnFocus_2HFrm Panel Focusable" style="--indent-level:0;padding-left:0px;padding-right:0px;">
|
||||
<div class="gamepaddialog_FieldLabelRow_2VcTl">
|
||||
<div class="gamepaddialog_FieldLabel_3jMlJ">Max (Health%)</div>
|
||||
<div class="gamepaddialog_FieldChildren_2rhav">
|
||||
<div class="gamepaddialog_LabelFieldValue_3pteV" id="batCapacityFull"> 9000+ (420%) </div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="quickaccesscontrols_PanelSectionRow_3LM_Z" onclick="updateVersion()">
|
||||
<div class="gamepaddialog_Field_eKmEX gamepaddialog_WithFirstRow_2bDqk gamepaddialog_InlineWrapShiftsChildrenBelow_3LCXh gamepaddialog_StandardPadding_xIITX gamepaddialog_HighlightOnFocus_2HFrm Panel Focusable" style="--indent-level:0;">
|
||||
<div class="gamepaddialog_FieldLabelRow_2VcTl">
|
||||
<div class="gamepaddialog_FieldLabel_3jMlJ">PowerTools</div>
|
||||
<div class="gamepaddialog_FieldChildren_2rhav">
|
||||
<div class="gamepaddialog_LabelFieldValue_3pteV" id="versionStr"> v0.42.0 </div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
|
Loading…
Reference in a new issue