# pitwall-tauri
Tauri integration for [Pitwall](../README.md) - stream iRacing telemetry to TypeScript frontends with compile-time type safety.
## Features
- **Type-Safe IPC**: Automatic TypeScript type generation from Rust structs
- **High Performance**: <1% CPU overhead for 60Hz telemetry streaming
- **Stateless Design**: Pure stream mirroring with no state management
- **Simple API**: One function (`to_channel`) handles all streaming
## Installation
```toml
# src-tauri/Cargo.toml
[dependencies]
pitwall = { version = "0.1", features = ["derive"] }
pitwall-tauri = "0.1"
tauri = "2"
tauri-specta = { version = "2.0.0-rc", features = ["typescript"] }
specta = { version = "2.0.0-rc", features = ["derive"] }
serde = { version = "1", features = ["derive"] }
tokio = { version = "1", features = ["full"] }
```
## Quick Start
### 1. Define Your Frame Type
```rust
use pitwall::PitwallFrame;
use serde::{Serialize, Deserialize};
use specta::Type;
#[derive(Debug, Clone, Serialize, Deserialize, Type, PitwallFrame)]
pub struct MyTelemetry {
#[pitwall(name = "Speed")]
pub speed: f32,
#[pitwall(name = "RPM")]
pub rpm: f32,
}
```
### 2. Create Tauri Command
```rust
use tauri::ipc::Channel;
use pitwall_tauri::{Pitwall, SessionInfo, to_channel};
#[tauri::command]
#[specta::specta]
pub async fn start_telemetry(
telemetry: Channel<MyTelemetry>,
session: Channel<SessionInfo>,
) -> Result<(), String> {
let conn = Pitwall::connect().await.map_err(|e| e.to_string())?;
// Stream telemetry frames (60Hz)
tokio::spawn(to_channel(
conn.subscribe::<MyTelemetry>(UpdateRate::Native),
telemetry
));
// Stream session updates
tokio::spawn(to_channel(
conn.session_updates(),
session
));
Ok(())
}
```
### 3. Generate TypeScript Bindings
```rust
// src-tauri/src/main.rs
#[cfg(debug_assertions)]
{
tauri_specta::ts::export(
specta::collect_types![start_telemetry],
"../src/bindings.ts"
).expect("Failed to export bindings");
}
```
### 4. Use in TypeScript
```typescript
import { invoke, Channel } from '@tauri-apps/api/core';
import type { MyTelemetry, SessionInfo } from './bindings';
const telemetryChannel = new Channel<MyTelemetry>();
telemetryChannel.onmessage = (data) => {
console.log(`Speed: ${data.speed}, RPM: ${data.rpm}`);
};
const sessionChannel = new Channel<SessionInfo>();
sessionChannel.onmessage = (info) => {
console.log(`Track: ${info.weekend_info.track_display_name}`);
};
await invoke('start_telemetry', {
telemetry: telemetryChannel,
session: sessionChannel,
});
```
## License
Licensed under the [MIT License](LICENSE).