Skip to content

Commit

Permalink
add charge limit toggle
Browse files Browse the repository at this point in the history
  • Loading branch information
aarron-lee committed Apr 7, 2024
1 parent 8aad6df commit b489d0a
Show file tree
Hide file tree
Showing 7 changed files with 97 additions and 8 deletions.
10 changes: 10 additions & 0 deletions main.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@ async def _main(self):
async def get_settings(self):
results = settings.get_settings()

if results.get("chargeLimitEnabled", False):
legion_space.set_charge_limit(True)

try:
results['pluginVersionNum'] = f'{decky_plugin.DECKY_PLUGIN_VERSION}'

Expand Down Expand Up @@ -141,6 +144,13 @@ async def set_power_led(self, enabled):

legion_space.set_power_light(enabled)

async def set_charge_limit(self, enabled):
try:
settings.set_setting('chargeLimitEnabled', enabled)

legion_space.set_charge_limit(enabled)
except Exception as e:
decky_plugin.logger.error(f'error while setting charge limit {e}')

async def remap_button(self, button: str, action: str):
decky_plugin.logger.info(f"remap_button {button} {action}")
Expand Down
13 changes: 10 additions & 3 deletions py_modules/legion_space.py
Original file line number Diff line number Diff line change
Expand Up @@ -139,8 +139,13 @@ def get_charge_limit():
# off
# echo '\_SB.GZFD.WMAE 0 0x12 {0x01, 0x00, 0x01, 0x03, 0x00, 0x00, 0x00, 0x00}' | sudo tee /proc/acpi/call
# 80% charge limit
def set_charging_limit(enabled: bool):
if enabled:
def set_charge_limit(enabled: bool):

current_charge_limit = get_charge_limit()

# decky_plugin.logger.info(f'charge limit {current_charge_limit} {current_charge_limit == 0}')

if enabled and current_charge_limit == 0:
return call(
r"\_SB.GZFD.WMAE",
[
Expand All @@ -160,7 +165,7 @@ def set_charging_limit(enabled: bool):
),
],
)
else:
elif not enabled and current_charge_limit == 1:
return call(
r"\_SB.GZFD.WMAE",
[
Expand All @@ -180,6 +185,8 @@ def set_charging_limit(enabled: bool):
),
],
)
# no changes required
return True

def call(method: str, args: Sequence[bytes | int], risky: bool = True):
cmd = method
Expand Down
13 changes: 11 additions & 2 deletions src/backend/utils.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ export enum ServerAPIMethods {
REMAP_BUTTON = 'remap_button',
LOG_INFO = 'log_info',
GET_SETTINGS = 'get_settings',
SET_POWER_LED = 'set_power_led'
SET_POWER_LED = 'set_power_led',
SET_CHARGE_LIMIT = 'set_charge_limit'
}

const createRgbOn =
Expand Down Expand Up @@ -46,6 +47,13 @@ const createSetPowerLed =
});
};

const createSetChargeLimit =
(serverAPI: ServerAPI) => async (enabled: boolean) => {
await serverAPI.callPluginMethod(ServerAPIMethods.SET_CHARGE_LIMIT, {
enabled
});
};

const createGetSettings = (serverAPI: ServerAPI) => async () => {
return await serverAPI.callPluginMethod(ServerAPIMethods.GET_SETTINGS, {});
};
Expand Down Expand Up @@ -73,7 +81,8 @@ export const createServerApiHelpers = (serverAPI: ServerAPI) => {
remapButton: createRemapButtons(serverAPI),
logInfo: createLogInfo(serverAPI),
getSettings: createGetSettings(serverAPI),
setPowerLed: createSetPowerLed(serverAPI)
setPowerLed: createSetPowerLed(serverAPI),
setChargeLimit: createSetChargeLimit(serverAPI)
};
};

Expand Down
13 changes: 13 additions & 0 deletions src/hooks/ui.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { useDispatch, useSelector } from 'react-redux';
import { selectChargeLimitEnabled, uiSlice } from '../redux-modules/uiSlice';

