LED Lighting Board Integration

To control the LED Lighting Board, three steps need to be done:

  1. Authentication: Getting the authentication token based on the obtained credentials (email and password).

  2. Command Sending: In this step, we will use a WebSocket client called Socket.io. It exists in many languages, but we will exemplify with JavaScript in this tutorial.

  3. Get LED Settings: Explanation of how to get information about LED settings configurations such as channel, group, label, etc.

  4. Command Syntax

API Testing

To facilitate testing and integration, you can access the API directly using the following base endpoint: https://manager-api.vysta.io/api

We recommend starting with the authentication route (/v1/auth/signIn) to obtain the token required for all other API requests. All endpoints described in this document use this base URL.

1. Authentication

To create the authorization token, send an HTTP POST request to the route https://manager-api.vysta.io/api/v1/auth/signIn. Set the Content-Type header to application/json.

The body of this request should be a JSON like this:

```
{

"email": "example@example.com",

"password": "example"

}
```

Change the example values to the credentials you received from Evolution. If you have not received these, please contact josh@evolutionv.com.

The response to this request should be a JSON with token information and user information. To send commands, only the “token” value is needed:

```
{

"user": {

"id": "example-userId",

"createdAt": "2024-01-08T00:23:14.364Z",

"updatedAt": "2024-01-08T00:23:14.364Z",

"firstName": "example",

"lastName": "example",

"email": "example@example.com",

"role": "CUSTOMER"

},

"token": "my_token"

}

```

The token will be valid for 30 days from your initial request. After which, you will need to perform the above request to receive a new token.

2. Command Sending

