Sample codes

This document describes a set of samples code you can run on your sensor, or by using its data. You will find the code

Hello world

The full sample code is available for downloading at the end of this document. It requires Python3.

The easiest way to start with the Ambient 16 is to change the color of its LED through a simple Python code.

In this Python script you will learn how to:
  • Retrieve the informations of your sensor.

  • Generate a MD5 secret phrase to secure communication.

  • Send a request for changing the color of the LED.

  • Understand the response and see that the request has been well accepted.

Prerequisite

Some information are required to run the Python script properly:

1- Get the IP address of your sensor:

  • from your WiFi router DHCP clients, search for a device with a name that includes the Unique Device ID (UDID) printed behind the device,

  • or from our app. There you can find the IP address of your Ambient 16.

2- Get your Unique User ID (UUID). It is available on our web site. Log in and navigate to your user profile. You will find a section where your UUID is accessible. For more information regarding the UUID, Read the section Creating a Unique User ID.

In this example, we assume that the IP address and UUID are:

ipAddress="192.168.1.56"
uuid="40b3c94c9dd033351a296bc3d008e9e6"

Retrieving the informations from your sensor

First perform a simple HTTP request and get its identity information. For now, only the IP address is needed.

versionGetURL="http://"+ipAddress # This is the URL you call

try:
    versionJSON = json.loads(requests.get(versionGetURL).text)
except :
    print("Cannot access ",versionGetURL)
    sys.exit()

# Just printing the obtained JSON for the sake of explanation
print("Version JSON: ",versionJSON)

It returns the following information in form of a JSON:

{
    "type":"Ambient16",
    "version":"ff16469",
    "udid":"100001f93d8f",
    "deviceType":"1000",
    "token":"eft85cem"
}

Two parameters are now of interest:

1- the Unique Device ID, udid.

2- the token. The security token changes every hour.

# Extract the module unique identifier (UDID)
udid=versionJSON['udid']
# Extract the security token. The security token remains valid one hour after your last valid HTTP request on the module.
# No need to obtain it for every consecutive calls.
token=versionJSON['token']

In this example, the data extraction prints:

udid="100001f93d8f"
token="eft85cem"

Generating the MD5 secret phrase

The MD5 secret phrase is a parameter used in every HTTP request performed on the sensor. It ensures that you are its rightful owner. It is created by concatenation of the token and your UUID, followed by a hash by a MD5 encryption. For more information regarding the MD5 secret phrase, Read the section The MD5 secret phrase.

# Now create a secret phrase in clear, before encrypting it....
nonEncryptedSecretPhrase=token+uuid
# ... and encrypt it with the MD5 encryption. You can reuse this encrypted secret again without generating a new one during one hour

# after your last request to the module. After this time, you need to generate a new one.
encryptedSecretPhrase = hashlib.md5(nonEncryptedSecretPhrase.encode()).hexdigest() # the MD5 encryption

# Printing it for the sake of example
print("Generating the secret:",nonEncryptedSecretPhrase," when encrypted becomes -> ",encryptedSecretPhrase)

In our example, the generated MD5 secret phrase becomes:

Generating the secret:"eft85cem40b3c94c9dd033351a296bc3d008e9e6"
when encrypted becomes -> "13f678cd7a3e26e14c9f2b93375735dd"

Sending a request to the sensor for changing the LED color

The request takes the form of a JSON payload. Here, the payload sets a red light lasting 5 seconds. The udid and the MD5 secret phrase are required in this HTTP request.

payload=json.dumps({"udid":udid,
                    "secret":encryptedSecretPhrase,
                    "setColor": {
                                "ledColorName": "red",
                                "duration":5
                                }
                    })

Then, we construct the URL where the light command is posted. Note that /light has been added at the end of the URL.

dataCommandURL="http://"+ipAddress+"/light"

Next, the code performs a HTTP POST request.

# Create the HTTP request
req=urllib.request.Request(dataCommandURL, payload.encode())

# Make the HTTP call to the sensor
resultJSON=json.loads(urllib.request.urlopen(req).read().decode())

# Finally, the module acknowledges the command by returning a JSON payload containing the error code (if any), and the current security token
print(resultJSON)

The response of the request is:

{"error": 0, "reason": "Ok.", "token": "vtt3mrwk"}

Understanding the sensor’s response

In this final step, the code checks for errors. An error value of 0 means it has been properly accepted. For other values, a short description of the error is returned under the field reason.

