Merge branch 'dev' into paste-text-keyboard-layouts

This commit is contained in:
Daniel Lorch 2025-05-11 22:46:09 +02:00 committed by GitHub
commit 94f36d0fac
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 108 additions and 22 deletions

View File

@ -90,6 +90,7 @@ type Config struct {
KeyboardLayout string `json:"keyboard_layout"` KeyboardLayout string `json:"keyboard_layout"`
EdidString string `json:"hdmi_edid_string"` EdidString string `json:"hdmi_edid_string"`
ActiveExtension string `json:"active_extension"` ActiveExtension string `json:"active_extension"`
DisplayRotation string `json:"display_rotation"`
DisplayMaxBrightness int `json:"display_max_brightness"` DisplayMaxBrightness int `json:"display_max_brightness"`
DisplayDimAfterSec int `json:"display_dim_after_sec"` DisplayDimAfterSec int `json:"display_dim_after_sec"`
DisplayOffAfterSec int `json:"display_off_after_sec"` DisplayOffAfterSec int `json:"display_off_after_sec"`
@ -109,6 +110,7 @@ var defaultConfig = &Config{
ActiveExtension: "", ActiveExtension: "",
KeyboardMacros: []KeyboardMacro{}, KeyboardMacros: []KeyboardMacro{},
KeyboardLayout: "en_US", KeyboardLayout: "en_US",
DisplayRotation: "270",
DisplayMaxBrightness: 64, DisplayMaxBrightness: 64,
DisplayDimAfterSec: 120, // 2 minutes DisplayDimAfterSec: 120, // 2 minutes
DisplayOffAfterSec: 1800, // 30 minutes DisplayOffAfterSec: 1800, // 30 minutes

View File

@ -73,6 +73,10 @@ func lvImgSetSrc(objName string, src string) (*CtrlResponse, error) {
return CallCtrlAction("lv_img_set_src", map[string]interface{}{"obj": objName, "src": src}) return CallCtrlAction("lv_img_set_src", map[string]interface{}{"obj": objName, "src": src})
} }
func lvDispSetRotation(rotation string) (*CtrlResponse, error) {
return CallCtrlAction("lv_disp_set_rotation", map[string]interface{}{"rotation": rotation})
}
func updateLabelIfChanged(objName string, newText string) { func updateLabelIfChanged(objName string, newText string) {
if newText != "" && newText != displayedTexts[objName] { if newText != "" && newText != displayedTexts[objName] {
_, _ = lvLabelSetText(objName, newText) _, _ = lvLabelSetText(objName, newText)
@ -373,6 +377,7 @@ func init() {
waitCtrlClientConnected() waitCtrlClientConnected()
displayLogger.Info().Msg("setting initial display contents") displayLogger.Info().Msg("setting initial display contents")
time.Sleep(500 * time.Millisecond) time.Sleep(500 * time.Millisecond)
_, _ = lvDispSetRotation(config.DisplayRotation)
updateStaticContents() updateStaticContents()
displayInited = true displayInited = true
displayLogger.Info().Msg("display inited") displayLogger.Info().Msg("display inited")

View File

@ -13,7 +13,8 @@ var defaultNTPServers = []string{
"time.aws.com", "time.aws.com",
"time.windows.com", "time.windows.com",
"time.google.com", "time.google.com",
"162.159.200.123", // time.cloudflare.com "162.159.200.123", // time.cloudflare.com IPv4
"2606:4700:f1::123", // time.cloudflare.com IPv6
"0.pool.ntp.org", "0.pool.ntp.org",
"1.pool.ntp.org", "1.pool.ntp.org",
"2.pool.ntp.org", "2.pool.ntp.org",
@ -57,6 +58,13 @@ func (t *TimeSync) queryMultipleNTP(servers []string, timeout time.Duration) (no
// query the server // query the server
now, response, err := queryNtpServer(server, timeout) now, response, err := queryNtpServer(server, timeout)
if err != nil {
scopedLogger.Warn().
Str("error", err.Error()).
Msg("failed to query NTP server")
results <- nil
return
}
// set the last RTT // set the last RTT
metricNtpServerLastRTT.WithLabelValues( metricNtpServerLastRTT.WithLabelValues(
@ -76,32 +84,33 @@ func (t *TimeSync) queryMultipleNTP(servers []string, timeout time.Duration) (no
strconv.Itoa(int(response.Precision)), strconv.Itoa(int(response.Precision)),
).Set(1) ).Set(1)
if err == nil { // increase success count
// increase success count metricNtpTotalSuccessCount.Inc()
metricNtpTotalSuccessCount.Inc() metricNtpSuccessCount.WithLabelValues(server).Inc()
metricNtpSuccessCount.WithLabelValues(server).Inc()
scopedLogger.Info(). scopedLogger.Info().
Str("time", now.Format(time.RFC3339)). Str("time", now.Format(time.RFC3339)).
Str("reference", response.ReferenceString()). Str("reference", response.ReferenceString()).
Str("rtt", response.RTT.String()). Str("rtt", response.RTT.String()).
Str("clockOffset", response.ClockOffset.String()). Str("clockOffset", response.ClockOffset.String()).
Uint8("stratum", response.Stratum). Uint8("stratum", response.Stratum).
Msg("NTP server returned time") Msg("NTP server returned time")
results <- &ntpResult{ results <- &ntpResult{
now: now, now: now,
offset: &response.ClockOffset, offset: &response.ClockOffset,
}
} else {
scopedLogger.Warn().
Str("error", err.Error()).
Msg("failed to query NTP server")
} }
}(server) }(server)
} }
result := <-results for range servers {
return result.now, result.offset result := <-results
if result == nil {
continue
}
now, offset = result.now, result.offset
return
}
return
} }
func queryNtpServer(server string, timeout time.Duration) (now *time.Time, response *ntp.Response, err error) { func queryNtpServer(server string, timeout time.Duration) (now *time.Time, response *ntp.Response, err error) {

View File

@ -55,6 +55,8 @@ var absoluteMouseCombinedReportDesc = []byte{
0x09, 0x38, // Usage (Wheel) 0x09, 0x38, // Usage (Wheel)
0x15, 0x81, // Logical Minimum (-127) 0x15, 0x81, // Logical Minimum (-127)
0x25, 0x7F, // Logical Maximum (127) 0x25, 0x7F, // Logical Maximum (127)
0x35, 0x00, // Physical Minimum (0) = Reset Physical Minimum
0x45, 0x00, // Physical Maximum (0) = Reset Physical Maximum
0x75, 0x08, // Report Size (8) 0x75, 0x08, // Report Size (8)
0x95, 0x01, // Report Count (1) 0x95, 0x01, // Report Count (1)
0x81, 0x06, // Input (Data, Var, Rel) 0x81, 0x06, // Input (Data, Var, Rel)

View File

@ -38,6 +38,10 @@ type JSONRPCEvent struct {
Params interface{} `json:"params,omitempty"` Params interface{} `json:"params,omitempty"`
} }
type DisplayRotationSettings struct {
Rotation string `json:"rotation"`
}
type BacklightSettings struct { type BacklightSettings struct {
MaxBrightness int `json:"max_brightness"` MaxBrightness int `json:"max_brightness"`
DimAfter int `json:"dim_after"` DimAfter int `json:"dim_after"`
@ -280,6 +284,24 @@ func rpcTryUpdate() error {
return nil return nil
} }
func rpcSetDisplayRotation(params DisplayRotationSettings) error {
var err error
_, err = lvDispSetRotation(params.Rotation)
if err == nil {
config.DisplayRotation = params.Rotation
if err := SaveConfig(); err != nil {
return fmt.Errorf("failed to save config: %w", err)
}
}
return err
}
func rpcGetDisplayRotation() (*DisplayRotationSettings, error) {
return &DisplayRotationSettings{
Rotation: config.DisplayRotation,
}, nil
}
func rpcSetBacklightSettings(params BacklightSettings) error { func rpcSetBacklightSettings(params BacklightSettings) error {
blConfig := params blConfig := params
@ -1024,6 +1046,8 @@ var rpcHandlers = map[string]RPCHandler{
"getWakeOnLanDevices": {Func: rpcGetWakeOnLanDevices}, "getWakeOnLanDevices": {Func: rpcGetWakeOnLanDevices},
"setWakeOnLanDevices": {Func: rpcSetWakeOnLanDevices, Params: []string{"params"}}, "setWakeOnLanDevices": {Func: rpcSetWakeOnLanDevices, Params: []string{"params"}},
"resetConfig": {Func: rpcResetConfig}, "resetConfig": {Func: rpcResetConfig},
"setDisplayRotation": {Func: rpcSetDisplayRotation, Params: []string{"params"}},
"getDisplayRotation": {Func: rpcGetDisplayRotation},
"setBacklightSettings": {Func: rpcSetBacklightSettings, Params: []string{"params"}}, "setBacklightSettings": {Func: rpcSetBacklightSettings, Params: []string{"params"}},
"getBacklightSettings": {Func: rpcGetBacklightSettings}, "getBacklightSettings": {Func: rpcGetBacklightSettings},
"getDCPowerState": {Func: rpcGetDCPowerState}, "getDCPowerState": {Func: rpcGetDCPowerState},

View File

@ -292,6 +292,9 @@ interface SettingsState {
developerMode: boolean; developerMode: boolean;
setDeveloperMode: (enabled: boolean) => void; setDeveloperMode: (enabled: boolean) => void;
displayRotation: string;
setDisplayRotation: (rotation: string) => void;
backlightSettings: BacklightSettings; backlightSettings: BacklightSettings;
setBacklightSettings: (settings: BacklightSettings) => void; setBacklightSettings: (settings: BacklightSettings) => void;
} }
@ -312,6 +315,10 @@ export const useSettingsStore = create(
developerMode: false, developerMode: false,
setDeveloperMode: enabled => set({ developerMode: enabled }), setDeveloperMode: enabled => set({ developerMode: enabled }),
displayRotation: "270",
setDisplayRotation: (rotation: string) =>
set({ displayRotation: rotation }),
backlightSettings: { backlightSettings: {
max_brightness: 100, max_brightness: 100,
dim_after: 10000, dim_after: 10000,

View File

@ -15,6 +15,25 @@ export default function SettingsHardwareRoute() {
const [send] = useJsonRpc(); const [send] = useJsonRpc();
const settings = useSettingsStore(); const settings = useSettingsStore();
const setDisplayRotation = useSettingsStore(state => state.setDisplayRotation);
const handleDisplayRotationChange = (rotation: string) => {
setDisplayRotation(rotation);
handleDisplayRotationSave();
};
const handleDisplayRotationSave = () => {
send("setDisplayRotation", { params: { rotation: settings.displayRotation } }, resp => {
if ("error" in resp) {
notifications.error(
`Failed to set display orientation: ${resp.error.data || "Unknown error"}`,
);
return;
}
notifications.success("Display orientation updated successfully");
});
};
const setBacklightSettings = useSettingsStore(state => state.setBacklightSettings); const setBacklightSettings = useSettingsStore(state => state.setBacklightSettings);
const handleBacklightSettingsChange = (settings: BacklightSettings) => { const handleBacklightSettingsChange = (settings: BacklightSettings) => {
@ -59,6 +78,24 @@ export default function SettingsHardwareRoute() {
description="Configure display settings and hardware options for your JetKVM device" description="Configure display settings and hardware options for your JetKVM device"
/> />
<div className="space-y-4"> <div className="space-y-4">
<SettingsItem
title="Display Orientation"
description="Set the orientation of the display"
>
<SelectMenuBasic
size="SM"
label=""
value={settings.displayRotation.toString()}
options={[
{ value: "270", label: "Normal" },
{ value: "90", label: "Inverted" },
]}
onChange={e => {
settings.displayRotation = e.target.value;
handleDisplayRotationChange(settings.displayRotation);
}}
/>
</SettingsItem>
<SettingsItem <SettingsItem
title="Display Brightness" title="Display Brightness"
description="Set the brightness of the display" description="Set the brightness of the display"