-
Notifications
You must be signed in to change notification settings - Fork 678
Open
Labels
component: ntcoreNetworkTables libraryNetworkTables librarytype: bugSomething isn't working.Something isn't working.
Description
Describe the bug
While testing PhotonVision HEAD, running a NT server, against Glass 2026 beta 1, I saw a NT connection formed but no data flowing.
To Reproduce
Some of the time (i was unable to reproduce this):
- start photonvision from HEAD as a NT client
- change it to NT server
- Open Glass, connect as NT client
- observe topics announced, but no data
When in this bad state, I can swap Photon from server -> client -> server and data flows nominally (Glass updates values, we see value updates in Wireshark).
In this Wireshark capture, we see pings exchanged every 100ms, but the only non-keepalive mesasges were:
(.venv) PS C:\Users\matth\Documents\GitHub\photonvision> & C:/Users/matth/Documents/GitHub/photonvision/.venv/Scripts/python.exe c:/Users/matth/Documents/GitHub/photonvision/analyze-nt4.py
[2026-01-01T18:50:50.072823000-0800] [62149 -> 5810] Binary Payload
{'topic_id': -1, 'timestamp': 0, 'value': 2}
[2026-01-01T18:50:50.072854000-0800] [5810 -> 62149] Binary Payload
{'topic_id': -1, 'timestamp': 832980544, 'value': 2}
[2026-01-01T18:50:50.179727000-0800] [62149 -> 5810] Text Payload: [{"method":"subscribe","params":{"options":{},"topics":["/SmartDashboard/PhotonAlerts/.type"],"subuid":1}},{"method":"subscribe","params":{"options":{"prefix":true},"topics":["","$"],"subuid":-1}},{"method":"subscribe","params":{"options":{"topicsonly":true,"prefix":true},"topics":[""],"subuid":-2}}]
[2026-01-01T18:50:50.188128000-0800] [5810 -> 62149] Text Payload: [{"method":"announce","params":{"id":6,"name":"/SmartDashboard/PhotonAlerts/.type","properties":{"SmartDashboard":"Alerts"},"type":"string"}}]
[2026-01-01T18:50:50.188224000-0800] [5810 -> 62149] Text Payload: [{"method":"announce","params":{"id":109,"name":"$pub$/.schema/photonstruct:MultiTargetPNPResult:541096947e9f3ca2d3f425ff7b04aa7b","properties":{"retained":true},"type":"msgpack"}},{"method":"announce","params":{"id":110,"name":"$sub$/.schema/photonstruct:MultiTargetPNPResult:541096947e9f3ca2d3f425ff7b04aa7b","properties":{"retained":true},"type":"msgpack"}},{"method":"announce","params":{"id":111,"name":"/.schema/photonstruct:PnpResult:ae4d655c0a3104d88df4f5db144c1e86","properties":{"retained":true},"type":"photonstructschema"}},{"method":"announce","params":{"id":112,"name":"$pub$/.schema/photonstruct:PnpResult:ae4d655c0a3104d88df4f5db144c1e86","properties":{"retained":true},"type":"msgpack"}},{"method":"announce","params":{"id":113,"name":"$sub$/.schema/photonstruct:PnpResult:ae4d655c0a3104d88df4f5db144c1e86","properties":{"retained":true},"type":"msgpack"}},{"method":"announce","params":{"id":114,"name":"/.schema/struct:Transform3d","properties":{"retained":true},"type":"structschema"}},{"method":"announce","params":{"id":115,"name":"$pub$/.schema/struct:Transform3d","properties":{"retained":true},"type":"msgpack"}},{"method":"announce","params":{"id":116,"name":"$sub$/.schema/struct:Transform3d","properties":{"retained":true},"type":"msgpack"}},{"method":"announce","params":{"id":117,"name":"/.schema/struct:Translation3d","properties":{"retained":true},"type":"structschema"}}]
[2026-01-01T18:50:50.188276000-0800] [5810 -> 62149] Text Payload: [{"method":"announce","params":{"id":215,"name":"$sub$/CameraPublisher/DESKTOP-PNNHDMI_Port_1183_Input_MJPEG_Server/modes","properties":{"retained":true},"type":"msgpack"}},{"method":"announce","params":{"id":216,"name":"/CameraPublisher/DESKTOP-PNNHDMI_Port_1184_Output_MJPEG_Server/source","properties":{},"type":"string"}},{"method":"announce","params":{"id":217,"name":"$pub$/CameraPublisher/DESKTOP-PNNHDMI_Port_1184_Output_MJPEG_Server/source","properties":{"retained":true},"type":"msgpack"}},{"method":"announce","params":{"id":218,"name":"$sub$/CameraPublisher/DESKTOP-PNNHDMI_Port_1184_Output_MJPEG_Server/source","properties":{"retained":true},"type":"msgpack"}},{"method":"announce","params":{"id":219,"name":"/photonvision/Microsoft_LifeCam_HD-3000 (Duplicate)/rawBytes","properties":{"message_uuid":"4b2ff16a964b5e2bf04be0c1454d91c4"},"type":"photonstruct:PhotonPipelineResult:4b2ff16a964b5e2bf04be0c1454d91c4"}},{"method":"announce","params":{"id":220,"name":"$pub$/photonvision/Microsoft_LifeCam_HD-3000 (Duplicate)/rawBytes","properties":{"retained":true},"type":"msgpack"}},{"method":"announce","params":{"id":221,"name":"$sub$/photonvision/Microsoft_LifeCam_HD-3000 (Duplicate)/rawBytes","properties":{"retained":true},"type":"msgpack"}},{"method":"announce","params":{"id":222,"name":"/CameraPublisher/DESKTOP-PNNHDMI_Port_1184_Output_MJPEG_Server/description","properties":{},"type":"string"}}]
[2026-01-01T18:50:50.188307000-0800] [5810 -> 62149] Binary Payload
{'topic_id': 1, 'timestamp': 326095327, 'value': 5}
[2026-01-01T18:50:50.188339000-0800] [5810 -> 62149] Binary Payload
{'topic_id': 102, 'timestamp': 327644941, 'value': 5}
{'topic_id': 103, 'timestamp': 326094752, 'value': 5}
{'topic_id': 104, 'timestamp': 833087934, 'value': 5}
{'topic_id': 105, 'timestamp': 0, 'value': 5}
{'topic_id': 106, 'timestamp': 326094756, 'value': 5}
{'topic_id': 107, 'timestamp': 833087935, 'value': 5}
[2026-01-01T18:50:50.288077000-0800] [62149 -> 5810] Text Payload: [{"method":"subscribe","params":{"options":{},"topics":["/SmartDashboard/PhotonAlerts/.type"],"subuid":2}},{"method":"unsubscribe","params":{"subuid":2}}]
[2026-01-01T18:50:50.316590000-0800] [5810 -> 62149] Binary Payload
{'topic_id': 8, 'timestamp': 833195887, 'value': 5}
{'topic_id': 305, 'timestamp': 833195893, 'value': 5}
[2026-01-01T18:51:25.267756000-0800] [62149 -> 5810] Text Payload: [{"method":"publish","params":{"name":"/photonvision/Microsoft_LifeCam_HD-3000/hasTarget","properties":{},"pubuid":0,"type":"boolean"}}]
[2026-01-01T18:51:25.292865000-0800] [5810 -> 62149] Binary Payload
{'topic_id': 160, 'timestamp': 868175535, 'value': 5}
{'topic_id': 304, 'timestamp': 868175538, 'value': 5}
[2026-01-01T18:51:26.894370000-0800] [62149 -> 5810] Binary Payload
{'topic_id': 0, 'timestamp': 869756045, 'value': 0}
(.venv) PS C:\Users\matth\Documents\GitHub\photonvision>
Decoder code:
import pyshark
import asyncio
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)
def decode_nt4_message(payload):
"""
Decodes an NT4 message payload based on the NT4 specification.
Args:
payload (bytes): The binary payload to decode.
Returns:
None
"""
import msgpack
try:
# Use an unpacker to handle multiple MessagePack objects in the payload
unpacker = msgpack.Unpacker()
unpacker.feed(payload)
for decoded_message in unpacker:
# Example structure based on NT4 spec (adjust as needed):
# Assuming the payload contains a topic ID, timestamp, and value
if isinstance(decoded_message, list) and len(decoded_message) >= 3:
topic_id = decoded_message[0] # Topic ID
timestamp = decoded_message[1] # Timestamp in microseconds
value = decoded_message[2] # Value (could be int, float, string, etc.)
data = {
"topic_id": topic_id,
"timestamp": timestamp,
"value": value
}
print(data)
else:
raise ValueError("Unexpected message format")
except Exception as e:
print(f"Failed to decode NT4 message: {e}")
return None
def analyze_websocket_pcap(file_name):
cap = pyshark.FileCapture(file_name, display_filter="websocket")
try:
for packet in cap:
if "websocket" in packet:
opcode = int(packet.websocket.opcode)
payload = packet.websocket.payload
# print(
# f"[{packet.frame_info.time}] WebSocket Packet: Opcode {opcode} - Payload length: {packet.websocket.payload_length}"
# )
try:
if opcode == 0x1: # Text frame
decoded_payload = bytes.fromhex(payload.replace(':', '')).decode('utf-8')
print(f"[{packet.frame_info.time}] [{packet.tcp.srcport} -> {packet.tcp.dstport}] Text Payload: {decoded_payload}")
elif opcode == 0x2: # Binary frame
decoded_payload = bytes.fromhex(payload.replace(':', ''))
print(f"[{packet.frame_info.time}] [{packet.tcp.srcport} -> {packet.tcp.dstport}] Binary Payload")
decode_nt4_message(decoded_payload)
elif opcode == 0x9: # Ping frame
# print(" Ping Frame")
pass
elif opcode == 0xA: # Pong frame
# print(" Pong Frame")
pass
else:
print(f" Unknown Opcode: {opcode}")
except Exception as e:
print(e)
print(f" Payload (raw hex): {payload}")
except Exception as e:
print(f"An error occurred: {e}")
finally:
cap.close()
if __name__ == "__main__":
analyze_websocket_pcap("networktables_photonserver_glassclient.pcapng")Expected behavior
Screenshots
If applicable, add screenshots to help explain your problem.
Desktop (please complete the following information):
- OS: Windows 11
Additional context
Pcap file:
Metadata
Metadata
Assignees
Labels
component: ntcoreNetworkTables libraryNetworkTables librarytype: bugSomething isn't working.Something isn't working.