export const useChargeLimitEnabled = () => {
const chargeLimitEnabled = useSelector(selectChargeLimitEnabled);
const dispatch = useDispatch();

const setChargeLimit = (enabled: boolean) => {
return dispatch(uiSlice.actions.setChargeLimit(enabled));
};

return { chargeLimitEnabled, setChargeLimit };
};
20 changes: 19 additions & 1 deletion src/index.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,11 @@
import { definePlugin, ServerAPI, staticClasses } from 'decky-frontend-lib';
import {
definePlugin,
PanelSection,
PanelSectionRow,
ServerAPI,
staticClasses,
ToggleField
} from 'decky-frontend-lib';
import { memo, VFC } from 'react';

import RemapButtons from './components/controller/RemapButtons';
Expand All @@ -13,14 +20,25 @@ import logo from '../assets/Icon.png';
import FanPanel from './components/fan/FanPanel';
import ErrorBoundary from './components/ErrorBoundary';
import OtaUpdates from './components/OtaUpdates';
import { useChargeLimitEnabled } from './hooks/ui';

const Content: VFC<{ serverAPI?: ServerAPI }> = memo(() => {
const loading = useSelector(getInitialLoading);
const { chargeLimitEnabled, setChargeLimit } = useChargeLimitEnabled();
if (loading) {
return null;
}
return (
<>
<PanelSection>
<PanelSectionRow>
<ToggleField
label="Enable Charge Limit (80%)"
checked={chargeLimitEnabled}
onChange={setChargeLimit}
/>
</PanelSectionRow>
</PanelSection>
<ErrorBoundary title={'Controller Lighting Panel'}>
<ControllerLightingPanel />
</ErrorBoundary>
Expand Down
3 changes: 2 additions & 1 deletion src/redux-modules/store.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { configureStore } from '@reduxjs/toolkit';
import { rgbSlice, saveRgbSettingsMiddleware } from './rgbSlice';
import { uiSlice } from './uiSlice';
import { uiSlice, uiSliceMiddleware } from './uiSlice';
import {
controllerSlice,
saveControllerSettingsMiddleware
Expand All @@ -17,6 +17,7 @@ export const store = configureStore({
},
middleware: (getDefaultMiddleware) =>
getDefaultMiddleware().concat([
uiSliceMiddleware,
saveRgbSettingsMiddleware,
saveControllerSettingsMiddleware,
saveFanSettingsMiddleware
Expand Down
33 changes: 32 additions & 1 deletion src/redux-modules/uiSlice.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,19 @@ import { createSlice } from '@reduxjs/toolkit';
import type { PayloadAction } from '@reduxjs/toolkit';
import { setCurrentGameId, setInitialState } from './extraActions';
import { RootState } from './store';
import { extractDisplayName, logInfo } from '../backend/utils';
import {
createServerApiHelpers,
extractDisplayName,
getServerApi,
logInfo
} from '../backend/utils';
// import type { RootState } from './store';

type UiStateType = {
initialLoading: boolean;
currentGameId: undefined | string;
currentDisplayName: undefined | string;
chargeLimitEnabled?: boolean;
pluginVersionNum?: string;
};

Expand All @@ -27,6 +33,9 @@ export const uiSlice = createSlice({
reducers: {
setInitialLoading: (state, action: PayloadAction<boolean>) => {
state.initialLoading = action.payload;
},
setChargeLimit(state, action: PayloadAction<boolean>) {
state.chargeLimitEnabled = action.payload;
}
},
extraReducers: (builder) => {
Expand All @@ -35,6 +44,9 @@ export const uiSlice = createSlice({
if (action.payload?.pluginVersionNum) {
state.pluginVersionNum = `${action.payload.pluginVersionNum}`;
}
if (action.payload?.chargeLimitEnabled) {
state.chargeLimitEnabled = Boolean(action.payload?.chargeLimitEnabled);
}
});
builder.addCase(setCurrentGameId, (state, action) => {
if (action?.payload) {
Expand All @@ -55,3 +67,22 @@ export const selectCurrentGameId = (state: RootState) =>

export const selectCurrentGameDisplayName = (state: RootState) =>
state.ui?.currentDisplayName || 'default';

export const selectChargeLimitEnabled = (state: RootState) =>
Boolean(state.ui?.chargeLimitEnabled);

export const uiSliceMiddleware =
(store: any) => (next: any) => (action: any) => {
const { type } = action;
const serverApi = getServerApi();

const result = next(action);

if (type === uiSlice.actions.setChargeLimit.type && serverApi) {
const { setChargeLimit } = createServerApiHelpers(serverApi);

setChargeLimit(action.payload);
}

return result;
};

0 comments on commit b489d0a

Please sign in to comment.