Skip to content

Commit 7267347

Browse files
authored
feat(dc-power-extension): power restore mode in DCPowerControl component (jetkvm#672)
* DC-extension: Supporting to set the power restore mode in DCPowerControl component * fixing lint issue
1 parent 393bc12 commit 7267347

File tree

3 files changed

+85
-6
lines changed

3 files changed

+85
-6
lines changed

jsonrpc.go

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -681,10 +681,11 @@ func rpcResetConfig() error {
681681
}
682682

683683
type DCPowerState struct {
684-
IsOn bool `json:"isOn"`
685-
Voltage float64 `json:"voltage"`
686-
Current float64 `json:"current"`
687-
Power float64 `json:"power"`
684+
IsOn bool `json:"isOn"`
685+
Voltage float64 `json:"voltage"`
686+
Current float64 `json:"current"`
687+
Power float64 `json:"power"`
688+
RestoreState int `json:"restoreState"`
688689
}
689690

690691
func rpcGetDCPowerState() (DCPowerState, error) {
@@ -700,6 +701,15 @@ func rpcSetDCPowerState(enabled bool) error {
700701
return nil
701702
}
702703

704+
func rpcSetDCRestoreState(state int) error {
705+
logger.Info().Int("state", state).Msg("Setting DC restore state")
706+
err := setDCRestoreState(state)
707+
if err != nil {
708+
return fmt.Errorf("failed to set DC restore state: %w", err)
709+
}
710+
return nil
711+
}
712+
703713
func rpcGetActiveExtension() (string, error) {
704714
return config.ActiveExtension, nil
705715
}
@@ -1088,6 +1098,7 @@ var rpcHandlers = map[string]RPCHandler{
10881098
"getBacklightSettings": {Func: rpcGetBacklightSettings},
10891099
"getDCPowerState": {Func: rpcGetDCPowerState},
10901100
"setDCPowerState": {Func: rpcSetDCPowerState, Params: []string{"enabled"}},
1101+
"setDCRestoreState": {Func: rpcSetDCRestoreState, Params: []string{"state"}},
10911102
"getActiveExtension": {Func: rpcGetActiveExtension},
10921103
"setActiveExtension": {Func: rpcSetActiveExtension, Params: []string{"extensionId"}},
10931104
"getATXState": {Func: rpcGetATXState},

serial.go

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,7 @@ var dcState DCPowerState
142142
func runDCControl() {
143143
scopedLogger := serialLogger.With().Str("service", "dc_control").Logger()
144144
reader := bufio.NewReader(port)
145+
hasRestoreFeature := false
145146
for {
146147
line, err := reader.ReadString('\n')
147148
if err != nil {
@@ -151,7 +152,13 @@ func runDCControl() {
151152

152153
// Split the line by semicolon
153154
parts := strings.Split(strings.TrimSpace(line), ";")
154-
if len(parts) != 4 {
155+
if len(parts) == 5 {
156+
scopedLogger.Debug().Str("line", line).Msg("Detected DC extension with restore feature")
157+
hasRestoreFeature = true
158+
} else if len(parts) == 4 {
159+
scopedLogger.Debug().Str("line", line).Msg("Detected DC extension without restore feature")
160+
hasRestoreFeature = false
161+
} else {
155162
scopedLogger.Warn().Str("line", line).Msg("Invalid line")
156163
continue
157164
}
@@ -163,6 +170,17 @@ func runDCControl() {
163170
continue
164171
}
165172
dcState.IsOn = powerState == 1
173+
if hasRestoreFeature {
174+
restoreState, err := strconv.Atoi(parts[4])
175+
if err != nil {
176+
scopedLogger.Warn().Err(err).Msg("Invalid restore state")
177+
continue
178+
}
179+
dcState.RestoreState = restoreState
180+
} else {
181+
// -1 means not supported
182+
dcState.RestoreState = -1
183+
}
166184
milliVolts, err := strconv.ParseFloat(parts[1], 64)
167185
if err != nil {
168186
scopedLogger.Warn().Err(err).Msg("Invalid voltage")
@@ -210,6 +228,25 @@ func setDCPowerState(on bool) error {
210228
return nil
211229
}
212230

231+
func setDCRestoreState(state int) error {
232+
_, err := port.Write([]byte("\n"))
233+
if err != nil {
234+
return err
235+
}
236+
command := "RESTORE_MODE_OFF\n"
237+
switch state {
238+
case 1:
239+
command = "RESTORE_MODE_ON\n"
240+
case 2:
241+
command = "RESTORE_MODE_LAST_STATE\n"
242+
}
243+
_, err = port.Write([]byte(command))
244+
if err != nil {
245+
return err
246+
}
247+
return nil
248+
}
249+
213250
var defaultMode = &serial.Mode{
214251
BaudRate: 115200,
215252
DataBits: 8,

ui/src/components/extensions/DCPowerControl.tsx

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,14 @@ import { useJsonRpc } from "@/hooks/useJsonRpc";
88
import notifications from "@/notifications";
99
import FieldLabel from "@components/FieldLabel";
1010
import LoadingSpinner from "@components/LoadingSpinner";
11+
import {SelectMenuBasic} from "@components/SelectMenuBasic";
1112

1213
interface DCPowerState {
1314
isOn: boolean;
1415
voltage: number;
1516
current: number;
1617
power: number;
18+
restoreState: number;
1719
}
1820

1921
export function DCPowerControl() {
@@ -43,6 +45,20 @@ export function DCPowerControl() {
4345
getDCPowerState(); // Refresh state after change
4446
});
4547
};
48+
const handleRestoreChange = (state: number) => {
49+
// const state = powerState?.restoreState === 0 ? 1 : powerState?.restoreState === 1 ? 2 : 0;
50+
send("setDCRestoreState", { state }, resp => {
51+
if ("error" in resp) {
52+
notifications.error(
53+
`Failed to set DC power state: ${resp.error.data || "Unknown error"}`,
54+
);
55+
return;
56+
}
57+
getDCPowerState(); // Refresh state after change
58+
});
59+
};
60+
61+
4662

4763
useEffect(() => {
4864
getDCPowerState();
@@ -63,7 +79,7 @@ export function DCPowerControl() {
6379
<LoadingSpinner className="h-6 w-6 text-blue-500 dark:text-blue-400" />
6480
</Card>
6581
) : (
66-
<Card className="h-[160px] animate-fadeIn opacity-0">
82+
<Card className="animate-fadeIn opacity-0">
6783
<div className="space-y-4 p-3">
6884
{/* Power Controls */}
6985
<div className="flex items-center space-x-2">
@@ -84,6 +100,21 @@ export function DCPowerControl() {
84100
onClick={() => handlePowerToggle(false)}
85101
/>
86102
</div>
103+
{powerState.restoreState > -1 ? (
104+
<div className="flex items-center">
105+
<SelectMenuBasic
106+
size="SM"
107+
label="Restore Power Loss"
108+
value={powerState.restoreState}
109+
onChange={e => handleRestoreChange(parseInt(e.target.value))}
110+
options={[
111+
{ value: '0', label: "Power OFF" },
112+
{ value: '1', label: "Power ON" },
113+
{ value: '2', label: "Last State" },
114+
]}
115+
/>
116+
</div>
117+
) : null}
87118
<hr className="border-slate-700/30 dark:border-slate-600/30" />
88119

89120
{/* Status Display */}

0 commit comments

Comments
 (0)