MQTT, JSON or webserver

I am currently working on motorization of my IKEA roller curtains. I have 3d pirnted a case where I installed a stepper motor. This motor is connected to an arduino esp wifi board, and now the question is how to implement it into OH.

On the arduino side I have enabled an end switch when its completely up and two buttons(up/down).

So now I am wondering on how to operate it in OH. In my sitemap I would like to have a switch which is up and down as well as a slider where you can set the position of the curtain.

So should I set up Mqtt? I am wondering if this is more complex, and that this is more likely to fail 5 years down the road. MQTT has the benefit of two way communication.

JSON seems to be the most common standard, but I am unsure how I can post JSON to OH(the other way from OH to the esp is fine), I know I can keep asking the esp every 1s of the status, but I rather want an event based solution.

The last way of solving is to run a webserver on the ESP so that i can simply do:
myIP/curtain/down.html and it moves down and to use the rest api in OH to update the status of the switch item in OH if manual switches are pressed on the ESP.

So which option is the easiest to maintain(for my girlfriend, future buyers) and most likely not to fail and require updates in the future?

I vote for MQTT.
Easy to setup, event based and it hasn’t failed me in multiple use cases
Example: [OH2] Control ESP8266 Relay using MQTT Eventbus
I have this ESP running for 6 months now and I haven’t done any maintenance to it (no need to change the sketch or the MQTT item. Very, very stable and reliable

2 Likes

Just a side mark, my router crashed the other day, so here is what I have learned by it.

  1. Heating and lights should be connected to RPI directly! You dont want your mum to freeze and sit in the dark because something fails and you are not available.

  2. The RPI can crash, so make sure you have pushbutton to reset it, either power your RPI through the GPIO or somehow solder the switch on to the usb cable(In theory you could unplug either the usb from RPI or from the outlet, but my mum finds it easier to just press a button instead of opening the fusebox and the locate the RPI)

  3. Always have a spare RPI with a clone of the system so that it easily can be changed if it breaks(like lighting, sd card malfunction etc can happen), this way with proper instruction some can get the system up running again. Maybe there is some possibility to run two systems in parallel?

  4. For heating connect them NC on the relay, because if all above fails the heating will be constantly on instead of off
    For lights the NC could also be used, but I have not done this so far. My RGB lights are running on a USB dongle instead of ethernet(HUE bridge might crash so consider wiring this togeheter with the rpi power supply). In addition I keep an extra lamp around as well as candle lights:)

5.I only have a few switches and these are hardwired to the RPI, this means if the router, tablet,alexa, phone crashes I can not set fancy scenes, but I have lights and heating!

  1. Keep a list of separate apps that can control devices in case all above fails…

  2. Make sure no automatic updates happens! We dont want our system to crash because of software changes.

I also have physically pushbutton to reset services such as olad, python and so on, to avoid needing to reset the whole rpi when a service go down.

For automatic hvac control, roller curtain, door opening etc MQTT or http is just fine, because these are just nice to have features:)

Maybe @Kai or @ThomDietrich can collaborate on this, but it is very important to communicate out to the users what can happen in a smart home if somethings go wrong, and how we can make it fail-safe… Being able to run two RPI in parallel with some mux in between the ribbon Cables(or USB) might be worth considering)

1 Like

I’d be happy to comment on the above but could you move the topic to it’s own thread first!? :wink: Thanks

done… How to set up a stable smart home system

So tomorrow afternoon I have my flat for a few hours and my plan is to try to setup the mqtt as it seems this is the way to go…

So I have a few question in that mather to @Dim , I tried to modify you code:

  Adafruit_MQTT_Subscribe *subscription;
  while ((subscription = mqtt.readSubscription(5000))) {
    if (subscription == &RollerCurtainMasterBedRoom) {
      Serial.print(F("Got: ")); Serial.println((char *)RollerCurtainMasterBedRoom.lastread);

      // how to obtain the value of steps sent from OpenHab??
      motor.step(stepsFromOH);

      //How to make sure that this never happens?? 
      if maxUp = HIGH {
        //Report back to OH that the curtain is max up
      }

      //Do this on every reboot of OH..
      //Startup rule of  OH: sendMqtt recalibrate, set curtain switch to up, set curtain slider to 0%
      //if received command recalibrate , run motor up untill end switch kicks in...
      motor.step(-9999);
      while maxUp = LOW {}
    }
  }

The stepper motor library which I am using is located here:

In Openhabian I can activate mqtt, what do I need to alter in my arduino sketch @ThomDietrich to make it work?

/************************* MQTT Broker Setup *********************************/
#define mqtt_server      "<mqtt_broker>" //What does OPenhabian use??
#define mqtt_serverport  1883             //What does OPenhabian use??      // use 8883 for SSL
#define mqtt_username    "<mqtt_username>" //What does OPenhabian use??
#define mqtt_password    "<mqtt_password>" //What does OPenhabian use??

Openhabian enable the MQTT binding and add the mqtt.cfg file correct?

How should my simple item file look like?
Switch RollerCurtainMasterBedRoom {mqtt="<direction>[<broker>:<topic>:<type>:<transformer>], <direction>[<broker>:<topic>:<type>:<transformation>], ..."}

Here is my complete arduino code:

/*
 * 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>
#include <StepperMotor.h>

/************************* WiFi Access Point *********************************/
#define WLAN_SSID       "<ssid>" //I change this of course
#define WLAN_PASS       "<pass>" // I change this of course

/************************* MQTT Broker Setup *********************************/
#define mqtt_server      "<mqtt_broker>" //What does OPenhabian use??
#define mqtt_serverport  1883             //What does OPenhabian use??      // use 8883 for SSL
#define mqtt_username    "<mqtt_username>" //What does OPenhabian use??
#define mqtt_password    "<mqtt_password>" //What does OPenhabian use??

