# super_cereal

Serial port proxy over [RustDDS](https://github.com/Atostek/RustDDS). Expose a UART on one machine and use it as a local virtual serial device on another over the LAN.

Install the `super_cereal` system binary from [crates.io](https://crates.io/crates/super_cereal):

```bash
cargo install super_cereal
```

## Requirements

- macOS or Linux
- Two machines on the **same LAN segment** (RustDDS multicast discovery)
- Rust toolchain (edition 2021) — only needed to build from source

Docker-on-Mac and Tailscale are not supported in v1 because RustDDS discovery relies on multicast. A unicast transport is planned for a future release.

## Install

From crates.io (recommended):

```bash
cargo install super_cereal
```

From source:

```bash
git clone https://github.com/victoryforphil/super_cereal.git
cd super_cereal
cargo install --path .
```

The installed binary is `~/.cargo/bin/super_cereal`.

## Usage

### Serve (machine with the physical serial device)

```bash
super_cereal serve --port /dev/ttyACM0 --baud 115200 --channel dev1
```

Reads from the UART and publishes bytes on DDS topic `super_cereal/dev1/up`. Writes client bytes from `super_cereal/dev1/down` back to the port.

### Attach (consumer machine)

```bash
super_cereal attach --channel dev1 --link /tmp/ttyVIRT0
```

Creates a PTY and symlinks it to `/tmp/ttyVIRT0`. Open that path with minicom, pyserial, or any tool that expects a serial device.

### List discovered channels

```bash
super_cereal list
super_cereal list --wait 5
```

Waits for DDS discovery (default 3 seconds), then prints channel names seen on the LAN.

## Two-machine validation

1. **Machine A** (device attached):

   ```bash
   super_cereal serve --port /dev/ttyACM0 --baud 115200 --channel dev1
   ```

2. **Machine B**:

   ```bash
   super_cereal attach --channel dev1 --link /tmp/ttyVIRT0
   ```

3. On machine B, open the virtual port:

   ```bash
   minicom -D /tmp/ttyVIRT0 -b 115200
   ```

   Or with Python:

   ```python
   import serial
   ser = serial.Serial("/tmp/ttyVIRT0", 115200)
   ser.write(b"hello\n")
   print(ser.read(64))
   ```

4. Confirm bidirectional traffic matches the real device on machine A. An MCU echo firmware or a TX–RX loopback jumper makes this easy to verify.

## Logging

Set `RUST_LOG` to control verbosity:

```bash
RUST_LOG=debug super_cereal serve --port /dev/ttyACM0 --channel dev1
```

## Background service templates

Shipped in the repository under `contrib/`:

- Linux: `contrib/systemd/super_cereal@.service`
- macOS: `contrib/launchd/com.vfp.super_cereal.plist`

Edit the port, baud, and channel before installing.

## Architecture

```
/dev/ttyACM0  <-->  serve  --DDS-->  attach  <-->  /tmp/ttyVIRT0 (PTY symlink)  <-->  your app
```

Topics per channel:

- `super_cereal/<channel>/up` — device → client
- `super_cereal/<channel>/down` — client → device

## Limitations (v1)

- Multicast LAN only; no Docker Desktop or Tailscale without phase-2 unicast support
- PTY baud/termios changes are not forwarded to the remote UART
- One attach client per channel is the expected use case

## License

GPL-3.0-or-later. See [LICENSE](LICENSE).