# Let's look at the error code
errorCode=resultJSON['error']
if errorCode==0:
    print("The light is well set to red.")
else :
    print("The light has not been set and the reason is: ",resultJSON['reason'])

In this example, the parsing returns:

The light is well set to red.

Going further with the script

At the end of the script, an additional request is sent to the sensor, for setting a steady green light. Note that the security token is reused. It is probably still valid as it has just been requested. However, as a good practice, for longer executions, the token should be updated from the previous response.

# Now we wait 10 seconds and set the color green, indefinitely
print("Waiting 10 seconds now ...")
time.sleep(10)

# We create the command payload. Setting the duration to 0 will leave the light on.
# Also note that we just have created and used the security token. It is still valid.
# No need to ask for it again, as we did at the begining of the script.
payload=json.dumps({"udid":udid,
                "secret":encryptedSecretPhrase,
                    "setColor": {
                                "ledColorName": "green",
                                "duration":0
                                }
                    })

# We create an HTTP request a this URL with the command JSON payload
req=urllib.request.Request(dataCommandURL, payload.encode())

# Now use this HTTP request to actually set the light (this makes the actual HTTP call)
resultJSON=json.loads(urllib.request.urlopen(req).read().decode())

# Let's look at the error code
errorCode=resultJSON['error']
if errorCode==0:
    print("The light is well set to green.")
else :
    print("The light has no been set as: ",resultJSON['reason'])


sys.exit()

Sample code

Thibaud will add soon the sample code to play with the LED of your sensor.

Magic Mirror2 displaying

The full sample code is available for downloading at the end of this document. It requires Javascript.

A fancy way to display data from your Ambient 16 on a screen.

In this example, you will learn how to:
  • Make a WEB request and display live data of your sensor.

  • Make a MQTT subscribing to your sensor events.

  • Make a local file request, such as JSON or SVG, to display computed data.

Install Magic Mirror2

Magic Mirror2 is required to execute the scripts. It is an open source modular smart mirror platform. you can download it via the link:

Download Magic Mirror

TO REDO: In this example, the config.js file is updated, and a generic module is added. It has been cut regarding the type of request.

WEB request

Once your module is paired and connected to network, it is continuously sending data to InfluxDB. The example script will perform a perdiodic request on InfluxDB, and display the data we want.

Configuration file script

Magic Mirror2 comes with a config.js with a list of default modules. To display the result of the WEB request, the corresponding module need to be added in the file.

This example details how to set a module for an InfluxDB request.

module: 'MMM-dataFromOneModule', // Displays dynamically the values of one selected module.
position: 'bottom_left',
config: {
    /***** GENERAL CONFIG VALUES *****/
    updateInterval:10000,
    animationSpeed: 0,

    /***** WEB REQUEST CONFIG VALUES *****/
    httpRequestURL: "https://serverAddress:serverPort/query?db=someInfluDBName&u=someUserName&p=somePassword&q=SELECT calibratedValue_celcius FROM temperature WHERE udid='someUDID' GROUP BY udid ORDER BY DESC LIMIT 1 %3B  SELECT calibratedValue FROM humidity WHERE udid='someUDID' GROUP BY udid ORDER BY DESC LIMIT 1 %3B SELECT calibratedValue FROM co2 WHERE udid='someUDID' GROUP BY udid ORDER BY DESC LIMIT 1 %3B SELECT calibratedValueSeaLevel FROM airpressure WHERE udid='someUDID' GROUP BY udid ORDER BY DESC LIMIT 1",
}

Three kind of parameters are defined in the config.js file:

1- The name of the module. It is the same as the script.js which actually perform the request.

2- The position correspond to the screen area where the values will be displayed.

3- Config is a list of customized variable used by the script to perform the request.

In this example, the requestURL corresponds to an InfluxDB request. It is composed of:

  • server address and port,

  • Influx database name, user and credentials,

  • an InfluxDB request list. Here, the request ask for the last measured values of one sensor for temperature, humidity, CO2 and air pressure.

Magic Mirror Module script

Default parameters

The variables defined in the config.js file are declared in the main script with default values.

defaults: {
    updateInterval: 20000,
    animationSpeed: 0,

    /***** HTTP REQUEST DEFAULT VALUES *****/
    httpRequestURL: "",
},
  • updateInterval corresponds the waiting time between two web request,

  • animationSpeed is the speed at which the text will appear on the screen,

  • httpRequestURL is the link on which the request is performed. It is empty by default.

Specific styles

