diff --git a/gui/public/i18n/en/translation.ftl b/gui/public/i18n/en/translation.ftl
index a02c9dab35..7ee1809323 100644
--- a/gui/public/i18n/en/translation.ftl
+++ b/gui/public/i18n/en/translation.ftl
@@ -331,6 +331,7 @@ tracker-table-column-name = Name
tracker-table-column-type = Type
tracker-table-column-battery = Battery
tracker-table-column-ping = Ping
+tracker-table-column-packet_loss = Packet Loss
tracker-table-column-tps = TPS
tracker-table-column-temperature = Temp. °C
tracker-table-column-linear-acceleration = Accel. X/Y/Z
@@ -370,6 +371,10 @@ tracker-infos-magnetometer-status-v1 = { $status ->
[ENABLED] Enabled
}
+tracker-infos-packet_loss = Packet Loss
+tracker-infos-packets_lost = Packets Lost
+tracker-infos-packets_received = Packets Received
+
## Tracker settings
tracker-settings-back = Go back to trackers list
tracker-settings-title = Tracker settings
diff --git a/gui/src/components/tracker/TrackerSettings.tsx b/gui/src/components/tracker/TrackerSettings.tsx
index ead4288e2b..ff01405f38 100644
--- a/gui/src/components/tracker/TrackerSettings.tsx
+++ b/gui/src/components/tracker/TrackerSettings.tsx
@@ -367,6 +367,34 @@ export function TrackerSettingsPage() {
{tracker?.device?.hardwareInfo?.networkProtocolVersion || '--'}
+ {tracker?.device?.hardwareStatus?.packetsReceived !== null && (
+ <>
+
+
+ {l10n.getString('tracker-infos-packet_loss')}
+
+
+ {((tracker?.device?.hardwareStatus?.packetLoss ?? 0) * 100).toFixed(0)}%
+
+
+
+
+ {l10n.getString('tracker-infos-packets_lost')}
+
+
+ {tracker?.device?.hardwareStatus?.packetsLost ?? '0'}
+
+
+
+
+ {l10n.getString('tracker-infos-packets_received')}
+
+
+ {tracker?.device?.hardwareStatus?.packetsReceived ?? '0'}
+
+
+ >
+ )}
{tracker?.tracker && (
diff --git a/gui/src/components/tracker/TrackerWifi.tsx b/gui/src/components/tracker/TrackerWifi.tsx
index 319833a199..6ebc32d3f0 100644
--- a/gui/src/components/tracker/TrackerWifi.tsx
+++ b/gui/src/components/tracker/TrackerWifi.tsx
@@ -1,15 +1,24 @@
import { WifiIcon } from '@/components/commons/icon/WifiIcon';
import { Typography } from '@/components/commons/Typography';
+import { Tooltip } from '@/components/commons/Tooltip';
export function TrackerWifi({
rssi,
ping,
rssiShowNumeric,
disabled,
+ packetLoss,
+ packetsLost,
+ packetsReceived,
+ showPacketLoss = false,
textColor = 'primary',
}: {
rssi: number | null;
ping: number | null;
+ packetLoss?: number | null;
+ packetsLost?: number | null;
+ packetsReceived?: number | null;
+ showPacketLoss?: boolean;
rssiShowNumeric?: boolean;
disabled?: boolean;
textColor?: string;
@@ -31,6 +40,17 @@ export function TrackerWifi({
{rssi} dBm
)}
+ {showPacketLoss && packetsReceived != null && (
+ }
+ >
+ {`${((packetLoss ?? 0) * 100).toFixed(0)}% (${packetsLost ?? 0} / ${packetsReceived})`}
+
+ )}
)) || (
diff --git a/gui/src/components/tracker/TrackersTable.tsx b/gui/src/components/tracker/TrackersTable.tsx
index 1a4fdb022e..e5bf67ceb0 100644
--- a/gui/src/components/tracker/TrackersTable.tsx
+++ b/gui/src/components/tracker/TrackersTable.tsx
@@ -243,6 +243,10 @@ function Row({
ping={device?.hardwareStatus?.ping}
disabled={tracker.status === TrackerStatusEnum.DISCONNECTED}
textColor={fontColor}
+ showPacketLoss
+ packetLoss={device.hardwareStatus.packetLoss}
+ packetsLost={device.hardwareStatus.packetsLost}
+ packetsReceived={device.hardwareStatus.packetsReceived}
/>
)}
@@ -330,7 +334,7 @@ export function TrackersTable({
'minmax(150px, 1.5fr)', // Name
'minmax(100px, 1fr)', // Type
'minmax(60px, 1fr)', // Battery
- '6rem', // Ping (w-24)
+ '8rem', // Ping (w-24)
'minmax(60px, 1fr)', // TPS
config?.devSettings?.preciseRotation ? '11rem' : '8rem', // Rotation
'minmax(60px, 1fr)', // Temp
@@ -354,6 +358,7 @@ export function TrackersTable({
+
diff --git a/server/core/src/main/java/dev/slimevr/protocol/datafeed/DataFeedBuilder.java b/server/core/src/main/java/dev/slimevr/protocol/datafeed/DataFeedBuilder.java
index 3c256ff2fd..db7ffdd3d2 100644
--- a/server/core/src/main/java/dev/slimevr/protocol/datafeed/DataFeedBuilder.java
+++ b/server/core/src/main/java/dev/slimevr/protocol/datafeed/DataFeedBuilder.java
@@ -310,6 +310,17 @@ public static int createDeviceData(
HardwareStatus.addRssi(fbb, (short) tracker.getSignalStrength().floatValue());
}
+ if (tracker.getPacketLoss() != null) {
+ HardwareStatus.addPacketLoss(fbb, tracker.getPacketLoss());
+ }
+
+ if (tracker.getPacketsLost() != null) {
+ HardwareStatus.addPacketsLost(fbb, tracker.getPacketsLost());
+ }
+
+ if (tracker.getPacketsReceived() != null) {
+ HardwareStatus.addPacketsReceived(fbb, tracker.getPacketsReceived());
+ }
int hardwareDataOffset = HardwareStatus.endHardwareStatus(fbb);
int hardwareInfoOffset = DataFeedBuilder.createHardwareInfo(fbb, device);
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 6392d2f7c1..d13dbd9374 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
@@ -116,6 +116,9 @@ class Tracker @JvmOverloads constructor(
var signalStrength: Int? = null
var temperature: Float? = null
var button: Int? = null
+ var packetsReceived: Int? = null
+ var packetsLost: Int? = null
+ var packetLoss: Float? = null
var customName: String? = null
var magStatus: MagnetometerStatus = magStatus
private set
diff --git a/server/core/src/main/java/dev/slimevr/tracking/trackers/hid/HIDCommon.kt b/server/core/src/main/java/dev/slimevr/tracking/trackers/hid/HIDCommon.kt
index 23d0a27ba1..371c6be68f 100644
--- a/server/core/src/main/java/dev/slimevr/tracking/trackers/hid/HIDCommon.kt
+++ b/server/core/src/main/java/dev/slimevr/tracking/trackers/hid/HIDCommon.kt
@@ -153,6 +153,10 @@ class HIDCommon {
var svr_status: Int? = null
// var status: Int? = null // raw status from tracker
var rssi: Int? = null
+ var packets_received: Int? = null
+ var packets_lost: Int? = null
+ var windows_hit: Int? = null
+ var windows_missed: Int? = null
// Tracker packets
when (packetType) {
@@ -207,6 +211,10 @@ class HIDCommon {
3 -> { // status
svr_status = dataReceived[i + 2].toUByte().toInt()
// status = dataReceived[i + 3].toUByte().toInt()
+ packets_received = dataReceived[i + 4].toUByte().toInt()
+ packets_lost = dataReceived[i + 5].toUByte().toInt()
+ windows_hit = dataReceived[i + 6].toUByte().toInt()
+ windows_missed = dataReceived[i + 7].toUByte().toInt()
rssi = dataReceived[i + 15].toUByte().toInt()
}
@@ -296,6 +304,11 @@ class HIDCommon {
if (rssi != null) {
tracker.signalStrength = -rssi
}
+ if (packets_received != null && packets_lost != null) {
+ tracker.packetsReceived = packets_received
+ tracker.packetsLost = packets_lost
+ tracker.packetLoss = if (packets_lost == 0) 0.0f else packets_lost.toFloat() / (packets_received + packets_lost).toFloat()
+ }
// Assign rotation and acceleration
if (packetType == 1 || packetType == 4) {
diff --git a/solarxr-protocol b/solarxr-protocol
index b0147eeffa..7fb914e6d3 160000
--- a/solarxr-protocol
+++ b/solarxr-protocol
@@ -1 +1 @@
-Subproject commit b0147eeffaa97a16400de174383c91be2ec31ab5
+Subproject commit 7fb914e6d3d05e6574eb93618b7c295d092dec0d