From 8cf85d6ac3dbef8230f67a6d60a0821e9c49a5fa Mon Sep 17 00:00:00 2001 From: art0007i Date: Sat, 14 Mar 2026 20:04:02 +0100 Subject: [PATCH 1/3] add tracker timeout setting --- gui/public/i18n/en/translation.ftl | 2 + gui/src/components/commons/Input.tsx | 4 ++ .../settings/pages/GeneralSettings.tsx | 44 ++++++++++++++++++- .../java/dev/slimevr/config/TimeoutConfig.kt | 23 ++++++++++ .../main/java/dev/slimevr/config/VRConfig.kt | 2 + .../rpc/settings/RPCSettingsBuilder.kt | 15 +++++++ .../rpc/settings/RPCSettingsHandler.kt | 10 ++++- .../dev/slimevr/tracking/trackers/Tracker.kt | 8 ++-- solarxr-protocol | 2 +- 9 files changed, 104 insertions(+), 6 deletions(-) create mode 100644 server/core/src/main/java/dev/slimevr/config/TimeoutConfig.kt diff --git a/gui/public/i18n/en/translation.ftl b/gui/public/i18n/en/translation.ftl index 7158573da2..5e7be823d2 100644 --- a/gui/public/i18n/en/translation.ftl +++ b/gui/public/i18n/en/translation.ftl @@ -582,6 +582,8 @@ settings-general-tracker_mechanics-trackers_over_usb = Trackers over USB settings-general-tracker_mechanics-trackers_over_usb-description = Enables receiving HID tracker data over USB. Make sure connected trackers have connection over HID enabled! settings-general-tracker_mechanics-trackers_over_usb-enabled-label = Allow HID trackers to connect directly over USB +settings-general-tracker_mechanics-timeout_duration = Timeout duration +settings-general-tracker_mechanics-timeout_duration-description = How long in seconds should the tracker be considered timed out, instead of disconnected. settings-stay_aligned = Stay Aligned settings-stay_aligned-description = Stay Aligned reduces drift by gradually adjusting your trackers to match your relaxed poses. diff --git a/gui/src/components/commons/Input.tsx b/gui/src/components/commons/Input.tsx index a6060b1258..6bd0e877d4 100644 --- a/gui/src/components/commons/Input.tsx +++ b/gui/src/components/commons/Input.tsx @@ -35,6 +35,7 @@ export const InputInside = forwardRef< value, error, variant = 'primary', + ...props }, ref ) { @@ -98,6 +99,7 @@ export const InputInside = forwardRef< value={computedValue} // Do we want that behaviour ? disabled={disabled} ref={ref} + {...props} /> {type === 'password' && (
['rules']; control: Control; @@ -154,6 +157,7 @@ export const Input = ({ onChange={onChange} ref={ref} name={name} + {...props} /> )} /> diff --git a/gui/src/components/settings/pages/GeneralSettings.tsx b/gui/src/components/settings/pages/GeneralSettings.tsx index 174601a93c..eec6d39580 100644 --- a/gui/src/components/settings/pages/GeneralSettings.tsx +++ b/gui/src/components/settings/pages/GeneralSettings.tsx @@ -15,6 +15,7 @@ import { SteamVRTrackersSettingT, TapDetectionSettingsT, HIDSettingsT, + TimeoutSettingsT, } from 'solarxr-protocol'; import { useConfig } from '@/hooks/config'; import { useWebsocketAPI } from '@/hooks/websocket-api'; @@ -43,6 +44,7 @@ import { loadResetSettings, ResetSettingsForm, } from '@/hooks/reset-settings'; +import { Input } from '@/components/commons/Input'; export type SettingsForm = { trackers: { @@ -105,6 +107,9 @@ export type SettingsForm = { hidSettings: { trackersOverHID: boolean; }; + timeout: { + duration: number + }; }; const defaultValues: SettingsForm = { @@ -161,6 +166,7 @@ const defaultValues: SettingsForm = { resetsSettings: defaultResetSettings, stayAligned: defaultStayAlignedSettings, hidSettings: { trackersOverHID: false }, + timeout: { duration: 3.0 }, }; export function GeneralSettings() { @@ -286,6 +292,10 @@ export function GeneralSettings() { hidSettings.trackersOverHid = values.hidSettings.trackersOverHID; settings.hidSettings = hidSettings; + const timeout = new TimeoutSettingsT(); + timeout.duration = values.timeout.duration; + settings.timeout = timeout; + if (values.resetsSettings) { settings.resetsSettings = loadResetSettings(values.resetsSettings); } @@ -407,6 +417,12 @@ export function GeneralSettings() { }; } + if (settings.timeout) { + formData.timeout = { + duration: settings.timeout.duration, + }; + } + reset({ ...getValues(), ...formData }); }); @@ -448,7 +464,10 @@ export function GeneralSettings() { setHandsWarning(false); }} /> -
+ e.preventDefault()} + > } id="steamvr"> <> @@ -726,6 +745,29 @@ export function GeneralSettings() { 'settings-general-tracker_mechanics-trackers_over_usb-enabled-label' )} /> +
+ + {l10n.getString('settings-general-tracker_mechanics-timeout_duration')} + +
+ + {l10n.getString( + 'settings-general-tracker_mechanics-timeout_duration-description' + )} + +
+
+
+ +
} id="fksettings"> diff --git a/server/core/src/main/java/dev/slimevr/config/TimeoutConfig.kt b/server/core/src/main/java/dev/slimevr/config/TimeoutConfig.kt new file mode 100644 index 0000000000..fb7c8a5120 --- /dev/null +++ b/server/core/src/main/java/dev/slimevr/config/TimeoutConfig.kt @@ -0,0 +1,23 @@ +package dev.slimevr.config + +import dev.slimevr.VRServer +import dev.slimevr.tracking.trackers.Tracker + +class TimeoutConfig { + // Timeout duration in seconds + var duration = 3.0f + + fun updateTimeoutDuration() { + if (this.duration.isNaN() || this.duration.isInfinite()) { + this.duration = 3.0f + } + if (this.duration < 1f) { + this.duration = 1f + } + if (this.duration > 1000000000000000f) { + this.duration = 1000000000000000f + } + println("Updated timeout duration to ${this.duration} seconds") + Tracker.DISCONNECT_MS = (this.duration * 1000L).toLong() + Tracker.TIMEOUT_MS + } +} diff --git a/server/core/src/main/java/dev/slimevr/config/VRConfig.kt b/server/core/src/main/java/dev/slimevr/config/VRConfig.kt index 9ef33f5e00..5899065814 100644 --- a/server/core/src/main/java/dev/slimevr/config/VRConfig.kt +++ b/server/core/src/main/java/dev/slimevr/config/VRConfig.kt @@ -19,6 +19,8 @@ class VRConfig { val filters: FiltersConfig = FiltersConfig() + val timeout: TimeoutConfig = TimeoutConfig() + val driftCompensation: DriftCompensationConfig = DriftCompensationConfig() val oscRouter: OSCConfig = OSCConfig() diff --git a/server/core/src/main/java/dev/slimevr/protocol/rpc/settings/RPCSettingsBuilder.kt b/server/core/src/main/java/dev/slimevr/protocol/rpc/settings/RPCSettingsBuilder.kt index a933bf1936..ca88814767 100644 --- a/server/core/src/main/java/dev/slimevr/protocol/rpc/settings/RPCSettingsBuilder.kt +++ b/server/core/src/main/java/dev/slimevr/protocol/rpc/settings/RPCSettingsBuilder.kt @@ -7,6 +7,7 @@ import dev.slimevr.config.AutoBoneConfig import dev.slimevr.config.DriftCompensationConfig import dev.slimevr.config.FiltersConfig import dev.slimevr.config.HIDConfig +import dev.slimevr.config.TimeoutConfig import dev.slimevr.config.LegTweaksConfig import dev.slimevr.config.OSCConfig import dev.slimevr.config.ResetsConfig @@ -24,6 +25,7 @@ import solarxr_protocol.rpc.AutoBoneSettings import solarxr_protocol.rpc.DriftCompensationSettings import solarxr_protocol.rpc.FilteringSettings import solarxr_protocol.rpc.HIDSettings +import solarxr_protocol.rpc.TimeoutSettings import solarxr_protocol.rpc.OSCRouterSettings import solarxr_protocol.rpc.OSCSettings import solarxr_protocol.rpc.OSCTrackersSetting @@ -421,6 +423,10 @@ fun createSettingsResponse(fbb: FlatBufferBuilder, server: VRServer): Int { server.configManager.vrConfig.stayAlignedConfig, ), createHIDSettings(fbb, server.configManager.vrConfig.hidConfig), + createTimeoutSettings( + fbb, + server.configManager.vrConfig.timeout, + ), ) } @@ -456,3 +462,12 @@ fun createHIDSettings( fbb, config.trackersOverHID, ) + +fun createTimeoutSettings( + fbb: FlatBufferBuilder, + timeoutConfig: TimeoutConfig, +): Int = TimeoutSettings + .createTimeoutSettings( + fbb, + timeoutConfig.duration, + ) diff --git a/server/core/src/main/java/dev/slimevr/protocol/rpc/settings/RPCSettingsHandler.kt b/server/core/src/main/java/dev/slimevr/protocol/rpc/settings/RPCSettingsHandler.kt index 5f0453107a..fe69da1d6f 100644 --- a/server/core/src/main/java/dev/slimevr/protocol/rpc/settings/RPCSettingsHandler.kt +++ b/server/core/src/main/java/dev/slimevr/protocol/rpc/settings/RPCSettingsHandler.kt @@ -360,6 +360,14 @@ class RPCSettingsHandler(var rpcHandler: RPCHandler, var api: ProtocolAPI) { config.trackersOverHID = requestConfig.trackersOverHid() } + if (req.timeout() != null) { + val timeoutConfig = api.server.configManager + .vrConfig + .timeout + timeoutConfig.duration = req.timeout().duration() + timeoutConfig.updateTimeoutDuration() + } + api.server.configManager.saveConfig() } @@ -376,7 +384,7 @@ class RPCSettingsHandler(var rpcHandler: RPCHandler, var api: ProtocolAPI) { val settings = SettingsResponse .createSettingsResponse( fbb, - createSteamVRSettings(fbb, bridge), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + createSteamVRSettings(fbb, bridge), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ) val outbound = rpcHandler.createRPCMessage(fbb, RpcMessage.SettingsResponse, settings) diff --git a/server/core/src/main/java/dev/slimevr/tracking/trackers/Tracker.kt b/server/core/src/main/java/dev/slimevr/tracking/trackers/Tracker.kt index bb70fbc830..128010d644 100644 --- a/server/core/src/main/java/dev/slimevr/tracking/trackers/Tracker.kt +++ b/server/core/src/main/java/dev/slimevr/tracking/trackers/Tracker.kt @@ -13,9 +13,6 @@ import io.github.axisangles.ktmath.Quaternion import io.github.axisangles.ktmath.Vector3 import kotlin.properties.Delegates -const val TIMEOUT_MS = 2_000L -const val DISCONNECT_MS = 3_000L + TIMEOUT_MS - /** * Generic tracker class for input and output tracker, * with flags on instantiation. @@ -98,6 +95,11 @@ class Tracker @JvmOverloads constructor( */ val trackerDataType: TrackerDataType = TrackerDataType.ROTATION, ) { + companion object { + const val TIMEOUT_MS = 2_000L + var DISCONNECT_MS = 3_000L + TIMEOUT_MS + } + private val timer = BufferedTimer(1f) private var timeAtLastUpdate: Long = System.currentTimeMillis() private var _rotation = Quaternion.IDENTITY diff --git a/solarxr-protocol b/solarxr-protocol index fa2895b19a..e2b5898540 160000 --- a/solarxr-protocol +++ b/solarxr-protocol @@ -1 +1 @@ -Subproject commit fa2895b19a53d9b1686de8c2a6efe2b3e9ca4fc6 +Subproject commit e2b58985407a88648e744dffd731d97462d4190c From 50a08a032c66c813e2f0724fe644fa97243c6d22 Mon Sep 17 00:00:00 2001 From: art0007i Date: Sat, 14 Mar 2026 20:23:56 +0100 Subject: [PATCH 2/3] fix formatting --- gui/src/components/settings/pages/GeneralSettings.tsx | 8 +++++--- .../src/main/java/dev/slimevr/config/TimeoutConfig.kt | 1 - .../slimevr/protocol/rpc/settings/RPCSettingsBuilder.kt | 4 ++-- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/gui/src/components/settings/pages/GeneralSettings.tsx b/gui/src/components/settings/pages/GeneralSettings.tsx index eec6d39580..2c1efbedf5 100644 --- a/gui/src/components/settings/pages/GeneralSettings.tsx +++ b/gui/src/components/settings/pages/GeneralSettings.tsx @@ -108,7 +108,7 @@ export type SettingsForm = { trackersOverHID: boolean; }; timeout: { - duration: number + duration: number; }; }; @@ -166,7 +166,7 @@ const defaultValues: SettingsForm = { resetsSettings: defaultResetSettings, stayAligned: defaultStayAlignedSettings, hidSettings: { trackersOverHID: false }, - timeout: { duration: 3.0 }, + timeout: { duration: 3.0 }, }; export function GeneralSettings() { @@ -747,7 +747,9 @@ export function GeneralSettings() { />
- {l10n.getString('settings-general-tracker_mechanics-timeout_duration')} + {l10n.getString( + 'settings-general-tracker_mechanics-timeout_duration' + )}
diff --git a/server/core/src/main/java/dev/slimevr/config/TimeoutConfig.kt b/server/core/src/main/java/dev/slimevr/config/TimeoutConfig.kt index fb7c8a5120..2d4c3d6ced 100644 --- a/server/core/src/main/java/dev/slimevr/config/TimeoutConfig.kt +++ b/server/core/src/main/java/dev/slimevr/config/TimeoutConfig.kt @@ -17,7 +17,6 @@ class TimeoutConfig { if (this.duration > 1000000000000000f) { this.duration = 1000000000000000f } - println("Updated timeout duration to ${this.duration} seconds") Tracker.DISCONNECT_MS = (this.duration * 1000L).toLong() + Tracker.TIMEOUT_MS } } diff --git a/server/core/src/main/java/dev/slimevr/protocol/rpc/settings/RPCSettingsBuilder.kt b/server/core/src/main/java/dev/slimevr/protocol/rpc/settings/RPCSettingsBuilder.kt index ca88814767..d5a31452d1 100644 --- a/server/core/src/main/java/dev/slimevr/protocol/rpc/settings/RPCSettingsBuilder.kt +++ b/server/core/src/main/java/dev/slimevr/protocol/rpc/settings/RPCSettingsBuilder.kt @@ -7,13 +7,13 @@ import dev.slimevr.config.AutoBoneConfig import dev.slimevr.config.DriftCompensationConfig import dev.slimevr.config.FiltersConfig import dev.slimevr.config.HIDConfig -import dev.slimevr.config.TimeoutConfig import dev.slimevr.config.LegTweaksConfig import dev.slimevr.config.OSCConfig import dev.slimevr.config.ResetsConfig import dev.slimevr.config.SkeletonConfig import dev.slimevr.config.StayAlignedConfig import dev.slimevr.config.TapDetectionConfig +import dev.slimevr.config.TimeoutConfig import dev.slimevr.config.VMCConfig import dev.slimevr.config.VRCOSCConfig import dev.slimevr.filtering.TrackerFilters.Companion.getByConfigkey @@ -25,7 +25,6 @@ import solarxr_protocol.rpc.AutoBoneSettings import solarxr_protocol.rpc.DriftCompensationSettings import solarxr_protocol.rpc.FilteringSettings import solarxr_protocol.rpc.HIDSettings -import solarxr_protocol.rpc.TimeoutSettings import solarxr_protocol.rpc.OSCRouterSettings import solarxr_protocol.rpc.OSCSettings import solarxr_protocol.rpc.OSCTrackersSetting @@ -34,6 +33,7 @@ import solarxr_protocol.rpc.SettingsResponse import solarxr_protocol.rpc.StayAlignedSettings import solarxr_protocol.rpc.SteamVRTrackersSetting import solarxr_protocol.rpc.TapDetectionSettings +import solarxr_protocol.rpc.TimeoutSettings import solarxr_protocol.rpc.VMCOSCSettings import solarxr_protocol.rpc.VRCOSCSettings import solarxr_protocol.rpc.settings.LegTweaksSettings From 6084b8fab210498231478ac944fc758a44a9b589 Mon Sep 17 00:00:00 2001 From: art0007i Date: Sat, 14 Mar 2026 21:52:25 +0100 Subject: [PATCH 3/3] improve wording of timeout setting description Co-authored-by: Sapphire --- gui/public/i18n/en/translation.ftl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gui/public/i18n/en/translation.ftl b/gui/public/i18n/en/translation.ftl index 5e7be823d2..0be5f2b699 100644 --- a/gui/public/i18n/en/translation.ftl +++ b/gui/public/i18n/en/translation.ftl @@ -583,7 +583,7 @@ settings-general-tracker_mechanics-trackers_over_usb-description = Enables receiving HID tracker data over USB. Make sure connected trackers have connection over HID enabled! settings-general-tracker_mechanics-trackers_over_usb-enabled-label = Allow HID trackers to connect directly over USB settings-general-tracker_mechanics-timeout_duration = Timeout duration -settings-general-tracker_mechanics-timeout_duration-description = How long in seconds should the tracker be considered timed out, instead of disconnected. +settings-general-tracker_mechanics-timeout_duration-description = How long until a tracker is marked as 'disconnected' when the connection is lost. settings-stay_aligned = Stay Aligned settings-stay_aligned-description = Stay Aligned reduces drift by gradually adjusting your trackers to match your relaxed poses.