# Haply (Rust client for the Haply Inverse Service)
Haply is a Rust client library for connecting to and controlling Haply Robotics devices via the Haply Inverse Service. It provides:
- A high-level device API (`HaplyDevice`) that talks HTTP and WebSocket
- An event channel client for real‑time device/events stream
- Strongly-typed data models shared with the TypeScript schema
- Simple physics utilities (e.g., virtual objects, force computation) for demos
This README gives you a quick tour of the architecture, setup, and examples.
## Architecture overview
- `src/device.rs` — High-level API. `HaplyDevice` manages:
- HTTP client (`interfaces::http::InverseHttpClient`) for device lists and version
- WebSocket client (`interfaces::websocket::InverseWebSocketClient`) for state and commands
- An internal, timestamped state cache (`TimestampedServiceData`)
- Command batching and sending (`ServiceMsg`, always includes a session-level `force_render_full_state` marker)
- `src/interfaces/` — Transport adapters
- `http.rs` — REST endpoints (e.g., GET /version, GET /3.1/devices)
- `websocket.rs` — Real-time simulation/control channel
- `events.rs` — Optional event channel client for device/session events
- `src/device_model/` — All request/response types used over HTTP/WS (device configs, states, commands, enums)
- `src/physics.rs` — Minimal physics helpers (e.g., `Sphere`, `Cube`, `compute_total_force`) used by demos
Companion mock service for local development:
- `haply-service-mock/` (separate crate inside this repo)
- HTTP API: `http://localhost:10000`
- Simulation WS: `ws://localhost:10001`
- Events WS: `ws://localhost:10020`
- Emulates an Inverse3 device and a Wireless VerseGrip device
## Getting started
Prerequisites:
- Rust (stable) with Cargo
Install dependencies (Cargo will handle this on first build):
1. Start the mock service (optional, for local testing)
```powershell
cd .\haply-service-mock
cargo run
```
2. In a separate terminal, run examples from the repo root
```powershell
cd ..
cargo run --example device_basics -- --http-only
```
Tip: enable logs for examples that rely on `env_logger` (e.g., `haptic_sample`):
```powershell
$env:RUST_LOG = 'info'
```
## Usage (quick snippet)
```rust
use haply::HaplyDevice;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
// Defaults for the mock service
let http_base = "http://localhost:10000";
let ws_url = "ws://localhost:10001";
let mut device = HaplyDevice::new(http_base, ws_url).await?;
// List device configs via HTTP
let configs = device.list_devices().await?;
println!("Configs: {:?}", configs);
// Read the latest cached state
let state = device.read_state().await?;
println!("State: {:?}", state);
Ok(())
}
```
## Examples
Examples live in the `examples/` folder. Run any of them with:
```powershell
cargo run --example <example_name>
```
Available examples and what they show:
- `device_basics` — Multi-purpose starter. Use `--http-only` for REST discovery, `--stream` to print device IDs, `--zero-force` to keep zero forces applied, and optionally `--probe <ID>` to issue probe commands.
- `events_demo` — Connects to the Events WS and polls new events (set `POLL_RATE` env var to control interval).
- `haptic_sample` — Demonstrates a haptics loop that reads device state and applies forces derived from virtual objects.
If you’re not using real hardware, start the mock service first (see Getting started).
## Mock service details (optional)
The mock service emulates device configuration and real‑time data:
- HTTP: `GET /version`, `GET /3.1/devices`, `GET /3.1/devices/:id`
- WS (simulation): emits initial full state and subsequent updates; accepts command payloads (e.g., `set_cursor_force`)
- WS (events): emits device connect/disconnect events
Start it with:
```powershell
cd .\haply-service-mock
cargo run
```
Then point your app/examples to:
- `http://localhost:10000`
- `ws://localhost:10001` (simulation/state/control)
- `ws://localhost:10020` (events)
## Project layout
```text
src/
device.rs # HaplyDevice high-level API
interfaces/ # HTTP, WebSocket, and Events clients
device_model/ # Wire types shared with the service
physics.rs # Minimal physics helpers for demos
haply-service-mock/ # Local mock service (HTTP+WS)
examples/ # Example apps demonstrating common flows
```
## Troubleshooting
- Ensure the mock service (or a real Haply Inverse Service) is reachable at the configured URLs
- If examples don’t print anything, set logging: `$env:RUST_LOG = 'info'`
- Firewall issues on Windows can block WS ports; allow 10000/10001/10020
## License
Dual-licensed under MIT or Apache-2.0 — see `Cargo.toml` for details.
## Changelog
See `CHANGELOG.md`.