Raspbian Jessie as OpenHAB + MQTT Server: Part 2: Add OpenHAB

I’ll be very brief on Part 2:  Since I already wrote extensively on the install and configuration:

sudo apt-get update
 sudo apt-get install oracle-java8-jdk
sudo update-java-alternatives -s jdk-8-oracle-arm-vfp-hflt
wget -qO - 'https://bintray.com/user/downloadSubjectPublicKey?username=openhab' | sudo apt-key add -
echo "deb http://dl.bintray.com/openhab/apt-repo stable main" | sudo tee /etc/apt/sources.list.d/openhab.list
sudo apt-get update
sudo apt-get install openhab-runtime
sudo service openhab status
sudo service openhab start

See https://openhardwarecoza.wordpress.com/2015/03/29/openhab-mqtt-arduino-and-esp8266-part-1-setting-up-your-environment/ for more details on configuring OpenHAB

 

Advertisements

PIR sensor, ESP8266 and MQTT

MQTT

Install MQTT and start a test subscribe:

 

sudo apt-get install mosquitto mosquitto-clients
mosquitto_sub -t outTopic

Arduino/ESP8266 Sketch

 

On the ESP8266:  Install the following sketch using Arduino ( Note I won’t go into detail on setting up Arduino for ESP8266, lots of articles on the Internet already explain that)

NB: Do make sue you install the MQTT library: https://github.com/knolleary/pubsubclient

 

/*
 Basic ESP8266 MQTT example

 This sketch demonstrates the capabilities of the pubsub library in combination
 with the ESP8266 board/library.

 It connects to an MQTT server then:
  - publishes "hello world" to the topic "outTopic" every two seconds
  - subscribes to the topic "inTopic", printing out any messages
    it receives. NB - it assumes the received payloads are strings not binary
  - If the first character of the topic "inTopic" is an 1, switch ON the ESP Led,
    else switch it off

 It will reconnect to the server if the connection is lost using a blocking
 reconnect function. See the 'mqtt_reconnect_nonblocking' example for how to
 achieve the same result without blocking the main loop.

 To install the ESP8266 board, (using Arduino 1.6.4+):
  - Add the following 3rd party board manager under "File -> Preferences -> Additional Boards Manager URLs":
       http://arduino.esp8266.com/stable/package_esp8266com_index.json
  - Open the "Tools -> Board -> Board Manager" and click install for the ESP8266"
  - Select your ESP8266 in "Tools -> Board"

*/

#include <ESP8266WiFi.h>
#include <PubSubClient.h>

// Update these with values suitable for your network.

const char* ssid = "openhardwarecoza";
const char* password = "novell1234";
const char* mqtt_server = "192.168.1.13";
int counter = 0;
int previousReading = LOW;



WiFiClient espClient;
PubSubClient client(espClient);
long lastMsg = 0;
char msg[50];
int value = 0;

void setup_wifi() {

  delay(10);
  // We start by connecting to a WiFi network
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);

  WiFi.begin(ssid, password);

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }

  Serial.println("");
  Serial.println("WiFi connected");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());
}

void callback(char* topic, byte* payload, unsigned int length) {
  Serial.print("Message arrived [");
  Serial.print(topic);
  Serial.print("] ");
  for (int i = 0; i < length; i++) {
    Serial.print((char)payload[i]);
  }
  Serial.println();

  // Switch on the LED if an 1 was received as first character
  if ((char)payload[0] == '1') {
    digitalWrite(BUILTIN_LED, LOW);   // Turn the LED on (Note that LOW is the voltage level
    // but actually the LED is on; this is because
    // it is acive low on the ESP-01)
  } else {
    digitalWrite(BUILTIN_LED, HIGH);  // Turn the LED off by making the voltage HIGH
  }

}

void reconnect() {
  // Loop until we're reconnected
  while (!client.connected()) {
    Serial.print("Attempting MQTT connection...");
    // Attempt to connect
    if (client.connect("ESP8266Client")) {
      Serial.println("connected");
      // Once connected, publish an announcement...
      client.publish("outTopic", "hello world");
      // ... and resubscribe
      client.subscribe("inTopic");
    } else {
      Serial.print("failed, rc=");
      Serial.print(client.state());
      Serial.println(" try again in 5 seconds");
      // Wait 5 seconds before retrying
      delay(5000);
    }
  }
}

void setup() {
  pinMode(BUILTIN_LED, OUTPUT);     // Initialize the BUILTIN_LED pin as an output
  Serial.begin(115200);
  setup_wifi();
  client.setServer(mqtt_server, 1883);
  client.setCallback(callback);
  pinMode(12, INPUT);
}

