buzzard is a small Rust tool for discovering devices on a local network and talking to selected home/lab devices through a few protocol-specific drivers.
Right now the repo covers three main jobs:
- scan a LAN and keep a local device state file,
- address known devices by name and query/control them through driver backends.
- expose the same device controls through a small built-in web UI.
buzzard can:
- scan a subnet with ICMP and MAC lookup,
- map scanned MAC addresses to friendly names from
inventory.yaml, - persist discovered devices in
_state.yaml, - talk to supported devices by logical name instead of hard-coded IPs,
- serve an HTMX-based web UI for status and control.
Currently implemented device families:
tuya / me82for thermostats,tuya / atorchfor the ATORCH power meter,midea / acfor Midea AC units,openbeken / smart_plugfor OpenBeken-based plugs/switches,dahua / camerafor Dahua snapshots.
src/cliCLI command handling forscan,devices, andweb.src/networkICMP scanning, MAC lookup, vendor lookup.src/inventoryYAML inventory loading.src/state.rs_state.yamlloading/saving.src/devicesDriver-specific device integrations.src/webBuilt-in HTMX web UI.
Two local YAML files are important:
inventory.yamlYour private inventory/config file. It is gitignored._state.yamlLast known scan results. It is gitignored.
The scan flow is:
- probe the subnet,
- discover IP and MAC,
- match MAC against
inventory.yaml, - update
_state.yaml.
_state.yaml is meant to preserve last-known devices, even if a device disappears from a later scan.
Minimal unmanaged device:
devices:
- name: device-1
mac: "aa:bb:cc:dd:ee:ff"Tuya thermostat:
devices:
- name: thermostat-1
mac: "aa:bb:cc:dd:ee:01"
driver: tuya
device_type: me82
tuya:
id: "..."
local_key: "..."
version: "3.4"Midea AC:
devices:
- name: ac-1
mac: "aa:bb:cc:dd:ee:02"
driver: midea
device_type: ac
midea:
id: "..."
token: "..."
key: "..."
port: 6444OpenBeken smart plug:
devices:
- name: plug-1
mac: "aa:bb:cc:dd:ee:03"
driver: openbeken
device_type: smart_plugDahua camera:
devices:
- name: camera-1
mac: "aa:bb:cc:dd:ee:04"
driver: dahua
device_type: camera
dahua:
nvh_host: "https://nvr-host.local"
channel: 5
username: "admin"
password: "..."Build:
cargo buildRun a scan:
target/debug/buzzard scanRun a scan with verbose diagnostics:
target/debug/buzzard scan --debugControl/query devices by name:
target/debug/buzzard devices thermostat-1 status
target/debug/buzzard devices thermostat-1 on
target/debug/buzzard devices thermostat-1 off
target/debug/buzzard devices thermostat-1 set temp 21
target/debug/buzzard devices ac-1 status
target/debug/buzzard devices ac-1 on
target/debug/buzzard devices ac-1 off
target/debug/buzzard devices ac-1 set temp 21
target/debug/buzzard devices ac-1 set fan silent
target/debug/buzzard devices ac-1 set swing horizontal
target/debug/buzzard devices meter-1 status
target/debug/buzzard devices meter-1 on
target/debug/buzzard devices meter-1 off
target/debug/buzzard devices plug-1 status
target/debug/buzzard devices plug-1 on
target/debug/buzzard devices plug-1 off
target/debug/buzzard devices camera-1 status
target/debug/buzzard devices camera-1 snapshotWildcard device selection is supported:
target/debug/buzzard devices "thermostat-*" status
target/debug/buzzard devices "thermostat-*" set temp 20Run the web UI:
target/debug/buzzard webDefault bind:
0.0.0.0:8666
devices status output depends on device type:
- thermostats are shown in a thermostat-oriented table,
- AC units are shown in an AC-oriented table,
- ATORCH is shown as a power/energy meter table,
- OpenBeken smart plugs are shown as a plug/power telemetry table,
- cameras are shown as snapshot URLs in CLI and images in the web UI.
Not every driver supports every command. For example:
me82supportsstatus,on,off,set temp,debug,midea/acsupportsstatus,on,off,set temp,set fan,set swing,atorchsupportsstatus,on,off,debug,openbeken/smart_plugsupportsstatus,on,off,dahua/camerasupportsstatusandsnapshot.
- Rust toolchain,
- local network access,
- permissions to use raw ICMP for scanning.
In practice scan usually needs elevated privileges:
sudo target/debug/buzzard scanOn Linux, you can usually avoid sudo by giving the built binary CAP_NET_RAW:
sudo setcap cap_net_raw+ep target/debug/buzzard
getcap target/debug/buzzardThere is a short note about this in scripts/README.md, together with the musl cross-build helper.
Device control commands usually do not need raw-socket privileges, but they do need the target device to be reachable on the LAN.
This is a personal/home-lab style tool, not a polished general-purpose product.
The repo is optimized for:
- local inventory-driven naming,
- practical device control,
- fast iteration over protocols used in one network.