[OH2] Control ESP8266 Relay using MQTT Eventbus

Thanks for helping out. Here’s the relevant code from mqtt.cfg. I just tested again with the user and pwd lines commented out, same problem.

# URL to the MQTT broker, e.g. tcp://localhost:1883 or ssl://localhost:8883
MQTT.url=tcp://192.168.1.110:1883

# Optional. Client id (max 23 chars) to use when connecting to the broker.
# If not provided a default one is generated.
MQTT.clientId=openhab

# Optional. User id to authenticate with the broker.
MQTT.user=openhab

# Optional. Password to authenticate with the broker.
MQTT.pwd=openhab

Here’s the serial printout:


Soft WDT reset

ctx: cont 
sp: 3ffefa30 end: 3ffefc20 offset: 01b0

>>>stack>>>
3ffefbe0:  00000001 3ffee878 3ffeeb3c 40202372  
3ffefbf0:  3fffdad0 00000000 3ffeebf0 402023be  
3ffefc00:  3fffdad0 00000000 3ffeebf0 40206d88  
3ffefc10:  feefeffe feefeffe 3ffeec00 40100718  
<<<stack<<<

 ets Jan  8 2013,rst cause:2, boot mode:(3,7)

load 0x4010f000, len 1384, room 16 
tail 8
chksum 0x2d
csum 0x2d
v3de0c112
~ld
⸮
Booting... v1.0
Connecting to [redacted]

Ready & WiFi connected
IP address: 192.168.1.124
Connecting to MQTT... Connection failed
Retrying MQTT connection in 5 seconds...
Connection failed
Retrying MQTT connection in 5 seconds...
Connection failed
Retrying MQTT connection in 5 seconds...

wait… don’t mix the 2 things (OH2 and ESP)
Both should connect to MQTT but they are different and should be dealt separately
For now, you are experiencing a problem with the ESP connection to the MQTT Broker.
You need to troubleshoot this connection first, before you start configuring OH2.

Can you connect to your broker from any kind of remote client?
Try MQTT.fx and make sure that the Broker is up and running properly

1 Like

Success! MQTT.fx was also refusing. It seems mosquitto wasn’t enabled on the RPi (checked with ‘sudo systemctl status mosquitto’).

Thank you for the help!

1 Like

What are best practice to use event bus ? usage of event bus may limit the freedom on topics .

I’m not sure what you are asking. The purpose of Event Bus is to share EVERY Item’s commands and updates with some other system (could be another instance of OH, could be Node Red, could be something else). By necessity, it requires constraints on the topics.

When using the event bus you define the state and command publish and subscribe topics. Somewhere in those topic definitions you put ${item} which will be replaced with the Item name.

This configuration must be complimentary on the other side. For example, the other client should subscribe to the the Publish topics defined in mqtt-eventbus.cfg and publish to the Subscribe topics in that file.

If you need topics that cannot conform to this or you do not want to share all updates and commands for all Items you shouldn’t use Event Bud.

I believe that you can continue using the regular item binding setup in parallel to the MQTT Event Bus link.

For example:
With MQTT Event Bus configured to publish everything to:

statePublishTopic=openhab/out/${item}/state
commandPublishTopic=openhab/out/${item}/command

and a specific item (bound to mqtt) defined as:

Switch	Robo500		"Robo 500"	{mqtt=">[HomeR:HomeAuto/ESP/whatever:command:ON:default]", autoupdate="false"}

I would get the command message published to both topics:

openhab/out/Robo500/command (due to the MQTT Event Bus)
as well as
HomeAuto/ESP/whatever (due to the item config)

So, I am not constrained in any way.
Note: I haven’t tested this out but I believe that it will work as I described it…
It could get tricky with subscriptions (2 sources of state updates for the same item…)

Hi @Dim
I love this tutorial and was able to successfully get it working with OH2. I could really use some help though. I’m attempting to combine your code with the code provided by Matt Kaczynski from MK-SmartHouse.
My hope is to use one ESP8266 to monitor and control my garage door. I have both sketches working separately but meshing them together is where I’m having problems. Here is the code and source I’m trying to modify.
https://www.mksmarthouse.com/door-sensor