void loop() {

  if (!client.connected()) {
    reconnect();
  }
  client.loop();
  int reading = digitalRead(12);
  Serial.println(reading);
  if (previousReading == LOW && reading == HIGH) {
    counter++;
    client.publish("outTopic", "Motion Detected");  
    Serial.print("Triggered ");
    Serial.print(counter);
    Serial.print("x Times! ");
    delay(1000);

  }
  previousReading = reading;

}

Wiring

Connect VCC on the IR Sensor to 5v (NB it has an onboard 3.3v regulator, so the output voltage is 3.3v (safe for ESP) but it needs to be powered off 5v!)
Connect Signal to pin 12 on the ESP8266 (or change the Arduino code to the pin where you wired it to)
Connect GND to GND

Order PIR Sensors?

AliExpress.com Product – 1pcs High Quality HC-SR501 Infrared PIR Motion Sensor Module For Arduino Raspberry pi

AliExpress.com Product – New HC-SR501 Adjust IR Pyroelectric Infrared PIR Motion Sensor Detector Module SG039-SZ

#include

OpenHAB and MiLight – Smart LED bulbs at a price even you can afford!

Recently I discovered that OpenHAB comes with a Binding to support cheap chinese Milight Smart LED bulbs:

milight1

You need:

Bulbs + Wifi Bridge:  AliExpress.com 4pcs/lot LED RGBW bulb 6W E27 base Milight AC85-265V & Four Zone Remote & WiFi Controller

or

4x 2.4G Wireless MiLight RGBW Warm White E27 9W LED Bulb Smart Light + Milight WiFi Controller iOS/Android

and the MiLight Binding from https://github.com/openhab/openhab/wiki/Milight-Binding

Here’s some Youtube videos I found of other people playing with MiLight:

Can’t wait for get some!  If you want to support the work I do consider donating me a set?

Have a good one!

OpenHAB and HTTP Toggle Buttons

Yesterday, one of my readers contacted me to ask:

do you have en example of a switch calling a url? failing quite badly at getting it to work

So, herewith I oblige:   Here’s how I would set it up:

 sudo vi /opt/openhab/configurations/items/dolphin.items

In my Items file, I add an item:

Switch Toggle "Toggle" (all) { autoupdate="true" }

Next, I add this item to my Sitemap:

sudo vi /opt/openhab/configurations/sitemaps/dolphin.sitemap

and add it like:

 Switch item=Toggle label="Toggle"

Next, we need to create a rule to manage this toggling action into HTTP requests:

sudo vi /opt/openhab/configurations/rules/httpreq.rules

and inside this file I add two rules, one to catch the ON and one to catch the OFF:

rule updateToggleOn
when
 Item Toggle received command ON
then
 sendHttpGetRequest("http://192.168.1.5/?pin=ON")
end
rule updateToggleOff
when
 Item Toggle received command OFF
then
 sendHttpGetRequest("http://192.168.1.5/?pin=OFF")
end

Now, in this case the device I am controlling is a simple ESP8266 WebApp from https://github.com/nodemcu/nodemcuirmware/blob/master/lua_examples/webap_toggle_pin.lua to demonstrate the idea to Michael.  Since its this simple sketch, you can expect a cosmetic error to popup in openhab.log:

05:37:12.169 ERROR o.openhab.io.net.http.HttpUtil[:230]- Fatal protocol violation: org.apache.commons.httpclient.ProtocolException: The server 192.168.1.5 failed to respond with a valid HTTP response

05:37:12.169 ERROR o.openhab.io.net.http.HttpUtil[:230]- Fatal protocol violation: org.apache.commons.httpclient.ProtocolException: The server 192.168.1.5 failed to respond with a valid HTTP response

The ESP8266 sketch doesnt return a valid HTTP header. No worries though, ignore the error – it still works!

So, the above example takes care of a device needing an “on” and “off” …

But what about a a “toggle” or “momentary” button (Garage door opener for example?)

Easy:  One simple change in the Items file and one less rule:

Switch Toggle "Toggle" (all) { autoupdate="false" }

Setting Autoupdate to False it will automatically revert to the OFF position after clicking the switch…

and in the rules:

rule updateToggleOn
when
 Item Toggle received command ON
then
 sendHttpGetRequest("http://192.168.1.5/?toggle=TRUE")
end

We only need the first rule, the On state – handle the on as your toggle command…

Easy!

OPENHAB, MQTT, ARDUINO AND ESP8266: PART 9: CUSTOM CIRCUIT BOARDS

