diff --git a/gui/public/i18n/en/translation.ftl b/gui/public/i18n/en/translation.ftl
index c54b92788..7158573da 100644
--- a/gui/public/i18n/en/translation.ftl
+++ b/gui/public/i18n/en/translation.ftl
@@ -336,6 +336,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
@@ -375,6 +376,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 bba3e36fc..47ae18c03 100644
--- a/gui/src/components/tracker/TrackerSettings.tsx
+++ b/gui/src/components/tracker/TrackerSettings.tsx
@@ -376,6 +376,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 319833a19..6ebc32d3f 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 37ac0b609..35feac422 100644
--- a/gui/src/components/tracker/TrackersTable.tsx
+++ b/gui/src/components/tracker/TrackersTable.tsx
@@ -245,6 +245,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}
/>
)}
@@ -356,6 +360,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 c6545dd68..b0e61f57f 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
@@ -317,6 +317,18 @@ public class DataFeedBuilder {
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());
+ }
+
if (tracker.getBatteryRemainingRuntime() != null) {
HardwareStatus.addBatteryRuntimeEstimate(fbb, tracker.getBatteryRemainingRuntime());
}
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 0212b1982..bb70fbc83 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
@@ -117,6 +117,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 8d9d4ce33..b1be8d133 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
@@ -155,6 +155,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) {
@@ -209,6 +213,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()
}
@@ -309,6 +317,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) {