/*
 * Device Title: MK-DoorSensor
 * Device Description: MQTT Door Sensor
 * Device information: https://www.MK-SmartHouse.com/door-sensor                
 * Author: Matt Kaczynski
 */

#include <ESP8266WiFi.h>
#include <MQTTClient.h>
#include <ESP8266WebServer.h>
#include <ESP8266mDNS.h>
#include <ESP8266HTTPUpdateServer.h>

/* WIFI Settings */
// Name of wifi network
const char* ssid = "wifissid";

// Password to wifi network
const char* password = "wifpassword"; 

/* Web Updater Settings */
// Host Name of Device
const char* host = "MK-DoorSensor1";

// Path to access firmware update page (Not Neccessary to change)
const char* update_path = "/firmware";

// Username to access the web update page
const char* update_username = "admin";

// Password to access the web update page
const char* update_password = "Admin";

/* MQTT Settings */
// Topic which listens for commands
char* outTopic = "MK-SmartHouse/security/MK-DoorSensor1"; 

//MQTT Server IP Address
const char* server = "192.168.0.4";

//Unique device ID 
const char* mqttDeviceID = "MK-SmartHouseDevice1"; 


//the time when the sensor outputs a low impulse
long unsigned int lowIn;         

//the amount of milliseconds the sensor has to be low 
//before we assume all detection has stopped
long unsigned int pause = 100;  

//sensor variables
boolean lockLow = true;
boolean takeLowTime;  

//the digital pin connected to the door sensor's output
int sensorPin = 13;  

//webserver 
ESP8266WebServer httpServer(80);
ESP8266HTTPUpdateServer httpUpdater;

//MQTT 
WiFiClient net;
MQTTClient client;

//Time Variable
unsigned long lastMillis = 0;

//Connect to WiFI and MQTT
void connect();

//Setup pins, wifi, webserver and MQTT
void setup() 
{
  pinMode(sensorPin, INPUT);
  digitalWrite(sensorPin, LOW);
  
  WiFi.mode(WIFI_STA);
  
  WiFi.begin(ssid, password);
  client.begin(server, net);

  connect();

  MDNS.begin(host);

  httpUpdater.setup(&httpServer, update_path, update_username, update_password);
  httpServer.begin();

  MDNS.addService("http", "tcp", 80);
}

//Connect to wifi and MQTT
void connect() 
{
  while (WiFi.status() != WL_CONNECTED) 
  {
    delay(1000);
  }

  while (!client.connect(mqttDeviceID)) 
  {
    delay(1000);
  }
}

void loop() 
{
  // MQTT Loop
  client.loop();
  delay(10);

  // Make sure device is connected
  if(!client.connected()) 
  {
    connect();
  }

  httpServer.handleClient();

  //Sensor Detection
  
  if(digitalRead(sensorPin) == HIGH)
  {
    if(lockLow)
    {  
      //makes sure we wait for a transition to LOW before any further output is made:
      lockLow = false;            
      client.publish(outTopic, "OPEN");  
      delay(50);
    }         
    takeLowTime = true;
  }

  if(digitalRead(sensorPin) == LOW)
  {       
    if(takeLowTime)
    {
      lowIn = millis();          //save the time of the transition from high to LOW
      takeLowTime = false;       //make sure this is only done at the start of a LOW phase
    }
    //if the sensor is low for more than the given pause, 
    //we assume that no more detection is going to happen
    if(!lockLow && millis() - lowIn > pause)
    {  
      //makes sure this block of code is only executed again after 
      //a new detection sequence has been detected
      lockLow = true;                        
      client.publish(outTopic, "CLOSED");
      delay(50);
    }
  }

}

void messageReceived(String topic, String payload, char * bytes, unsigned int length) 
{
  //This sensor does not recieve anything from MQTT Server so this is blank
}

I don’t mind using your code and just modify it to keep an eye on the door sensor I just found this code above first.
Any help or advise would be greatly appreciated.

