DE
dewiweb/emberplus_rust
rust implementation of ember+ client(consumer) and server(provider)
Ember+ Rust Implementation
A complete Rust implementation of Lawo's Ember+ control protocol.
Ember+ is a control protocol used in broadcast and professional audio/video equipment, providing a tree-based data structure for parameters, nodes, functions, and matrices.
Features
-
Complete Protocol Support
- S101 framing protocol (transport layer)
- ASN.1 BER encoding/decoding
- Glow DTD (Ember+ schema)
-
Client (Consumer)
- Connect to Ember+ providers
- Browse tree structure
- Read/write parameter values
- Subscribe to changes
- Invoke functions
- Matrix operations
-
Server (Provider)
- Host an Ember+ tree
- Handle client connections
- Callbacks for value changes
- Function invocation handlers
- Matrix operation handlers
-
Async/Await
- Built on Tokio for efficient async I/O
- Non-blocking operations
Installation
Add to your Cargo.toml:
[dependencies]
ember-plus = "0.1"
tokio = { version = "1", features = ["full"] }Quick Start
Client Example
use ember_plus::{EmberClient, EmberValue, Result};
#[tokio::main]
async fn main() -> Result<()> {
// Connect to a provider
let client = EmberClient::connect("192.168.1.100:9000").await?;
// Get the root directory
let root = client.get_directory().await?;
// Get element by path
let node = client.get_element_by_path("0.1.2").await?;
// Set a parameter value
client.set_value("0.1.2", EmberValue::Integer(42)).await?;
// Subscribe to changes
client.subscribe("0.1").await?;
// Register callback for updates
client.on_value_change(Box::new(|path, value| {
println!("Value changed: {:?} = {}", path, value);
})).await;
// Invoke a function
let result = client.invoke("0.2.1", vec![
EmberValue::Integer(1),
EmberValue::String("test".into()),
]).await?;
client.disconnect().await?;
Ok(())
}Server Example
use std::sync::Arc;
use ember_plus::{EmberServer, EmberValue, InvocationResult, Result};
use ember_plus::tree::TreeNode;
#[tokio::main]
async fn main() -> Result<()> {
let mut server = EmberServer::bind("0.0.0.0:9000").await?;
// Build your tree
let mut root = TreeNode::new_node(0);
// ... add children, parameters, etc.
server.init(root).await;
// Handle setValue operations
server.set_value_handler(Arc::new(|path, value| {
println!("setValue: {:?} = {}", path, value);
Ok(true) // Accept the change
}));
// Handle function invocations
server.invoke_handler(Arc::new(|path, id, args| {
Ok(InvocationResult::success(id, vec![]))
}));
server.run().await?;
Ok(())
}CLI Tool
The crate includes a CLI tool for testing:
# Connect to a provider
cargo run -- client 192.168.1.100:9000
# Start a test server
cargo run -- server 9000Examples
See the examples/ directory for more detailed examples:
# Run the client example
cargo run --example client -- localhost:9000
# Run the server example
cargo run --example server -- 9000Module Structure
ber- ASN.1 BER encoding/decodings101- S101 framing protocolglow- Glow DTD types and tagstree- Runtime tree data structurescodec- High-level Glow encoding/decodingclient- Ember+ client (consumer)server- Ember+ server (provider)
Protocol Compatibility
This implementation aims to be compatible with:
- Lawo's official Ember+ SDK
- sofie-emberplus-connection
- Other compliant Ember+ implementations
Tested with:
- Lawo Ruby
- Lawo R3lay
- Lawo MxGUI
License
Licensed under either of:
- Apache License, Version 2.0 (LICENSE-APACHE)
- MIT License (LICENSE-MIT)
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.