brainwires-hardware 0.7.0

Hardware I/O for the Brainwires Agent Framework — audio, GPIO, Bluetooth, and network
Documentation
# brainwires-hardware

Hardware I/O for the [Brainwires Agent Framework](https://github.com/Brainwires/brainwires-framework).

Provides a unified hardware abstraction layer covering audio, GPIO, Bluetooth, and network hardware — all behind opt-in feature flags so you only compile what you need.

## Modules

| Module | Feature | Description |
|--------|---------|-------------|
| `audio` | `audio` | Audio capture/playback, STT, TTS (16 cloud providers + local Whisper) |
| `audio/vad` | *(always)* / `vad` | Voice activity detection — `EnergyVad` (always) + `WebRtcVad` (`vad`) |
| `audio/wake_word` | `wake-word` | Wake word detection — `EnergyTriggerDetector` + optional ML backends |
| `audio/assistant` | `voice-assistant` | End-to-end voice assistant pipeline |
| `gpio` | `gpio` | GPIO pin management with safety allow-lists and PWM (Linux) |
| `bluetooth` | `bluetooth` | BLE advertisement scanning and adapter enumeration |
| `network` | `network` | NIC enumeration, IP config, ARP host discovery, port scanning |
| `camera` | `camera` | Webcam/camera frame capture (V4L2/AVFoundation/MSMF) |
| `usb` | `usb` | Raw USB device enumeration and transfers (no libusb) |

## Getting started

```toml
[dependencies]
# Pick only what you need:
brainwires-hardware = { version = "0.7", features = ["audio"] }
brainwires-hardware = { version = "0.7", features = ["gpio"] }
brainwires-hardware = { version = "0.7", features = ["bluetooth"] }
brainwires-hardware = { version = "0.7", features = ["network"] }

# Or enable everything:
brainwires-hardware = { version = "0.7", features = ["full"] }
```

## Feature flags

| Feature | Description |
|---------|-------------|
| `audio` | Hardware audio I/O via CPAL + 16 cloud STT/TTS providers |
| `flac` | FLAC encode/decode |
| `local-stt` | Local Whisper STT inference via whisper-rs (heavy dep, opt-in) |
| `vad` | WebRTC VAD algorithm (`EnergyVad` is always available with `audio`) |
| `wake-word` | Wake word detection — `EnergyTriggerDetector` (zero deps) |
| `wake-word-rustpotter` | `RustpotterDetector` — pure-Rust ML wake word (opt-in, see notes) |
| `wake-word-porcupine` | `PorcupineDetector` — Picovoice Porcupine (requires AccessKey + git dep) |
| `voice-assistant` | Full pipeline: capture → wake word → VAD → STT → handler → TTS |
| `gpio` | GPIO pin control via Linux character device API (`gpio-cdev`) |
| `bluetooth` | BLE scanning and adapter enumeration via `btleplug` |
| `network` | NIC enumeration, IP config, ARP discovery, port scanning |
| `camera` | Webcam/camera capture via nokhwa (V4L2/AVFoundation/MSMF) |
| `usb` | Raw USB device access and transfers via nusb (no libusb) |
| `full` | All features (except `local-stt`, `wake-word-rustpotter`, `wake-word-porcupine`) |

## Audio

Supports hardware capture and playback via [CPAL](https://crates.io/crates/cpal), plus cloud STT/TTS integrations:

**STT:** OpenAI, Azure, Deepgram, ElevenLabs, Fish Audio
**TTS:** OpenAI, Azure, Deepgram, ElevenLabs, Fish Audio, Google, Murf, Cartesia

```rust
use brainwires_hardware::{TextToSpeech, TtsOptions, OutputFormat};

let tts = OpenAiTts::new(api_key);
let audio = tts.synthesize("Hello, world!", &TtsOptions::default()).await?;
```

## GPIO (Linux)

Safe GPIO access with explicit allow-lists — no pin can be used unless it appears in the configured policy.

```rust
use brainwires_hardware::{GpioPinManager, GpioSafetyPolicy};
use brainwires_hardware::gpio::device::GpioDirection;

let mut manager = GpioPinManager::from_config(&config);
let pin = manager.acquire(0, 17, GpioDirection::Output, "my-agent")?;
```

## Bluetooth

Cross-platform BLE scanning using [btleplug](https://crates.io/crates/btleplug):

```rust
use brainwires_hardware::bluetooth;
use std::time::Duration;

let devices = bluetooth::scan_ble(Duration::from_secs(5)).await;
for d in &devices {
    println!("{} — {:?}", d.address, d.name);
}
```

## Network

```rust
use brainwires_hardware::network;
use std::time::Duration;

// List interfaces
for iface in network::list_interfaces() {
    println!("{} ({:?})", iface.name, iface.kind);
}

// IP config with gateways
for cfg in network::get_ip_configs() {
    println!("{}: gateway={:?}", cfg.interface, cfg.gateway);
}

// Port scan
let results = network::scan_common_ports(
    "192.168.1.1".parse().unwrap(),
    Duration::from_millis(500),
).await;

// ARP host discovery (requires CAP_NET_RAW)
let hosts = network::arp_scan("192.168.1.0/24".parse().unwrap()).await;
```

## Voice Activity Detection

`EnergyVad` is always available (no extra feature needed beyond `audio`). `WebRtcVad` requires the `vad` feature.

```rust
use brainwires_hardware::{EnergyVad, VoiceActivityDetector};

let vad = EnergyVad::default(); // -40 dBFS threshold
if vad.is_speech(&audio_buffer) {
    println!("Speech detected!");
}
```

## Wake Word Detection

```rust
use brainwires_hardware::{EnergyTriggerDetector, WakeWordDetector};

let mut detector = EnergyTriggerDetector::new(-20.0, 3, 16_000);
// Feed 30 ms i16 frames from the mic:
if let Some(detection) = detector.process_frame(&frame) {
    println!("Wake trigger! score={:.2}", detection.score);
}
```

## Voice Assistant Pipeline

```rust
use brainwires_hardware::{VoiceAssistant, VoiceAssistantHandler, VoiceAssistantConfig};
use brainwires_hardware::audio::types::Transcript;
use async_trait::async_trait;

struct MyHandler;

#[async_trait]
impl VoiceAssistantHandler for MyHandler {
    async fn on_speech(&self, transcript: &Transcript) -> Option<String> {
        println!("You said: {}", transcript.text);
        Some("I heard you!".to_string())
    }
}

// Build and run
let mut assistant = VoiceAssistant::builder(capture, stt)
    .with_playback(playback)
    .with_tts(tts)
    .with_wake_word(Box::new(EnergyTriggerDetector::default()))
    .build();

assistant.run(&MyHandler).await?;
```

## Migration from brainwires-audio

```toml
# Before
brainwires-audio = "0.7"

# After
brainwires-hardware = { version = "0.7", features = ["audio"] }
```

All public types and traits are re-exported from the crate root — existing code using
`brainwires_audio::*` can switch to `brainwires_hardware::*` with no further changes.

## Examples

```bash
cargo run -p brainwires-hardware --example text_to_speech --features audio
cargo run -p brainwires-hardware --example bluetooth_scan --features bluetooth
cargo run -p brainwires-hardware --example network_interfaces --features network
cargo run -p brainwires-hardware --example port_scan --features network -- 192.168.1.1
sudo cargo run -p brainwires-hardware --example host_discovery --features network -- 192.168.1.0/24

# Wake word demo (prints detections from mic)
cargo run -p brainwires-hardware --example wake_word_demo --features wake-word

# Full voice assistant demo (requires OPENAI_API_KEY)
cargo run -p brainwires-hardware --example voice_assistant --features voice-assistant

# Standalone voice assistant binary
cargo run -p voice-assistant -- --list-devices
cargo run -p voice-assistant -- --verbose
```