- Rust 65.7%
- Nix 34.3%
| bin | ||
| crates | ||
| docs | ||
| examples | ||
| nix | ||
| .gitignore | ||
| Cargo.lock | ||
| Cargo.toml | ||
| flake.lock | ||
| flake.nix | ||
| README.md | ||
| renovate.json | ||
| rust-toolchain.toml | ||
💠 edgecore
A lean, declarative agent that turns a physical device into a discoverable,
composable capability surface — speaking W3C Web of Things.
edgecore is a framework for special devices and a control daemon, ecd,
that exposes a device's capabilities and values. You describe a device once, in a
single declarative TOML manifest; ecd then:
- generates a conformant WoT Thing Description (TD 1.1),
- serves a WoT HTTP API plus a small built-in web GUI,
- routes each interaction to its backing (a command, file, HTTP endpoint, …),
- announces the device on the LAN over DNS-SD/mDNS (
_wot._tcp).
Any WoT consumer can drive the device with zero edgecore-specific knowledge.
edgecore is a subproject of git.hydrar.de/jmarya/myverse.
Quick start
With Nix (flakes enabled):
nix develop # dev shell with the pinned Rust toolchain
nix build .#ecd # build the daemon
nix flake check # build + clippy + rustfmt + tests
Run the daemon against a manifest:
ecd path/to/device.toml # serve the device
ecd --check device.toml # validate the manifest and exit
ecd --td device.toml # print the generated Thing Description
One process can host several Things (a WoT Servient) — pass multiple manifests
or a directory of them. They share one port; each keeps its own base path, and
GET /things lists every hosted Thing Description:
ecd things.d/ # every *.toml in the directory
ecd lobby-01.toml door-02.toml # or an explicit list
Then visit http://<host>:<port><base> for the GUI, or fetch the TD at
<base>/.well-known/wot.
A minimal manifest
[device]
id = "urn:edgecore:kiosk:lobby-01"
title = "Lobby Kiosk"
class = "kiosk"
[property.brightness]
type = "integer"
unit = "percent"
minimum = 0
maximum = 100
source = { exec = "backlight-get" }
sink = { exec = "backlight-set {value}" }
[action.reload]
run = { exec = "kiosk-reload {hard}" }
[action.reload.input.properties.hard]
type = "boolean"
[expose]
bind = ["http"]
gui = true
[expose.http]
port = 9688
base = "/things/lobby-01"
[expose.discovery]
mdns = true
See the examples/ directory for full manifests:
lobby-01.toml (kiosk),
camera-01.toml (camera),
env-sensor-01.toml (sensor),
light-01.toml (smart light),
speaker-01.toml (speaker).
See docs/manifest.md for the complete schema.
HTTP surface
| Route | WoT operation |
|---|---|
GET /.well-known/wot |
fetch the Thing Description |
GET /properties/{name} |
read a property (SSE observe with Accept: text/event-stream) |
PUT /properties/{name} |
write a property |
POST /actions/{name} |
invoke an action (JSON body → backing) |
GET /events/{name} |
subscribe to an event (SSE) |
ANY /stream/{*rest} |
authenticated reverse proxy to a local media server (when [stream] is set) |
GET / |
the web GUI (when expose.gui = true) |
All routes are mounted under the device's expose.http.base, and are served over
HTTPS when [expose.http.tls] is set.
Documentation
- docs/manifest.md — the manifest schema, backings, and WoT mapping
- docs/architecture.md — crate layout, data flow, NixOS modules, and capability system
- docs/devices/camera.md — the
cameraarchetype - docs/devices/kiosk.md — the
kioskarchetype - docs/devices/smart-light.md — the
smart-lightarchetype - docs/devices/env-sensor.md — the
env-sensorarchetype - docs/devices/presence-detector.md — the
presence-detectorarchetype - docs/devices/speaker.md — the
speakerarchetype - docs/devices/access-controller.md — the
access-controllerarchetype
Repository layout
crates/manifest manifest types · parse · validate
crates/td Thing Description model · generation
crates/backing the Backing trait + exec/file/http/const/journal
crates/server axum WoT HTTP surface + web GUI + auth
crates/discovery mDNS / DNS-SD advertise + browse
bin/ecd the daemon
bin/edgectl fleet CLI/TUI: discover and drive Things
nix/modules NixOS modules: ecd, kiosk, camera
examples example manifests
edgectl — the fleet client
edgectl discovers Things on the LAN over mDNS and drives them by a short
handle — multi-Thing from the start, no per-command endpoint juggling.
edgectl discover # browse _wot._tcp → list the whole fleet
edgectl get webcam resolution # read a property (Thing addressed by handle)
edgectl set lobby brightness 70 # write a property
edgectl invoke webcam snapshot '{"output_dir":"/tmp"}'
edgectl watch door state # live SSE stream
edgectl tui # interactive fleet browser
Add --url <servient> to include hosts not on mDNS, --token/$ECD_TOKEN for
auth (applied per each Thing's advertised scheme), and -k to accept the
self-signed certs edge devices serve.
Status
v0 speaks HTTP(S) (optional TLS with an operator or persisted self-signed
cert — no ACME), uses SSE for property observation and events, and a single
device-wide security scheme that also gates an optional authenticated media
reverse proxy ([stream]). Implemented backings: exec, file, http,
const, journal. See docs/architecture.md for the
current state of each crate.