Update README.md
This commit is contained in:
parent
24dd8e1d46
commit
17a1dbb784
506
README.md
506
README.md
@ -1,2 +1,504 @@
|
|||||||
# Takeone Event Managment And Scoring System
|
# 🥋 Taekwondo Electronic Scoring System – Developer Documentation
|
||||||
This software is for running events smoothly and accuratly and keeps a record of the events history.
|
|
||||||
|
> **Version:** 4.0 (Final & Complete)
|
||||||
|
> **Last Updated:** July 2025
|
||||||
|
> **Target Developer:** .NET Android (MAUI/Xamarin) with TCP experience
|
||||||
|
> **Project Goal:** Build a **fully automated, secure, broadcast-quality** Taekwondo scoring system that works **without any technical knowledge** from referees or staff.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📌 Table of Contents
|
||||||
|
|
||||||
|
- [1. System Overview](#1-system-overview)
|
||||||
|
- [2. Network Setup (Zero-Config Wi-Fi Hotspot)](#2-network-setup-zero-config-wi-fi-hotspot)
|
||||||
|
- [3. Device Connection & Discovery](#3-device-connection--discovery)
|
||||||
|
- [4. Device Identity Format (NAME, TYPE, MAC)](#4-device-identity-format-name-type-mac)
|
||||||
|
- [5. Score Control App (Android Tablet)](#5-score-control-app-android-tablet)
|
||||||
|
- [6. Android TV Apps](#6-android-tv-apps)
|
||||||
|
- [7. Scoring Rules & Auto-Scoring Logic](#7-scoring-rules--auto-scoring-logic)
|
||||||
|
- [8. Scoreboard Display Requirements](#8-scoreboard-display-requirements)
|
||||||
|
- [9. Match Presentation Flow](#9-match-presentation-flow)
|
||||||
|
- [10. Match Management](#10-match-management)
|
||||||
|
- [11. Result Logging](#11-result-logging)
|
||||||
|
- [12. Security & Validation](#12-security--validation)
|
||||||
|
- [13. Full JSON Message Examples](#13-full-json-message-examples)
|
||||||
|
- [14. Developer To-Do List](#14-developer-to-do-list)
|
||||||
|
- [15. Appendix: Resources](#15-appendix-resources)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 1. System Overview
|
||||||
|
|
||||||
|
This system automates **Taekwondo sparring (kyorugi)** scoring for **clubs, tournaments, and non-technical users**.
|
||||||
|
|
||||||
|
### 🎯 Key Principles
|
||||||
|
- **No IP, port, or network configuration** required
|
||||||
|
- **Center referee has no device** — uses only voice and hand signals
|
||||||
|
- **Scorekeeper** uses an Android tablet to manage the system
|
||||||
|
- **All devices auto-connect** to a self-hosted Wi-Fi network
|
||||||
|
- **Fully automatic scoring** based on sensors and corner referee votes
|
||||||
|
- **Broadcast-quality display flow** for audience engagement
|
||||||
|
|
||||||
|
### 🧩 Components
|
||||||
|
| Device | Role |
|
||||||
|
|-------|------|
|
||||||
|
| **Android Tablet** | TCP server, score control, match manager |
|
||||||
|
| **ESP32-C3 Sensors** | Detect impact on hogu and headgear |
|
||||||
|
| **ESP32-C3 Joysticks** | Corner referee voting (4 units) |
|
||||||
|
| **Android TV 1** | Live scoreboard (ring display) |
|
||||||
|
| **Android TV 2** | Upcoming matches (lobby display) |
|
||||||
|
|
||||||
|
All devices connect via Wi-Fi and identify themselves securely.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. Network Setup (Zero-Config Wi-Fi Hotspot)
|
||||||
|
|
||||||
|
To eliminate technical barriers, the **Android tablet creates its own Wi-Fi network**.
|
||||||
|
|
||||||
|
### 📶 Wi-Fi Settings
|
||||||
|
- **SSID**: `TKD_SCORING_COURT1`
|
||||||
|
- **Password**: `taekwondo123` (default, printed on device label)
|
||||||
|
- **Tablet IP**: `192.168.4.1` (fixed in hotspot mode)
|
||||||
|
- **Server Ports**:
|
||||||
|
- TCP: `5000` (data)
|
||||||
|
- UDP: `5002` (discovery)
|
||||||
|
|
||||||
|
### 🔧 How It Works
|
||||||
|
1. Scorekeeper powers on tablet
|
||||||
|
2. App **automatically enables Wi-Fi hotspot**
|
||||||
|
3. Staff connects all devices to `TKD_SCORING_COURT1`
|
||||||
|
4. Devices **auto-discover and connect** to `192.168.4.1`
|
||||||
|
5. No user enters IP or port
|
||||||
|
|
||||||
|
> ✅ Works **offline** — no internet required.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. Device Connection & Discovery
|
||||||
|
|
||||||
|
All devices **auto-discover** the server and connect with zero input.
|
||||||
|
|
||||||
|
### 🔄 Connection Flow
|
||||||
|
1. Device powers on → connects to `TKD_SCORING_COURT1`
|
||||||
|
2. Sends UDP broadcast:
|
||||||
|
```text
|
||||||
|
TKD_DISCOVER
|
||||||
|
```
|
||||||
|
3. Tablet responds:
|
||||||
|
```text
|
||||||
|
SERVER_IP:192.168.4.1
|
||||||
|
```
|
||||||
|
4. Device connects to `192.168.4.1:5000`
|
||||||
|
5. Sends identity:
|
||||||
|
```
|
||||||
|
DEVICE:NAME=HOGU_RED,TYPE=SENSOR,MAC=30:85:A9:12:34:56
|
||||||
|
```
|
||||||
|
6. Server validates and registers
|
||||||
|
|
||||||
|
### 📱 Android TV Setup
|
||||||
|
- Pre-install app
|
||||||
|
- Auto-connect to `TKD_SCORING_COURT1`
|
||||||
|
- App starts on boot and connects to server
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4. Device Identity Format (NAME, TYPE, MAC)
|
||||||
|
|
||||||
|
Every device must send this **exact format** as the **first line** after connection:
|
||||||
|
|
||||||
|
```
|
||||||
|
DEVICE:NAME=<name>,TYPE=<type>,MAC=<mac>
|
||||||
|
```
|
||||||
|
|
||||||
|
| Field | Description | Example |
|
||||||
|
|------|-------------|--------|
|
||||||
|
| `NAME` | Descriptive name | `HOGU_RED`, `JOYSTICK_CORNER_1`, `TV_SCOREBOARD` |
|
||||||
|
| `TYPE` | Device category | `SENSOR`, `JOYSTICK`, `DISPLAY` |
|
||||||
|
| `MAC` | Uppercase, colon-separated | `30:85:A9:12:34:56` |
|
||||||
|
|
||||||
|
### ✅ Valid Examples
|
||||||
|
```
|
||||||
|
DEVICE:NAME=HOGU_RED,TYPE=SENSOR,MAC=30:85:A9:12:34:56
|
||||||
|
```
|
||||||
|
```
|
||||||
|
DEVICE:NAME=HEAD_BLUE,TYPE=SENSOR,MAC=30:85:A9:12:34:57
|
||||||
|
```
|
||||||
|
```
|
||||||
|
DEVICE:NAME=JOYSTICK_CORNER_1,TYPE=JOYSTICK,MAC=30:85:A9:12:34:58
|
||||||
|
```
|
||||||
|
```
|
||||||
|
DEVICE:NAME=TV_SCOREBOARD,TYPE=DISPLAY,MAC=18:3D:A2:01:02:03
|
||||||
|
```
|
||||||
|
|
||||||
|
### 🛠️ ESP32: Get MAC Address
|
||||||
|
```cpp
|
||||||
|
#include <WiFi.h>
|
||||||
|
String getMacAddress() {
|
||||||
|
uint8_t mac[6];
|
||||||
|
WiFi.macAddress(mac);
|
||||||
|
char macStr[18];
|
||||||
|
sprintf(macStr, "%02X:%02X:%02X:%02X:%02X:%02X", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
|
||||||
|
return String(macStr);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 🖥️ Server: Parse Identity (C#)
|
||||||
|
```csharp
|
||||||
|
Dictionary<string, string> ParseDeviceIdentity(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('=');
|
||||||
|
if (kv.Length == 2) result[kv[0]] = kv[1];
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 5. Score Control App (Android Tablet)
|
||||||
|
|
||||||
|
Built with **.NET MAUI / Xamarin**, this app is the **central brain**.
|
||||||
|
|
||||||
|
### 🎯 Responsibilities
|
||||||
|
- Act as **TCP server** (Port 5000)
|
||||||
|
- Receive sensor/joystick data
|
||||||
|
- Apply **WT scoring rules**
|
||||||
|
- Control **Android TV displays** (Port 5001)
|
||||||
|
- Manage **match lifecycle**
|
||||||
|
- Log results
|
||||||
|
- Monitor connected devices
|
||||||
|
|
||||||
|
### 🖼️ UI Screens
|
||||||
|
|
||||||
|
#### 🏁 Home Screen
|
||||||
|
```
|
||||||
|
[Start Setup Mode]
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 🔍 Setup Mode
|
||||||
|
- Auto-detects devices:
|
||||||
|
```
|
||||||
|
✅ HOGU_RED
|
||||||
|
✅ HEAD_BLUE
|
||||||
|
🔔 Waiting for JOYSTICK_CORNER_1...
|
||||||
|
```
|
||||||
|
- When all found:
|
||||||
|
```
|
||||||
|
[Lock System & Start Match]
|
||||||
|
```
|
||||||
|
|
||||||
|
#### ⚔️ Live Match Screen
|
||||||
|
- Timer (2:00)
|
||||||
|
- Score: 🔴 4 vs 2 🔵
|
||||||
|
- Event log
|
||||||
|
- Referee vote indicators
|
||||||
|
- Controls: `Shi-jak`, `Kal-yeo`, `Next Round`
|
||||||
|
|
||||||
|
#### 🖥️ Device Monitor
|
||||||
|
| MAC | Name | Type | Status |
|
||||||
|
|-----|------|------|--------|
|
||||||
|
| 30:.. | HOGU_RED | SENSOR | ✅ |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 6. Android TV Apps
|
||||||
|
|
||||||
|
### 📺 TV 1: Scoreboard App (Ring Display)
|
||||||
|
|
||||||
|
#### Modes
|
||||||
|
- `faceoff`: Fighter face-off
|
||||||
|
- `score`: Live scoring
|
||||||
|
- `break`: Ads + highlights
|
||||||
|
- `call_to_action`: "Fighters, return!"
|
||||||
|
- `winner`: Winner celebration
|
||||||
|
|
||||||
|
#### Connection
|
||||||
|
- Connects to `192.168.4.1:5001`
|
||||||
|
- Sends device identity
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 📺 TV 2: Match Display App (Lobby)
|
||||||
|
|
||||||
|
#### Features
|
||||||
|
- Scrollable list of next 3–5 matches
|
||||||
|
- Pulls from CSV or cloud
|
||||||
|
- Tournament logo and sponsors
|
||||||
|
|
||||||
|
#### Connection
|
||||||
|
- Same as above, name: `TV_MATCH_DISPLAY`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 7. Scoring Rules & Auto-Scoring Logic
|
||||||
|
|
||||||
|
Based on **World Taekwondo (WT) 2024 rules**.
|
||||||
|
|
||||||
|
### ✅ Valid Techniques
|
||||||
|
| Technique | Points |
|
||||||
|
|---------|--------|
|
||||||
|
| Kick to trunk | 1 |
|
||||||
|
| Kick to head | 3 |
|
||||||
|
| Spinning kick to trunk | 4 |
|
||||||
|
| Spinning kick to head | 5 |
|
||||||
|
| Punch to trunk | 1 |
|
||||||
|
| Gam-jeom (penalty) | +1 to opponent |
|
||||||
|
|
||||||
|
> ❗ **No input from center referee** — only voice and signals.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 🔄 Auto-Scoring Logic
|
||||||
|
|
||||||
|
A point is awarded if:
|
||||||
|
1. Sensor detects impact (force > threshold)
|
||||||
|
2. **≥3 out of 4 corner referees** press within **1 second**
|
||||||
|
3. For spinning kicks: MPU6050 confirms rotation > 180°
|
||||||
|
|
||||||
|
#### Force Thresholds
|
||||||
|
- **Hogu**: ≥ 500 (analog) or 800g
|
||||||
|
- **Head**: ≥ 400 (for safety)
|
||||||
|
|
||||||
|
#### Timing Window
|
||||||
|
- Referee button presses must be within **±1 second** of impact
|
||||||
|
- Debounce: Ignore same sensor hits within 500ms
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
void CheckForValidPoint(ImpactEvent impact)
|
||||||
|
{
|
||||||
|
var votes = GetJoystickPressesInRange(impact.Time, 1000);
|
||||||
|
if (votes.Count >= 3)
|
||||||
|
{
|
||||||
|
int points = CalculatePoints(impact);
|
||||||
|
AddPoints(impact.Attacker, points);
|
||||||
|
BroadcastScoreUpdate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 8. Scoreboard Display Requirements
|
||||||
|
|
||||||
|
The main scoreboard displays **13 elements**:
|
||||||
|
|
||||||
|
| # | Element | Source |
|
||||||
|
|---|--------|--------|
|
||||||
|
| 1 | Court Number | Match data |
|
||||||
|
| 2 | Match Number | Schedule |
|
||||||
|
| 3 | Match Timer | App timer |
|
||||||
|
| 4 | Round Counter | Match state |
|
||||||
|
| 5 | Country Flag | Fighter data |
|
||||||
|
| 6 | Country ISO3 | Fighter data |
|
||||||
|
| 7 | Team Logo | Fighter data |
|
||||||
|
| 8 | Fighter Name | Match setup |
|
||||||
|
| 9 | Fighter Score | Scoring engine |
|
||||||
|
| 10 | Fighter Fouls | Penalty tracker |
|
||||||
|
| 11 | Fighter Weight (kg) | Fighter profile |
|
||||||
|
| 12 | Weight Class & Category | Match data |
|
||||||
|
| 13 | Team Name | Fighter data |
|
||||||
|
|
||||||
|
### 🎨 Example Layout
|
||||||
|
```
|
||||||
|
COURT 1 MATCH #105 ROUND 2/3
|
||||||
|
MEN'S -68KG SEMIFINAL
|
||||||
|
|
||||||
|
🇰🇷 KIM Min-jae vs LEE Jung-ho 🇨🇳
|
||||||
|
Seoul TKD Club vs Beijing TKD
|
||||||
|
[Logo] vs [Logo]
|
||||||
|
|
||||||
|
8 vs 5
|
||||||
|
⚠️ ⚠️⚠️
|
||||||
|
|
||||||
|
⏱️ 01:45
|
||||||
|
|
||||||
|
67.2 kg 67.8 kg
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 9. Match Presentation Flow
|
||||||
|
|
||||||
|
### 1. Face-Off (10 sec)
|
||||||
|
- Fighter photos, names, flags
|
||||||
|
- Before "Shi-jak"
|
||||||
|
|
||||||
|
### 2. Live Scoring (2:00)
|
||||||
|
- Real-time score, timer, fouls
|
||||||
|
|
||||||
|
### 3. Break (60 sec)
|
||||||
|
- 0–50 sec: Sponsor ad
|
||||||
|
- 50–58 sec: Round highlights (video)
|
||||||
|
- 58–60 sec: Fade to next phase
|
||||||
|
|
||||||
|
### 4. Call to Action (10 sec)
|
||||||
|
- Full-screen: "FIGHTERS, RETURN TO THE RING!"
|
||||||
|
- Flashing text, sound cues at 5 and 1 sec
|
||||||
|
|
||||||
|
### 5. Winner Screen (15 sec)
|
||||||
|
- Winner enlarged
|
||||||
|
- Confetti animation
|
||||||
|
- Final score
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 10. Match Management
|
||||||
|
|
||||||
|
Matches can be created in three ways:
|
||||||
|
|
||||||
|
### 1. Single Match (Manual)
|
||||||
|
- Enter red/blue names, weight, team
|
||||||
|
- Ideal for training
|
||||||
|
|
||||||
|
### 2. CSV Import
|
||||||
|
```csv
|
||||||
|
match_id,red_name,blue_name,weight,round,red_country,blue_country,red_photo,blue_photo
|
||||||
|
M101,Kim,Lee,-58kg,Quarter,KOR,CHN,https://...,https://...
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. Cloud API Sync
|
||||||
|
- GET `https://api.tournament.com/matches`
|
||||||
|
- Polls every 60 seconds
|
||||||
|
|
||||||
|
### 🔄 Auto-Advance
|
||||||
|
After match ends:
|
||||||
|
1. Log result
|
||||||
|
2. Load next match
|
||||||
|
3. Show face-off on TVs
|
||||||
|
4. Wait for "Start Match"
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 11. Result Logging
|
||||||
|
|
||||||
|
After each match, results are saved.
|
||||||
|
|
||||||
|
### 📄 JSON Format
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"match_id": "M105",
|
||||||
|
"court": "1",
|
||||||
|
"weight_class": "Men's -68kg",
|
||||||
|
"round": "Final",
|
||||||
|
"red": { "name": "Kim", "team": "Seoul", "score": 8, "fouls": 1 },
|
||||||
|
"blue": { "name": "Lee", "team": "Beijing", "score": 5, "fouls": 2 },
|
||||||
|
"winner": "red",
|
||||||
|
"duration": 180,
|
||||||
|
"timestamp": "2025-07-10T11:15:30Z"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 💾 Export Options
|
||||||
|
- Save to `Documents/results.json`
|
||||||
|
- Append to `results.csv`
|
||||||
|
- POST to cloud API
|
||||||
|
- Share via email or USB
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 12. Security & Validation
|
||||||
|
|
||||||
|
### 🔐 Allowed Device List
|
||||||
|
- Server has **pre-loaded list** of allowed MAC addresses
|
||||||
|
- Stored in app (JSON or SQLite)
|
||||||
|
- Unknown devices are **ignored silently**
|
||||||
|
|
||||||
|
### 🚫 Connection Rules
|
||||||
|
- After "Lock System" → **no new connections**
|
||||||
|
- Disconnected device → **can only rejoin in Setup Mode**
|
||||||
|
- Only devices with correct `TYPE` and `NAME` are accepted
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 13. Full JSON Message Examples
|
||||||
|
|
||||||
|
### From Sensor
|
||||||
|
```json
|
||||||
|
{"type":"impact","device":"head_blue","force":900,"spinning":true,"time":1712345678901}
|
||||||
|
```
|
||||||
|
|
||||||
|
### From Joystick
|
||||||
|
```json
|
||||||
|
{"type":"button","device":"corner_2","pressed":true,"time":1712345678905}
|
||||||
|
```
|
||||||
|
|
||||||
|
### To Scoreboard TV
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 14. Developer To-Do List
|
||||||
|
|
||||||
|
| Task | Status |
|
||||||
|
|------|--------|
|
||||||
|
| Implement Wi-Fi hotspot mode (Android) | ☐ |
|
||||||
|
| Build TCP server (Port 5000) | ☐ |
|
||||||
|
| Implement UDP discovery (Port 5002) | ☐ |
|
||||||
|
| Parse device identity (NAME,TYPE,MAC) | ☐ |
|
||||||
|
| Validate devices against allowed list | ☐ |
|
||||||
|
| Implement auto-scoring logic | ☐ |
|
||||||
|
| Design Match Setup UI with all fields | ☐ |
|
||||||
|
| Add country flag, team logo support | ☐ |
|
||||||
|
| Send rich scoreboard JSON (13 fields) | ☐ |
|
||||||
|
| Create Android TV apps | ☐ |
|
||||||
|
| Support video playback for highlights | ☐ |
|
||||||
|
| Implement break mode with ads | ☐ |
|
||||||
|
| Add call-to-action screen | ☐ |
|
||||||
|
| Create winner screen with animation | ☐ |
|
||||||
|
| Add match flow timer engine | ☐ |
|
||||||
|
| Implement CSV import with all fields | ☐ |
|
||||||
|
| Implement Cloud API sync | ☐ |
|
||||||
|
| Add match auto-advance | ☐ |
|
||||||
|
| Implement result logging (file + API) | ☐ |
|
||||||
|
| Export results to CSV | ☐ |
|
||||||
|
| Add Device Monitor screen | ☐ |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 15. Appendix: Resources
|
||||||
|
|
||||||
|
- [.NET TCP](https://learn.microsoft.com/en-us/dotnet/api/system.net.sockets.tcpclient)
|
||||||
|
- [Android Wi-Fi Hotspot API](https://developer.android.com/reference/android/net/wifi/WifiManager)
|
||||||
|
- [UDP in .NET](https://learn.microsoft.com/en-us/dotnet/api/system.net.sockets.udpclient)
|
||||||
|
- [ESP32 Arduino](https://github.com/espressif/arduino-esp32)
|
||||||
|
- [CSV Helper](https://joshclose.github.io/CsvHelper/)
|
||||||
|
- [ExoPlayer (Video)](https://github.com/google/ExoPlayer)
|
||||||
|
- [Android TV](https://developer.android.com/tv)
|
||||||
|
|
||||||
|
Hardware: ESP32-C3, FSR, MPU6050, push buttons, batteries
|
||||||
|
|
||||||
|
Testing: `telnet 192.168.4.1 5000`, Wireshark, Serial Monitor
|
||||||
Loading…
x
Reference in New Issue
Block a user