Permalink
737feac Nov 13, 2013
1 contributor

Users who have contributed to this file

191 lines (144 sloc) 6.95 KB

Fadecandy: WebSocket Protocol

The Fadecandy Server (fcserver) operates as a bridge between LED controllers attached over USB, and visual effects that communicate via a TCP socket.

The primary protocol supported by fcserver is Open Pixel Control, a super simple way to send RGB values over a socket. But in addition to OPC, fcserver also supports WebSockets to allow clients to be written in Javascript.

Connecting

To connect to fcserver, create a WebSocket. By default, fcserver listens on port 7890.

You can try this out in the Javascript Console in your web browser:

> ws = new WebSocket("ws://localhost:7890")
WebSocket {binaryType: "blob", extensions: "", protocol: "", onclose: null, onerror: null…}

In a real application, you'll also want to handle events like onopen() and onclose(). Take a look at the full WebSockets API if you haven't seen it yet.

Open Pixel Control Packets

Any binary packets sent over this socket are treated as Open Pixel Control packets. Since the WebSocket protocol includes its own length field, the original two length bytes in the OPC packet are reserved and should be sent as zero.

Channel Command Reserved (Zero) Data
1 byte 1 byte 2 bytes N bytes of message data

To send a binary packet, you can use Typed Arrays. For example, this sets the first three LEDs to red, green, and blue respectively. (We send the packet twice to force interpolation to happen immediately, since we don't have a predictable frame rate when entering commands like this.)

> ws = new WebSocket("ws://localhost:7890")
> packet = new Uint8Array([ 0,0,0,0, 255,0,0, 0,255,0, 0,0,255 ]);
> ws.send(packet.buffer)
> ws.send(packet.buffer)

This is the recommended way of sending pixel data from a web app. The mapping settings from the fcserver config file take effect, and any OPC packet can be sent in this way.

JSON Packets

Any WebSocket frames that contain text rather than binary data are expected to be JSON. These packets can be sent from client to server or from server to client. All JSON packets are objects with a "type" string.

Unless otherwise specified, all command packets that can be successfully parsed will generate replies by the server. If a problem occurred in processing the command, an "error" member will be added with an error message string to explain the problem. When the server replies to a command from the client, additional JSON object members in the command are preserved so clients can associate metadata with requests.

list_connected_devices

This is sent from client to server to ask for a list of all connected devices:

{ "type": "list_connected_devices" }

The server will respond with a message like:

{
    "type": "list_connected_devices",
    "devices": [
        {
            "type": "fadecandy",
            "serial": "ENICCULVLDQJQDWD",
            "timestamp": 1384320928627,
            "version": "1.06",
            "bcd_version": 262
        }
    ]
}

Each device is a JSON object within a list of devices. Each device object must uniquely identify a particular connection of a particular device. Fields may include:

Name Description
type String identifying the device type ("fadecandy", "enttec")
serial Serial number for this particular device instance
timestamp When did this device connect? Timestamp in milliseconds
version Firmware version for the device, as a string
bcd_version BCD encoded firmware version, from the USB descriptors

connected_devices_changed

This packet can be sent unsolicited by the server any time a new device is attached or an existing device is removed. The response is identical to list_connected_devices, aside from the packet type.

server_info

This is sent from client to server to ask for information about the server itself:

{ "type": "server_info" }

The server will respond with a message like:

{
    "type": "server_info",
    "version": "fcserver-1.01",
    "config": {
        "listen": ["127.0.0.1",7890],
        "verbose": true,
        "color": {"gamma": 2.5, "whitepoint": [1,1,1]},
        "devices": [{"type": "fadecandy", "map": [[0,0,0,512]]}]
    }
}

Fields in the response include:

Name Description
version Server version string
config JSON object with the server's current configuration file contents

device_color_correction

Write color correction info directly to a single device. Does not change the global color correction settings. The client first provides a message with color correction settings in the same format as the server's configuration file, and a device specification in the same format as list_connected_devices.

This example changes the whitepoint on a specific Fadecandy controller, to make the brightness very dim:

{
    "type": "device_color_correction",
    "device": {
        "type": "fadecandy",
        "serial": "ENICCULVLDQJQDWD"
    },
    "color": {
        "gamma": 2.5,
        "whitepoint": [0.2,0.2,0.2]
    }
}

device_options

Change the configuration options for a single device. This loads the same options supported by the server's JSON configuration file in the section for a single device.

For example, a Fadecandy device supports the following options:

Name Values Default Description
led true / false / null null Is the LED on, off, or under automatic control?
dither true / false true Is dithering enabled?
interpolate true / false true Is inter-frame interpolation enabled?

This example turns on the LED on a specific Fadecandy controller:

{
    "type": "device_options",
    "device": {
        "type": "fadecandy",
        "serial": "ENICCULVLDQJQDWD"
    },
    "options": {
        "led": true
    }
}

device_pixels

Sends pixel data directly to a single device, bypassing the OPC mapping. This accepts pixel data as an array of integers, and it's a lot less efficient than using OPC packets. This is mostly useful for special-purpose clients like configuration tools.

For example, setting the first three pixels to red, green, and blue for a specific Fadecandy controller:

{
    "type": "device_pixels",
    "device": {
        "type": "fadecandy",
        "serial": "ENICCULVLDQJQDWD"
    },
    "pixels": [
		255, 0, 0,
		0, 255, 0,
		0, 0, 255
    ]
}