External Application Data Recorder - Network Integration Guide
This guide explains how to control the SightLab Data Recorder from external applications like Unreal Engine, Unity, or other networked programs.
Overview
The recorder supports UDP-based networking to receive commands from external applications. This allows you to:
- Start/stop recording trials remotely
- Send synchronization markers during experiments
- Receive acknowledgment messages from the recorder
Configuration
In Data_Recorder_Config.py
# Enable network control
USE_NETWORK_EVENT = True # Enable network listening
NETWORK_START = True # Use network events to start trials (instead of spacebar)
# Network settings
NETWORK_HOST = 'localhost' # Host to listen on
NETWORK_PORT = 4950 # UDP port number
# Event names (must match what your external app sends)
NETWORK_START_EVENT_NAME = 'start_trial' # JSON event name to trigger recording
# Sync settings
NETWORK_SYNC_KEY = 't' # Keyboard key for manual sync
NETWORK_SYNC_EVENT = 'triggerPress' # Event name for sync markers
How It Works
1. Network Setup
The recorder creates a UDP listener on the specified NETWORK_HOST and NETWORK_PORT. It listens for incoming JSON messages from external applications.
2. Message Format
External applications should send JSON-formatted strings via UDP:
{
"event": "start_trial"
}
3. Supported Events
| Event Name | Purpose | Response |
|---|---|---|
start_trial (configurable via NETWORK_START_EVENT_NAME) |
Starts a recording trial | Sends {"event":"ack_start", "trial": N} |
sync |
Inserts a synchronization marker in the data | Broadcasts sync to external apps |
4. Bidirectional Communication
The recorder can also send messages back to external apps:
- Acknowledgments when trials start
- Sync event notifications
- Custom trial/timestamp data
Example: Unreal Engine Integration
Unreal Blueprint Setup
- Create a UDP Socket (port
4950) - Send JSON string to start recording:
{"event": "start_trial"}
- Listen for acknowledgment:
{"event": "ack_start", "trial": 1}
Sample Unreal C++ Code
// Send start command
FString JsonMsg = TEXT("{\"event\":\"start_trial\"}");
Socket->SendTo((uint8*)TCHAR_TO_UTF8(*JsonMsg), JsonMsg.Len(), BytesSent, *RemoteAddr);
Example: Unity Integration
using System.Net;
using System.Net.Sockets;
using System.Text;
UdpClient client = new UdpClient();
IPEndPoint endPoint = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 4950);
// Start recording
string json = "{\"event\":\"start_trial\"}";
byte[] data = Encoding.UTF8.GetBytes(json);
client.Send(data, data.Length, endPoint);
Workflow
With NETWORK_START = True:
- External app sends
{"event": "start_trial"} - Recorder receives message and starts trial automatically
- Recorder sends acknowledgment back
- Recording begins
- Use timer or manual stop to end trial
With NETWORK_START = False:
- Use spacebar (or
START_END_SESSION_KEY) to start - External app can still send
syncevents during recording - Spacebar to stop
Sync Markers
During a trial, send sync events to mark important moments:
{"event": "sync"}
This will:
- Log a timestamp in the trial data
- Insert a marker in Biopac (if enabled)
- Broadcast the sync to all connected apps
Testing
Simple Python Test Script
import socket
import json
# Create UDP socket
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
server_address = ('localhost', 4950)
# Send start command
message = json.dumps({"event": "start_trial"})
sock.sendto(message.encode(), server_address)
print("Sent start command to recorder")
Troubleshooting
- No response from recorder
- Verify
USE_NETWORK_EVENT = True - Check firewall settings for UDP port
4950 -
Ensure recorder is running before sending messages
-
Wrong event name
- Match
NETWORK_START_EVENT_NAMEin config with JSON"event"field -
Case-sensitive matching
-
Port conflicts
- Change
NETWORK_PORTif4950is already in use - Update external app to match
Advanced: Custom Data Exchange
You can extend the network handler in External_Application_Data_Recorder.py (around line 770):
def onNetwork(e):
try:
msg = e.raw_data.decode('utf-8', errors='ignore')
data = json.loads(msg)
evt = data.get('event')
if evt == 'custom_event':
# Your custom handling here
print('Received custom event:', data)
except Exception:
print('[NET] Error parsing:', e.raw_data)
Summary
- UDP-based: Lightweight, connectionless protocol
- JSON messages: Simple, human-readable format
- Bidirectional: Recorder can send acknowledgments back
- Flexible: Works with Unity, Unreal, Python, and any UDP-capable app
- Sync markers: Insert timestamps during experiments for alignment