takeone-event-managment/doc/displays-signals.md

10 KiB
Raw Blame History

📡 Taekwondo Scoring System Score Control to Display Communication

Version: 1.0
Last Updated: July 2025
Target Developer: .NET Android (Score Control) & Android TV App Developers
Purpose: Define real-time data signals from Score Control Unit to Scoreboard and Upcoming Matches displays


📌 Table of Contents


1. Overview

The Score Control Unit (Android tablet) sends real-time data to two Android TVs:

Display Purpose
Scoreboard TV Live match: score, timer, fighter info
Upcoming Matches TV Lobby: next matches, tournament flow

All communication is:

  • Real-time
  • Bidirectional-ready (optional)
  • Over Wi-Fi (TCP)
  • Zero-config for users

2. System Architecture

[Score Control Tablet] → Wi-Fi → [Scoreboard TV (Port 5001)]
                             ↘
                              [Upcoming Matches TV (Port 5002)]
  • Score Control acts as TCP server
  • TVs act as TCP clients
  • TVs connect at startup and stay connected
  • Score Control broadcasts JSON messages

All devices on same network (TKD_SCORING_COURT1)


3. Communication Protocol (TCP)

🔌 Connection Flow

  1. TV powers on → connects to TKD_SCORING_COURT1
  2. TV app starts → connects to tablet IP (192.168.4.1)
  3. TV sends identity:
    DISPLAY:NAME=TV_SCOREBOARD,TYPE=SCOREBOARD,MAC=18:3D:A2:01:02:03
    
  4. Score Control registers TV
  5. TV listens for JSON messages

4. Scoreboard (Live Match Display)

Displays real-time match data.

🖼️ 13 Display Elements

Element Source
Court Number Match data
Match Number Schedule
Match Timer App timer
Round Counter Match state
Country Flag Fighter data
Country ISO3 Fighter data
Team Logo Fighter data
Fighter Name Match setup
Fighter Score Scoring engine
Fighter Fouls Penalty tracker
Fighter Weight (kg) Fighter profile
Weight Class & Category Match data
Team Name Fighter data

🔄 Display Modes

Mode Trigger Duration
faceoff Before match 10 sec
score Match start 2:00
break Round end 60 sec
call_to_action Last 10 sec of break 10 sec
winner Match end 15 sec

5. Upcoming Matches Screen

Displays next 35 matches.

🖼️ Display Elements

  • Match number
  • Red vs Blue names
  • Weight class
  • Round
  • Scheduled time
  • Tournament logo

🔄 Auto-Advance

  • Updates when current match ends
  • Pulls from CSV or cloud
  • Scrolls if more than 5 matches

6. Message Format (JSON)

All messages are JSON and end with \n.


6.1 To Scoreboard TV (Port 5001)

faceoff Mode

{
  "mode": "faceoff",
  "red": {
    "name": "Kim Min-jae",
    "country": "KOR",
    "flag": "https://flags/kor.png",
    "photo": "https://photos/kim.jpg"
  },
  "blue": {
    "name": "Lee Jung-ho",
    "country": "CHN",
    "flag": "https://flags/chn.png",
    "photo": "https://photos/lee.jpg"
  },
  "weight_class": "Men's -68kg",
  "round": "Semifinal"
}

score Mode

{
  "mode": "score",
  "court": "1",
  "match_number": "105",
  "weight_class": "Men's -68kg",
  "category": "Semifinal",
  "round": "2",
  "timer": "01:45",
  "red": {
    "name": "Kim Min-jae",
    "country": "KOR",
    "team": "Seoul TKD Club",
    "logo": "https://logos/seoul.png",
    "flag": "https://flags/kor.png",
    "score": 8,
    "fouls": 1,
    "weight_kg": 67.2
  },
  "blue": {
    "name": "Lee Jung-ho",
    "country": "CHN",
    "team": "Beijing TKD",
    "logo": "https://logos/beijing.png",
    "flag": "https://flags/chn.png",
    "score": 5,
    "fouls": 2,
    "weight_kg": 67.8
  }
}

break Mode

{
  "mode": "break",
  "ad_image": "https://ads/sponsor1.png",
  "highlight_video": "https://videos/round1.mp4",
  "countdown": true
}

call_to_action Mode

{
  "mode": "call_to_action",
  "message": "FIGHTERS, RETURN TO THE RING!",
  "timer": 10
}

winner Mode

{
  "mode": "winner",
  "winner": "red",
  "red": {
    "name": "Kim Min-jae",
    "photo": "https://photos/kim.jpg",
    "final_score": 8
  },
  "blue": {
    "name": "Lee Jung-ho",
    "photo": "https://photos/lee.jpg",
    "final_score": 5
  },
  "weight_class": "Men's -68kg",
  "round": "Final",
  "animation": "fireworks"
}

6.2 To Upcoming Matches TV (Port 5002)