You could try to add some code in the last section (messageReceived)
In my example, I monitor the topic from the ESP side but I don’t publish anything to the Broker from the ESP
In your example, the reverse is true

So: You want an ESP code that does both (publishes the state as well as subscribes to a topic) basically… correct?

Hi @Dim

Correct.
My thought was to have a reed switch connected to pin D7 and GND using the internal pullup to send a MQTT stating the door is open. And have a relay connected to D1 that would allow me to close it when a software switch is pressed in the OH2 UI. I believe that requires the ESP code to both publish and subscribe but I’m open to any suggestions.

1 Like

Great tutorial. Already using this for my home made rollershutters. Thanks!

1 Like

Matt Kaczynski is the best what he do. Can’t wait for more videos

hello im quite new to rpi3 and open hap2

i was following this tutorial
i made connection between mqqt and nodemcu trigger relay via mqqt.fx
but im un able to toggle out via rpi paper ui

I have the same error as you, jdeka1…
Using Wemos D1 R2 (Arduino) board, RPi and OH2.3. Tried to test connection also with MQTT.fx bellow.
But I’m getting error trying to connect Arduino to OH2.3.

Connecting to MQTT... Connection failed
Retrying MQTT connection in 5 seconds...

Checked also RPi with ‘sudo systemctl status mosquitto’ and there is Active.


● mosquitto.service - LSB: mosquitto MQTT v3.1 message broker
   Loaded: loaded (/etc/init.d/mosquitto; generated; vendor preset: enabled)
   Active: active (running) since Sat 2018-07-14 21:36:06 EEST; 15h ago
     Docs: man:systemd-sysv-generator(8)
  Process: 272 ExecStart=/etc/init.d/mosquitto start (code=exited, status=0/SUCCESS)
   CGroup: /system.slice/mosquitto.service
           └─332 /usr/sbin/mosquitto -c /etc/mosquitto/mosquitto.conf

Jul 14 21:36:04 openHABianPi systemd[1]: Starting LSB: mosquitto MQTT v3.1 message broker...
Jul 14 21:36:06 openHABianPi mosquitto[272]: Starting network daemon:: mosquitto.
Jul 14 21:36:06 openHABianPi systemd[1]: Started LSB: mosquitto MQTT v3.1 message broker.

This is mttq.cfg:

MQTT.url=tcp://192.168.1.2:1883
MQTT.clientId=
MQTT.user=
MQTT.pwd=

This is the error result from MQTT.fx:

2018-07-15 13:57:22,793  INFO --- MqttFX ClientModel             : MqttClient with ID MQTT_FX_Client assigned.
2018-07-15 13:57:24,813 ERROR --- MqttFX ClientModel             : Error when connecting
org.eclipse.paho.client.mqttv3.MqttException: Unable to connect to server
	at org.eclipse.paho.client.mqttv3.internal.TCPNetworkModule.start(TCPNetworkModule.java:94) ~[org.eclipse.paho.client.mqttv3-1.2.0.jar:?]
	at org.eclipse.paho.client.mqttv3.internal.ClientComms$ConnectBG.run(ClientComms.java:701) ~[org.eclipse.paho.client.mqttv3-1.2.0.jar:?]
	at java.util.concurrent.Executors$RunnableAdapter.call(Unknown Source) ~[?:1.8.0_162]
	at java.util.concurrent.FutureTask.run(Unknown Source) ~[?:1.8.0_162]
	at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(Unknown Source) ~[?:1.8.0_162]
	at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(Unknown Source) ~[?:1.8.0_162]
	at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source) [?:1.8.0_162]
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source) [?:1.8.0_162]
	at java.lang.Thread.run(Unknown Source) [?:1.8.0_162]
