zbanks / flux

Middlelayer for controlling lux devices & more: "jackd for lights"
MIT License
5 stars 3 forks source link

flux

Join the chat at https://gitter.im/zbanks/flux

Middlelayer for controlling lux devices & more: "jackd for lights".

Model

Project Goals

Flux is intended to connect user interfaces for running visual displays to the physical hardware that controls the lights and other effects.It needs to be low-latency (millisecond) while carrying enough bandwidth for raw (low-resolution) video data.

You should use flux if you're building one (or both!) of the following:

The intent is to add some interoperability between the two layers.

Design

Flux uses a three-part model: the broker, clients, and servers.

These processes communicate using nanomsg (usually TCP sockets), so they can exist on separate machines. Fundamentally, the client is agnostic to which devices are connected to which servers.

Messages

Flux API

Client-server communications follows the request-reply model: servers cannot initiate contact with clients. Each client message results in exactly one message from a server, or no response (error).

Client messages to the server (requests) consist of a destination, command, body, and body_size.

Server messages to the client (replies) only consist of a char * reply and its corresponding length.

Usage

The Flux C API exposes methods for handling messages under this request-reply model:

Client

On the client side, the primary method flux_cli_send synchronously sends a message and waits for a reply (or timeout/error).

int flux_cli_send(flux_cli_t * client, const flux_id_t destination, const flux_cmd_t command, const char * body, size_t body_size, char ** reply)

reply should be a reference to a NULL pointer that will be populated with the response, which you then need to destroy after use.

The return value is -1 on failure (timeout, destination does not exist, "500" response from server, etc.). If the function is successful, the reply is stored in the *reply variable and the length of the reply is returned.

Server

On the server side, each flux_dev_t (which corresponds to a device) has a request function with the following type (flux_request_fn_t):

int request(void * args, const lux_cmd_t command, char * body, size_t body_size, char ** reply)

When the server receives a message for a given device, this method is called. args is populated from flux_dev_t and can be used to pass device-specific information.

Ownership here is weird: request does not own body, but it owns whatever it populates reply with. (This is considered a bug and will likely be refactored)

To indicate success, populate reply with a new (possibly empty) pointer and return the length of the reply. (The calling context will destory body after sending *reply, which allows you to implement echo without copy: *reply = body; return body_size;)

To indicate failure, return -1. You can optionally populate reply if you want to send additional information about the error to the client (e.g. an error message).

Common Commands

The following commands should be implemented for all devices on the server.

Example Usage

(In general, these can start in any order.)

flux-server

./flux-server is a lux bridge.

It looks for a serial port in the form /dev/ttyUSBx. Before running ./flux-server, you need to run python setup_serial.py to configure the serial port with the correct settings (setting the speed to 3 megabaud, which I can't figure out how to do from C correctly). You may also need to sudo chown $USER /dev/ttyUSB*.

It takes in an optional command line argument, a dummy ID (i.e. -d "dummy:0"). If this argument is passed in, then the server will create a mock device that will respond to ECHO PING and INFO commands but will be otherwise uninteresting.

Due to hardware issues (unreliable receive), the server can operate in write-only mode by passing in the -r flag. In this mode, no data is read over the lux bus, and frames are sent blindly to all configured addresses.

flux-client

flux-client is an example client which sends some ECHO and INFO commands to available devices for debugging.

Building

Flux is based on nanomsg. You can compile it from source as follows:

git clone git@github.com:nanomsg/nanomsg.git
cd nanomsg
./autogen.sh
./configure
make
make check
sudo make install

You can also installing it from your package manager. On Ubuntu:

sudo apt-get install libnanomsg-dev

Once you have nanomsg, you can build flux:

git clone git@github.com:zbanks/flux.git
cd flux
make
sudo make install