10 KiB
🌐 Taekwondo Scoring System – Wi-Fi Connectivity Guide
Version: 1.0
Last Updated: July 2025
Target Developer: Embedded & Android developers
Purpose: Detailed guide on Wi-Fi connectivity for single and multi-court setups with auto-discovery and conflict prevention
📌 Table of Contents
- 1. Overview
- 2. Mode 1: Wi-Fi Hotspot-Based (Single Court)
- 3. Mode 2: Wi-Fi Non-Hotspot (Tournament Mode)
- 4. Auto-Discovery Mechanism
- 5. Multi-Court Safety & Conflict Prevention
- 6. ESP32 Code Examples
- 7. Android .NET Server Code
- 8. Best Practices
1. Overview
This guide details two Wi-Fi connection modes for the Taekwondo Scoring System:
| Mode | Use Case | Network Control |
|---|---|---|
| 1. Hotspot-Based | Clubs, single court | Tablet creates Wi-Fi |
| 2. Non-Hotspot (Client) | Tournaments, multi-court | Tablet joins existing Wi-Fi |
Both modes use auto-discovery so devices (sensors, joysticks, TVs) can find the server without IP input.
Key goals:
- ✅ Zero-config for non-technical users
- ✅ Reliable auto-discovery
- ✅ Prevent cross-talk between courts
- ✅ Secure and scalable
2. Mode 1: Wi-Fi Hotspot-Based (Single Court)
Ideal for training clubs or local events with one court.
📶 Network Setup
- Score Control Tablet creates a Wi-Fi hotspot:
- SSID:
TKD_SCORING_COURT1 - Password:
taekwondo123 - IP:
192.168.4.1(default hotspot IP)
- SSID:
- All devices connect to this network.
✅ Advantages
- No dependency on venue Wi-Fi
- Fixed server IP:
192.168.4.1 - Fast, stable, low-latency
- Simple for staff: "Connect to TKD_SCORING_COURT1"
🔄 Auto-Discovery Flow
[ESP32 Device] → Connects to TKD_SCORING_COURT1
↓
Sends UDP broadcast: TKD_DISCOVER
↓
[Tablet] ← Responds: SERVER_IP:192.168.4.1
↓
Device connects to 192.168.4.1:5000
Since the tablet is the only router, it's always the first IP (
192.168.4.1).
3. Mode 2: Wi-Fi Non-Hotspot (Tournament Mode)
Used in multi-court tournaments where multiple score systems run on the same venue Wi-Fi.
📶 Network Setup
- Score Control Tablet connects to existing Wi-Fi (e.g.,
Venue_Guest) - Gets IP via DHCP (e.g.,
192.168.1.100) - Starts TCP server on Port
5000 - Devices must discover the server IP
⚠️ Challenge
- Server IP is not fixed
- Devices must find the correct server among many
✅ Solution: UDP Broadcast Discovery
Devices send a broadcast to find any active Taekwondo scoring server.
4. Auto-Discovery Mechanism
To enable auto-discovery in both modes, we use UDP broadcast.
📡 Discovery Protocol
| Step | Message |
|---|---|
| 1 | Device sends: TKD_DISCOVER |
| 2 | Server responds: SERVER_IP:<ip>:<port>:<court_id> |
| 3 | Device connects to ip:port |
Example Response
SERVER_IP:192.168.1.100:5000:COURT1
This allows devices to:
- Find the server
- Know which court they belong to
🔄 Discovery Flow (Non-Hotspot Mode)
[ESP32 Device] → Joins venue Wi-Fi
↓
Sends UDP broadcast: TKD_DISCOVER
↓
[Court 1 Server] ← Responds: SERVER_IP:192.168.1.100:5000:COURT1
[Court 2 Server] ← Responds: SERVER_IP:192.168.1.101:5000:COURT2
↓
[Device] → Uses SSID or config to choose COURT1 → connects
Devices only connect to the server matching their court ID.
5. Multi-Court Safety & Conflict Prevention
To prevent cross-talk between courts:
✅ 1. Unique SSID per Court (Recommended)
- Court 1:
TKD_COURT1 - Court 2:
TKD_COURT2 - Devices are pre-configured to connect only to their court’s SSID
✅ Best for tournaments — no discovery conflicts
✅ 2. Court ID in Discovery Response
- Server includes
COURT1,COURT2in response - Device validates: only connect if
court_idmatches
✅ 3. MAC Address Whitelisting
- Each server has a pre-loaded list of allowed device MACs
- Blocks devices from other courts
✅ 4. Separate UDP Ports (Optional)
- Court 1 listens on UDP
5002 - Court 2 listens on UDP
5003 - Prevents broadcast overlap
🛡️ Safety Summary
| Risk | Solution |
|---|---|
| Device connects to wrong court | Unique SSID or Court ID check |
| Two tablets respond to discovery | Use Court ID filtering |
| Unauthorized device connects | MAC whitelisting |
| IP conflict | Let DHCP handle it |
6. ESP32 Code Examples
📡 ESP32: Auto-Discovery & Connect (Arduino C++)
#include <WiFi.h>
#include <WiFiUdp.h>
const char* ssid = "TKD_SCORING_COURT1"; // Change per court
const char* password = "taekwondo123";
const int udpPort = 5002;
const char* discoverMsg = "TKD_DISCOVER";
const char* expectedCourt = "COURT1";
WiFiUDP udp;
String getServerIP() {
udp.beginPacket("255.255.255.255", udpPort);
udp.print(discoverMsg);
udp.endPacket();
unsigned long timeout = millis() + 3000;
while (millis() < timeout) {
int len = udp.parsePacket();
if (len > 0) {
char response[64];
udp.read(response, len);
response[len] = '\0';
// Parse: SERVER_IP:192.168.1.100:5000:COURT1
String resp = String(response);
int ipStart = resp.indexOf("SERVER_IP:") + 10;
int courtStart = resp.lastIndexOf(":") + 1;
String courtId = resp.substring(courtStart);
if (courtId == expectedCourt) {
int portEnd = resp.lastIndexOf(":");
int ipEnd = resp.lastIndexOf(":", portEnd - 1);
return resp.substring(ipStart, ipEnd);
}
}
delay(100);
}
return "";
}
void setup() {
Serial.begin(115200);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
udp.begin(udpPort + 1); // Use different port for listening
String serverIP = getServerIP();
if (serverIP != "") {
Serial.println("Found server: " + serverIP);
// Now connect to TCP server
WiFiClient client;
if (client.connect(serverIP.c_str(), 5000)) {
client.println("DEVICE:NAME=HOGU_RED,TYPE=SENSOR,MAC=" + WiFi.macAddress());
// Send data...
}
} else {
Serial.println("No server found!");
}
}
7. Android .NET Server Code
🖥️ Android: UDP Discovery Server (C# .NET MAUI)
using System.Net;
using System.Net.Sockets;
using System.Text;
public class UdpDiscoveryServer
{
private UdpClient _udp;
private string _serverIp;
private string _courtId;
private int _tcpPort = 5000;
private int _udpPort = 5002;
public UdpDiscoveryServer(string courtId)
{
_courtId = courtId;
_serverIp = GetLocalIPAddress(); // e.g., 192.168.1.100
}
public void Start()
{
_udp = new UdpClient(_udpPort);
Task.Run(async () => {
while (true)
{
var remote = new IPEndPoint(IPAddress.Any, 0);
try
{
byte[] data = _udp.Receive(ref remote);
string request = Encoding.UTF8.GetString(data);
if (request.Trim() == "TKD_DISCOVER")
{
string response = $"SERVER_IP:{_serverIp}:{_tcpPort}:{_courtId}";
byte[] responseData = Encoding.UTF8.GetBytes(response);
_udp.Send(responseData, responseData.Length, remote);
}
}
catch (Exception ex)
{
// Handle error
}
}
});
}
private string GetLocalIPAddress()
{
// Get Wi-Fi IP (simplified)
// In practice, use ConnectivityManager or WifiManager
return "192.168.4.1"; // Or get dynamically
}
}
🖥️ Android: TCP Server (Score Control App)
using System.Net;
using System.Net.Sockets;
public class TcpServer
{
private TcpListener _listener;
private Dictionary<string, TcpClient> _clients = new();
public async Task Start(int port)
{
_listener = new TcpListener(IPAddress.Any, port);
_listener.Start();
while (true)
{
TcpClient client = await _listener.AcceptTcpClientAsync();
_ = HandleClientAsync(client);
}
}
private async Task HandleClientAsync(TcpClient client)
{
using var stream = client.GetStream();
using var reader = new StreamReader(stream);
string identity = await reader.ReadLineAsync();
if (identity?.StartsWith("DEVICE:") == true)
{
var parts = ParseIdentity(identity);
string mac = parts["MAC"];
string name = parts["NAME"];
// Validate MAC against whitelist
if (IsAllowed(mac))
{
_clients[mac] = client;
// Start reading data...
}
else
{
// Send DENIED and close
var writer = new StreamWriter(stream);
await writer.WriteLineAsync("DENIED");
await writer.FlushAsync();
client.Close();
}
}
}
private Dictionary<string, string> ParseIdentity(string line)
{
var result = new Dictionary<string, string>();
if (!line.StartsWith("DEVICE:")) return result;
var parts = line.Substring(7).Split(',');
foreach (var part in parts)
{
var kv = part.Split('=', 2);
if (kv.Length == 2) result[kv[0]] = kv[1];
}
return result;
}
private bool IsAllowed(string mac) => AllowedDevices.Contains(mac);
}
8. Best Practices
| Practice | Why |
|---|---|
| Use unique SSID per court | Prevents discovery conflicts |
| Pre-configure device Wi-Fi | No user setup needed |
| Include Court ID in discovery | Safe multi-court operation |
| Whitelist device MACs | Prevents spoofing |
| Use UDP broadcast on 5002+ | Avoids port conflicts |
| Fixed hotspot IP (192.168.4.1) | Simplifies client logic |
| Reconnect logic on ESP32 | Handles Wi-Fi drops |
| Log connection events | Debugging and auditing |