Caused by: java.net.ConnectException: Connection refused: connect
	at java.net.DualStackPlainSocketImpl.waitForConnect(Native Method) ~[?:1.8.0_162]
	at java.net.DualStackPlainSocketImpl.socketConnect(Unknown Source) ~[?:1.8.0_162]
	at java.net.AbstractPlainSocketImpl.doConnect(Unknown Source) ~[?:1.8.0_162]
	at java.net.AbstractPlainSocketImpl.connectToAddress(Unknown Source) ~[?:1.8.0_162]
	at java.net.AbstractPlainSocketImpl.connect(Unknown Source) ~[?:1.8.0_162]
	at java.net.PlainSocketImpl.connect(Unknown Source) ~[?:1.8.0_162]
	at java.net.SocksSocketImpl.connect(Unknown Source) ~[?:1.8.0_162]
	at java.net.Socket.connect(Unknown Source) ~[?:1.8.0_162]
	at org.eclipse.paho.client.mqttv3.internal.TCPNetworkModule.start(TCPNetworkModule.java:84) ~[org.eclipse.paho.client.mqttv3-1.2.0.jar:?]
	... 8 more
2018-07-15 13:57:24,815 ERROR --- MqttFX ClientModel             : Please verify your Settings (e.g. Broker Address, Broker Port & Client ID) and the user credentials!
org.eclipse.paho.client.mqttv3.MqttException: Unable to connect to server
	at org.eclipse.paho.client.mqttv3.internal.TCPNetworkModule.start(TCPNetworkModule.java:94) ~[org.eclipse.paho.client.mqttv3-1.2.0.jar:?]
	at org.eclipse.paho.client.mqttv3.internal.ClientComms$ConnectBG.run(ClientComms.java:701) ~[org.eclipse.paho.client.mqttv3-1.2.0.jar:?]
	at java.util.concurrent.Executors$RunnableAdapter.call(Unknown Source) ~[?:1.8.0_162]
	at java.util.concurrent.FutureTask.run(Unknown Source) ~[?:1.8.0_162]
	at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(Unknown Source) ~[?:1.8.0_162]
	at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(Unknown Source) ~[?:1.8.0_162]
	at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source) [?:1.8.0_162]
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source) [?:1.8.0_162]
	at java.lang.Thread.run(Unknown Source) [?:1.8.0_162]
Caused by: java.net.ConnectException: Connection refused: connect
	at java.net.DualStackPlainSocketImpl.waitForConnect(Native Method) ~[?:1.8.0_162]
	at java.net.DualStackPlainSocketImpl.socketConnect(Unknown Source) ~[?:1.8.0_162]
	at java.net.AbstractPlainSocketImpl.doConnect(Unknown Source) ~[?:1.8.0_162]
	at java.net.AbstractPlainSocketImpl.connectToAddress(Unknown Source) ~[?:1.8.0_162]
	at java.net.AbstractPlainSocketImpl.connect(Unknown Source) ~[?:1.8.0_162]
	at java.net.PlainSocketImpl.connect(Unknown Source) ~[?:1.8.0_162]
	at java.net.SocksSocketImpl.connect(Unknown Source) ~[?:1.8.0_162]
	at java.net.Socket.connect(Unknown Source) ~[?:1.8.0_162]
	at org.eclipse.paho.client.mqttv3.internal.TCPNetworkModule.start(TCPNetworkModule.java:84) ~[org.eclipse.paho.client.mqttv3-1.2.0.jar:?]
	... 8 more
2018-07-15 13:57:24,834  INFO --- ScriptsController              : Clear console.
2018-07-15 13:57:24,834 ERROR --- BrokerConnectService           : Unable to connect to server

At file mqtt-eventbus.cfg I tried with and without these:

broker=MQTT
statePublishTopic=openhab/out/$.{item}/state
commandPublishTopic=openhab/out/${item}/command
stateSubscribeTopic=openhab/in/${item}/state
commandSubscribeTopic=openhab/in/${item}/command

OH2 tells me that there a broker is started:

2018-07-15 22:12:33.471 [INFO ] [t.mqtt.internal.MqttBrokerConnection] - Starting MQTT broker connection 'broker'

Do you have any ideea what to try further?
Thanks.

I managed to connected.

