echonet 1.3.2

ECHONET Lite framework for Rust
Documentation
# Copilot Instructions

## Project Overview

**uecho-rs** (published as crate `echonet`) is a Rust framework for the [ECHONET Lite](https://echonet.jp/english/) IoT protocol, used by home appliances in Japan. It supports both **controller** nodes (discover/control devices) and **device** nodes (implement IoT devices), plus an encoder/decoder and a standard device database built from the Machine Readable Appendix (MRA).

## Build, Test, and Lint

```bash
make build        # cargo fmt + cargo build
make test         # cargo fmt + cargo build + cargo test -- --test-threads=1
make format       # cargo fmt
make doc          # cargo doc --open
```

**Tests must run single-threaded** — always pass `--test-threads=1`:

```bash
# Run full test suite
cargo test -- --test-threads=1

# Run a single test by name
cargo test <test_name> -- --test-threads=1

# Run a specific integration test file
cargo test --test node_test -- --test-threads=1

# Run a unit test in a specific module
cargo test --lib transport::manager_test -- --test-threads=1
```

Run CLI tools:

```bash
cargo run --bin uechosearch -v
cargo run --bin uechopost -v
cargo run --example monolight -v
```

## Architecture

The crate is organized into three layers:

1. **Domain layer** (`src/`) — `Node`, `Object`, `Property`, `RemoteNode`, `Device`, `Controller`. A `Node` contains `Object`s, each with `Property` values. A `Device` wraps a `Node` for server-side use; a `Controller` wraps a `Node` for client-side discovery and control.

2. **Protocol layer** (`src/protocol/`) — `Message` (ECHONET packet), `ESV` (18 service code enum: `WriteRequest`, `ReadRequest`, `Notification`, etc.), and protocol-level `Property`.

3. **Transport layer** (`src/transport/`) — UDP multicast/unicast managers, socket abstractions, and the `Observer` notification system.

The `StandardDatabase` is a singleton (accessed via `StandardDatabase::shared()`) that holds MRA object/property definitions and manufacturer codes generated from `src/std/`.

Public API surface is defined in `src/lib.rs` via `pub use` re-exports.

**Platform features** (selected in `Cargo.toml`):
- `unix` (default) — uses `pnet`, `nix`, `net2`
- `win` — Windows support
- `esp` — ESP32 / no_std support

## Key Conventions

### Concurrency
Shared state uses `Arc<Mutex<T>>`. Constructors like `Node::new()` return `Arc<Mutex<Node>>`. Locks are taken with `.lock().unwrap()`. Inter-thread communication uses `mpsc` channels.

### Test placement
- Unit tests live in colocated `*_test.rs` files (e.g., `src/transport/manager_test.rs`), not inside the implementation file.
- Integration tests live in `tests/` and share utilities via `tests/test.rs`.

### Public traits
Two extension points:
- `RequestHandler` — implement to handle property read/write/notify requests on a `Device`:
  ```rust
  fn property_request_received(&mut self, deoj: &mut Object, esv: ESV, prop: &Property) -> bool
  ```
- `Observer` — implement to receive raw `Message` events from a node.

### Type aliases
| Alias | Underlying | Notes |
|---|---|---|
| `ObjectCode` | `u32` | 3-byte group/class/instance |
| `PropertyCode` | `u8` | 0x80–0xFF |
| `PropertyData` | `Vec<u8>` | Big-endian binary |
| `ManufactureCode` | `u16` | |

### ESV enum
`ESV` uses `strum_macros` for iteration. Use `ESV::from_u8()` to decode, `.is_request()` / `.is_response()` for classification.

### Byte encoding
Use `util::Bytes::from_u32()` / `Bytes::to_u32()` for big-endian property data encoding — do not hand-roll byte manipulation.

### Builder pattern
Setters return `&mut Self` for method chaining (e.g., `object.set_code(0x05FD).set_name("light")`).

### Commit style
Short, imperative commit messages. One logical change per commit. Run `make test` before pushing.