How to Control a Network Connected Light Panel

Working from the Ceiling Down

In contrast to the age-old advice - work from the ground up - in smart building automation the easiest place to start is at the top. Lighting is going through a revolution of its own as LEDs become the standard in office and professional buildings everywhere. This makes them the perfect place to start implementing smart technology in building automation systems.


In this blog, we will demonstrate how to build an application in NodeJS to facilitate the connection between sensors and an LED NuLEDs panel.


Joining the Dots through the Digital Ceiling 

Cisco’s new Digital Ceiling initiative harnesses the value in building automation, beginning with lighting and moving on to all systems. relayr is Cisco’s first software partner in this initiative.


Cisco’s Digital Ceiling is a framework and solution set to build lighting standard across building infrastructures using Cisco’s networking technologies. This enables customers to make 30% savings across capital and operating expenses.

 Read more about the


relayr’s hardware agnostic “any-to-any” IoT middleware further enhances Cisco’s Digital Ceiling by bringing together previously siloed building systems through digital retrofits of existing legacy assets, allowing customers to:

  • Save energy and money by heating and lighting only occupied spaces.
  • Gain insightful data on how and when spaces are used.
  • Streamline repairs by offering predictive maintenance.
  • Improve security with established patterns of usage.


relayr’s software is an enabling layer that helps businesses extract value from the data collected via connected devices and systems. We provide the means to analyze it and deliver the right data in the right way to the right people and services.


Demo of relayr and Cisco’s working Digital Ceiling Solution



Read more about the  

The next section of the blog will help explain the details of the working solution so that you can replicate this demo using Cisco, relayr, and NuLEDs technologies.


Controlling a NuLEDs Panel through the relayr Cloud

The application we're going to write establishes MQTT connections to the devices using two clients: one for the NuLEDs panel, and one for the sensor from which we will read data (in this instance, a CO2 sensor). The sensor client subscribes to the MQTT data topic of the sensor and reads the sensor data. When successful, it calls a method to process the data and pick a color based on the what the sensor reads. Then, it sends a command to relayr's NuLEDs adapter, which then tells the light panel to change color.


Before getting started, make sure that you have connected both your light panel and your sensor to the relayr cloud. See the devices documentation for more information.


First, make sure you have the mqtt library installed (use npm install mqtt if you don't).

Then, set up a new NodeJS file:

'use strict';

const mqtt = require('mqtt');


We'll start by creating objects for the panel and the sensor. Each object will contain the MQTT credentials (usernamepassword, and clientId) necessary to establish the MQTT connection to its respective device. These credentials can be found in each device's Device Settings section on the Developer Dashboard.


For the panel:

const panelDevice = {
  "username": "d00fbsx8-b42e-4ea4-802c-798593f74a1a",   // Use the credentials for the light panel
  "password": "fo46.Op9kU_g",                           // (see directions above)
  "clientId": "GwA-7rcN+Tq5ALHmFk/dKGg"

For the sensor:

const sensorDevice = {
  "username": "d74d1129-866f-43f0-86ee-09a6ccacbd62",   // Use the credentials for the CO2 sensor
  "password": "cT11SJGodenF",                           // (see directions above)
  "clientId": "T101AeYl/Q/DP7dnrkKy9Yg"

Next, we'll create the panelClient to establish the MQTT connection for the light panel using the credentials in panelDevice:

// Connect the MQTT client for the panel
const panelClient = mqtt.connect({
  servers: [{ host: '' }],
  username: panelDevice.username,
  password: panelDevice.password,
  clientId: panelDevice.clientId,
  protocol: 'mqtts',

panelClient.on('connect', () => {
  console.log('MQTT connection established to panel.');

panelClient.on('error', (err) => {
  console.log('ERROR with MQTT panel connection', err);

With panelClient created, now we can move on to the sensorClient. This client will subscribe to the readings from the sensor device. When it successfully establishes a connection to the sensor, it will set up a listener to handle the readings from the device as they are recieved. Each reading will be passed to the processData method, which chooses a color value based on the sensor data and then calls the sendPreset method to send the chosen color to the light panel via MQTT.


// Connect the MQTT client for the sensor
const sensorClient = mqtt.connect({
  servers: [{ host: '' }],
  username: sensorDevice.username,
  password: sensorDevice.password,
  clientId: sensorDevice.clientId,
  protocol: 'mqtts',

sensorClient.on('connect', () => {
  console.log('MQTT connected for panel.');
  // Listens for data from sensor
  sensorClient.on('message', (topic, message) => {                  
    if (topic.endsWith('/data')) {
      try {
      // Reads sensor data, chooses color, sends it to light panel
        processData(topic, JSON.parse(message.toString()));         
      } catch (err) {
        console.log(`ERROR parsing data from sensor: ${message.toString()}`);
  const subTopic = `/v1/${sensorDevice.username}/data`;
  // Subscribes to the MQTT data topic from the sensor

sensorClient.on('error', (err) => {
  console.log('ERROR with MQTT sensor connection', err);

To wrap things up, we'll define the processData method from the above snippet:
// Process incoming sensor data and send commands to panel as needed
function processData(topic, data) {
  let co2value = 0;
  let colour = '';

  // This device sends multiple readings.  Find the CO2 value.
  // Each "reading" from a device contains sensor data as a meaning/value pair
  data.forEach((reading) => {
    if (reading.meaning === 'CO2') {
      co2value = reading.value;                 

  if (co2value < 500) {
    colour = 'White';
  } else if (co2value < 1000) {
    colour = 'Blue';
  } else if (co2value < 1500) {
    colour = 'Green';
  } else {
    colour = 'Red';


And then we'll define the sendPreset method to pass the color from processData to the "cmd" MQTT topic on the panel.

// Send an MQTT command to the panel via the relayr cloud
// cmd is panel's MQTT topic for receiving commands
function sendPreset(colour) {
  const cmd = {
    name: 'presets',
    value: colour,
  console.log(`publishing ${JSON.stringify(cmd)} to /v1/${panelDevice.username}/cmd`);
  panelClient.publish(`/v1/${panelDevice.username}/cmd`, JSON.stringify(cmd));


Learn more about this innovative initiative in Cisco’s Digital Ceiling White Paper, and more on relayr’s partnership in this blog.