post the contents of your /etc/mosquitto/mosquitto.conf plz
something is wrong with your Broker (maybe?)

Dim, I’ve managed to connected Arduino (D1) to MQTT now. But I’m trying to figure out how I can control the relays from Habpanel.

1 Like

You need to define an Item in your OH2 system that is bound to the proper MQTT topic
Then, use this new Item in your HABPanel layout.

edit: I recommend that you don’t use the MQTT - EventBus integration but setup a focused MQTT bound Item
(unless you need all of the integration features)

I’ve already define it:

Switch InverterBlue "Testing..." { mqtt="<[brokerInverterBlue:mqtt/topic:state:ON], >[brokerInverterBlue:mqtt/back-topic:command:*:OFF]" }  

I’ve created also a button in Habpanel with ON/OFF .
I can see the action of this button in OH2 log:

2018-07-16 13:42:42.496 [ome.event.ItemCommandEvent] - Item 'InverterBlue' received command ON

2018-07-16 13:42:42.503 [vent.ItemStateChangedEvent] - InverterBlue changed from OFF to ON

2018-07-16 13:42:45.082 [ome.event.ItemCommandEvent] - Item 'InverterBlue' received command OFF

2018-07-16 13:42:45.096 [vent.ItemStateChangedEvent] - InverterBlue changed from ON to OFF

I’ve update Arduino sketch to connect with this broker:

/*
 * Dim - Relay Shield Toggle v1.0
 * Closes the relay for 100 ms, then opens based on OH2 event
 * Relay Shield transistor closes relay when D1 is HIGH
*/

#include <ESP8266WiFi.h>
#include <ESP8266mDNS.h>
#include <WiFiUdp.h>
#include <ArduinoOTA.h>
#include <Adafruit_MQTT.h>
#include <Adafruit_MQTT_Client.h>

/************************* WiFi Access Point *********************************/
#define WLAN_SSID       "xxx"
#define WLAN_PASS       "x"

/************************* MQTT Broker Setup *********************************/
#define mqtt_server      "192.168.1.2"
#define mqtt_serverport  1883                   // use 8883 for SSL
#define mqtt_username    ""
#define mqtt_password    ""

/************************* Constants, Variables, Integers, etc *********************************/
const int relayPin = D1;
const long togDelay = 100;  // pause for 100 milliseconds before toggling to Open
const long postDelay = 200;  // pause for 200 milliseconds after toggling to Open
int value = 0;
int relayState = LOW;

// Create an ESP8266 WiFiClient class to connect to the MQTT server.
WiFiClient client;

// Setup the MQTT client class by passing in the WiFi client and MQTT server and login details.
Adafruit_MQTT_Client mqtt(&client, mqtt_server, mqtt_serverport, mqtt_username, mqtt_password);

// Setup subscription 'Robo500' for monitoring topic for changes.
Adafruit_MQTT_Subscribe InverterBlue = Adafruit_MQTT_Subscribe(&mqtt, "openhab/out/brokerInverterBlue");

/*************************** Sketch Code ************************************/
void MQTT_connect();

void setup() {
  Serial.begin(115200);
  Serial.println(""); Serial.println(F("Booting... v1.0"));
  pinMode(relayPin, OUTPUT);
  // Connect to WiFi access point.
  Serial.print("Connecting to "); Serial.println(WLAN_SSID);
  WiFi.mode(WIFI_STA);
  WiFi.begin(WLAN_SSID, WLAN_PASS);
  while (WiFi.waitForConnectResult() != WL_CONNECTED) {
  Serial.println("Connection Failed! Rebooting in 5 secs...");
  delay(5000);
  ESP.restart();
  }

  // Setup MQTT subscription for Robo500 feed.
  mqtt.subscribe(&InverterBlue);

  // Begin OTA
  ArduinoOTA.setPort(8266); // Port defaults to 8266
  ArduinoOTA.setHostname("InverterBlueChipID");   // Hostname defaults to esp8266-[ChipID]
  ArduinoOTA.setPassword((const char *)"<pass>");   // No authentication by default

  ArduinoOTA.onStart([]() {
    Serial.println("Start");
  });
  ArduinoOTA.onEnd([]() {
    Serial.println("\nEnd");
  });
  ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) {
    Serial.printf("Progress: %u%%\r", (progress / (total / 100)));
  });
  ArduinoOTA.onError([](ota_error_t error) {
    Serial.printf("Error[%u]: ", error);
    if (error == OTA_AUTH_ERROR) Serial.println("Auth Failed");
    else if (error == OTA_BEGIN_ERROR) Serial.println("Begin Failed");
    else if (error == OTA_CONNECT_ERROR) Serial.println("Connect Failed");
    else if (error == OTA_RECEIVE_ERROR) Serial.println("Receive Failed");
    else if (error == OTA_END_ERROR) Serial.println("End Failed");
  });
  ArduinoOTA.begin();
  Serial.println("");
  Serial.println("Ready & WiFi connected");
  Serial.print("IP address: "); Serial.println(WiFi.localIP());
}

