Files
TurboSu/README.md
T

266 lines
8.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# TurboSu
赛车遥测仪表盘 — 基于 Web 的 B/S 架构外置仪表盘,支持多种赛车游戏遥测数据实时显示。
![License](https://img.shields.io/badge/license-Apache%202.0-blue)
![Python](https://img.shields.io/badge/python-3.10%2B-blue)
![Platform](https://img.shields.io/badge/platform-web%20%7C%20lan-brightgreen)
## 功能特性
- **多游戏支持** — 插件化架构,内置 Forza Horizon 4/5、Forza Motorsport、Assetto Corsa/ACC、F1、iRacing
- **社区扩展** — 游戏插件可独立打包导入导出 (`.tsp`),方便社区贡献小众游戏支持
- **实时仪表盘** — 速度表、转速表、档位指示器、圈速计时器
- **独立仪表盘** — 每个仪表盘是独立文件夹 (`manifest.json` + `index.html`),启动自动扫描
- **场景模式** — 多仪表盘布局组合,支持多比例画布切换
- **局域网共享** — 仪表盘/场景生成独立链接,手机/平板/笔记本均可全屏访问
- **跨端自适应** — 响应式布局:桌面侧边栏 / 平板折叠 / 手机底部导航
- **比例约束渲染** — 仪表盘可指定比例 (`auto`/`16:9`/`4:3`/`1:1`) 和渲染模式 (`contain`/`cover`/`fill`/`center`)
- **HyperOS 风格** — Miuix 设计语言,毛玻璃模糊效果,日间/夜间模式
- **社区分发** — 仪表盘 `.tsd`、场景 `.tss`、插件 `.tsp` — zip 格式,便于分享
## 快速开始
### 环境要求
- Python 3.10+
- pip
### 运行
```bash
git clone ssh://git@git.yeij.top:2222/AskaEth/TurboSu.git
cd TurboSu
# 一键启动 (自动创建 venv 并安装依赖)
./run.sh
# 或手动启动
python3 -m venv venv && source venv/bin/activate
pip install -r requirements.txt
python app.py
```
浏览器访问 `http://localhost:9527`
## 使用指南
### 1. 选择游戏
侧边栏 → 游戏列表展开 → 选择你要玩的游戏。列表来自 `games/builtin/` (内置) 和 `games/user/` (社区)。
### 2. 配置遥测输出
在各游戏中开启 UDP 数据输出功能:
| 游戏 | 设置位置 | 端口 |
|------|----------|------|
| Forza Horizon 4/5 | 设置 → HUD与游戏 → 数据输出 | 20777 |
| Forza Motorsport | 设置 → 游戏玩法 → UDP数据输出 | 20777 |
| Assetto Corsa | 内容管理器 → 自定义UDP | 9996 |
| ACC | 设置 → 电子设备 → UDP | 20777 |
| F1 24 | 设置 → 遥测设置 → UDP | 20777 |
| iRacing | 选项 → 杂项 → 数据记录 | 20777 |
### 3. 浏览仪表盘
侧边栏 → 仪表盘 → 浏览/分类筛选 → 点击卡片在新标签打开全屏仪表盘。
链接自动复制,局域网设备可直接访问。右键卡片可导出 `.tsd` 文件。
### 4. 创建场景
侧边栏 → 场景 → 新建场景 → 编辑添加多个仪表盘 → 选择画布比例 → 渲染。
场景卡片支持导出 `.tss`,页面顶栏可导入。
### 5. 数据调试
侧边栏 → 数据测试 → 实时查看解析字段和原始 JSON 数据流。
## 开发指南
### 自定义仪表盘格式
每个仪表盘是一个独立文件夹,放在 `dashboards/``data/dashboards/`
```
dashboards/my_dashboard/
├── manifest.json # 元信息
└── index.html # 完整独立页面 (含 WS 连接 + 数据绑定)
```
#### manifest.json
```json
{
"id": "my_dashboard",
"name": "我的仪表盘",
"category": "custom",
"description": "简短描述",
"author": "你的名字",
"version": "1.0.0",
"config": {
"icon": "🏎️",
"aspect_ratio": "16:9",
"render_mode": "contain"
}
}
```
#### index.html
完全独立的 HTML 页面。需包含:
- WebSocket 连接到 `ws://<host>/ws` 接收遥测数据
- `data-bind` 属性绑定数据字段(如 `data-bind="speed_kmh"`
- 比例约束渲染逻辑(参考内置仪表盘)
打包分发:将整个文件夹压缩为 zip,改后缀为 `.tsd`
### 自定义游戏插件
插件文件夹放在 `games/user/`
```
games/user/my_game/
├── manifest.json # 元信息
└── parser.py # 解析逻辑 (get_parser() + parse())
```
#### manifest.json
```json
{
"id": "my_game",
"name": "我的游戏",
"parser_type": "forza",
"description": "自定义游戏遥测",
"author": "你的名字",
"version": "1.0.0",
"default_port": 20777
}
```
#### parser.py
```python
import time
from server.telemetry.data import TelemetryData
def get_parser():
return MyGameParser()
class MyGameParser:
def game_id(self) -> str:
return "my_game"
def parse(self, data: bytes, addr: tuple) -> TelemetryData:
td = TelemetryData(game_id="my_game", timestamp=time.time())
td.raw = {"raw_hex": data.hex(), "length": len(data)}
# 解析你的游戏数据...
# td.speed_kmh = ...
# td.rpm = ...
# td.gear = ...
return td
```
打包分发:将文件夹压缩为 zip,改后缀为 `.tsp`,在设置页面导入。
### TelemetryData 可用字段
| 字段 | 类型 | 说明 |
|------|------|------|
| `speed_kmh` | float | 速度 (km/h) |
| `speed_mph` | float | 速度 (mph) |
| `rpm` | float | 发动机转速 |
| `max_rpm` | float | 最大转速 |
| `gear` | int | 档位 (0=N, -1=R) |
| `throttle` | float | 油门 (0~1) |
| `brake` | float | 刹车 (0~1) |
| `clutch` | float | 离合 (0~1) |
| `handbrake` | float | 手刹 (0~1) |
| `steering` | float | 转向 (-1~1) |
| `lap_time` | float | 当前圈速 (秒) |
| `best_lap` | float | 最佳圈速 (秒) |
| `last_lap` | float | 上圈时间 (秒) |
| `lap_number` | int | 圈数 |
| `fuel` | float | 燃油 |
| `boost` | float | 涡轮增压 |
| `horsepower` | float | 马力 |
| `torque` | float | 扭矩 |
| `position_x/y/z` | float | 坐标 |
| `engine_temp` | float | 发动机温度 |
| `oil_temp` | float | 油温 |
| `raw` | dict | 原始数据 |
## 项目结构
```
TurboSu/
├── app.py # FastAPI 主入口 (lifespan)
├── run.sh # 一键启动脚本
├── requirements.txt
├── config/settings.py # 全局配置 (JSON 持久化)
├── server/
│ ├── api.py # REST API (状态/配置/CRUD/导入导出)
│ ├── websocket.py # WebSocket 广播 (30fps 限流)
│ ├── game_manager.py # 游戏插件发现/加载/导入导出(.tsp)
│ └── telemetry/
│ ├── data.py # TelemetryData 27字段数据类
│ ├── listener.py # UDP 异步监听器
│ └── parsers/ # 内置解析器 (base/forza/ac/acc/f1/iracing)
├── games/
│ ├── builtin/ # 7 款内置游戏插件
│ │ ├── forza_horizon_5/ # manifest.json + parser.py
│ │ ├── forza_horizon_4/
│ │ ├── forza_motorsport/
│ │ ├── assetto_corsa/
│ │ ├── assetto_corsa_competizione/
│ │ ├── f1_24/
│ │ └── iracing/
│ └── user/ # 社区插件 (运行时安装)
├── dashboards/ # 内置仪表盘 (4 款)
│ ├── speedometer/ # manifest.json + index.html
│ ├── tachometer/
│ ├── gear_indicator/
│ └── lap_timer/
├── models/
│ ├── dashboard.py # 仪表盘模型 + 自动扫描 + zip导入导出
│ └── scene.py # 场景模型 + 画布/布局 + zip导入导出
├── templates/
│ ├── index.html # 主 SPA 页面
│ └── scene.html # 场景渲染页 (iframe组合)
├── static/
│ ├── css/
│ │ ├── miuix.css # HyperOS/Miuix 样式框架 (CSS变量+毛玻璃+主题)
│ │ └── main.css # 布局 + 跨端响应式 (3断点)
│ └── js/
│ ├── app.js / router.js # 应用入口 + Hash路由
│ ├── api.js / ws.js # API + WebSocket 客户端
│ ├── components/ # sidebar.js / topbar.js
│ ├── pages/ # home / dashboard / scene / debug / settings
│ └── utils/ # theme.js / toast.js
├── data/ # 运行时数据 (user dashboards, scenes, config)
├── logs/ # 日志 (轮转文件, 10MB x5)
├── README.md
└── CONTRIBUTING.md
```
## 导入导出格式
| 格式 | 后缀 | 本质 | 说明 |
|------|------|------|------|
| 仪表盘 | `.tsd` | zip | 含 `manifest.json` + `index.html` |
| 场景 | `.tss` | zip | 含 `scene.json` |
| 游戏插件 | `.tsp` | zip | 含 `manifest.json` + `parser.py` |
## 作者
**Yei.J. (AskaEth)**
## 许可证
Apache License 2.0