# 仪表盘开发指南 每个仪表盘是 `dashboards/` (内置) 或 `data/dashboards/` (用户) 下的独立文件夹,启动时自动扫描。 ## 文件夹结构 ``` dashboards/my_dashboard/ ├── manifest.json # 元信息 ├── index.html # 完整独立页面 └── preview.png # 预览图 (可选) ``` ## manifest.json 格式 ```json { "id": "my_dashboard", "name": "我的仪表盘", "category": "custom", "description": "简短描述", "author": "你的名字", "version": "1.0.0", "supported_games": "all", "config": { "icon": "🏎️", "aspect_ratio": "16:9", "render_mode": "contain" } } ``` | 字段 | 类型 | 必填 | 说明 | |------|------|------|------| | `id` | string | 是 | 唯一标识,= 文件夹名 | | `name` | string | 是 | 显示名称 | | `category` | string | 否 | 分类 (speed/rpm/basic/timing/custom) | | `description` | string | 否 | 描述文字 | | `author` | string | 否 | 作者 | | `version` | string | 否 | 版本号 | | `supported_games` | string | 否 | 支持的游戏: `"all"` 或 ID 逗号分隔 (如 `"forza_horizon,f1_24"`) | | `config.icon` | string | 否 | 预览图标 emoji | | `config.aspect_ratio` | string | 否 | 渲染比例: `auto` / `16:9` / `4:3` / `1:1` / `21:9` | | `config.render_mode` | string | 否 | 渲染模式: `contain` / `cover` / `fill` / `center` | ### 渲染模式说明 | 模式 | 行为 | |------|------| | `contain` | 保持比例完整显示,不足处留黑边 (推荐) | | `cover` | 保持比例铺满屏幕,超出部分裁切 | | `fill` | 拉伸填满视口,忽略比例 | | `center` | 居中显示,不超过 `max_width` × `max_height` | ## index.html 规范 `index.html` 是完整的独立 HTML 页面,直接通过 `/dashboard/` 访问。 ### 必须包含 1. **WebSocket 连接** — 连接到 `ws:///ws` 接收遥测数据 ```javascript const proto = location.protocol === 'https:' ? 'wss:' : 'ws:'; const wsUrl = `${proto}//${location.host}/ws`; const ws = new WebSocket(wsUrl); ws.onmessage = (event) => { const msg = JSON.parse(event.data); if (msg.type === 'telemetry') { // msg.data 包含所有遥测字段 updateUI(msg.data); } }; ws.onclose = () => { // 断线重连 setTimeout(connect, 2000); }; ``` 2. **数据绑定** — 使用 `data-bind` 属性自动绑定 ```html
0
0 ``` 3. **比例约束渲染** — 处理不同设备屏幕比例 ```javascript const CONFIG = { aspect_ratio: "16:9", render_mode: "contain" }; function applyAspectRatio() { const ratio = parseRatio(CONFIG.aspect_ratio); const vw = window.innerWidth, vh = window.innerHeight; if (CONFIG.render_mode === 'contain') { // 缩放以完整显示,不足处留黑边 const scale = Math.min(vw / refW, vh / refH); canvas.style.width = (refW * scale) + 'px'; canvas.style.height = (refH * scale) + 'px'; } // ... 其他模式 } ``` ## 可绑定的遥测字段 | data-bind | 字段 | 类型 | 说明 | |-----------|------|------|------| | `speed_kmh` | speed_kmh | float | 速度 (km/h) | | `speed_mph` | speed_mph | float | 速度 (mph) | | `rpm` | rpm | float | 发动机转速 | | `max_rpm` | max_rpm | float | 最大转速 | | `gear` | gear | int | 档位 (0=N, -1=R, 1~8) | | `throttle` | throttle | float | 油门 (0~1) | | `brake` | brake | float | 刹车 (0~1) | | `clutch` | clutch | float | 离合 (0~1) | | `steering` | steering | float | 转向 (-1~1) | | `lap_time` | lap_time | float | 当前圈速 (秒) | | `best_lap` | best_lap | float | 最佳圈速 (秒) | | `last_lap` | last_lap | float | 上圈时间 (秒) | | `lap_number` | lap_number | int | 圈数 | | `fuel` | fuel | float | 燃油量 | | `boost` | boost | float | 涡轮增压 | | `horsepower` | horsepower | float | 马力 | | `torque` | torque | float | 扭矩 | | `engine_temp` | engine_temp | float | 发动机温度 | | `oil_temp` | oil_temp | float | 油温 | 特殊自定义属性: | 属性 | 说明 | |------|------| | `data-bind-rpm` | CSS 变量 `--rpm` / `--rpm-pct` / `--rpm-max` | | `data-bind-speed` | CSS 变量 `--speed` | | `data-bind-gear` | CSS 变量 `--gear` | ## 快速模板 ```html TurboSu - My Dashboard
0
KM/H
``` ## 打包分发 将整个文件夹压缩为 zip,改后缀为 `.tsd`,即可在 TurboSu 仪表盘页面导入或在社区分享。 ```bash zip -r my_dashboard.tsd my_dashboard/ ```