Esp8266 Window Blinds MQTT

@jjhtpc He! Thanks! I’m trying to set this up with a continues servo. Do you perhaps still have the original sketch from BRUH? His link is offline, i’d really like this.

Hi jjhtpc,

Do you think it is possible to shut off the wifi on the esp8266 since we are using only the mqtt to control the blind. I am thinking to connect it to a solar power panel that is charging the battery.

MQTT is just Message Queue Telemetry Transport and that transport is still occurring over wifi. The wifi connection is still needed.

The only thing that I borrowed from BRUH on this was the MQTT configuration. I think there were others that were using continuous rotation though. I know that I had created my blinds originally on Smarttings with a Spark Core chip and there were definitely people that adapted my code to continuous rotation. You could look over there.

Thanks for your reply, i’ve been tinkering around, cursing, smashing, but i got it, with continuous rotation. I have 50/50 curtains. So just have to figure out the time needed to open/close

Anyone intergrated OTA? Can’t seem to get it working. (webserver or just Arduino IDE)

Just follow the guide to make the servo a continuous one:

Then i’ve used this code:

#include <PubSubClient.h>
#include <Servo.h>
#include <WiFiClientSecure.h>
#include <ESP8266WiFiAP.h>
#include <WiFiUdp.h>
#include <ESP8266WiFiMulti.h>
#include <ESP8266WiFiSTA.h>
#include <ESP8266WiFiGeneric.h>
#include <ESP8266WiFi.h>
#include <WiFiServer.h>
#include <ESP8266WiFiScan.h>
#include <WiFiClient.h>
#include <ESP8266WiFiType.h>

#define wifi_ssid "<input here>"
#define wifi_password "<input here>8"
#define mqtt_server "<input here>" 
#define mqtt_user "<input here>"
#define mqtt_password "<input here>"

WiFiClient espClient;
PubSubClient client(espClient);
Servo myservo;

int val;
int itsatrap = 0;

void setup() {
  Serial.begin(9600);
  setup_wifi();
  client.setServer(mqtt_server, 1883); //CHANGE PORT HERE IF NEEDED
  client.setCallback(callback);
}

