diff --git a/gui/public/i18n/en/translation.ftl b/gui/public/i18n/en/translation.ftl index ab43c26b63..1d6ae93fa1 100644 --- a/gui/public/i18n/en/translation.ftl +++ b/gui/public/i18n/en/translation.ftl @@ -584,6 +584,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 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. diff --git a/gui/src/components/commons/Input.tsx b/gui/src/components/commons/Input.tsx index ba93fc99b3..8f83084a65 100644 --- a/gui/src/components/commons/Input.tsx +++ b/gui/src/components/commons/Input.tsx @@ -37,6 +37,7 @@ export const InputInside = forwardRef< value, error, variant = 'primary', + ...props }, ref ) { @@ -100,6 +101,7 @@ export const InputInside = forwardRef< value={computedValue} // Do we want that behaviour ? disabled={disabled} ref={ref} + {...props} /> {type === 'password' && (
({ disabled, variant = 'primary', rules, + ...props }: { rules?: UseControllerProps>['rules']; control: Control; @@ -157,6 +160,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 678d698299..07d3e38b76 100644 --- a/gui/src/components/settings/pages/GeneralSettings.tsx +++ b/gui/src/components/settings/pages/GeneralSettings.tsx @@ -15,12 +15,14 @@ import { SteamVRTrackersSettingT, TapDetectionSettingsT, HIDSettingsT, + TimeoutSettingsT, VelocitySettingsT, BodyPart, } from 'solarxr-protocol'; import { useConfig } from '@/hooks/config'; import { useWebsocketAPI } from '@/hooks/websocket-api'; import { useLocaleConfig } from '@/i18n/config'; +import { Input } from '@/components/commons/Input'; import { CheckBox } from '@/components/commons/Checkbox'; import { SteamIcon } from '@/components/commons/icon/SteamIcon'; import { WrenchIcon } from '@/components/commons/icon/WrenchIcons'; @@ -115,6 +117,9 @@ export type SettingsForm = { hidSettings: { trackersOverHID: boolean; }; + timeout: { + duration: number; + }; velocitySettings: { sendDerivedVelocity: boolean; }; @@ -177,6 +182,7 @@ const defaultValues: SettingsForm = { resetsSettings: defaultResetSettings, stayAligned: defaultStayAlignedSettings, hidSettings: { trackersOverHID: false }, + timeout: { duration: 3.0 }, velocitySettings: { sendDerivedVelocity: false }, }; @@ -358,6 +364,10 @@ export function GeneralSettings() { values.velocitySettings.sendDerivedVelocity; settingsReq.velocitySettings = velocitySettings; + const timeout = new TimeoutSettingsT(); + timeout.duration = values.timeout.duration; + settings.timeout = timeout; + if (values.resetsSettings) { settingsReq.resetsSettings = loadResetSettings(values.resetsSettings); } @@ -491,6 +501,12 @@ export function GeneralSettings() { }; } + if (settings.timeout) { + formData.timeout = { + duration: settings.timeout.duration, + }; + } + if (settings.velocitySettings) { formData.velocitySettings = { sendDerivedVelocity: settings.velocitySettings.sendDerivedVelocity, @@ -521,7 +537,10 @@ export function GeneralSettings() { setShowHandsWarning(null); }} /> -
+ e.preventDefault()} + > } id="steamvr"> <> @@ -799,6 +818,31 @@ 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..2d4c3d6ced --- /dev/null +++ b/server/core/src/main/java/dev/slimevr/config/TimeoutConfig.kt @@ -0,0 +1,22 @@ +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 + } + 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 903750aa8a..688bc380c8 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 05ac3ef16a..75c8aa98e8 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 @@ -13,6 +13,7 @@ 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.config.VelocityConfig @@ -33,6 +34,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.VRMSettings @@ -437,6 +439,10 @@ fun createSettingsResponse(fbb: FlatBufferBuilder, server: VRServer): Int { server.configManager.vrConfig.stayAlignedConfig, ), createHIDSettings(fbb, server.configManager.vrConfig.hidConfig), + createTimeoutSettings( + fbb, + server.configManager.vrConfig.timeout, + ), 0, createVelocitySettings(fbb, server.configManager.vrConfig.velocityConfig), createVRMSettings( @@ -479,6 +485,15 @@ fun createHIDSettings( config.trackersOverHID, ) +fun createTimeoutSettings( + fbb: FlatBufferBuilder, + timeoutConfig: TimeoutConfig, +): Int = TimeoutSettings + .createTimeoutSettings( + fbb, + timeoutConfig.duration, + ) + fun createVelocitySettings( fbb: FlatBufferBuilder, config: VelocityConfig, 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 4b0a95659b..8913bbc405 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 @@ -375,6 +375,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() + } + if (req.velocitySettings() != null) { val velocityConfig = api.server.configManager.vrConfig.velocityConfig velocityConfig.sendDerivedVelocity = req.velocitySettings().sendDerivedVelocity() 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 61186d10fc..0da17ed8f2 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 @@ -17,9 +17,6 @@ import kotlin.time.Duration.Companion.milliseconds import kotlin.time.DurationUnit import kotlin.time.TimeSource -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. @@ -112,6 +109,11 @@ class Tracker @JvmOverloads constructor( */ val usesSleep: Boolean = false, ) { + 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 timeScheduledSleep: Long = Long.MAX_VALUE