Magic Mirror2 comes with a set of styles, available in the file main.css Specific styles can be created for a Magic Mirror Module. These styles can be used thanks to the following function and genericModule.css file.

// Define specific styles of the module.
getStyles: function() {
    return ["genericModule.css"];
},

In this example, no specific styles are created.

Starting the module

This function is used to launch the module when Magic Mirror2 starts. It sets the functions and variables to execute the request.

// Start the module
start: function () {
    console.log(this.name + " started.");

    /***** Define the options for displaying *****/
    var self = this;
    var context= this;
    setInterval(function () {
        context.updateDom(self.config.animationSpeed);
        context.updateRequest(); // WEB request
        context.getJson(); // Local file request
    },this.config.updateInterval);

    /***** WEB REQUEST *****/
    this.updateRequest();
    this.nodes = [];
    this.currentValueIndex = 0;
},
Making the request

Once the request is complete, a parsing is performed on the result. It extracts the measured values of the sensor.

getNextValue : function(){
    var index = this.currentValueIndex;
    if(this.currentValueIndex + 1 === this.nodes.length-1){
        this.currentValueIndex = 0;
    }
    else {
        this.currentValueIndex++;
    }
    return this.nodes[index];
},

// Generate a request using a URL.
updateRequest: function() {
    var req = new XMLHttpRequest();
    // req.responseType = 'json';
    req.open('GET', this.config.httpRequestURL, false);
    req.setRequestHeader('Content-type', 'application/json');

    req.onload  = function() {
        var jsonResponse = JSON.parse(req.response);
        console.log("jsonresponse: ",jsonResponse);
        temperature = jsonResponse['results'][0]['series'][0]['values'][0][1];
        humidity = jsonResponse ['results'][1]['series'][0]['values'][0][1];
        co2 = jsonResponse ['results'][2]['series'][0]['values'][0][1];
        airPressure = jsonResponse ['results'][3]['series'][0]['values'][0][1];
        Log.info({"temperature":temperature,"humidity":humidity,"co2":co2,"airPressure":airPressure});
    };
    req.send();
},

The function getNextValue is used to replace the displayed values each time they change.

The function updateRequest is used to perfom the web request and parse the result. The parsing can be updated according to the result layout.

Creating the display

Finally, the exctrated values from the request are included in the Magic Mirror2 with styles provided with it.

getDom: function () {
    self = this;
    var wrapper = document.createElement("div");
    wrapper.className = "small";
    var percentageLabel = "%";
    var degreeLabel = "°";
    var decimalSymbol= ".";

    /***** WEB REQUEST DISPLAY *****/
    // Temperature displaying for one module
    var temperatureDisplay = document.createElement("div");

        var temperatureValueDisplay=document.createElement("span");
        temperatureValueDisplay.className = "large bright light";
        temperatureValueDisplay.innerHTML=temperature.toFixed(1).replace(".",decimalSymbol) + degreeLabel;
        temperatureDisplay.appendChild(temperatureValueDisplay);

    var humidityco2airPressureDisplay = document.createElement("div");
        // Humidity displaying for one module
        var humidityValueDisplay=document.createElement("span");
        humidityValueDisplay.className = "small bright light";
        humidityValueDisplay.innerHTML=humidity.toFixed(0);
        humidityco2airPressureDisplay.appendChild(humidityValueDisplay);

        var humidityUnitDisplay = document.createElement("span");
        humidityUnitDisplay.className = "xsmall normal light";
        humidityUnitDisplay.innerHTML="%RH   ";
        humidityco2airPressureDisplay.appendChild(humidityUnitDisplay);

        // CO2 displaying for one module
        var co2ValueDisplay=document.createElement("span");
        co2ValueDisplay.className = "small bright light";
        co2ValueDisplay.innerHTML=co2.toFixed(0);
        humidityco2airPressureDisplay.appendChild(co2ValueDisplay);

        var co2UnitDisplay = document.createElement("span");
        co2UnitDisplay.className = "xsmall normal light";
        co2UnitDisplay.innerHTML="ppm   ";
        humidityco2airPressureDisplay.appendChild(co2UnitDisplay);

        // Air pressure displaying for one module
        var airPressureValueDisplay=document.createElement("span");
        airPressureValueDisplay.className = "small bright light";
        airPressureValueDisplay.innerHTML=airPressure.toFixed(0);
        humidityco2airPressureDisplay.appendChild(airPressureValueDisplay);

        var airPressureUnitDisplay = document.createElement("span");
        airPressureUnitDisplay.className = "xsmall normal light";
        airPressureUnitDisplay.innerText="mBar";
        humidityco2airPressureDisplay.appendChild(airPressureUnitDisplay);

    wrapper.appendChild(temperatureDisplay);
    wrapper.appendChild(humidityco2airPressureDisplay);

    return wrapper;
    }

