- Rust 92.2%
- Nix 7.8%
| bin/ecd | ||
| crates | ||
| docs | ||
| examples | ||
| nix/modules | ||
| .gitignore | ||
| Cargo.lock | ||
| Cargo.toml | ||
| flake.lock | ||
| flake.nix | ||
| README.md | ||
| 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 = 8080
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).
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) |
GET / |
the web GUI (when expose.gui = true) |
All routes are mounted under the device's expose.http.base.
Documentation
- docs/manifest.md — the manifest schema, backings, and WoT mapping
- docs/architecture.md — crate layout and data flow
- docs/devices/kiosk.md — the
kioskdevice class - docs/devices/camera.md — the
cameradevice class
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 advertisement
bin/ecd the daemon
nix/modules NixOS modules: ecd, kiosk, camera
examples example manifests
Status
v0 is HTTP-only, uses SSE for property observation and events, and a
single device-wide security scheme. Implemented backings: exec, file,
http, const, journal. See
docs/architecture.md for the current state of each crate.