Saturday, February 7, 2015

ESP8266 and OpenHAB

ESP8266, MQTT and OpenHAB


Here is a quick little demo on how to use the ESP8266 as an ultra cheap ($3) sensor/control node for OpenHAB.

Setup

ESP8266 (ESP-01) with nodemcu LUA firmware (1/24/2015 build or later)
Mosquitto (or equivalent) mqtt broker running on your network (stock config)
OpenHAB installed and running the demo site (add all MQTT modules)

Circuit

This represents an independently controlled device that you also want to also be able to view/control in OpenHAB. The ESP-01 only has 2 available GPIO pins so this setup connects a button to GPIO0 (must be high on boot) and a LED on GPIO2. Standard power, enable and serial connections not displayed.
Basic circuit - Switch on GPIO0, LED on GPIO2

Procedure


Load the following code on the ESP8266

(See updated post for latest code)

This code is pretty basic and is hard coded to control one of the OpenHAB demo items (FF bathroom ceiling light). Before uploading replace the two instances of the mqtt broker IP with your value. This assumes you have a working LUA instance (1/24/2015 build or greater) and it is already configured to connect to your wireless network.

I used ESPlorer to load the files 

mqtt.lua

gpio.mode(3,gpio.INPUT,gpio.PULLUP)
gpio.mode(4,gpio.OUTPUT)
gpio.write(4,gpio.LOW)

m = mqtt.Client("ESP8266", 180, "user", "password")
m:lwt("/lwt", "ESP8266", 0, 0)

m:on("offline", function(con) 
     print ("reconnecting...") 
     print(node.heap())
     tmr.alarm(1, 10000, 0, function()
          m:connect("192.168.0.32", 1883, 0)
     end)
end)

gpio.trig(3, "down",function (level)
      local PinValue=gpio.read(4)
      --Change the state
      if (PinValue==1) then
         --The read resets the output to 0, put it back
          gpio.write(4,0)
          print("Light was on, turn off")    
          m:publish("/openHAB/in/Light_FF_Bath_Ceiling/state","OFF",0,0)
      else
          gpio.write(4,1)
          print("Light was off, turn on")    
          m:publish("/openHAB/in/Light_FF_Bath_Ceiling/state","ON",0,0)
       end
end)

-- on publish message receive event
m:on("message", function(conn, topic, data) 
     print("Recieved:" .. topic .. ":" .. data) 
if (data=="ON") then
          print("Enabling LED") 
          gpio.write(4,gpio.HIGH)
          m:publish("/openHAB/in/Light_FF_Bath_Ceiling/state","ON",0,0)
     elseif (data=="OFF") then
          print("Disabling LED") 
          gpio.write(4,gpio.LOW)
          m:publish("/openHAB/in/Light_FF_Bath_Ceiling/state","OFF",0,0)
     else
          print("Invalid - Ignoring") 
     end 
end)

tmr.alarm(0, 1000, 1, function()
 if wifi.sta.status() == 5 then
     tmr.stop(0)
     m:connect("192.168.0.32", 1883, 0, function(conn) 
          print("connected")
          m:subscribe("home/openHAB/out/Light_FF_Bath_Ceiling/command",0, function(conn) 
               m:publish("Debug","Starting",0,0, function(conn) print("sent") end)
          end)
     end)
 end
end)

init.lua

dofile('mqtt.lua')


Test the circuit and mqtt

If you just uploaded the code you need to restart the device and ensure it reports Connected and Sent to the serial out. (LUA is finicky and you may need to reboot a couple times).
At this point it would be good to verify the circuit and MQTT components work. The switch should turn the light on and off and you should see your broker receive messages for each change. (If using Mosquitto run it in verbose mode to see the messages coming in/out. (use -v)).



Configure OpenHAB demo to connect to MQTT and process the ESP messages


Add these lines to the mqtt config section in  
C:\openhab\configurations\openhab.cfg (if under windows)
Replace the IP and port with your MQTT broker details

mqtt:broker.url=tcp://192.168.0.32:1883
mqtt:broker.clientId=openhab
mqtt-eventbus:broker=broker
mqtt-eventbus:commandPublishTopic=home/openHAB/out/${item}/command
mqtt-eventbus:statePublishTopic=home/openHAB/state/${item}/state
mqtt-eventbus:stateSubscribeTopic=/openHAB/in/${item}/state


The lines above create an eventbus which allows you to control all OpenHAB items via mqtt. You can also skip the bus and individually connect a single item to mqtt but this is an easier way to start.


Test it all

Open the demo OpenHAB site (replace localhost with your OpenHAB values)

http://localhost:8080/openhab.app?sitemap=demo

Expand FirstFloor ->Bathroom
If you toggle the Ceiling light it should toggle the state of your led, if you press the button it should control the led and update the page.

Next Steps

OpenHAB seems to assume things work, for instance when you change the light state it actually changes the website state before it receives confirmation from the ESP, this seems less than reliable. I wonder if its possible for it to be in a pending state until the ESP process the change and sends back updated state details. (See Part 2 for details on how this can be fixed)

4 comments:

  1. Is it possible that you showed the configuration openhab.
    I mean specifically the section mtqq.
    Please.

    ReplyDelete
    Replies
    1. I mean configuration mqtt::lwt
      because it does not work for me.

      Delete
  2. Hi. I'm trying to implement your code as a way to connect my own ESP8266 to OPENHAB but I don't quite understand the syntax. What do the lines:
    m:lwt("/lwt", "ESP8266", 0, 0)
    and
    m:on("offline", function(con)
    do? Where can I find documentation on this syntax? Thanks in advance for your help.

    ReplyDelete
    Replies
    1. http://www.nodemcu.com/docs/mqtt-client-module/

      Delete