Finally arrived, soldered up and tested!

2015 - 1 (1)

Schematics, Board and Gerbers are released as open source hardware under a CC-BY-SA licence and you can find it on my GitHub repo at https://github.com/openhardwarecoza/esp8266-PROJECTS/tree/master/ESP8266-%204%20channel%20mosfet%20switch

2015 - 1

OPENHAB, MQTT, ARDUINO AND ESP8266: PART 8: RGB+W LED Strips

Lets kickoff with a demo video!

And the code as always

(ESP8266 with Arduino)

#include <ESP8266WiFi.h>
#include <PubSubClient.h>


// #define PWMRANGE 255
// #define PWM_VALUE 31
//int gamma_table[PWM_VALUE+1] = {
// 0, 1, 2, 2, 2, 3, 3, 4, 5, 6, 7, 8, 10, 11, 13, 16, 19, 23,
// 27, 32, 38, 45, 54, 64, 76, 91, 108, 128, 152, 181, 215, 255
//};
 
 #define PWM_VALUE 63
//int gamma_table[PWM_VALUE+1] = {
// 0, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 4, 4, 5, 5, 6, 6, 7, 8, 9, 10,
// 11, 12, 13, 15, 17, 19, 21, 23, 26, 29, 32, 36, 40, 44, 49, 55,
// 61, 68, 76, 85, 94, 105, 117, 131, 146, 162, 181, 202, 225, 250,
// 279, 311, 346, 386, 430, 479, 534, 595, 663, 739, 824, 918, 1023
//};

int gamma_table[PWM_VALUE+1] = {
 0, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 8, 9, 10,
 11, 12, 13, 15, 17, 19, 21, 23, 26, 29, 32, 36, 40, 44, 49, 55,
 61, 68, 76, 85, 94, 105, 117, 131, 146, 162, 181, 202, 225, 250,
 279, 311, 346, 386, 430, 479, 534, 595, 663, 739, 824, 918, 1023
};



// RGB FET
#define redPIN 12
#define greenPIN 14
#define bluePIN 16


// W FET
#define w1PIN 13

// note 
// TX GPIO2 @Serial (Serial ONE)
// RX GPIO3 @Serial 

const char *ssid = "openhardwarecoza"; // your network SSID (name)
const char *pass = "novell1234"; // your network password


// Update these with values suitable for your network.
IPAddress server(192, 168, 1, 200);

void callback(const MQTT::Publish& pub) {
 Serial.print(pub.topic());
 Serial.print(" => ");
 Serial.println(pub.payload_string());
 
 String payload = pub.payload_string();

if(String(pub.topic()) == "/openHAB/RGB_2/Color"){
 int c1 = payload.indexOf(';');
 int c2 = payload.indexOf(';',c1+1);
 
 int red = map(payload.toInt(),0,100,0,PWM_VALUE);
 red = constrain(red,0,PWM_VALUE);
 int green = map(payload.substring(c1+1,c2).toInt(),0,100,0,PWM_VALUE);
 green = constrain(green, 0, PWM_VALUE);
 int blue = map(payload.substring(c2+1).toInt(),0,100,0,PWM_VALUE);
 blue = constrain(blue,0,PWM_VALUE);
 
 red = gamma_table[red];
 green = gamma_table[green];
 blue = gamma_table[blue];
 
 
 analogWrite(redPIN, red);
 analogWrite(greenPIN, green);
 analogWrite(bluePIN, blue);

// Serial.println(red);
// Serial.println(green);
// Serial.println(blue);
 }
 else if(String(pub.topic()) == "/openHAB/RGB_2/SW1"){
 int value = map(payload.toInt(),0,100,0,PWM_VALUE);
 value = constrain(value,0,PWM_VALUE);
 value = gamma_table[value];
 analogWrite(w1PIN, value);
 //Serial.println(value);
 }
 
}

PubSubClient client(server);

void setup()
{
 
 pinMode(redPIN, OUTPUT);
 pinMode(greenPIN, OUTPUT);
 pinMode(bluePIN, OUTPUT);
 pinMode(w1PIN, OUTPUT);
 
 // Setup console
 Serial.begin(115200);
 delay(10);
 Serial.println();
 Serial.println();

 client.set_callback(callback);

 WiFi.begin(ssid, pass);


 
 while (WiFi.status() != WL_CONNECTED) {

 
 delay(500);
 Serial.print(".");
 
 }
 
 Serial.println("");
 
 Serial.println("WiFi connected");
 Serial.println("IP address: ");
 Serial.println(WiFi.localIP());
 
 
 if (client.connect("WiFi_RGB_2")) {
 client.subscribe("/openHAB/RGB_2/Color");
 client.subscribe("/openHAB/RGB_2/SW1");
 Serial.println("MQTT connected"); 
 }

 Serial.println("");
}


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

 

