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()
|
_ = unmountATXControl()
|
||||||
case "dc-power":
|
case "dc-power":
|
||||||
_ = unmountDCControl()
|
_ = unmountDCControl()
|
||||||
|
case "serial-buttons":
|
||||||
|
_ = unmountSerialButtons()
|
||||||
}
|
}
|
||||||
config.ActiveExtension = extensionId
|
config.ActiveExtension = extensionId
|
||||||
if err := SaveConfig(); err != nil {
|
if err := SaveConfig(); err != nil {
|
||||||
|
@ -768,6 +770,8 @@ func rpcSetActiveExtension(extensionId string) error {
|
||||||
_ = mountATXControl()
|
_ = mountATXControl()
|
||||||
case "dc-power":
|
case "dc-power":
|
||||||
_ = mountDCControl()
|
_ = mountDCControl()
|
||||||
|
case "serial-buttons":
|
||||||
|
_ = mountSerialButtons()
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -802,6 +806,15 @@ func rpcGetATXState() (ATXState, error) {
|
||||||
return state, nil
|
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 {
|
type SerialSettings struct {
|
||||||
BaudRate string `json:"baudRate"`
|
BaudRate string `json:"baudRate"`
|
||||||
DataBits string `json:"dataBits"`
|
DataBits string `json:"dataBits"`
|
||||||
|
@ -1296,6 +1309,7 @@ var rpcHandlers = map[string]RPCHandler{
|
||||||
"setActiveExtension": {Func: rpcSetActiveExtension, Params: []string{"extensionId"}},
|
"setActiveExtension": {Func: rpcSetActiveExtension, Params: []string{"extensionId"}},
|
||||||
"getATXState": {Func: rpcGetATXState},
|
"getATXState": {Func: rpcGetATXState},
|
||||||
"setATXPowerAction": {Func: rpcSetATXPowerAction, Params: []string{"action"}},
|
"setATXPowerAction": {Func: rpcSetATXPowerAction, Params: []string{"action"}},
|
||||||
|
"sendCustomCommand": {Func: rpcSendCustomCommand, Params: []string{"command"}},
|
||||||
"getSerialSettings": {Func: rpcGetSerialSettings},
|
"getSerialSettings": {Func: rpcGetSerialSettings},
|
||||||
"setSerialSettings": {Func: rpcSetSerialSettings, Params: []string{"settings"}},
|
"setSerialSettings": {Func: rpcSetSerialSettings, Params: []string{"settings"}},
|
||||||
"getSerialButtonConfig": {Func: rpcGetSerialButtonConfig},
|
"getSerialButtonConfig": {Func: rpcGetSerialButtonConfig},
|
||||||
|
|
27
serial.go
27
serial.go
|
@ -251,6 +251,33 @@ func setDCRestoreState(state int) error {
|
||||||
return nil
|
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{
|
var defaultMode = &serial.Mode{
|
||||||
BaudRate: 115200,
|
BaudRate: 115200,
|
||||||
DataBits: 8,
|
DataBits: 8,
|
||||||
|
|
|
@ -76,15 +76,10 @@ export function SerialButtons() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const cfg = resp.result as ButtonConfig;
|
|
||||||
console.log("loaded button config: ");
|
|
||||||
console.log(cfg);
|
|
||||||
setButtonConfig(resp.result as ButtonConfig);
|
setButtonConfig(resp.result as ButtonConfig);
|
||||||
});
|
});
|
||||||
|
|
||||||
console.log("loaded loaded settings through effect.");
|
});
|
||||||
|
|
||||||
}, [send]);
|
|
||||||
|
|
||||||
const handleSerialSettingChange = (setting: keyof SerialSettings, value: string) => {
|
const handleSerialSettingChange = (setting: keyof SerialSettings, value: string) => {
|
||||||
const newSettings = { ...serialSettings, [setting]: value };
|
const newSettings = { ...serialSettings, [setting]: value };
|
||||||
|
@ -104,21 +99,27 @@ export function SerialButtons() {
|
||||||
notifications.error(`Failed to update button config: ${resp.error.data || "Unknown error"}`);
|
notifications.error(`Failed to update button config: ${resp.error.data || "Unknown error"}`);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// setButtonConfig(newButtonConfig);
|
setButtonConfig(newButtonConfig);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
/** build final string to send:
|
const onClickButton = (btn: QuickButton) => {
|
||||||
* if the user's button command already contains a terminator, we don't append the selected terminator safely
|
|
||||||
*/
|
/** build final string to send:
|
||||||
const buildOutgoing = (raw: string): string => {
|
* if the user's button command already contains a terminator, we don't append the selected terminator safely
|
||||||
const t = buttonConfig.terminator ?? "";
|
*/
|
||||||
return raw.endsWith("\r") || raw.endsWith("\n") ? raw : raw + t;
|
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 */
|
/** CRUD helpers */
|
||||||
|
@ -134,11 +135,11 @@ export function SerialButtons() {
|
||||||
setDraftCmd(btn.command);
|
setDraftCmd(btn.command);
|
||||||
};
|
};
|
||||||
|
|
||||||
// const removeBtn = async (id: string) => {
|
const removeBtn = (id: string) => {
|
||||||
// const next = { ...buttonConfig, buttons: buttonConfig.buttons.filter(b => b.id !== id).map((b, i) => ({ ...b, sort: i })) };
|
const nextButtons = buttonConfig.buttons.filter(b => b.id !== id).map((b, i) => ({ ...b, sort: i })) ;
|
||||||
// // await setButtonConfig(next);
|
handleSerialButtonConfigChange("buttons", stableSort(nextButtons) );
|
||||||
// setEditorOpen(null);
|
setEditorOpen(null);
|
||||||
// };
|
};
|
||||||
|
|
||||||
const saveDraft = () => {
|
const saveDraft = () => {
|
||||||
const label = draftLabel.trim() || "Unnamed";
|
const label = draftLabel.trim() || "Unnamed";
|
||||||
|
@ -327,7 +328,7 @@ export function SerialButtons() {
|
||||||
theme="danger"
|
theme="danger"
|
||||||
LeadingIcon={LuTrash2}
|
LeadingIcon={LuTrash2}
|
||||||
text="Delete"
|
text="Delete"
|
||||||
// onClick={() => removeBtn(editorOpen!.id)}
|
onClick={() => removeBtn(editorOpen.id!)}
|
||||||
aria-label={`Delete ${draftLabel}`}
|
aria-label={`Delete ${draftLabel}`}
|
||||||
/>)}
|
/>)}
|
||||||
</div>
|
</div>
|
||||||
|
|
Loading…
Reference in New Issue