Let’s focus on the temperature displaying style as an example.

// Temperature displaying for one module
var temperatureDisplay = document.createElement("div");

    var temperatureValueDisplay=document.createElement("span");
    temperatureValueDisplay.className = "large bright light";
    temperatureValueDisplay.innerHTML=temperature.toFixed(1).replace(".",decimalSymbol) + degreeLabel;
    temperatureDisplay.appendChild(temperatureValueDisplay);

wrapper.appendChild(temperatureDisplay);

First, a global variable temperatureDisplay is created. It contains all the displayed elements related to temperature:

var temperatureDisplay = document.createElement("div");

In this example, only one element temperatureValueDisplay is created:

var temperatureValueDisplay=document.createElement("span");

Then displaying styles are applied on this element:

temperatureValueDisplay.className = "large bright light";

The styles are available in the main.css file:

.large {
    font-size: 65px;
    line-height: 65px;
}
.bright {
    color: #fff;
}

.light {
    font-family: "Roboto Condensed", sans-serif;
    font-weight: 300;
}

The next row is the concatenation of the temperature value and the degree label. The decimal symbol is updated.

temperatureValueDisplay.innerHTML=temperature.toFixed(1).replace(".",decimalSymbol) + degreeLabel;

The last raw append the element temperatureValueDisplay to the variable temperatureDisplay

Finally, the variable temperatureDisplay is wrapped and returned by the function getDom for displaying.

The display of this module is:

_images/MMM-dataFromOneModule.png

MQTT subscription

Events can be configured in the sensor. When a configured event occurs to the sensor, it is stored in a MQTT database. For the complete list of events and how to configure them, read the section settings in Commands and settings. In this example, the Magic Mirror2 Module perfoms a MQTT subscription to events sent by a sensor.

Configuration file script

Magic Mirror2 comes with a config.js with a list of default modules. To display the result of a MQTT request, the corresponding module need to be added in the file.

{
module: 'MMM-MqttTap', // Display a message on the screen after a specific event triggering
position: 'bottom_right',
config: {
    /***** GENERAL CONFIG VALUES *****/
    updateInterval:0,
    animationSpeed: 0,

    /***** MQTT REQUEST CONFIG VALUES *****/
    mqttServer: {

        address: 'mqtt.descamps.technology',
        port: '8883',
        user: 'someUser',
        password: 'somePassword',
        subscriptions: [
            {
            topic: '/someUDID/event',
            }
        ]
    }
}
},

Three kind of parameters are defined in the config.js file:

1- The name of the module. It is the same as the script.js which actually perform the request.

2- The position correspond to the screen area where the module will be displayed.

3- Config is a list of customized variable used by the script to perform the request.

In this example, the config variable decribes the MQTT server informations and topic on which the Magic Mirror module subscribes.

Magic Mirror Module script

Default parameters

The variables defined in the config.js file are declared in the main script with default values.

defaults: {
    updateInterval: 20000,
    animationSpeed: 0,

    /***** MQTT REQUEST DEFAULT VALUES *****/
    mqttServer: {},
},

- *updateInterval* corresponds the waiting time between two web request,
- *animationSpeed* is the speed at which the text will appear on the screen,
- *mqttServer* regroups all the informations related to the MQTT server. It is empty by default.
Specific styles

Magic Mirror2 comes with a set of styles, available in the file main.css Specific styles can be created for a Magic Mirror Module. These styles can be used thanks to the following function and genericModule.css file.

// Define specific styles of the module.
getStyles: function() {
    return ["genericModule.css"];
},

In this example, no specific styles are created.

Starting the module

This function is used to launch the module functionnality when Magic Mirror2 starts. In this example, it starts the connectin to MQTT server

// Start the module
start: function () {
    console.log(this.name + " started.");

    /***** Define the options for displaying *****/
    var self = this;
    var context= this;
    setInterval(function () {
        context.updateDom(self.config.animationSpeed);
        context.updateRequest(); // WEB request
        context.getJson(); // Local file request
    },this.config.updateInterval);

    /***** MQTT REQUEST START *****/
    var s = this.config.mqttServer;
    console.log(this.name + ": Adding config for " + s.address + " port " + s.port + " user " + s.user);
    this.openMqttConnection();
},
Send MQTT server parameters to the node helper