{
  "mode": "next_matches",
  "matches": [
    {
      "match_number": "106",
      "red": "Park S.",
      "blue": "Wang L.",
      "weight": "+87kg",
      "round": "Final",
      "time": "11:30",
      "category": "Men's"
    },
    {
      "match_number": "107",
      "red": "Choi M.",
      "blue": "Tanaka Y.",
      "weight": "-58kg",
      "round": "Semifinal",
      "time": "11:50",
      "category": "Women's"
    }
  ],
  "tournament_name": "National Taekwondo Championship 2025",
  "logo": "https://logos/tournament.png"
}

7. C# Server Code (Score Control)

public class DisplayServer
{
    private TcpListener _scoreboardServer;
    private TcpListener _matchesServer;
    private List<TcpClient> _scoreboardClients = new();
    private List<TcpClient> _matchesClients = new();

    public async Task Start()
    {
        _scoreboardServer = new TcpListener(IPAddress.Any, 5001);
        _matchesServer = new TcpListener(IPAddress.Any, 5002);

        _scoreboardServer.Start();
        _matchesServer.Start();

        _ = AcceptScoreboardClients();
        _ = AcceptMatchesClients();
    }

    private async Task AcceptScoreboardClients()
    {
        while (true)
        {
            var client = await _scoreboardServer.AcceptTcpClientAsync();
            _scoreboardClients.Add(client);
            _ = HandleDisplayClient(client, "SCOREBOARD");
        }
    }

    private async Task AcceptMatchesClients()
    {
        while (true)
        {
            var client = await _matchesServer.AcceptTcpClientAsync();
            _matchesClients.Add(client);
            _ = HandleDisplayClient(client, "MATCHES");
        }
    }

    private async Task HandleDisplayClient(TcpClient client, string type)
    {
        using var stream = client.GetStream();
        using var reader = new StreamReader(stream);

        string identity = await reader.ReadLineAsync();
        // Validate: DISPLAY:NAME=...,TYPE=...,MAC=...

        // Keep connection open
        while (client.Connected)
        {
            await Task.Delay(1000); // Wait for broadcast
        }

        // Remove on disconnect
        if (type == "SCOREBOARD")
            _scoreboardClients.Remove(client);
        else
            _matchesClients.Remove(client);
    }

    public void BroadcastToScoreboard(object data)
    {
        string json = JsonSerializer.Serialize(data) + "\n";
        byte[] bytes = Encoding.UTF8.GetBytes(json);

        for (int i = _scoreboardClients.Count - 1; i >= 0; i--)
        {
            var client = _scoreboardClients[i];
            if (client?.Connected == true)
            {
                try
                {
                    client.GetStream().Write(bytes, 0, bytes.Length);
                }
                catch
                {
                    _scoreboardClients.RemoveAt(i); // Cleanup
                }
            }
        }
    }

    public void BroadcastToMatches(object data)
    {
        string json = JsonSerializer.Serialize(data) + "\n";
        byte[] bytes = Encoding.UTF8.GetBytes(json);

        for (int i = _matchesClients.Count - 1; i >= 0; i--)
        {
            var client = _matchesClients[i];
            if (client?.Connected == true)
            {
                try
                {
                    client.GetStream().Write(bytes, 0, bytes.Length);
                }
                catch
                {
                    _matchesClients.RemoveAt(i);
                }
            }
        }
    }
}

8. Android TV App Logic

📺 Scoreboard TV App

  • Connects to 192.168.4.1:5001
  • Sends identity
  • Listens for JSON
  • Renders based on mode
  • Supports video playback for highlight_video

📺 Upcoming Matches TV App

  • Connects to 192.168.4.1:5002
  • Displays scrollable list
  • Updates on new message
  • Shows tournament logo

9. Display Modes & Transitions

Action Broadcast To Mode
Match selected Scoreboard faceoff
"Shi-jak" pressed Scoreboard score
Round ends Scoreboard break
10 sec before next round Scoreboard call_to_action
Match ends Scoreboard winner
Match ends Upcoming Matches next_matches
Tournament starts Upcoming Matches next_matches

10. Best Practices

Practice Why
Use separate ports (5001, 5002) Avoid mode conflicts
Send \n after each message Easy parsing
Validate device identity Security
Reconnect logic on TV Handle Wi-Fi drops
Broadcast only on change Reduce network load
Use UTC time in logs Debugging
Include mode in every message Safe rendering

🎯 This document fully defines the communication between Score Control and Displays.
You now have everything to build real-time, synchronized, broadcast-quality displays.
📬 For help: Contact project lead.


---

### ✅ How to Use

1. Save as `DISPLAY_COMMUNICATION.md`
2. Place in `/docs` folder
3. Commit to GitHub

---

Let me know if you want:
- A **Figma mockup** of the TV screens
- A **sample Android TV app** (Kotlin)
- A **test tool** to simulate messages
- A **Lottie animation** for the winner screen

You're now building a **fully integrated, professional tournament system**. 🏆