/************************* Constants, Variables, Integers, etc *********************************/
const int maxUp = D1; //My endswitch
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;


// Create the stepper object
StepperMotor motor(8,9,10,11);

// 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 'RollerCurtainMasterBedRoom' for monitoring topic for changes.
Adafruit_MQTT_Subscribe RollerCurtainMasterBedRoom = Adafruit_MQTT_Subscribe(&mqtt, "openhab/out/RollerCurtainMasterBedRoom/command");

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

void setup() {
  Serial.begin(115200);
  Serial.println(""); Serial.println(F("Booting... v1.0"));

  // Set up the stepper motor
  pinMode(maxUp, INPUT);
  motor.setStepDuration(1);
  
  // 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(&RollerCurtainMasterBedRoom);

  // Begin OTA
  ArduinoOTA.setPort(8266); // Port defaults to 8266
  ArduinoOTA.setHostname("RollerCurtainMasterBedRoom");   // 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 == &RollerCurtainMasterBedRoom) {
      Serial.print(F("Got: ")); Serial.println((char *)RollerCurtainMasterBedRoom.lastread);

      // how to obtain the value of steps sent from OpenHab??
      motor.step(stepsFromOH);

      //How to make sure that this never happens?? 
      if maxUp = HIGH {
        //Report back to OH that the curtain is max up
      }

      //Do this on every reboot of OH..
      //Startup rule of  OH: sendMqtt recalibrate, set curtain switch to up, set curtain slider to 0%
      //if received command recalibrate , run motor up untill end switch kicks in...
      motor.step(-9999);
      while maxUp = LOW {}
    }
  }

  // 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!");

I will update this post with some photos of the IKEA hack when I get it to work:)

1 Like

Most of that ESP code is not mine… I just adopted it to my needs but I found it on the internet (and this forum)

I theory, you would enter in the motor.step the value that you get from OH2 item (which is publishing to the monitored topic).
Something like:

motor.step(RollerCurtainMasterBedRoom.lastread);

I am not sure, try to play around with the code and use trial and error :slight_smile:

If you have installed the Mosquitto MQTT Broker on the same rPi3 host, use the IP Address of the rPi3 for the server and 1883 port.
If you have configured Mosquitto with authentication, put the username and password for the connection.

Remember: All parameters with < > need to be replaced. Same applies for the OTA password.

A switch item will send only ON / OFF states to MQTT.
If you want to send a value to the motor (e.g. 0 to 100) you should use a Number item (or Dimmer or another type?)

Number RollerCurtainMasterBedRoom {mqtt=">[broker_name:topic/01:command:*:default]}

This is for outbound (publish) from OH2 to MQTT
Regarding inbound (subscribe) from MQTT to OH2… it depends on your ESP code (if it reports statuses)

Install mosquitto via openhabian-config and you’ll be able to enter a password. For the rest:

/************************* MQTT Broker Setup *********************************/
#define mqtt_server      "openhabianpi" //or the IP address.
#define mqtt_serverport  1883
#define mqtt_username    "openhabian" 
#define mqtt_password    "..." //you are asked to choose one
1 Like

It seems to be some problem with the openhabian and configure item 22:

  405  Not Allowed
Ign http://repo.mosquitto.org jessie/main Translation-en
Hit http://ppa.launchpad.net trusty/main Sources
Hit http://archive.raspberrypi.org jessie/main armhf Packages
Hit http://ppa.launchpad.net trusty/main armhf Packages
Hit http://ppa.launchpad.net trusty/main Translation-en
Ign http://archive.raspberrypi.org jessie/main Translation-en_US
Ign http://archive.raspberrypi.org jessie/main Translation-en
Get:4 http://mirrordirector.raspbian.org jessie/contrib armhf Packages [43.3 kB]
Get:5 http://mirrordirector.raspbian.org jessie/non-free armhf Packages [84.2 kB                                                                                        ]
Get:6 http://mirrordirector.raspbian.org jessie/firmware armhf Packages [1,232 B                                                                                        ]
Ign http://mirrordirector.raspbian.org jessie/contrib Translation-en_US
Ign http://mirrordirector.raspbian.org jessie/contrib Translation-en
Ign http://mirrordirector.raspbian.org jessie/firmware Translation-en_US
Ign http://mirrordirector.raspbian.org jessie/firmware Translation-en
Ign http://mirrordirector.raspbian.org jessie/main Translation-en_US
Ign http://mirrordirector.raspbian.org jessie/main Translation-en
Ign http://mirrordirector.raspbian.org jessie/non-free Translation-en_US
Ign http://mirrordirector.raspbian.org jessie/non-free Translation-en
Fetched 9,677 kB in 16s (574 kB/s)
W: Failed to fetch http://dl.bintray.com/openhab/apt-repo2/dists/stable/main/bin                                                                                        ary-armhf/Packages  405  Not Allowed

E: Some index files failed to download. They have been ignored, or old ones used                                                                                         instead.
FAILED

I will try to upgrade everything tomorrow, to make sure that’s not the problem…

Did you update your openhabian?

Yes, now its up running, I will try to get around to install the software on esp this summer. Quite busy these days. So tips to all using openhabian, update to latest version of openhabian before trying to install mosquitto.

1 Like

This should always be the first step, one day I’ll just make it an automated step :smiley:

Maybe something that should not be to hard to program in is to check when you run openhabian -config, first it checks your version against latest version on the web, then prompt you if you want to upgrade or read the release note :slight_smile:
if it does not match up…

Sounds good and most of what is needed for that already exists. Would you create an Issue for it? :slight_smile:

1 Like