Previous posts in this project:

 

 

Introduction

 

After setting everything up in last post, I started working on the actual configuration of openHAB and control of the Arduino Yun via MQTT.

 

This is the result so far ...

 

openHAB

 

To be able to control the colors and animations of my digital Christmas tree, I opted for openHAB. I discovered openHAB during the Forget Me Not Design Challenge and like it very much. I find it easy to work with and very versatile (home automation, pet feeding, controlling Christmas lights).

 

In my previous post, I covered the installation and basic configuration. Now, i will document how I've created following interface to control my lights:

Screen Shot 2014-12-23 at 22.16.52.pngScreen Shot 2014-12-23 at 22.16.45.pngScreen Shot 2014-12-23 at 22.17.01.png

 

Items

 

The openHAB documentation on MQTT was sufficient to get me started. It describes how to define items to subscribe to or publish MQTT messages.

 

At this stage, I'm using openHAB to publish values selected in the web interface such as color or animation.

 

Here are some example items (the others are just duplicates of this with other names and topics):

Group All

Color TreeLight "Tree Color" (All)
String TreeLightColor (All) {mqtt=">[eclipse:/fvanTestOpenHAB/tree/color:command:*:default]"}
Number TreeAnimation "Tree Animation" (All) {mqtt=">[eclipse:/fvanTestOpenHAB/tree/animation:command:*:default]"}






 

You'll notice that I've separated the MQTT binding from the color picker. This is because I want to process the color picker's value before sending it over MQTT.

The processing of the color picker's value is done with a rule and then assigned to another item which then triggers the binding.

 

Rules

 

The color picker's default value format was not really usable in my case, so I needed to convert it to something I could use.

Taking the state of the color picker, I extracted the R, G, B and brightness values and put everything in one big string.

 

import org.openhab.core.library.types.*

rule "Set RGB value TreeLight"
when
        Item TreeLight changed
then
        val hsbValue = TreeLight.state as HSBType

        val brightness = hsbValue.brightness.intValue
        val redValue   = ((((hsbValue.red.intValue * 255) / 100) * brightness) / 100).toString
        val greenValue = ((((hsbValue.green.intValue * 255) / 100) * brightness) / 100).toString
        val blueValue  = ((((hsbValue.blue.intValue *255) / 100) * brightness) / 100).toString

        val color = redValue + "," + greenValue + "," + blueValue

        sendCommand( TreeLightColor, color )
end






 

The processed data is then sent to the correct variable, triggering the MQTT binding.

 

Sitemap

 

Finally, there is the sitemap, in charge of the layout of the web interface. This configuration defines how items are ordered in the GUI.

The configuration is very basic and categorises everything per LED strip. You've seen the result in one of the screenshots above.

 

sitemap xmas label="Holiday Lights" {
        Frame label="Topper" {
                Colorpicker item=TopperLight icon="slider"
                Colorpicker item=TopperLight2 icon="slider"
                Selection item=TopperAnimation mappings=[0=OFF, 1=Random_position, 2=Side_fill, 3=Middle_fill, 4=Alternating_colors]
        }
        Frame label="Tree" {
                Colorpicker item=TreeLight icon="slider"
                Selection item=TreeAnimation mappings=[0=OFF, 1=Pulse_slow, 2=Pulse_fast]
        }
}






 

Retain

 

One more thing ... Because some of my functions (animations) take longer to execute, I might miss certain MQTT messages. Also, if power is lost, no state is kept in the Arduino to restore colors and animations.

 

To remedy this, I enabled the option to "retain" messages. This will ensure the MQTT broker will keep the messages even after being sent, so that new or late subscribers are sent the messages again instead of having to wait for an update.

 

This is change in the "openhab.cfg" file:

 

# Optional. True or false. Defines if the broker should retain the messages sent to
# it. Defaults to false.
mqtt:eclipse.retain=true


 

 

Arduino

 

Benjamin Cabé did a great job to help us forward with his post on MQTT with the Paho client.

 

Still, I decided to give another library a try, not because I'm stubborn (perhaps a little bit ) but because I believe in multiple solutions to a certain problem.

This is why I used the following library: Arduino Client for MQTT « knolleary

 

The library is easy to use. The following bit of code reflects the general use:

 

#include <PubSubClient.h>
#include <Bridge.h>
#include <YunClient.h>

YunClient yunClient;
PubSubClient client("iot.eclipse.org", 1883, callback, yunClient);

void callback(char* topic, byte* payload, unsigned int length) {
  // handle message arrived
}

void setup() {
  if (client.connect("arduinoClient")) {
    client.publish("outTopic","hello world");
    client.subscribe("inTopic");
  }
}

void loop() {
  client.loop();
}








 

The hardest part (for me) was converting the received messages in a format I could use to compare/parse/etc ...

As you can see in the code above, the payload and topic are not strings.

 

For example, the MQTT messages sent for color codes, are formatted in RGB format with values ranging from 0, 0, 0 to 255, 255, 255.

 

To parse these, I did the following:

void callback(char* topic, byte* payload, unsigned int length) {
  // check for messages on subscribed topics
  Console.print("Topic: ");
  Console.println(String(topic));

  // check topic to identify type of content
  if(String(topic) == "\/fvanTestOpenHAB\/topper/color") {
    // convert payload to String
    String value = String((char*)payload);

    // split string at every "," and store in proper variable
    // convert final result to integer
    TopperR = value.substring(0,value.indexOf(',')).toInt();
    TopperG = value.substring(value.indexOf(',')+1,value.lastIndexOf(',')).toInt();
    TopperB = value.substring(value.lastIndexOf(',')+1).toInt();

    // print obtained values for debugging
    Console.print("RED: ");
    Console.println(TopperR);

    Console.print("GREEN: ");
    Console.println(TopperG);

    Console.print("BLUE: ");
    Console.println(TopperB);
  }
}








 

I repeated the "if" statement for every topic and am now able to receive all the messages required to apply color and animation of both strips.

 

 

Troubleshooting

 

During testing of this project, there are two "tools" I'm using quite often: MQTT Lens and Arduino Console.

 

MQTT Lens

 

MQTT Lens is an MQTT client capable of subscribing to and publishing MQTT messages.

Screen Shot 2014-12-23 at 21.04.04.png

 

Using this tool, I was able to verify the following:

  • MQTT messages are being sent properly
  • the content of the messages is correct
  • the content is published for the correct topic

 

Arduino Console

 

The Arduino Yun makes it possible to upload sketches wirelessly, so it must be able to debug wirelessly as well.

 

I initially tried to use "Serial.println()" statements for debugging, but that only works when connected to the Yun via USB.

After some digging around, I found the command to be used is very similar: "Console.println()".

 

In short, you can use the console as follows:


#include <Bridge.h>

#include <Console.h>


void setup() {
  Bridge.begin();
  Console.begin();
}

void loop() {
  Console.println("Output");
}











When placed at relevant places in your code, the output becomes very useful:

Screen Shot 2014-12-23 at 21.44.16.png

As you can see in the screenshot above, I'm using the console to verify the incoming MQTT messages on both topic and content.

This is very useful to know if the received content is parsed properly before being passed to the next function.

 

 

Demo

 

Finally, here's a short video demonstrating the control of both analog and digital LED strips connected to the Arduino Yun via openHAB and MQTT.

 

 

 

Happy Holidays

 

If you've come this far reading this blog post (or if you skipped ahead ), I'd like to wish you and your family happy holidays! May they be fun and festive.

 

I'll be back with more blogs for you to read in 2015! But in the mean time, enjoy this painting my 4yo daughter made:

kerstman.png