Files
TurboSu/docs/IRACING_DATA_FORMAT.md
T

753 lines
22 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.
# 📡 iRacing Telemetry APIIRSDK)完整规范
## 一、概述
iRacing 的遥测系统通过 **共享内存映射文件(Memory-Mapped File** 工作,所有数据是**只读**的。API 版本当前为 **IRSDK_VER = 2**
### 三种数据通道
| 通道 | 形式 | 频率 | 说明 |
|---|---|---|---|
| **Live Telemetry** | 共享内存 `Local\IRSDKMemMapFileName` | 60Hz(或 360Hz) | 实时变量数据,三缓冲机制 |
| **Session String** | 共享内存中的 YAML 字符串 | 变更时更新 | 会话元数据(赛道、车手、天气等) |
| **Disk Telemetry (.ibt)** | 二进制文件 | 60Hz | 按 `Alt+L` 录制,结构等同于 Live 数据 |
### 启用遥测
在 iRacing 的 `app.ini` 中确认:
```ini
[External Telemetry]
enableTelemetry=1 # 启用遥测
enableIRSDKTelemetry=1 # 启用 IRSDK
```
---
## 二、核心架构
### 共享内存布局
```
[irsdk_header]
[irsdk_varHeader[0] ... irsdk_varHeader[numVars-1]]
[Session Info YAML String]
[irsdk_varBuf[0]] → [Telemetry Data Line 0]
[irsdk_varBuf[1]] → [Telemetry Data Line 1]
[irsdk_varBuf[2]] → [Telemetry Data Line 2]
[irsdk_varBuf[3]] → [Telemetry Data Line 3] (IRSDK_MAX_BUFS = 4)
```
- **三缓冲**:模拟器写满一个缓冲区后立即切到下一个,给客户端 16ms+ 窗口来读取
- **同步事件**`Local\IRSDKDataValidEvent` — 新数据就绪时触发
### 字节序与编码
- **字节序**Little Endian
- **YAML 编码**UTF-8
- **对齐**16 字节对齐
- **变量名最大长**`IRSDK_MAX_STRING = 32`
- **描述最大长**`IRSDK_MAX_DESC = 64`
---
## 三、数据结构
### 1. irsdk_header(主头部)
```c
struct irsdk_header {
int ver; // API 版本 = 2
int status; // 位字段 (irsdk_stConnected = 1)
int tickRate; // tick 频率 (60 或 360)
// 会话信息(变更时更新)
int sessionInfoUpdate; // 会话信息变更计数
int sessionInfoLen; // YAML 字符串长度(字节)
int sessionInfoOffset; // 距头部的偏移
// 遥测变量
int numVars; // 变量数量
int varHeaderOffset; // varHeader 数组偏移
int numBuf; // 缓冲区数量(4
int bufLen; // 每行字节数
int pad1[2]; // 16 字节对齐
irsdk_varBuf varBuf[IRSDK_MAX_BUFS]; // 4 个缓冲区
};
```
### 2. irsdk_varHeader(变量描述头)
```c
struct irsdk_varHeader {
int type; // irsdk_VarType 枚举
int offset; // 在缓冲区行中的偏移
int count; // 数组元素数(标量 = 1
bool countAsTime;
char pad[3]; // 16 字节对齐
char name[IRSDK_MAX_STRING]; // 变量名,如 "Speed"
char desc[IRSDK_MAX_DESC]; // 描述,如 "GPS vehicle speed"
char unit[IRSDK_MAX_STRING]; // 单位,如 "m/s"
};
```
### 3. irsdk_varBuf(数据缓冲区)
```c
struct irsdk_varBuf {
int tickCount; // 检测数据更新
int bufOffset; // 距头部的偏移
int pad[2]; // 16 字节对齐
};
```
### 4. irsdk_VarType(变量类型)
| 枚举值 | 类型 | 字节数 |
|---|---|---|
| `irsdk_char = 0` | char | 1 |
| `irsdk_bool` | bool | 1 |
| `irsdk_int` | int32 | 4 |
| `irsdk_bitField` | bitfield (int32) | 4 |
| `irsdk_float` | float32 | 4 |
| `irsdk_double` | float64 | 8 |
### 5. irsdk_diskSubHeader(仅 .ibt 文件)
```c
struct irsdk_diskSubHeader {
time_t sessionStartDate;
double sessionStartTime;
double sessionEndTime;
int sessionLapCount;
int sessionRecordCount;
};
```
---
## 四、Session StringYAML 结构)
YAML 字符串通过 `irsdk_getSessionInfoStr()` 获取,包含以下顶级节点:
### WeekendInfo
```yaml
WeekendInfo:
TrackName: "suzuka"
TrackID: 123
TrackLength: "5807 m"
TrackDisplayName: "Suzuka International Racing Course"
TrackCity: "Suzuka"
TrackCountry: "JPN"
TrackNumTurns: 18
TrackPitSpeedLimit: "80 kph"
TrackType: "road"
TrackWeatherType: "Dynamic"
TrackSkies: "Partly Cloudy"
TrackSurfaceTemp: "38 C"
TrackAirTemp: "25 C"
TrackWindVel: "3 m/s"
TrackWindDir: "180 deg"
TrackRelativeHumidity: "55 %"
TrackFogLevel: "0 %"
SeriesID: 100
SeasonID: 2024
SessionID: 456
SubSessionID: 789
LeagueID: 0
Official: 1
RaceWeek: 5
EventType: "Race"
Category: "Road"
SimMode: "full"
TeamRacing: 0
MinDrivers: 6
MaxDrivers: 26
NumCarClasses: 1
NumCarTypes: 3
WeekendOptions:
NumStarters: 20
StartingGrid: "2x2"
QualifyScoring: "single"
CourseCautions: "full"
StandingStart: 0
Restarts: "singleFile"
WeatherType: "Dynamic"
Skies: "Partly Cloudy"
WindDirection: "180 deg"
WindSpeed: "3 m/s"
WeatherTemp: "25 C"
RelativeHumidity: "55 %"
FogLevel: "0 %"
Unofficial: 0
IsFixedSetup: 0
HardcoreLevel: 1
```
### SessionInfo
```yaml
SessionInfo:
Sessions:
- SessionNum: 0
SessionLaps: "unlimited"
SessionTime: "30 min"
SessionType: "Practice"
ResultsPositions: []
ResultsFastestLap: []
- SessionNum: 1
SessionLaps: "2 laps"
SessionTime: "10 min"
SessionType: "Lone Qualify"
- SessionNum: 2
SessionLaps: "12 laps"
SessionTime: "30 min"
SessionType: "Race"
```
### DriverInfo
```yaml
DriverInfo:
DriverCarIdx: 0
DriverCarIdleRPM: 3500.0
DriverCarRedLine: 9500.0
DriverCarSLFirstRPM: 8500.0
DriverCarSLShiftRPM: 9000.0
DriverCarSLLastRPM: 9500.0
DriverCarSLBlinkRPM: 9200.0
Drivers:
- CarIdx: 0
UserName: "John Doe"
AbbrevName: "J. Doe"
Initials: "JD"
CarNumber: "23"
CarPath: "mercedesamggt3"
CarClassID: 1
IRating: 2500
LicString: "A 4.99"
IsSpectator: 0
```
### CameraInfo
```yaml
CameraInfo:
Groups:
- GroupNum: 1
GroupName: "TV1"
Cameras:
- CameraNum: 1
CameraName: "TV1_Turn1"
```
### SplitTimeInfo
```yaml
SplitTimeInfo:
Sectors:
- SectorNum: 0
SectorStartPct: 0.0
- SectorNum: 1
SectorStartPct: 0.35
- SectorNum: 2
SectorStartPct: 0.70
```
---
## 五、核心遥测变量列表(完整)
### 🏎️ 玩家车辆控制
| 变量名 | 类型 | 单位 | 说明 |
|---|---|---|---|
| `SteeringWheelAngle` | float | rad | 方向盘转角 |
| `Throttle` | float | % (0-1) | 油门(处理后的) |
| `Brake` | float | % (0-1) | 刹车(处理后的) |
| `Clutch` | float | % (0-1) | 离合 |
| `Gear` | int | — | -1=R0=N1~n=前进档 |
| `RPM` | float | revs/min | 引擎转速 |
| `ThrottleRaw` | float | % (0-1) | 原始油门输入 |
| `BrakeRaw` | float | % (0-1) | 原始刹车输入 |
| `HandbrakeRaw` | float | % (0-1) | 原始手刹输入 |
| `Speed` | float | m/s | GPS 车速 |
| `OnPitRoad` | bool | — | 是否在维修区通道 |
### 📐 位置与运动
| 变量名 | 类型 | 单位 | 说明 |
|---|---|---|---|
| `Yaw` | float | rad | 偏航角 |
| `YawNorth` | float | rad | 相对北方的偏航角 |
| `Pitch` | float | rad | 俯仰角 |
| `Roll` | float | rad | 侧倾角 |
| `YawRate` / `YawRate_ST` | float | rad/s | 偏航率(ST=子tick精度) |
| `PitchRate` / `PitchRate_ST` | float | rad/s | 俯仰率 |
| `RollRate` / `RollRate_ST` | float | rad/s | 侧倾率 |
| `VelocityX` / `VelocityX_ST` | float | m/s | X 方向速度 |
| `VelocityY` / `VelocityY_ST` | float | m/s | Y 方向速度 |
| `VelocityZ` / `VelocityZ_ST` | float | m/s | Z 方向速度 |
| `LatAccel` / `LatAccel_ST` | float | m/s² | 横向加速度 |
| `LongAccel` / `LongAccel_ST` | float | m/s² | 纵向加速度 |
| `VertAccel` / `VertAccel_ST` | float | m/s² | 垂向加速度 |
> `_ST` 后缀变量提供 **子 tick 精度**,适合运动平台等精密场景。
### ⏱️ 圈速与计时
| 变量名 | 类型 | 单位 | 说明 |
|---|---|---|---|
| `Lap` | int | — | 当前圈号 |
| `LapCompleted` | int | — | 已完成圈数 |
| `LapDist` | float | m | 当前圈已跑距离 |
| `LapDistPct` | float | % | 当前圈完成百分比 |
| `RaceLaps` | int | — | 比赛中已完成圈数 |
| `LapBestLap` | int | — | 最佳圈号 |
| `LapBestLapTime` | float | s | 最佳圈速 |
| `LapLastLapTime` | float | s | 上一圈用时 |
| `LapCurrentLapTime` | float | s | 当前圈用时(F3 黑盒) |
| `LapBestNLapLap` | int | — | 最佳 N 圈均值的最后一圈 |
| `LapBestNLapTime` | float | s | 最佳 N 圈平均时间 |
| `LapLastNLapTime` | float | s | 最近 N 圈平均时间 |
| `LapLasNLapSeq` | int | — | 连续干净圈数 |
### 🎯 Delta 时间
| 变量名 | 类型 | 单位 | 说明 |
|---|---|---|---|
| `LapDeltaToBestLap` | float | s | 与个人最佳圈的差距 |
| `LapDeltaToBestLap_DD` | float | s/s | 差距变化率 |
| `LapDeltaToBestLap_OK` | bool | — | delta 数据是否有效 |
| `LapDeltaToOptimalLap` | float | s | 与理论最佳圈的差距 |
| `LapDeltaToOptimalLap_DD` | float | s/s | 差距变化率 |
| `LapDeltaToOptimalLap_OK` | bool | — | 是否有效 |
| `LapDeltaToSessionBestLap` | float | s | 与全场最佳圈差距 |
| `LapDeltaToSessionBestLap_DD` | float | s/s | 差距变化率 |
| `LapDeltaToSessionBestLap_OK` | bool | — | 是否有效 |
| `LapDeltaToSessionOptimalLap` | float | s | 与全场理论最佳差距 |
| `LapDeltaToSessionLastlLap` | float | s | 与全场上一圈差距 |
### ⛽ 引擎 & 燃油
| 变量名 | 类型 | 单位 | 说明 |
|---|---|---|---|
| `FuelLevel` | float | L | 剩余油量(升) |
| `FuelLevelPct` | float | % | 剩余油量百分比 |
| `FuelPress` | float | bar | 燃油压力 |
| `FuelUsePerHour` | float | kg/h | 瞬时油耗率 |
| `ManifoldPress` | float | bar | 进气歧管压力 |
| `OilLevel` | float | L | 机油液位 |
| `OilPress` | float | bar | 机油压力 |
| `OilTemp` | float | °C | 机油温度 |
| `WaterLevel` | float | L | 冷却液液位 |
| `WaterTemp` | float | °C | 冷却液温度 |
| `Voltage` | float | V | 电压 |
| `EngineWarnings` | bitfield | — | 引擎警告灯(见下文) |
| `BrakeABSactive` | bool | — | ABS 是否激活 |
### 🛞 轮胎数据(每轮 LF/RF/LR/RR
`X` ∈ {LF, RF, LR, RR}
| 变量名 | 类型 | 单位 | 说明 |
|---|---|---|---|
| `XcoldPressure` | float | kPa | 冷胎压 |
| `Xpressure` | float | kPa | 当前胎压 |
| `XtempCL/M/R` | float | °C | 胎面左/中/右温度 |
| `XwearL/M/R` | float | % | 胎面左/中/右磨损 |
| `XbrakeLinePress` | float | bar | 刹车管压力 |
| `XshockDefl` | float | mm | 悬挂压缩量 |
| `XshockVel` | float | mm/s | 悬挂速度 |
| `XrideHeight` | float | mm | 行驶高度 |
| `Xspeed` | float | rad/s | 轮速 |
### 🎛️ 力反馈
| 变量名 | 类型 | 单位 | 说明 |
|---|---|---|---|
| `SteeringWheelTorque` | float | N·m | 转向轴输出扭矩 |
| `SteeringWheelTorque_ST` | float | N·m | 转向轴扭矩(子tick |
| `SteeringWheelPctTorque` | float | % | FFB 扭矩百分比(无符号) |
| `SteeringWheelPctTorqueSign` | float | % | FFB 扭矩百分比(有符号) |
| `SteeringWheelPctTorqueSignStops` | float | % | FFB 扭矩百分比(含止挡) |
| `SteeringWheelPctDamper` | float | % | FFB 阻尼百分比 |
| `SteeringWheelAngleMax` | float | rad | 方向盘最大转角 |
| `SteeringWheelPeakForceNm` | float | N·m | FFB 峰值力映射 |
| `SteeringWheelMaxForceNm` | float | N·m | 最大力 |
| `SteeringWheelUseLinear` | bool | — | 是否线性模式 |
### 🏁 会话状态
| 变量名 | 类型 | 单位 | 说明 |
|---|---|---|---|
| `SessionTime` | double | s | 当前会话已过时间 |
| `SessionTimeRemain` | double | s | 会话剩余时间 |
| `SessionTimeTotal` | double | s | 会话总时间 |
| `SessionLapsRemain` | int | — | 剩余圈数 |
| `SessionLapsRemainEx` | int | — | 扩展剩余圈数 |
| `SessionLapsTotal` | int | — | 总圈数 |
| `SessionNum` | int | — | 会话序号 |
| `SessionState` | int | — | 会话状态(见枚举) |
| `SessionUniqueID` | int | — | 会话唯一 ID |
| `SessionFlags` | bitfield | — | 旗语(见下文) |
| `SessionTick` | int | — | Tick 计数 |
| `SessionTimeOfDay` | float | s | 赛道时间 |
### 🚩 旗语 & 状态
**SessionFlags** 位字段:
| 位标记 | 含义 |
|---|---|
| `0x00000001` | 🏁 方格旗 |
| `0x00000002` | ⬜ 白旗 |
| `0x00000004` | 🟩 绿旗 |
| `0x00000008` | 🟨 黄旗 |
| `0x00000010` | 🟥 红旗 |
| `0x00000020` | 🟦 蓝旗 |
| `0x00000040` | 💥 碎片 |
| `0x00000100` | 🟨 黄旗挥动 |
| `0x00000200` | 绿旗前最后一圈 |
| `0x00004000` | ⚠️ Full Course Caution |
| `0x00010000` | ⬛ 黑旗 |
| `0x00020000` | ❌ DSQ |
| `0x10000000` | 🔴 发车灯隐藏 |
| `0x20000000` | 🔴 发车灯就绪 |
| `0x40000000` | 🔴 发车灯 Set |
| `0x80000000` | 🟢 发车灯 Go |
**EngineWarnings** 位字段:
| 位标记 | 含义 |
|---|---|
| `0x0001` | 水温警告 |
| `0x0002` | 燃油压力警告 |
| `0x0004` | 机油压力警告 |
| `0x0008` | 引擎熄火 |
| `0x0010` | Pit Speed Limiter |
| `0x0020` | 转速限制器激活 |
| `0x0040` | 油温警告 |
### 🚗 多车数据(CarIdx 数组,最多 64 辆车)
| 变量名 | 类型 | 说明 |
|---|---|---|
| `CarIdxLap` | int[] | 每辆车的圈数 |
| `CarIdxLapCompleted` | int[] | 每辆车已完成圈数 |
| `CarIdxLapDistPct` | float[] | 每辆车的位置百分比 |
| `CarIdxPosition` | int[] | 每辆车的排名 |
| `CarIdxClassPosition` | int[] | 组别排名 |
| `CarIdxClass` | int[] | 组别 ID |
| `CarIdxF2Time` | float[] | 与领先者的差距(或最快圈速) |
| `CarIdxEstTime` | float[] | 预计到达当前位置的时间 |
| `CarIdxLastLapTime` | float[] | 上一圈时间 |
| `CarIdxBestLapTime` | float[] | 最佳圈时间 |
| `CarIdxBestLapNum` | int[] | 最佳圈号 |
| `CarIdxSteer` | float[] | 方向盘转角 |
| `CarIdxRPM` | float[] | 引擎转速 |
| `CarIdxGear` | int[] | 档位 |
| `CarIdxOnPitRoad` | bool[] | 是否在维修区 |
| `CarIdxTrackSurface` | int[] | 赛道位置类型 |
| `CarIdxTrackSurfaceMaterial` | int[] | 路面材质 |
| `CarIdxTireCompound` | int[] | 轮胎配方 |
| `CarIdxP2P_Status` | bool[] | Push-to-Pass 状态 |
| `CarIdxP2P_Count` | int[] | Push-to-Pass 剩余次数 |
### 🛑 进站 & 维修
| 变量名 | 类型 | 单位 | 说明 |
|---|---|---|---|
| `PitsOpen` | bool | — | 维修区是否开放 |
| `PitstopActive` | bool | — | 正在进站 |
| `PitRepairLeft` | float | s | 强制维修剩余时间 |
| `PitOptRepairLeft` | float | s | 可选维修剩余时间 |
| `PitSvFlags` | bitfield | — | 进站服务勾选 |
| `PitSvLFP/RFP/LRP/RRP` | float | kPa | 指定胎压 |
| `PitSvFuel` | float | L | 指定加油量 |
| `PitSvTireCompound` | int | — | 指定轮胎配方 |
| `FastRepairUsed` | int | — | 已用快速维修次数 |
| `FastRepairAvailable` | int | — | 可用快速维修次数 |
| `PlayerCarInPitStall` | bool | — | 玩家在维修位 |
| `PlayerCarPitSvStatus` | int | — | 进站服务状态 |
**PitSvFlags** 位字段:
| 位标记 | 含义 |
|---|---|
| `0x0001` | 左前换胎 |
| `0x0002` | 右前换胎 |
| `0x0004` | 左后换胎 |
| `0x0008` | 右后换胎 |
| `0x0010` | 加油 |
| `0x0020` | 撕膜 |
| `0x0040` | 快速维修 |
### 🌦️ 天气 & 环境
| 变量名 | 类型 | 单位 | 说明 |
|---|---|---|---|
| `TrackTemp` | float | °C | 赛道温度(起终点) |
| `TrackTempCrew` | float | °C | 赛道温度(Pit 区) |
| `TrackWetness` | float | — | 赛道湿度级别 |
| `AirTemp` | float | °C | 空气温度 |
| `AirDensity` | float | kg/m³ | 空气密度 |
| `AirPressure` | float | Hg | 气压 |
| `WindVel` | float | m/s | 风速 |
| `WindDir` | float | rad | 风向 |
| `RelativeHumidity` | float | % | 相对湿度 |
| `FogLevel` | float | % | 雾级别 |
| `WeatherType` | int | — | 0=恒定,1=动态 |
| `Skies` | int | — | 0=晴,1=少云,2=多云,3=阴 |
### 🎥 回放 & 系统
| 变量名 | 类型 | 说明 |
|---|---|---|
| `IsReplayPlaying` | bool | 是否回放中 |
| `ReplayFrameNum` | int | 回放当前帧号 |
| `ReplayFrameNumEnd` | int | 回放末尾帧号 |
| `ReplayPlaySpeed` | int | 回放速度 |
| `ReplayPlaySlowMotion` | bool | 是否慢动作 |
| `ReplaySessionTime` | double | 回放中的会话时间 |
| `ReplaySessionNum` | int | 回放会话序号 |
| `IsOnTrack` | bool | 玩家是否在赛道上 |
| `IsInGarage` | bool | 是否在车库 |
| `IsDiskLoggingEnabled` | bool | 磁盘遥测是否开启 |
| `IsDiskLoggingActive` | bool | 是否正在录制 .ibt |
### 👥 车手变更(Team Racing
| 变量名 | 类型 | 说明 |
|---|---|---|
| `DCLapStatus` | int | Driver Change 圈数状态 |
| `DCDriversSoFar` | int | 已驾驶过的车手数 |
### 📷 摄像机
| 变量名 | 类型 | 说明 |
|---|---|---|
| `CamCarIdx` | int | 当前焦点车辆索引 |
| `CamCameraNumber` | int | 当前摄像机编号 |
| `CamGroupNumber` | int | 当前摄像机组编号 |
| `CamCameraState` | bitfield | 摄像机状态位字段 |
---
## 六、重要枚举汇总
### SessionState
| 值 | 状态 |
|---|---|
| 0 | StateInvalid |
| 1 | StateGetInCar(上车中) |
| 2 | StateWarmup(暖胎圈) |
| 3 | StateParadeLaps(编队圈) |
| 4 | **StateRacing**(正赛中) |
| 5 | StateCheckered(方格旗) |
| 6 | StateCoolDown(冷却圈) |
### TrkLoc(赛道位置)
| 值 | 含义 |
|---|---|
| -1 | NotInWorld |
| 0 | OffTrack |
| 1 | InPitStall(维修区) |
| 2 | AproachingPits |
| 3 | OnTrack |
### TrkSurf(路面材质)
| 值 | 材质 |
|---|---|
| 0 | Undefined |
| 1-4 | Asphalt |
| 5-6 | Concrete |
| 7-8 | Racing Dirt |
| 9-10 | Paint |
| 11-14 | Rumble Strip(路肩) |
| 15-18 | Grass |
| 19-22 | Dirt |
| 23 | Sand |
| 24-25 | Gravel |
| 26 | Grasscrete |
| 27 | Astroturf |
### TrackWetness(赛道湿度)
| 值 | 级别 |
|---|---|
| 0 | Unknown |
| 1 | Dry |
| 2 | Mostly Dry |
| 3 | Very Lightly Wet |
| 4 | Lightly Wet |
| 5 | Moderately Wet |
| 6 | Very Wet |
| 7 | Extremely Wet |
### PaceMode
| 值 | 模式 |
|---|---|
| 0 | Single File Start |
| 1 | Double File Start |
| 2 | Single File Restart |
| 3 | Double File Restart |
| 4 | Not Pacing |
### CarLeftRight
| 值 | 含义 |
|---|---|
| 0 | Off |
| 1 | Clear(两侧无车) |
| 2 | Car Left |
| 3 | Car Right |
| 4 | Cars on Both Sides |
| 5 | 2 Cars Left |
| 6 | 2 Cars Right |
---
## 七、SDK 客户端 API(C 语言接口)
```c
// 初始化 / 关闭
bool irsdk_startup();
void irsdk_shutdown();
// 连接检测
bool irsdk_isConnected();
// 获取头部
const irsdk_header* irsdk_getHeader();
// 等待新数据并复制到本地缓冲区(推荐方式)
bool irsdk_waitForDataReady(int timeOut, char *data);
// 获取会话 YAML 字符串
const char* irsdk_getSessionInfoStr();
int irsdk_getSessionInfoStrUpdate(); // 检测会话信息更新
// 获取变量头
const irsdk_varHeader* irsdk_getVarHeaderPtr();
const irsdk_varHeader* irsdk_getVarHeaderEntry(int index);
// 按名称查找变量
int irsdk_varNameToIndex(const char *name);
int irsdk_varNameToOffset(const char *name);
// 获取指定缓冲区的数据
const char* irsdk_getData(int index);
```
---
## 八、Broadcast Messages(远程控制)
通过 Windows 消息 `IRSDK_BROADCASTMSG` 发送控制命令:
### 摄像机控制
```c
// 切换摄像机:按位置
irsdk_broadcastMsg(irsdk_BroadcastCamSwitchPos, carPosition, group, camera);
// 切换摄像机:按车号
irsdk_broadcastMsg(irsdk_BroadcastCamSwitchNum, driverNum, group, camera);
// 设置摄像机状态
irsdk_broadcastMsg(irsdk_BroadcastCamSetState, irsdk_CameraState, 0, 0);
```
### 回放控制
```c
// 设置播放速度
irsdk_broadcastMsg(irsdk_BroadcastReplaySetPlaySpeed, speed, slowMotion, 0);
// 跳转位置
irsdk_broadcastMsg(irskd_BroadcastReplaySetPlayPosition,
irsdk_RpyPos_Begin, frameHigh, frameLow);
// 搜索事件
irsdk_broadcastMsg(irsdk_BroadcastReplaySearch,
irsdk_RpySrch_NextLap, 0, 0);
// 搜索会话时间
irsdk_broadcastMsg(irsdk_BroadcastReplaySearchSessionTime,
sessionNum, sessionTimeMS_high, sessionTimeMS_low);
```
### 进站控制
```c
// 清空所有勾选
irsdk_broadcastMsg(irsdk_BroadcastPitCommand, irsdk_PitCommand_Clear, 0);
// 加油(0 = 使用默认值)
irsdk_broadcastMsg(irsdk_BroadcastPitCommand, irsdk_PitCommand_Fuel, addLiters);
// 换左前胎(指定胎压 kPa,0 = 默认)
irsdk_broadcastMsg(irsdk_BroadcastPitCommand, irsdk_PitCommand_LF, pressureKpa);
// 换胎配方
irsdk_broadcastMsg(irsdk_BroadcastPitCommand, irsdk_PitCommand_TC, compound);
// 快速维修
irsdk_broadcastMsg(irsdk_BroadcastPitCommand, irsdk_PitCommand_FR, 0);
```
### 遥测录制控制
```c
irsdk_broadcastMsg(irsdk_BroadcastTelemCommand, irsdk_TelemCommand_Start, 0, 0);
irsdk_broadcastMsg(irsdk_BroadcastTelemCommand, irsdk_TelemCommand_Stop, 0, 0);
irsdk_broadcastMsg(irsdk_BroadcastTelemCommand, irsdk_TelemCommand_Restart, 0, 0);
```
### 聊天宏
```c
irsdk_broadcastMsg(irsdk_BroadcastChatComand, irsdk_ChatCommand_Macro, macroNum, 0);
```
---
## 九、与 F1 24 / ACC 的对比
| 特性 | iRacing | F1 24 | ACC |
|---|---|---|---|
| **协议** | 共享内存 | UDP | UDP + 共享内存 |
| **更新频率** | 60Hz(可 360Hz | 最高 60Hz | 物理步进 |
| **多车数据** | ✅ CarIdx 数组(≤64 辆车) | ✅ 22 辆车 | ✅ Broadcasting |
| **回放数据** | ✅ .ibt 文件 | ❌ | ❌ |
| **远程控制** | ✅ Broadcast Msg | ❌ | ✅ Camera/Focus |
| **写入支持** | ✅ 进站/摄像机/遥测 | ❌ | ✅ Camera/HUD |
| **变量动态性** | 每车/每会话不同 | 固定结构 | 固定结构 |
| **子 Tick 精度** | ✅ `_ST` 后缀变量 | ❌ | ❌ |
| **运动平台** | ✅ 完整扭矩/加速度 | ✅ Motion Ex | ✅ Shared Memory |
---
## 十、关键注意事项
1. **变量动态性**:iRacing 的变量列表不是固定的—不同车辆/会话中可能不同,必须先读取 `varHeader` 来确定可用的变量和偏移量
2. **只读**:所有遥测数据只读,不能通过 SDK 修改车辆参数(只能通过 Broadcast Message 控制进站选项)
3. **三缓冲**:务必在 `irsdk_waitForDataReady()` 返回后立即拷贝数据,不要直接引用共享内存
4. **Session Info 更新**:通过 `sessionInfoUpdate` 计数器检测 YAML 字符串是否变化
5. **.ibt 兼容**:磁盘遥测文件结构与 Live 相同,可用相同代码解析(多了 `irsdk_diskSubHeader`
6. **启动时序**:先调用 `irsdk_startup()` → 等待 `irsdk_isConnected()` → 等待 `SessionState >= StateRacing`
7. **360Hz 模式**:部分车辆支持 360Hz 遥测,检查 `tickRate` 字段