zeevonk 0.1.2

A new lighting control system server, that serves as a hub for lighting communication, processing and interaction.
Documentation
# Zeevonk

A modular lighting control system for modern DMX-based lighting setups.

> ⚠️ **Warning**
>
> Zeevonk is currently in early development. APIs, features, and behavior may change frequently and without notice.
> It is **not yet recommended for production use**.

## What is Zeevonk?

Zeevonk is a modular system for controlling lighting fixtures. It consists of a server and two types of clients:

- **Server**: Manages clients, processes triggers and attribute updates, and sends DMX data.
- **Processor Client**: Calculates and sends fixture attribute values (like color, position, intensity) to the server.
- **Controller Client**: Sends triggers (such as button presses or fader moves) to the server.

## Some notable controllers:
- [**zv-ctrl-bmdse**]https://github.com/BaukeWestendorp/zv-ctrl-bmdse: A Black Magic Design Speed Editor controller client based on [bmdse]https://crates.io/crates/bmdse.

## Run the Zeevonk server

You can install zeevonk as a binary (called `zv`) using the following command:

```sh
cargo install --path crates/cli
```

## Use as a library

### Features

The crate has three main features you can enable:

`server`: Start and configure the server from your own code instead of the CLI.

`client-processor`: Use the processor client.

`client-controller`: Use the controller client.

### Example: Starting the Server

```rust
use zeevonk::server::Server;
use zeevonk::project::definition::ProjectDefinition;

// Create a project definition.
let project_def = ProjectDefinition::default();

// Create and start the server.
let server = Server::new(project_def).unwrap();
server.start();
```

### Example: Processor Client

```rust
use zeevonk::attr::Attribute;
use zeevonk::client::processor::Client;
use zeevonk::ident::Identifier;
use zeevonk::project::patch::{FixtureId, FixtureIdPart};
use zeevonk::value::AttributeValues;

#[tokio::main]
async fn main() {
    let mut client = Client::new(Identifier::new("zv-example-processor").unwrap());
    client.on_trigger(|from_client, trigger| eprintln!("{from_client}: {trigger:?}"));
    client.connect("ws://127.0.0.1:7334").await.unwrap();

    let fid = FixtureId::new(FixtureIdPart::new(101).unwrap());

    let mut values = AttributeValues::new();
    
    // Set attribute values for your fixtures here...
    values.set(fid, Attribute::Dimmer, 1.0);
    
    client.update_attributes(values, false).await.unwrap();

    loop {}
}

```

### Example: Controller Client

```rust
use zeevonk::client::controller::Client;
use zeevonk::ident::Identifier;
use zeevonk::trigger::{Trigger, TriggerValue};

#[tokio::main]
async fn main() {
    pretty_env_logger::init();

    let mut client = Client::new(Identifier::new("zv-example-controller").unwrap());
    client.connect("ws://127.0.0.1:7335").await.unwrap();

    loop {
        client
            .send_trigger(Trigger::new(
                Identifier::new("button-1").unwrap(),
                TriggerValue::Boolean(true),
            ))
            .await
            .unwrap();

        std::thread::sleep(std::time::Duration::from_secs_f32(1.0 / 10.0));
    }
}
```

For more details, see the documentation for each module in the crate.