generated from SteamDeckHomebrew/decky-plugin-template
-
-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* fan slice * save fan profiles to backend * add default fan curve * add acpi_call check * add custom fan panel * add toggle for enabling/disabling fan curves * add per game toggle for fan control * add per game fan curve toggle * update currentGameId selector * fix bug in fanSlice * refactor currentDisplayName into uiSlice * add fancurvesliders * add labels + show/hide fan curve toggle * add legion_space fan speed funcs * have backend set fan profile * add default value for 0C * remove sudo from legion_space * remove 0C default value * add set_full_fan_speed * formatting fixes * update README
- Loading branch information
1 parent
f137916
commit 26cbdc2
Showing
15 changed files
with
584 additions
and
9 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
import subprocess | ||
import decky_plugin | ||
|
||
# all credit goes to corando98 | ||
# source: https://github.com/corando98/LLG_Dev_scripts/blob/main/LegionSpace.py | ||
|
||
def execute_acpi_command(command): | ||
""" | ||
Executes an ACPI command and returns the output. | ||
Uses subprocess for robust command execution. | ||
Args: | ||
command (str): The ACPI command to be executed. | ||
Returns: | ||
str: The output from the ACPI command execution. | ||
""" | ||
try: | ||
result = subprocess.run(command, shell=True, check=True, text=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) | ||
return result.stdout.strip() | ||
except subprocess.CalledProcessError as e: | ||
decky_plugin.logger.error(f"Error executing command: {e.stderr}") | ||
return None | ||
|
||
def set_fan_curve(fan_table): | ||
""" | ||
Sets a new fan curve based on the provided fan table array. | ||
The fan table should contain fan speed values that correspond to different temperature thresholds. | ||
Args: | ||
fan_table (list): An array of fan speeds to set the fan curve. | ||
Returns: | ||
str: The output from setting the new fan curve. | ||
""" | ||
# Assuming Fan ID and Sensor ID are both 0 (as they are ignored) | ||
fan_id_sensor_id = '0x00, 0x00' | ||
|
||
# Assuming the temperature array length and values are ignored but required | ||
temp_array_length = '0x0A, 0x00, 0x00, 0x00' # Length 10 in hex | ||
temp_values = ', '.join([f'0x{temp:02x}, 0x00' for temp in range(0, 101, 10)]) + ', 0x00' | ||
|
||
# Fan speed values in uint16 format with null termination | ||
fan_speed_values = ', '.join([f'0x{speed:02x}, 0x00' for speed in fan_table]) + ', 0x00' | ||
|
||
# Constructing the full command | ||
command = f"echo '\\_SB.GZFD.WMAB 0 0x06 {{{fan_id_sensor_id}, {temp_array_length}, {fan_speed_values}, {temp_array_length}, {temp_values}}}' | tee /proc/acpi/call; cat /proc/acpi/call" | ||
return execute_acpi_command(command) | ||
|
||
# FFSS Full speed mode set on /off | ||
# echo '\_SB.GZFD.WMAE 0 0x12 0x0104020000' | sudo tee /proc/acpi/call; sudo cat /proc/acpi/call | ||
# echo '\_SB.GZFD.WMAE 0 0x12 0x0004020000' | sudo tee /proc/acpi/call; sudo cat /proc/acpi/call | ||
def set_full_fan_speed(enable): | ||
""" | ||
Enable or disable full fan speed mode. | ||
Args: | ||
enable (bool): True to enable, False to disable. | ||
Returns: | ||
str: The result of the operation. | ||
""" | ||
status = '0x01' if enable else '0x00' | ||
command = f"echo '\\_SB.GZFD.WMAE 0 0x12 {status}04020000' | tee /proc/acpi/call; cat /proc/acpi/call" | ||
return execute_acpi_command(command) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
import { useDispatch, useSelector } from 'react-redux'; | ||
import { fanSlice, selectActiveFanCurve } from '../../redux-modules/fanSlice'; | ||
import { PanelSection, PanelSectionRow, SliderField } from 'decky-frontend-lib'; | ||
import { VFC } from 'react'; | ||
|
||
type Props = { | ||
showSliders: boolean; | ||
}; | ||
|
||
const FanCurveSliders: VFC<Props> = ({ showSliders }) => { | ||
const activeFanCurve = useSelector(selectActiveFanCurve); | ||
const dispatch = useDispatch(); | ||
|
||
const updateFanCurveValue = (temp: string, fanSpeed: number) => { | ||
return dispatch(fanSlice.actions.updateFanCurve({ temp, fanSpeed })); | ||
}; | ||
|
||
const sliders = Object.entries(activeFanCurve).map( | ||
([temp, fanSpeed], idx) => { | ||
return ( | ||
<PanelSectionRow> | ||
<SliderField | ||
label={`${temp} \u2103`} | ||
value={fanSpeed} | ||
showValue | ||
valueSuffix="%" | ||
step={5} | ||
min={0} | ||
max={100} | ||
validValues="range" | ||
bottomSeparator="none" | ||
key={idx} | ||
onChange={(newSpeed) => { | ||
return updateFanCurveValue(temp, newSpeed); | ||
}} | ||
/> | ||
</PanelSectionRow> | ||
); | ||
} | ||
); | ||
|
||
return ( | ||
<> | ||
{showSliders && ( | ||
<PanelSection title={'Temp (\u2103) | Fan Speed (%)'}> | ||
{sliders} | ||
</PanelSection> | ||
)} | ||
</> | ||
); | ||
}; | ||
|
||
export default FanCurveSliders; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
import { | ||
ButtonItem, | ||
PanelSection, | ||
PanelSectionRow, | ||
ToggleField | ||
} from 'decky-frontend-lib'; | ||
import { | ||
useCustomFanCurvesEnabled, | ||
useFanPerGameProfilesEnabled, | ||
useSupportsCustomFanCurves | ||
} from '../../hooks/fan'; | ||
import { capitalize } from 'lodash'; | ||
import { useSelector } from 'react-redux'; | ||
import { useState } from 'react'; | ||
import { selectCurrentGameDisplayName } from '../../redux-modules/uiSlice'; | ||
import FanCurveSliders from './FanCurveSliders'; | ||
import { IoMdArrowDropdown, IoMdArrowDropup } from 'react-icons/io'; | ||
|
||
const useTitle = (fanPerGameProfilesEnabled: boolean) => { | ||
const currentDisplayName = useSelector(selectCurrentGameDisplayName); | ||
|
||
if (!fanPerGameProfilesEnabled) { | ||
return 'Fan Control'; | ||
} | ||
|
||
const title = `Fan Control - ${capitalize(currentDisplayName)}`; | ||
|
||
return title; | ||
}; | ||
|
||
const FanPanel = () => { | ||
const supportsFanCurves = useSupportsCustomFanCurves(); | ||
const [showSliders, setShowSliders] = useState(false); | ||
|
||
const { customFanCurvesEnabled, setCustomFanCurvesEnabled } = | ||
useCustomFanCurvesEnabled(); | ||
const { fanPerGameProfilesEnabled, setFanPerGameProfilesEnabled } = | ||
useFanPerGameProfilesEnabled(); | ||
const title = useTitle(fanPerGameProfilesEnabled); | ||
|
||
if (!supportsFanCurves) { | ||
return null; | ||
} | ||
|
||
return ( | ||
<> | ||
<PanelSection title={title}> | ||
<PanelSectionRow> | ||
<ToggleField | ||
label={'Enable Custom Fan Curves'} | ||
checked={customFanCurvesEnabled} | ||
onChange={setCustomFanCurvesEnabled} | ||
/> | ||
</PanelSectionRow> | ||
{customFanCurvesEnabled && ( | ||
<> | ||
<PanelSectionRow> | ||
<ToggleField | ||
label={'Enable Per Game Fan Curves'} | ||
checked={fanPerGameProfilesEnabled} | ||
onChange={setFanPerGameProfilesEnabled} | ||
/> | ||
</PanelSectionRow> | ||
<PanelSectionRow> | ||
<ButtonItem | ||
layout="below" | ||
bottomSeparator={showSliders ? 'none' : 'thick'} | ||
style={{ | ||
width: '100%', | ||
height: '20px', | ||
display: 'flex', // Set the display to flex | ||
justifyContent: 'center', // Center align horizontally | ||
alignItems: 'center' // Center align vertically | ||
}} | ||
onClick={() => setShowSliders(!showSliders)} | ||
> | ||
{showSliders ? <IoMdArrowDropup /> : <IoMdArrowDropdown />} | ||
</ButtonItem> | ||
</PanelSectionRow> | ||
</> | ||
)} | ||
</PanelSection> | ||
{customFanCurvesEnabled && <FanCurveSliders showSliders={showSliders} />} | ||
</> | ||
); | ||
}; | ||
|
||
export default FanPanel; |
Oops, something went wrong.