ALPINE is a modern, secure, vendor-agnostic lighting control protocol built for deterministic streaming, signed control envelopes, and constrained deployments. This directory is the protocol layer; SDKs, CLI, and the embedded runtime live beside it in the workspace.
| Layer | Purpose | Location |
|---|---|---|
| Protocol | Low-level, stable CBOR helpers that map the wire format to Rust/TypeScript/C/Python/C++. Publish these independently so embedded or constrained builds can link without the SDK. | protocol/ |
| SDKs | High-level, ergonomic clients that orchestrate discovery → connect → stream workflows and enforce stream profiles. These depend only on the published protocol public APIs. | ../sdk/ |
| Embedded runtime | Hook-based embedded runtime and adapters. | ../embedded-runtime/ |
| CLI | Operational tooling built on the SDK. | ../cli/ |
- Rust:
rust/alpine-protocol-rsis the protocol crate. It exports wire types, crypto helpers, stream profile validation, and stateless codecs. The crate is intentionally GUI, I/O, and runtime agnostic so futures and embedded platforms can reuse the primitives. - TypeScript:
tscompiles to@alpine-core/protocoland mirrors the Rust types (CBOR helpers, control envelopes, stream builders). Use it when you need the raw format on Node, Deno, or browser platforms that can’t run the SDK. - Python:
pythonexposes the same helpers via a minimal package (alnp). It stays free of sockets or async concerns so it can be imported inside constrained environments. - C/C++:
candcpp/alnp.hppprovide the C API plus an embedded-friendlyALPINE_EMBEDDEDguard. These headers/libraries are produced byscripts/build_c.sh.
- Create
sdk::DiscoveryClient. It is stateless, explicit, and observable: you choose when to calldiscover(), you inspect every reply, and no sessions are created until you callAlpineClient::connect. - Call
DiscoveryClient::discover()and inspect the returnedDiscoveredDeviceentries for identity, capability set, socket address, and whether replies were signed. - Choose a
StreamProfile(Auto / Realtime / Install) and callsdk::AlpineClient::connect. - Once connected, call
start_stream(profile)and send frames; the client enforces profile guarantees and keeps a single steady stream once it starts.
We treat this workspace as two independent release axes:
- Protocol release (
vX.Y.Z) — coversprotocol/*, including the Rust crate, TypeScript protocol helpers, Python helpers, and C/C++ artifacts. - SDK release (
sdk-vA.B.C) — publishessdk/rust(and other SDKs in the future) on its own version schedule.
To keep releases boring:
- The
protocol-publishworkflow runs on everyv*tag, builds the protocol layer, runs the tests, packages the artifacts, and publishes to crates.io/npm/PyPI/GitHub Packages. (It also validates the embedded C++ build viascripts/build_embedded_cpp.sh.) - The
sdk-publishworkflow runs afterprotocol-publishsucceeds. It builds the SDK crate, ensures it compiles against the freshly published protocol artifacts, and publishes the SDK with its own version.
Before tagging:
- Run
cargo test --manifest-path rust/alpine-protocol-rs/Cargo.toml. - Run
../scripts/build_c.sh. - Run
../scripts/build_embedded_cpp.sh. - Run
../scripts/build_ts.shand../scripts/build_python.shfor the newprotocol/packages. - Run
cargo test --manifest-path ../sdk/rust/Cargo.toml.
roadmap.mddocs/release_process.mddocs/architecture.mddocs/documentation_policy.mddocs/discovery.mdSPEC.mddocs/status.md
For a high-level, system-agnostic comparison of DMX-over-IP approaches (Art-Net, sACN) and how ALPINE differs architecturally, see: https://www.y-link.no/guides/art-net-vs-sacn-vs-alpine
UDP E2E Tests(../.github/workflows/e2e-tests.yml) validates the protocol’s UDP control/streaming paths.embedded(../.github/workflows/embedded.yml) validates the embedded C++ flags via../scripts/build_embedded_cpp.sh.protocol-publishandsdk-publishensure release artifacts are reproducible.
Apache-2.0