void loop() {
  ArduinoOTA.handle();
  // Ensure the connection to the MQTT server is alive (this will make the first
  // connection and automatically reconnect when disconnected).  See the MQTT_connect
  // function definition further below.
  MQTT_connect();
  
  // this is our 'wait for incoming subscription packets' busy subloop
  // try to spend your time here

  Adafruit_MQTT_Subscribe *subscription;
  while ((subscription = mqtt.readSubscription(5000))) {
    if (subscription == &InverterBlue) {
      Serial.print(F("Got: ")); Serial.println((char *)InverterBlue.lastread);
      // close the relay for 100 ms
      Serial.println("Close Relay for 100 ms & then Open");
      digitalWrite(relayPin, HIGH);
      delay(togDelay);
      digitalWrite(relayPin, LOW);
      delay(postDelay);
    }
  }

  // ping the server to keep the mqtt connection alive
  // NOT required if you are publishing once every KEEPALIVE seconds
//   if(! mqtt.ping()) {
//    mqtt.disconnect();
//  }
}

// Function to connect and reconnect as necessary to the MQTT server.
// Should be called in the loop function and it will take care if connecting.
void MQTT_connect() {
  int8_t ret;

  // Stop if already connected.
  if (mqtt.connected()) {
    return;
  }
  
  Serial.print("Connecting to MQTT... ");
  
  uint8_t retries = 3;
  while ((ret = mqtt.connect()) != 0) { // connect will return 0 for connected
       Serial.println(mqtt.connectErrorString(ret));
       Serial.println("Retrying MQTT connection in 5 seconds...");
       mqtt.disconnect();
       delay(5000);  // wait 5 seconds
       retries--;
       if (retries == 0) {
         // basically die and wait for WDT to reset me
         while (1);
       }
  }
  Serial.println("MQTT Connected!");
}

The serial from Arduino tells me that MQTT connected.

Ready & WiFi connected
IP address: 192.168.1.102
Connecting to MQTT... MQTT Connected!

mqtt-eventbus file has been modified:

broker=brokerInverterBlue
statePublishTopic=openhab/out/${item}/state
commandPublishTopic=openhab/out/${item}/command
stateSubscribeTopic=openhab/in/${item}/state
commandSubscribeTopic=openhab/in/${item}/command

But I cannot see any action in Arduino when I clicked the button in OH2. What’s wrong?

First of all, verify that the Broker is receiving the message from OH2.
Use MQTT.fx to see if the payload arrives to the topic you are publishing

Secondly:

  1. Remove all settings from mqtt-eventbus.cfg. You don’t need this if you use an MQTT Bound item
  2. Use the same MQTT Broker alias in your Item config as in your mqtt.cfg file (MQTT vs brokerInverterBlue)
Switch InverterBlue "Testing..." { mqtt="<[MQTT:mqtt/topic:state:ON], >[MQTT:mqtt/back-topic:command:*:OFF]" }  

mqtt.cfg has this:

brokerInverterBlue.url=tcp://192.168.2:1883

I have this broker only.