In your Items configuration, add the following

// WiFi RGB 2
Group WIFI_RGB_2 "WiFi RGB 2" (All)
Color fWIFI_RGB_2 "RGB" <slider> (WIFI_RGB_2)
String WIFI_RGB_2_RGB (WIFI_RGB_2) {mqtt=">[broker:/openHAB/RGB_2/Color:command:*:default]"}
Switch WIFI_RGB_2_Switch1 "W1" (WIFI_RGB_2) {mqtt=">[broker:/openHAB/RGB_2/SW1:command:ON:100],>[broker:/openHAB/RGB_2/SW1:command:OFF:0]"}

New to what we’ve done so far, we need to add a Rule as well into a new file under /opt/openhab/configuration/rules/dolphin.rules for example.

This rule takes the inputs from the Item above and transforms it into RGB values to send over MQTT

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

var HSBType hsbValue
var int redValue
var int greenValue
var int blueValue
var String RGBvalues

rule "Set RGB 2 value"
 when
 Item fWIFI_RGB_2 changed
 then
 hsbValue = fWIFI_RGB_2.state as HSBType

 redValue = hsbValue.red.intValue
 greenValue = hsbValue.green.intValue
 blueValue = hsbValue.blue.intValue


 RGBvalues= redValue.toString + ";" + greenValue.toString + ";" + blueValue.toString
 sendCommand( WIFI_RGB_2_RGB, RGBvalues )

 logInfo( "fWIFI_RGB_2", RGBvalues )
end

Finally, add the new item to your sitemap:

Frame label="RGB" {
Colorpicker item=fWIFI_RGB_2 icon="slider"
Switch item=WIFI_RGB_2_Switch1 label="Ch4"
}

rgb

