mirror of https://github.com/jetkvm/kvm.git
Add backend to send custom commands
This commit is contained in:
parent
b2b3ee40a7
commit
d8f670fcba
14
jsonrpc.go
14
jsonrpc.go
|
@ -758,6 +758,8 @@ func rpcSetActiveExtension(extensionId string) error {
|
|||
_ = unmountATXControl()
|
||||
case "dc-power":
|
||||
_ = unmountDCControl()
|
||||
case "serial-buttons":
|
||||
_ = unmountSerialButtons()
|
||||
}
|
||||
config.ActiveExtension = extensionId
|
||||
if err := SaveConfig(); err != nil {
|
||||
|
@ -768,6 +770,8 @@ func rpcSetActiveExtension(extensionId string) error {
|
|||
_ = mountATXControl()
|
||||
case "dc-power":
|
||||
_ = mountDCControl()
|
||||
case "serial-buttons":
|
||||
_ = mountSerialButtons()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -802,6 +806,15 @@ func rpcGetATXState() (ATXState, error) {
|
|||
return state, nil
|
||||
}
|
||||
|
||||
func rpcSendCustomCommand(command string) error {
|
||||
logger.Info().Str("Command", command).Msg("JSONRPC: Sending custom serial command")
|
||||
err := sendCustomCommand(command)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to set DC power state: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type SerialSettings struct {
|
||||
BaudRate string `json:"baudRate"`
|
||||
DataBits string `json:"dataBits"`
|
||||
|
@ -1296,6 +1309,7 @@ var rpcHandlers = map[string]RPCHandler{
|
|||
"setActiveExtension": {Func: rpcSetActiveExtension, Params: []string{"extensionId"}},
|
||||
"getATXState": {Func: rpcGetATXState},
|
||||
"setATXPowerAction": {Func: rpcSetATXPowerAction, Params: []string{"action"}},
|
||||
"sendCustomCommand": {Func: rpcSendCustomCommand, Params: []string{"command"}},
|
||||
"getSerialSettings": {Func: rpcGetSerialSettings},
|
||||
"setSerialSettings": {Func: rpcSetSerialSettings, Params: []string{"settings"}},
|
||||
"getSerialButtonConfig": {Func: rpcGetSerialButtonConfig},
|
||||
|
|
27
serial.go
27
serial.go
|
@ -251,6 +251,33 @@ func setDCRestoreState(state int) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func mountSerialButtons() error {
|
||||
_ = port.SetMode(defaultMode)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func unmountSerialButtons() error {
|
||||
_ = reopenSerialPort()
|
||||
return nil
|
||||
}
|
||||
|
||||
func sendCustomCommand(command string) error {
|
||||
scopedLogger := serialLogger.With().Str("service", "custom-buttons").Logger()
|
||||
scopedLogger.Info().Str("Command", command).Msg("Sending custom command.")
|
||||
_, err := port.Write([]byte("\n"))
|
||||
if err != nil {
|
||||
scopedLogger.Warn().Err(err).Msg("Failed to send serial output \\n")
|
||||
return err
|
||||
}
|
||||
_, err = port.Write([]byte(command))
|
||||
if err != nil {
|
||||
scopedLogger.Warn().Err(err).Str("line", command).Msg("Failed to send serial output")
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
var defaultMode = &serial.Mode{
|
||||
BaudRate: 115200,
|
||||
DataBits: 8,
|
||||
|
|
|
@ -76,15 +76,10 @@ export function SerialButtons() {
|
|||
return;
|
||||
}
|
||||
|
||||
const cfg = resp.result as ButtonConfig;
|
||||
console.log("loaded button config: ");
|
||||
console.log(cfg);
|
||||
setButtonConfig(resp.result as ButtonConfig);
|
||||
});
|
||||
|
||||
console.log("loaded loaded settings through effect.");
|
||||
|
||||
}, [send]);
|
||||
});
|
||||
|
||||
const handleSerialSettingChange = (setting: keyof SerialSettings, value: string) => {
|
||||
const newSettings = { ...serialSettings, [setting]: value };
|
||||
|
@ -104,21 +99,27 @@ export function SerialButtons() {
|
|||
notifications.error(`Failed to update button config: ${resp.error.data || "Unknown error"}`);
|
||||
return;
|
||||
}
|
||||
// setButtonConfig(newButtonConfig);
|
||||
setButtonConfig(newButtonConfig);
|
||||
});
|
||||
};
|
||||
|
||||
/** build final string to send:
|
||||
* if the user's button command already contains a terminator, we don't append the selected terminator safely
|
||||
*/
|
||||
const buildOutgoing = (raw: string): string => {
|
||||
const t = buttonConfig.terminator ?? "";
|
||||
return raw.endsWith("\r") || raw.endsWith("\n") ? raw : raw + t;
|
||||
};
|
||||
const onClickButton = (btn: QuickButton) => {
|
||||
|
||||
/** build final string to send:
|
||||
* if the user's button command already contains a terminator, we don't append the selected terminator safely
|
||||
*/
|
||||
const raw = btn.command;
|
||||
const t = buttonConfig.terminator ?? "";
|
||||
const command = raw.endsWith("\r") || raw.endsWith("\n") ? raw : raw + t;
|
||||
|
||||
send("sendCustomCommand", { command }, (resp: JsonRpcResponse) => {
|
||||
if ("error" in resp) {
|
||||
notifications.error(
|
||||
`Failed to send ATX power action: ${resp.error.data || "Unknown error"}`,
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
const onClickButton = async (btn: QuickButton) => {
|
||||
buildOutgoing(btn.command);
|
||||
// Try to send via backend method
|
||||
};
|
||||
|
||||
/** CRUD helpers */
|
||||
|
@ -134,11 +135,11 @@ export function SerialButtons() {
|
|||
setDraftCmd(btn.command);
|
||||
};
|
||||
|
||||
// const removeBtn = async (id: string) => {
|
||||
// const next = { ...buttonConfig, buttons: buttonConfig.buttons.filter(b => b.id !== id).map((b, i) => ({ ...b, sort: i })) };
|
||||
// // await setButtonConfig(next);
|
||||
// setEditorOpen(null);
|
||||
// };
|
||||
const removeBtn = (id: string) => {
|
||||
const nextButtons = buttonConfig.buttons.filter(b => b.id !== id).map((b, i) => ({ ...b, sort: i })) ;
|
||||
handleSerialButtonConfigChange("buttons", stableSort(nextButtons) );
|
||||
setEditorOpen(null);
|
||||
};
|
||||
|
||||
const saveDraft = () => {
|
||||
const label = draftLabel.trim() || "Unnamed";
|
||||
|
@ -327,7 +328,7 @@ export function SerialButtons() {
|
|||
theme="danger"
|
||||
LeadingIcon={LuTrash2}
|
||||
text="Delete"
|
||||
// onClick={() => removeBtn(editorOpen!.id)}
|
||||
onClick={() => removeBtn(editorOpen.id!)}
|
||||
aria-label={`Delete ${draftLabel}`}
|
||||
/>)}
|
||||
</div>
|
||||
|
|
Loading…
Reference in New Issue