In this step, we are going to start an instance of a socket.io client (If you are not using JavaScript, the official website of socket.io has documentation for other languages: https://socket.io/docs/v4/). Also, you need to specify which board (or boards) you want to control. To get this information, log into the Lighting Manager and click on the “View Project Details” button of the project you are working on:

Once you are on the project page, you should be able to get the MAC ADDRESS for all the boards related to the project under the Board Details page. Copy it to use in the next steps:

Socket client: Add the Authorization parameter inside the auth configuration, the token obtained from the Authorization step. It follows the Bearer Token pattern, so the resulting value for this parameter should be a Bearer string followed by the token (separated by space). With the base URL being wss://manager-api.vysta.io, path pointing to /ws and transports should include websocket:


  ```
import io from 'socket.io-client';

const baseUrl = 'wss://manager-api.vysta.io'; 
const path = '/ws';
const token = 'my token'; const client = io(baseUrl, {
    transports: ['websocket'],
    path: path,
    auth: {
        Authorization: 'Bearer ' + token,
    },
});
this.client.connect();
```

For sending the commands through the web socket connection, emit an event with the event name: “message”. In the payload, include the MAC ADDRESS of the desired board and the command to send.

The following JavaScript code snippet exemplifies the explained process above:


  ```
const command = 'ch 1 on'; // replace by the sending command.
const macAddress = '00:00:00:00:00:00'; // replace by the 
board address


client.emit('message', {
    command: command,
    macAddress: macAddress,
});
```

Firmware 2.0.x

If you're using firmware version 2.0.x, commands must be sent as JSON objects directly over WebSocket. However, you can use the Command Conversor (explained below), which simplifies command formatting by allowing you to send plain text instructions.

To turn off all the strips and all the LEDs, you will need to send:


  ```
[{"command": "SET_STATE", "targets": 
[{"strip": "all", "ranges": [{"start": 0, "end": 170}]}],
"parameters": {"on": true, "color": {"r": 0, "g": 255, "b": 0},
"brightness": 150}}]
```

Note that the ranges are relative to what is in the Channel LED table minus 1, so if you want to light up channel 41, you need to send:


  ```
[{"command": "SET_STATE", "targets": 
[{"strip": 4, "ranges": [{"start": 31, "end": 35}]}],
"parameters": {"on": true, "color": {"r": 0, "g": 255, "b": 0},
"brightness": 150}}]
```

The other parameters are relative to the color, brightness, and if it's on or off. For off (false), you can send:


  ```
[{"command": "SET_STATE", "targets": 
[{"strip": "all", "ranges": [{"start": 0, "end": 170}]}],
"parameters": {"on": false}}]
```

  ```
[{"command":"SET_STATE","targets":
[{"strip":3,"ranges":[{"start":121,"end":125}]},
{"strip":10,"ranges":[{"start":51,"end":51}]},
"parameters":{"color":{"r":255,"g":0,"b":0},
"brightness":128,"on":true}}
```

In channels where there is more than 1 range of LEDs, you can send this ch 29 as example:

Important: LED range values (start and end) must always be offset by -1 relative to what's shown in the Channel LED table. Failing to subtract 1 may result in incorrect LED behavior (e.g., lighting unintended zones).

Effect Commands (JSON Summary)

Each of the following commands applies one visual effect using the command field and appropriate parameters. Replace strip and ranges according to your needs.

1. FADE_EFFECT

Fades in and out between black and a target color.


  ```
[{"command": "FADE_EFFECT", "targets": 
[{"strip": 3, "ranges": [{"start": 0, "end": 143}]}],
"parameters": {"color": {"r": 0, "g": 0, "b": 255},
"fade_duration": 10000}}]
```

2. CHASE_EFFECT

Single moving point of light.


  ```
[{"command": "CHASE_EFFECT", "targets": 
[{"strip": "all","ranges": [{"start": 0, "end": 143}]}],
"parameters": {"color": {"r": 255, "g": 0, "b": 255},
"fade_duration": 10000}}]
```

3. RAINBOW_EFFECT

Rainbow cycling across the strip.


  ```
 [{"command": "RAINBOW_EFFECT", "targets": 
 [{"strip": 4, "ranges": [{"start": 0, "end": 143}]}],
 "parameters": {"fade_duration": 5000, "brightness": 255}}]
```

4. PULSE_EFFECT

Smooth brightness pulsing.


  ```
 [{"command": "PULSE_EFFECT", "targets": 
 [{"strip": 5, "ranges": [{"start": 0, "end": 143}]}],
 "parameters": {"color": {"r": 200, "g": 0, "b": 200},
 "fade_duration": 15000}}]
```

5. SPARKLE_EFFECT

Randomly blinking pixels.


  ```
[{"command": "SPARKLE_EFFECT", "targets": 
[{"strip": 6, "ranges": [{"start": 0, "end": 143}]}],
"parameters": {"color": {"r": 255, "g": 255, "b": 255}}}]
```

6. GRADIENT_WAVE_EFFECT

Animated gradient wave between two colors.


  ```
 [{"command": "GRADIENT_WAVE_EFFECT", "targets": 
 [{"strip": 7, "ranges": [{"start": 0, "end": 143}]}],
 "parameters": {"color1": {"r": 255, "g": 0, "b": 0},
 "color2": {"r": 0, "g": 0, "b": 255}, "fade_duration":
 3000}}]
```

7. SPOTLIGHT_EFFECT

A moving color “spot” with a fading edge.


  ```
 [{"command": "SPOTLIGHT_EFFECT", "targets": [{"strip":
 8, "ranges":  [{"start": 0, "end": 143}]}], 
 "parameters":  {"color": {"r": 0, "g": 255, "b": 255},
 "width": 10, "fade_duration": 2500}}]
```

  ```
 [{"command": "AMBIENT_EFFECT", "targets": 
 [{"strip": 9, "ranges": [{"start": 0, "end": 143}]}],
 "parameters": {"fade_duration": 10000, "brightness": 150}}]
```

8. AMBIENT_EFFECT

Slow ambient color shifting.

9. MULTI_CHASE_EFFECT

Multiple light points chasing along the strip.


  ```
 [{"command": "MULTI_CHASE_EFFECT", "targets": 
 [{"strip": 10, "ranges": [{"start": 0, "end": 143}]}],
 "parameters": {"color": {"r": 255, "g": 0, "b": 255},
 "fade_duration": 800, "num_points": 5}}]
```

10. OCEAN_WAVE_EFFECT

Ocean-like wave animation with multiple range support.


  ```
 [{"command": "OCEAN_WAVE_EFFECT", "targets":
 [{"strip": 1, "ranges": [{"start": 25, "end": 70}]}],
 "parameters": {"fade_duration": 3000, "brightness": 70}}]
```

11. FADE_IN

Smoothly fades in to a target color.


  ```
  [{"command": "FADE_IN", "targets": 
  [{"strip": 1, "ranges": [{"start": 0, "end": 143}]}],
  "parameters": {"color": {"r": 255, "g": 255, "b": 255,
  "w": 0}, "duration": 2000, "brightness": 200}}]
```

12. FADE_OUT

Fades current color to black.


  ```
[{"command": "FADE_OUT", "targets": 
[{"strip": 1, "ranges": [{"start": 0, "end": 143}]}],
"parameters": {"duration": 2000}}]
```

Limitations & Notes

  • Maximum Simultaneous Effects:
    Each strip can support up to 3 simultaneous ranges running effects.
    Given there are 11 strips, this means a total of 33 effects can run simultaneously across the system.

  • Non-Cyclic Effects:
    The effects FADE_IN and FADE_OUT are non-cyclic, meaning they execute once and do not loop.

    • After the specified duration, they are considered completed.

    • FADE_IN results in an active light state, equivalent to having sent a SET_STATE command.

  • Usage Restrictions:
    These JSON-based effect commands cannot be used with the Command Conversor (text-based interface).
    Instead, they must be:

    • Created and managed via the Lighting Manager interface, and

    • Activated/deactivated through the effects API endpoint.

Command Conversor (available from the firmware version v.2.0.0)
Command Conversor is a feature prepared for those who are already using some most recent firmware version (> v.2.0.0) and desire to send commands through the API using the same pattern based on text commands, for example:   “ch 1 c FF0000 @ 45 on”.

To take advantage of this feature  use the API endpoint below:

POST /api/v1/boards/command-conversor


Add the Authorization header using the Bearer token pattern and send the payload containing the macAddress of the desired board and the command to be sent.

The following JavaScript code snippet exemplifies the explained process above:


  ```
import axios from 'axios';

const baseUrl = 'https://manager-api.vysta.io';
const token = 'my token';

const command = 'ch 1 on'; // replace by the sending command.
const macAddress = '00:00:00:00:00:00'; // replace by 
the board address


const payload = {
 macAddress,
 command
};

axios.post(`${baseUrl}/api/v1/boards/command-conversor`, 
payload, {
 headers: {
   Authorization: 'Bearer ' + token
 }
})
.then(response => {
 console.log('Response:', response.data);
})
.catch(error => {
 console.error('Error:', error);
});

```

Start/Pause Effects

Here we describe the process to start or pause any effect that is already created.

Observation:
Add the Authorization header using the Bearer token pattern

Step 1: Get effects data through the API endpoint below

GET /api/v1/boards/{boardId}/effects

Example of response:


  ```
{
    "e7292609-9364-40b0-9649-7e102dfe5c49": {
        "id": "e7292609-9364-40b0-9649-7e102dfe5c49",
        "name": "Effects Set 1",
        "targets": [],
        "targetsStrips": [],
        "effects": [
            {
                "id": "bbd72b90-1767-4bc9-b820-37e64ac40b92",
                "type": "AMBIENT_EFFECT",
                "name": "Ambient Effect",
                "data": {
                    "brightness": 168,
                    "fade_duration": 3000
                },
                "executionMode": "immediate",
                "status": "inactive"
            },
            {
                "id": "54590703-a7f4-44d6-8377-b55d8ecb0885",
                "type": "FADE_EFFECT",
                "name": "Fade Effect",
                "data": {
                    "color": {
                        "r": 255,
                        "g": 255,
                        "b": 255
                    },
                    "fade_duration": 5000,
                    "brightness": 66
                },
                "executionMode": "immediate",
                "status": "inactive"
            }
        ]
    },
    "9f0aeba8-f3eb-4b1c-9086-e66a63dfb790": {
        "id": "9f0aeba8-f3eb-4b1c-9086-e66a63dfb790",
        "name": "Effects Set 2",
        "targets": [
            {
                "label": "26C",
                "type": "unit",
                "ledSettingId": "841b759e-2e15-481e-98ea-dd29520973da",
                "floor": "26"
            }
        ],
        "targetsStrips": [],
        "effects": [
            {
                "id": "464b29e5-9421-474d-9bf3-44a37730df10",
                "type": "PULSE_EFFECT",
                "name": "Pulse Effect",
                "data": {
                    "color": {
                        "r": 201,
                        "g": 47,
                        "b": 47
                    },
                    "fade_duration": 1000,
                    "brightness": 137
                },
                "executionMode": "immediate",
                "status": "inactive"
            }
        ]
    }
}
```

Step 2: Select the effect, and use the API endpoints below to start or pause it
POST /api/v1/boards/{boardId}/effects/{effectsGroupId}/activate/{effectId}

 POST /api/v1/boards/{boardId}/effects/{effectsGroupId}/inactivate/{effectId}

The following JavaScript code snippet exemplifies the explained process above:


  ```
import axios from 'axios';

const baseUrl = 'https://manager-api.vysta.io';
const token = 'my token';

const boardId = '0ef4cd5f-80c0-4f5d-9e4e-eface7d98fb3'; // replace by the board id


const effectsData = await axios.get(`${baseUrl}/api/v1/boards/${boardId}/effects`, {
 headers: {
   Authorization: 'Bearer ' + token
 }
})
.then(response => {
  console.log('Response:', response.data);
  return response.data;
})
.catch(error => {
 console.error('Error:', error);
});

const effectsGroups = Object.values(effectsData);

// Every effect is part of an effect group
// So specify an effect group and an effect that is part of it
const selectedEffectsGroup = effectsGroups[0];
const effectGroupId = selectedEffectsGroup.id;

const effects = selectedEffectsGroup.effects;
const selectedEffect = effects[0];
const effectId = selectedEffect.id;

// Start the effect
await axios.post(`${baseUrl}/api/v1/boards/${boardId}/effects/${effectGroupId}/activate/${effectId}`, {}, {
 headers: {
   Authorization: 'Bearer ' + token
 }
})
.then(response => {
  console.log('Response:', response);
})
.catch(error => {
 console.error('Error:', error);
});

// Pause the effect
await axios.post(`${baseUrl}/api/v1/boards/${boardId}/effects/${effectGroupId}/inactivate/${effectId}`, {}, {
 headers: {
   Authorization: 'Bearer ' + token
 }
})
.then(response => {
  console.log('Response:', response);
})
.catch(error => {
 console.error('Error:', error);
});

```

3a. Get LED Settings

To get LED settings specifications of an existing board, send an HTTP GET request to the route https://manager-api.vysta.io/api/v1/boards/{macAddress}/ledSettings/parsedn this case, you will need to:

  • Set the Content-Type header to application/json

  • Replace the macAddress route parameter to the controlling board MAC address (i.e. https://manager-api.vysta.io/api/v1/boards/00:00:00:00:00:00/ledSettings/parsed).

  • Add the authorization header: put Authorization in the header name and write Bearer yourAuthorizationToken in the header value (replace “yourAuthorizationToken” with the token retrieved from the Authentication step).

After making the request, the JSON response should be in the following format:


  ```
[
  {
      "channel": 1,
	"group": 2,
	"label": "Lobby",
	"ledRanges": [
	  {
	     "ledRange": "1-15",
	     "strip": 1
	  },
	  {
	     "ledRange": "16-35",
	     "strip": 1
	  }
	]
  },
  {
      "channel": 2,
	"group": 2,
	"label": "Unit 123",
	"ledRanges": [
	  {
	     "ledRange": "6-32",
	     "strip": 2
	  },
	  {
	     "ledRange": "33-35",
	     "strip": 2
	  }
	]
  }
  // ...more settings
]
```

3b. Get Board State

To get all channel states of an existing board, send an HTTP GET request to the route https://manager-api.vysta.io/api/v1/boards/{macAddress}/state.

As the same from the LED settings method, you will need to:

  • Set the Content-Type header to application/json

  • Replace the macAddress route parameter to the controlling board MAC address (i.e. https://manager-api.vysta.io/api/v1/boards/00:00:00:00:00:00/ledSettings/parsed).

  • Add the authorization header: put Authorization in the header name and write Bearer yourAuthorizationToken in the header value (replace “yourAuthorizationToken” with the token retrieved from the Authentication step).

After making the request, the API retrieves a JSON response where it contains all the LED channels aggregated by groups numbered by integer values. The identification of the groups and channels are identified by the object keys inside the JSON object. As you can see in the example response:


  ```
{
  "1": {
    "60": {
      "agregator": "ch",
      "number": 60,
      "state": "off"
    },
    "61": {
      "agregator": "ch",
      "number": 61,
      "state": "on"
    }
  },
  "2": {
    "1": {
      "agregator": "ch",
      "number": 1,
      "state": "on"
    },
    "2": {
      "agregator": "ch",
      "number": 2,
      "state": "off"
    },
    "3": {
      "agregator": "ch",
      "number": 3,
      "state": "on"
    }
  },
  lastUpdate": "2024-07-23T16:00:00.701Z"
}
```

In the example above, the API returned a JSON with two groups that can be identified by the most hierarchical keys (“1” and “2”). Inside each group object, there are LED channels. In this example:

  • The group “1” contains two LED channels identified by the internal object keys (“60” and “61”), while the group “2” contains three led channels (“1”, “2” and “3”).

  • Each channel contains its state label that can only assume the values “on” and “off”.

1. Association Table

After the architectural model has been constructed, the individual LEDs will be assigned to specific channels within the lighting controller. A table will then be provided associating the Channels to Building Units/Amenities.

Command Syntax

2. Commands

The commands for controlling the lighting controller are a custom command structure.

2.1 Simple commands:

  • all on: turn on all LED channels.

  • all off: turn off all LED channels.

2.2 Structured lighting commands

In the majority of cases, the command starts with either the channel or group keyword (ch or group), followed by the channel or group number to control, which is then followed by the specific sub-command codes. The available sub-command codes are as follows:

  • ch: Channel

  • group: Group

  • on/off: The "on" sub-command will turn on all LEDs for that specific group or channel. Likewise for the "off" sub-command.

  • @: This is the brightness sub-command and is followed by a brightness value from 0 to 100 (100 indicating full brightness).

  • c: Color command, which changes the color associated with the channel or the group. Following the "c" command is the hex value for the color. A "0x" or "#" is not needed. Example: To change the color to blue, the command will be "c 0000FA".

  • w: White value and consists of 2 hex values. "FF" represents maximum brightness, and "00" represents off. The formatting is similar to the "c" command. Example: "w FF".

  • changegroup: This sub-command changes the group of the channel to a new group. This command should not be used in conjunction with the "group" command or any other sub-command. Each channel can be associated with a maximum of 2 groups. The syntax for the "changegroup" command is as follows: "ch 1 changegroup 1 2". This will take channel 1 and change the first group it is associated with to group 2. "ch 1 changegroup 2 5" will.

2.3 Examples

  • ch 1 @ 5 c 4287f5 w 11 on”: turn on channel 1, set the brightness of the LEDs to 5%, change the color to a blue color, and change the white brightness to 6% (17 / 255 ≈ 6%).

  • ch 4 off”: turn off all LEDs associated with channel 4.

  • group 6 @ 60”: change all channels associated with group 6 to a brightness of 60%. 

  • ch 80 c FCBA03 on”: change all LEDs associated with channel 80 to a yellow color.

  • group 7 @ 60 on”: change the brightness of a group and push change.

Important: To push changes to the LEDs when they are already on, you will need to first specify the setting (brightness or color value) and then send the on command.

Contact us

Schedule a demo with us here.

Or contact our sales team to learn more:

- Worldwide: sales@lightitwithvibrant.com

- UK / Europe: Sean Wouters 
sw@evolutionv.com

- Middle East: Seran Gheorghe
 +971504077007, sg@gadzai.com

- Middle East / Asia: Fred Wayne fred@evolutionv.com

Customer Support: support@lightitwithvibrant.com