void setup_wifi() {
  delay(10);
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(wifi_ssid);
  WiFi.mode(WIFI_STA);
  WiFi.begin(wifi_ssid, wifi_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) {
    char p[length + 1];
    memcpy(p, payload, length);
    p[length] = NULL;
    String message(p);
    String mytopic(topic);
    if (itsatrap == 0 && mytopic == "blinds/back/cmnd" && message.equals("ON")){  
      myservo.attach(D4); // make sure to use pin D4, or change it
      delay(500);
      myservo.write(180); // this makes the servo rotate in one direction for 6 seconds
      client.publish("blinds/back/state", "ON");
      delay(6000);
      myservo.detach();
      }
    else if (mytopic == "blinds/back/cmnd" && message.equalsIgnoreCase("OFF")){
      myservo.attach(D4); // make sure to use pin D4, or change it
      delay(500);
      myservo.write(0);  
      client.publish("blinds/back/state", "OFF");
      delay(6000); // this makes the servo rotate the other direction for 6 seconds
      myservo.detach();
    }
    else{
        itsatrap = 0;
    }
}

void loop() {
  if (!client.connected()) {
    reconnect();
  }
  client.loop();
}

void reconnect() {
  while (!client.connected()) {
    Serial.print("Attempting MQTT connection...");
    // Attempt to connect
  if (client.connect("ESPBlindstl", mqtt_user, mqtt_password)) {
      Serial.println("connected");
      client.subscribe("blinds/back/cmnd");
      client.publish("blinds/back/state", "OFF");
    } else {
      Serial.print("failed, rc=");
      Serial.print(client.state());
      Serial.println(" try again in 5 seconds");
      // Wait 5 seconds before retrying
      delay(5000);
    }
  }
}

Where you have a state topic:
blinds/back/state

Where you can read the state eg. ON/OFF (hass sensor open/closed)

And a command topic:

blinds/back/cmnd

Where you can command ON (one way) and OFF (the other)

If you have multiple (like me, around 7) just change every ‘back’ to the device corresponding on every flash.

Edit:

I have this MQTT cover setup:

cover:
  - platform: mqtt
    name: "Ground floor back"
    command_topic: "blinds/back/cmnd"
    state_topic: "blinds/back/state"
    qos: 2
    retain: false
    payload_open: "ON"
    payload_close: "OFF"
    state_open: "open"
    state_closed: "closed"
    optimistic: false

I have tried to use a solar panel to charge my power bank and at the same time to power the esp8266 with s3003. Its not capable of powering the servo but the esp8266 is up and running. Any idea what i can do? Or is there a servo that i can use which draw less current?

It is not the servo. It is the wifi chip on the 8266. I have not found a solar solution that works even with deep sleep, but deep sleep kind of goes against the concept of automation. I ran USB in my walls, this way you don’t see wires and you always have proper power.

I need help with my code. Could somebody check my code for mistakes?

HA config


light:
  - platform: mqtt
    name: "Window Bottom Center"
    state_topic: "blind/bc/state"
    command_topic: "blind/bc/command"
    brightness_state_topic: "blind/bc/state"
    brightness_command_topic: "blind/bc/level"
    brightness_scale: 100
    qos: 0
    payload_on: "ON"
    payload_off: "OFF"
    optimistic: false
    retain: true

Arduino code


#include 

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

#include 


/************ WIFI and MQTT INFORMATION (CHANGE THESE FOR YOUR SETUP) ******************/
#define wifi_ssid "Kalaverkko" //enter your WIFI SSID
#define wifi_password "qwerty12" //enter your WIFI Password

#define mqtt_server "192.168.1.147" // Enter your MQTT server adderss or IP. I use my DuckDNS adddress (yourname.duckdns.org) in this field
#define mqtt_user "mqttadmin" //enter your MQTT username
#define mqtt_password "qwerty12" //enter your password








WiFiClient espClient;
PubSubClient client(espClient);

Servo myservo;

int val;
int itsatrap = 0;


void setup() {
  Serial.begin(115200);

  setup_wifi();

  client.setServer(mqtt_server, 1883); //CHANGE PORT HERE IF NEEDED
  client.setCallback(callback);

}


void setup_wifi() {

  delay(10);
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(wifi_ssid);

  WiFi.mode(WIFI_STA);
  WiFi.begin(wifi_ssid, wifi_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) {
    char p[length + 1];
    memcpy(p, payload, length);
    p[length] = NULL;
    String message(p);
    String mytopic(topic);
    if (itsatrap == 0 && mytopic == "blind/bc/command" && message.equals("ON")){  
      myservo.attach(D4);
      delay(500);
      myservo.write(90); 
      client.publish("blind/bc/state", "ON");
      delay(1000);
      myservo.detach();
      }
    else if (mytopic == "blind/bc/command" && message.equalsIgnoreCase("OFF")){
      myservo.attach(D4);
      delay(500);
      myservo.write(0);  
      client.publish("blind/bc/state", "OFF");
      delay(1000);
      myservo.detach();
    }
    else if (mytopic == "blind/bc/level"){
      myservo.attach(D4);
      delay(500);
      val = message.toInt(); //converts command to integer to be used for positional arrangement
      val = map (val, 0, 99, 0, 180);
      myservo.write(val);
      client.publish("blind/bc/state", "ON");
      delay(3000);
      myservo.detach();
      itsatrap = 1;
    }
    else{
        itsatrap = 0;
    }

}



void loop() {

  if (!client.connected()) {
    reconnect();
  }
  client.loop();
}


void reconnect() {
  // Loop until we're reconnected
  while (!client.connected()) {
    Serial.print("Attempting MQTT connection...");
    // Attempt to connect
  if (client.connect("ESP_blind", mqtt_user, mqtt_password)) {
      Serial.println("connected");

      client.subscribe("blind/bc/command");
      client.subscribe("blind/bc/level");
      client.publish("blind/bc/state", "OFF");
    } else {
      Serial.print("failed, rc=");
      Serial.print(client.state());
      Serial.println(" try again in 5 seconds");
      // Wait 5 seconds before retrying
      delay(5000);
    }
  }
}

MQTT log


1554224006: New connection from 192.168.1.248 on port 1883. 1554224006: |-- mosquitto_auth_unpwd_check(mqttadmin) 1554224006: |-- ** checking backend http 1554224006: |-- url=http://127.0.0.1:8080/login 1554224006: |-- data=username=mqttadmin&password=qwerty12&topic=&acc=-1&clientid= [INFO] found mqttadmin on local database 1554224008: |-- getuser(mqttadmin) AUTHENTICATED=1 by http 1554224008: New client connected from 192.168.1.248 as ESP_blind (c1, k15, u'mqttadmin'). 1554224008: |-- mosquitto_auth_acl_check(..., client id not available, mqttadmin, blind/bc/command, MOSQ_ACL_WRITE) 1554224008: |-- aclcheck(mqttadmin, blind/bc/command, 4) CACHEDAUTH: 0 1554224008: |-- mosquitto_auth_acl_check(..., client id not available, mqttadmin, blind/bc/level, MOSQ_ACL_WRITE) 1554224008: |-- aclcheck(mqttadmin, blind/bc/level, 4) CACHEDAUTH: 0 1554224008: |-- mosquitto_auth_acl_check(..., client id not available, mqttadmin, blind/bc/state, MOSQ_ACL_WRITE) 1554224008: |-- aclcheck(mqttadmin, blind/bc/state, 2) CACHEDAUTH: 0

Solved. My MQTT settings were not correct. I’m a total noob with home assistant and MQTT but I’m learning every day.

Did your code work?
I’m just getting started with a stepper.

Hi

Yes I got it working. I ended up using code from here https://github.com/thehookup/MQTT_Motorized_Shades

Since then I have moved to geared DC motor because my roller shade was too heavy for the stepper motor and it was making aloud noise in every rotation.

2 Likes

Hi,
I followed the instructions, but the HA log shows the following error. I appreciate any help:

2020-12-31 13:25:20 ERROR (MainThread) [homeassistant.util.logging] Exception in brightness_received when handling msg on 'blind/bc/state': 'ON'
Traceback (most recent call last):
  File "/usr/src/homeassistant/homeassistant/components/mqtt/debug_info.py", line 35, in wrapper
    msg_callback(msg)
  File "/usr/src/homeassistant/homeassistant/components/mqtt/light/schema_basic.py", line 340, in brightness_received
    device_value = float(payload)
ValueError: could not convert string to float: 'ON'

2020-12-31 13:25:48 ERROR (MainThread) [homeassistant.util.logging] Exception in brightness_received when handling msg on 'blind/bc/state': 'OFF'
Traceback (most recent call last):
  File "/usr/src/homeassistant/homeassistant/components/mqtt/debug_info.py", line 35, in wrapper
    msg_callback(msg)
  File "/usr/src/homeassistant/homeassistant/components/mqtt/light/schema_basic.py", line 340, in brightness_received
    device_value = float(payload)
ValueError: could not convert string to float: 'OFF'

This is the parameter I have configured:

#include <Servo.h>

#include <ESP8266WiFi.h>
#include <ESP8266WiFiAP.h>
#include <ESP8266WiFiGeneric.h>
#include <ESP8266WiFiMulti.h>
#include <ESP8266WiFiScan.h>
#include <ESP8266WiFiSTA.h>
#include <ESP8266WiFiType.h>
#include <WiFiClient.h>
#include <WiFiClientSecure.h>
#include <WiFiServer.h>
#include <WiFiUdp.h>

#include <PubSubClient.h>


/************ WIFI and MQTT INFORMATION (CHANGE THESE FOR YOUR SETUP) ******************/
#define wifi_ssid "*****" //enter your WIFI SSID
#define wifi_password "*****" //enter your WIFI Password

#define mqtt_server "******" // Enter your MQTT server adderss or IP. I use my DuckDNS adddress (yourname.duckdns.org) in this field
#define mqtt_user "******" //enter your MQTT username
#define mqtt_password "******" //enter your password








WiFiClient espClient;
PubSubClient client(espClient);

Servo myservo;

int val;
int itsatrap = 0;


void setup() {
  Serial.begin(115200);

  setup_wifi();

  client.setServer(mqtt_server, 1883); //CHANGE PORT HERE IF NEEDED
  client.setCallback(callback);

}


void setup_wifi() {

  delay(10);
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(wifi_ssid);

  WiFi.mode(WIFI_STA);
  WiFi.begin(wifi_ssid, wifi_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) {
    char p[length + 1];
    memcpy(p, payload, length);
    p[length] = NULL;
    String message(p);
    String mytopic(topic);
    if (itsatrap == 0 && mytopic == "blind/bc/command" && message.equals("ON")){  
      myservo.attach(D4);
      delay(500);
      myservo.write(90); 
      client.publish("blind/bc/state", "ON");
      delay(1000);
      myservo.detach();
      }
    else if (mytopic == "blind/bc/command" && message.equalsIgnoreCase("OFF")){
      myservo.attach(D4);
      delay(500);
      myservo.write(0);  
      client.publish("blind/bc/state", "OFF");
      delay(1000);
      myservo.detach();
    }
    else if (mytopic == "blind/bc/level"){
      myservo.attach(D4);
      delay(500);
      val = message.toInt(); //converts command to integer to be used for positional arrangement
      val = map (val, 0, 99, 0, 180);
      myservo.write(val);
      client.publish("blind/bc/state", "ON");
      delay(3000);
      myservo.detach();
      itsatrap = 1;
    }
    else{
        itsatrap = 0;
    }

}



void loop() {

  if (!client.connected()) {
    reconnect();
  }
  client.loop();
}


void reconnect() {
  // Loop until we're reconnected
  while (!client.connected()) {
    Serial.print("Attempting MQTT connection...");
    // Attempt to connect
  if (client.connect("ESPBlindstl", mqtt_user, mqtt_password)) {
      Serial.println("connected");

      client.subscribe("blind/bc/command");
      client.subscribe("blind/bc/level");
      client.publish("blind/bc/state", "OFF");
    } else {
      Serial.print("failed, rc=");
      Serial.print(client.state());
      Serial.println(" try again in 5 seconds");
      // Wait 5 seconds before retrying
      delay(5000);
    }
  }
}

Config HA:

light:
  - platform: mqtt
    name: "Window Bottom Center"
    state_topic: "blind/bc/state"
    command_topic: "blind/bc/command"
    brightness_state_topic: "blind/bc/state"
    brightness_command_topic: "blind/bc/level"
    brightness_scale: 100
    qos: 0
    payload_on: "ON"
    payload_off: "OFF"
    optimistic: false
    retain: true

I cut my blinds over to covers. I don’t know that there is anything different here, and I didn’t see anything that was necessarily wrong with your setup, but I can’t compare apples to apples since I have cut over to a cover instead of a light.

cover: 
  - platform: mqtt
    name: "Window Bottom Center"
    state_topic: "blind/bc/state"
    command_topic: "blind/bc/command"
    position_topic: "blind/bc/lstate"
    set_position_topic: "blind/bc/level"
    tilt_min: 0
    tilt_max: 180
    qos: 0
    payload_open: "ON"
    payload_close: "OFF"
    retain: true
1 Like

Nice one. Just tried this last night. Tasmota wasn’t doing the job for me so gave this a try and it worked great. Had a slight issue with the servo always wanting to go the wrong way for the first half a second so I commented out the delay(500) lines and it’s perfect now. Seems like payload_open is no longer a valid option in HA but changing it to payload_on worked fine. Cheers for uploading this!

@jjhtpc could you publish any updates to your code now that you’ve cut over to cover from light? For example you have position_topic now which isn’t part of the code in your repo. Just trying to muddle through this and would appreciate any additional advice. Thanks!

Edit: Got it working as lights with this config. I’ve moved to an ESPHome-based setup since quite a bit has advanced on that front since this was first published - it makes things quite a bit less complicated. Will post my code when I have it cleaned up.

Hi @planetix , do you mind posting your ESPHome code? I’m trying to do the same thing but really not sure how or where to start.

I already have a tested and working version of a blind with ESPhome here if you’re interested.

It will only run one blind per ESP if you don’t have a problem with that.

1 Like

Thank you, I will check it out.

Thanks to the tips in this thread, got my blinds automated with MQTT. Thanks!