The purpose of the following function is to transmit the MQTT server credentials to the script nodeHelper.js. This script will receive the credentials, open the connection and subscribe to the MQTT topic. Read the nodeHelper section below for details.

// Send MQTT server configuration to the node helper
openMqttConnection: function () {
    this.sendSocketNotification("MQTT_CONFIG", this.config);
},
Analyze the received events from MQTT

When an event occurs on the subscribed topic, the node helper receive it and transmit it to the main script. In this example, when a specific event arrives, a message is displayed on the screen. The MQTT event is identified using a notification MQTT_PAYLOAD, created in the node helper and sent with the event payload.

socketNotificationReceived: function (notification, payload) {
// console.log(self.name + ": socketNotificationReceived 1>>>>" + payload.value);

    /***** MQTT REQUEST PAYLOAD ANALYSIS *****/
    if (notification === "MQTT_PAYLOAD") {
        var value = JSON.parse(payload.value);
        this.eventIdentification = value.eventId;
        console.log("EventID is: " + this.eventIdentification);

        if (this.eventIdentification === 54 ) {
            this.eventAction = "Single Tap";

        } else if (this.eventIdentification === 55 ) {
            this.eventAction = "Double Tap";

        }else{
            this.eventAction = " Event unknown";
            }
    }
},
Creating the display

The message defined by the event is displayed on the screen using the function getDom

getDom: function () {
self = this;
var wrapper = document.createElement("div");
wrapper.className = "small";

/***** MQTT REQUEST DISPLAY *****/
var eventDisplay = document.createElement("div");

    // action linked to the event number
    var eventActionValueDisplay=document.createElement("div");
    eventActionValueDisplay.className = "small bright light";
    eventActionValueDisplay.innerHTML= this.eventAction;
    eventDisplay.appendChild(eventActionValueDisplay);

wrapper.appendChild(eventDisplay);

return wrapper;
}
First, a global variable eventDisplay is created. It contains all the displayed elements related to the MQTT event

var eventDisplay = document.createElement("div");

Then, the element eventActionValueDisplay is defined. It corresponds to the message created according to the event number.

var eventActionValueDisplay=document.createElement("div");

A displaying style is applied to the element.

eventActionValueDisplay.className = "small bright light";

These style are available in the main.css file:

.small {
    font-size: 20px;
    line-height: 25px;
}
.bright {
    color: #fff;
}
.light {
    font-family: "Roboto Condensed", sans-serif;
    font-weight: 300;
}
The actual message is added in the element:

eventActionValueDisplay.innerHTML= this.eventAction;

The element is wrapped into the display variable.

eventDisplay.appendChild(eventActionValueDisplay);

Finally, the variable eventDisplay is wrapped and returned by the function for display

wrapper.appendChild(eventDisplay);

Node helper script

Thibaud will describe the content of the node helper.

Local JSON file request

This request describes how to perform a Magic Mirror query on a local file.

Configuration file script

Magic Mirror2 comes with a config.js with a list of default modules. To display the result of a local file request, the corresponding module need to be added in the file.

{
module: 'MMM-roomStatistics24hours', // Displays the percentage usage of the room by people and light
position: 'bottom_right',
config: {
    /***** GENERAL CONFIG VALUES *****/
    updateInterval:10000,
    animationSpeed: 0,

    /***** LOCAL JSON FILE CONFIG VALUES *****/
    url: 'http://localhost:8080/modules/outputJson/IJsonOutputMeetingRoomAction.json', // Meeting Room usage Json
    url1: 'http://localhost:8080/modules/outputJson/IJsonOutputTemp24Action_100101f9be35.json', // Temperature Json
    url2: 'http://localhost:8080/modules/outputJson/IJsonOutputHumi24Action_100101f9be35.json', // Humidity Json
}
},

Three kind of parameters are defined in the config.js file:

1- The name of the module. It is the same as the script.js which actually perform the request.

2- The position correspond to the screen area where the module will be displayed.

3- Config is a list of customized variable used by the script to perform the request.

In this example, the config variable decribes the URL of the local file on which the request is performed.

Magic Mirror Module script

Default parameters

defaults: {
updateInterval: 20000,
animationSpeed: 0,

/***** LOCAL JSON FILE REQUEST DEFAULT VALUES *****/
url: "",
url1:"",
url2:"",

},
Specific styles