Note: Based off code written by Andreas Holldorfer (http://chaozlabs.blogspot.co.za/2015/08/esp8266-in-wild-wifi-led-controller-hack.html) but adapted to my own PCBs

Updated MQTT/ESP8266 sketch to automatically reconnect Wifi and MQTT if the Wifi went down

I made a few changes to the m:on(“offline”) function to handle failed Wifi connections better.

I had a few issues where my wifi router restarted, upon restarting (with the old sketch on the ESP07) once the wifi was back up, it reconnected to the Wifi though the magic of NodeMCU’s wifi.sta.autoconnect(1) functionality.  However despite the Wifi reconnecting, the MQTT stopped working.

I added a new function called reconnect() to handle the dropped connection.   It sets up a timer action to check when the Wifi is up again (Status = 5 and IP is not = null) then reruns the MQTT connect/subscribe:

function reconnect()
 print ("Waiting for Wifi")
 if wifi.sta.status() == 5 and wifi.sta.getip() ~= nil then 
 print ("Wifi Up!")
 tmr.stop(1) 
 m:connect(Broker, 1883, 0, function(conn) 
 print("Mqtt Connected to:" .. Broker) 
 mqtt_sub() --run the subscription function 
 end)
 end
 end

Here’s the full sketch now

  • Elegant reconnect after wifi fails
  • 7 channels
  • /dev1/ch1-7 mqtt names
-- One time ESP Setup --
wifi.setmode(wifi.STATION)
wifi.sta.config ( "openhardwarecoza" , "novell1234" ) 
print(wifi.sta.getip())


 Broker="192.168.1.200"
 --GPIO2 is connected to LED via resistor, initially off 
 gpio.mode(1,gpio.OUTPUT) 
 gpio.write(1,gpio.LOW) 
 gpio.mode(2,gpio.OUTPUT) 
 gpio.write(2,gpio.LOW) 
 gpio.mode(3,gpio.OUTPUT) 
 gpio.write(3,gpio.LOW) 
 gpio.mode(4,gpio.OUTPUT) 
 gpio.write(4,gpio.LOW) 
 gpio.mode(5,gpio.OUTPUT) 
 gpio.write(5,gpio.LOW) 
 gpio.mode(6,gpio.OUTPUT) 
 gpio.write(6,gpio.LOW) 
 gpio.mode(7,gpio.OUTPUT) 
 gpio.write(7,gpio.LOW)

 function reconnect()
 print ("Waiting for Wifi")
 if wifi.sta.status() == 5 and wifi.sta.getip() ~= nil then 
 print ("Wifi Up!")
 tmr.stop(1) 
 m:connect(Broker, 1883, 0, function(conn) 
 print("Mqtt Connected to:" .. Broker) 
 mqtt_sub() --run the subscripion function 
 end)
 end
 end
 m = mqtt.Client("KITCHEN", 180, "user", "password") 
 m:lwt("/lwt", "ESP8266", 0, 0) 
 m:on("offline", function(con) 
 print ("Mqtt Reconnecting...") 
 tmr.alarm(1, 10000, 1, function() 
 reconnect()
 end) 
 end)
 

 
 -- on publish message receive event 
 m:on("message", function(conn, topic, data) 
 print("Recieved:" .. topic .. ":" .. data) 
 
 if (data=="ON") and (topic=="/dev1/ch1/com") then 
 print("Enabling Output") 
 gpio.write(1,gpio.HIGH) 
 m:publish("/dev1/ch1/state","ON",0,0) 
 elseif (data=="OFF") and (topic=="/dev1/ch1/com") then 
 print("Disabling Output") 
 gpio.write(1,gpio.LOW) 
 m:publish("/dev1/ch1/state","OFF",0,0)
 elseif (data=="ON") and (topic=="/dev1/ch2/com") then 
 print("Enabling Output") 
 gpio.write(2,gpio.HIGH) 
 m:publish("/dev1/ch2/state","ON",0,0) 
 elseif (data=="OFF") and (topic=="/dev1/ch2/com") then 
 print("Disabling Output") 
 gpio.write(2,gpio.LOW) 
 m:publish("/dev1/ch2/state","OFF",0,0)
 elseif (data=="ON") and (topic=="/dev1/ch3/com") then 
 print("Enabling Output") 
 gpio.write(3,gpio.HIGH) 
 m:publish("/dev1/ch3/state","ON",0,0) 
 elseif (data=="OFF") and (topic=="/dev1/ch3/com") then 
 print("Disabling Output") 
 gpio.write(3,gpio.LOW) 
 m:publish("/dev1/ch3/state","OFF",0,0)
 elseif (data=="ON") and (topic=="/dev1/ch4/com") then 
 print("Enabling Output") 
 gpio.write(4,gpio.HIGH) 
 m:publish("/dev1/ch4/state","ON",0,0) 
 elseif (data=="OFF") and (topic=="/dev1/ch4/com") then 
 print("Disabling Output") 
 gpio.write(4,gpio.LOW) 
 m:publish("/dev1/ch4/state","OFF",0,0)
 elseif (data=="ON") and (topic=="/dev1/ch5/com") then 
 print("Enabling Output") 
 gpio.write(5,gpio.HIGH) 
 m:publish("/dev1/ch5/state","ON",0,0) 
 elseif (data=="OFF") and (topic=="/dev1/ch5/com") then 
 print("Disabling Output") 
 gpio.write(5,gpio.LOW) 
 m:publish("/dev1/ch5/state","OFF",0,0)
 elseif (data=="ON") and (topic=="/dev1/ch6/com") then 
 print("Enabling Output") 
 gpio.write(6,gpio.HIGH) 
 m:publish("/dev1/ch6/state","ON",0,0) 
 elseif (data=="OFF") and (topic=="/dev1/ch6/com") then 
 print("Disabling Output") 
 gpio.write(6,gpio.LOW) 
 m:publish("/dev1/ch6/state","OFF",0,0)
 elseif (data=="ON") and (topic=="/dev1/ch7/com") then 
 print("Enabling Output") 
 gpio.write(7,gpio.HIGH) 
 m:publish("/dev1/ch7/state","ON",0,0) 
 elseif (data=="OFF") and (topic=="/dev1/ch7/com") then 
 print("Disabling Output") 
 gpio.write(7,gpio.LOW) 
 m:publish("/dev1/ch7/state","OFF",0,0) 
 end 
 end) 
 
 
 function mqtt_sub() 
 m:subscribe("/dev1/#",0, function(conn) 
 print("Mqtt Subscribed to OpenHAB feed for device KITCHEN") 
 end) 
 end 
 
 tmr.alarm(0, 1000, 1, function() 
 print ("Connecting to Wifi... ")
 if wifi.sta.status() == 5 and wifi.sta.getip() ~= nil then 
 print ("Wifi connected")
 tmr.stop(0) 
 m:connect(Broker, 1883, 0, function(conn) 
 print("Mqtt Connected to:" .. Broker) 
 mqtt_sub() --run the subscription function 
 end) 
 end
 
 end)