Magic Mirror2 comes with a set of styles, available in the file main.css Specific styles can be created for a Magic Mirror Module. These styles can be used thanks to the following function and genericModule.css file.

// Define specific styles of the module.
getStyles: function() {
    return ["genericModule.css"];
},

In this example, no specific styles are created.

Starting the module

This function is used to launch the module functionnality when Magic Mirror2 starts. In this example, it starts a local file request

// Start the module
start: function () {
console.log(this.name + " started.");

/***** Define the options for displaying *****/
var self = this;
var context= this;
setInterval(function () {
    context.updateDom(self.config.animationSpeed);
    context.updateRequest(); // WEB request
    context.getJson(); // Local file request
},this.config.updateInterval);

/***** LOCAL JSON FILE REQUEST *****/
this.getJson();
},

Send local file url to the node helper

// Request for a local Json file
    getJson: function () {
this.sendSocketNotification("GET_JSON_FILE", this.config.url);
this.sendSocketNotification("GET_JSON_FILE", this.config.url2);
this.sendSocketNotification("GET_JSON_FILE", this.config.url3);
},

Analyze the informations coming from a local JSON file

socketNotificationReceived: function (notification, payload) {
// console.log(self.name + ": socketNotificationReceived 1>>>>" + payload.value);

/***** LOCAL JSON FILE REQUEST ANALYSIS *****/
if (notification === "JSON_FILE_RESULT") {
var json = JSON.parse(payload.value);
// console.log("json from local file: ",json);

            if(payload.url==this.config.url) {
                    this.meanTemperature1 = json["module"][0]["meanTemperature"];
                    console.log("meanTemperature of the module is : " + this.meanTemperature1 );

            } else if(payload.url==this.config.url2) {
                    this.averageHumidity1 = json["module"][0]["averageHumidity"];
                    console.log("averageHumidity1 of the module is : " + this.averageHumidity1);

            } else if(payload.url==this.config.url3) {
                    this.meetingRoomUsingPresentage = json["message"][0]["meetingRoomUsingPresentage"];
                    console.log("meeting Room Using Precentage is : " + this.meetingRoomUsingPresentage);
            }}},

Creating the display

getDom: function () {
self = this;
var wrapper = document.createElement("div");
wrapper.className = "small";
var percentageLabel = "%";
var degreeLabel = "°";
var decimalSymbol= ".";

/***** LOCAL JSON FILE REQUEST DISPLAY *****/
var headerMessage = document.createElement("div");

    var roomUsageHeader=document.createElement("span");
    roomUsageHeader.className = "medium bright thin";
    roomUsageHeader.innerHTML= 'Room statistics';
    headerMessage.appendChild(roomUsageHeader);

    var roomUsageHeader2=document.createElement("div");
    roomUsageHeader2.className = "medium bright thin";
    roomUsageHeader2.innerHTML= 'Last 24 hours';
    headerMessage.appendChild(roomUsageHeader2);

var peoplePresence = document.createElement("div");

    var peopleMessage=document.createElement("span");
    peopleMessage.className = "small bright thin";
    peopleMessage.innerHTML= 'Occupancy ';
    peoplePresence.appendChild(peopleMessage);

    var peopleValue=document.createElement("span");
    peopleValue.className = "medium bright light";
    peopleValue.innerHTML= this.meetingRoomUsingPresentage.toFixed(0);
    peoplePresence.appendChild(peopleValue);

    var peopleValueUnit=document.createElement("span");
    peopleValueUnit.className = "small normal light";
    peopleValueUnit.innerHTML= percentageLabel;
    peoplePresence.appendChild(peopleValueUnit);

var lightUsage = document.createElement("div");

    var lightMessage=document.createElement("span");
    lightMessage.className = "small bright thin";
    lightMessage.innerHTML= 'Lights ';
    lightUsage.appendChild(lightMessage);

    var lightValue=document.createElement("span");
    lightValue.className = "medium bright light";
    lightValue.innerHTML= this.lightIntensityLevelAbove100Percentage.toFixed(0);
    lightUsage.appendChild(lightValue);

    var lightValueUnit=document.createElement("span");
    lightValueUnit.className = "small normal light";
    lightValueUnit.innerHTML= percentageLabel;
    lightUsage.appendChild(lightValueUnit);

wrapper.appendChild(headerMessage);
wrapper.appendChild(peoplePresence);
wrapper.appendChild(lightUsage);

return wrapper;
}

Node helper script

Thibaud will describe the content of the node helper.

Sample code

Thibaud will add soon the sample code of our use of the Magic Mirror.