Window Blinds - MQTT / Nodemcu problems

Hi mate, I’ve just got around to looking at this project again, did you ever figure out how to add the retain flag to messages sent and received using the sketch?

Would you be able to provide a copy of your whole sketch?

Thanks in advance!

Hi Simo, sure, i at work, so later this week :slight_smile:

Hi Simo, use this on your mqtt broker:

mosquitto_pub -t YOUR_MQTT -r -n -u mqtt_user -P mqtt_password

That works insofar as it’ll reset itself to the previous state if it loses power (ie, if it’s “on” when it loses power, when it powers back up, it’ll turn “on” again - ie, will spin on), whereas, what I’m trying to do is when it loses power, NOT to automatically change state, just subscribe back to the state topic, but not change its state based on the retained message on that topic.

ie - when it connects back to the mqtt server, have it receive a null message rather than the “on” or “off” (which I know is what that line that you said to use does).

Is there some way to convert that line (sent from console) to a line of arduino code that I can add to my sketch?

I should also say my sketch is a little different to the one you’ve published above.

#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>
int spinTime = 7000;

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

#define mqtt_server "X" // Enter your MQTT server adderss or IP. 
#define mqtt_user "X" //enter your MQTT username
#define mqtt_password "X" //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/payload" && message.equals("ON")){  
      myservo.attach(D4);
      delay(500);
      myservo.write(180); 
      client.publish("blind/state", "ON", true);
      delay(spinTime);
      myservo.detach();
      }
    else if (mytopic == "blind/payload" && message.equalsIgnoreCase("OFF")){
      myservo.attach(D4);
      delay(500);
      myservo.write(0);  
      client.publish("blind/state", "OFF", true);
      delay(spinTime);
      myservo.detach();
    }
    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/payload");
      } else {
      Serial.print("failed, rc=");
      Serial.println(" try again in 5 seconds");
      // Wait 5 seconds before retrying
      delay(5000);
    }
  }
}

Please try this command.

I dont udnerstand what you like to have it working?

It works perfectly, but for when it loses power - then when it repowers, it tries to set it to the state that it was in previously.

What I want it to do, is wait for a new message to be published before anything happens.

Does that make sense?

I understand, but it should be that command to fix that.
Because the servo dont send the last state.
The ha have that state, so i will check the ha configuration for that thing, and will give you that.

Please help me with Sketch Code

config.yaml

        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: "OPEN"
        payload_off: "CLOSE"
        optimistic: true
        retain: false    

Sketch Code

    #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******************/
    #define wifi_ssid "Asus" //enter your WIFI SSID
    #define wifi_password "asus712" //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_PORT            1883             // [MqttPort] MQTT port (10123 on CloudMQTT)
    #define mqtt_user "someone" //enter your MQTT username
    #define mqtt_password "someone" //enter your password
    #define topic_state = "/troomblinds1/state";
    #define topic_command = "/troomblinds1/command";
    WiFiClient espClient;
    PubSubClient client (espClient);








    Servo myservo;
    int state = 0;
    int prevstate = 0;
    int dirc = 0;
    int spintime = 0;
    int servoPin = D4; //CHANGE TO WHATEVETR PIN YOUR USING

    void MQTT_connect();
    void callback(char* topic, byte* payload, unsigned int length);


    void setup() {
      Serial.begin(115200);
      myservo.detach();
      delay(10);
      Serial.println("Blind Startup Sequence");
      Serial.println(); Serial.println();
      Serial.print("Connecting to ");
      Serial.println(WLAN_SSID);

      WiFi.begin(WLAN_SSID, WLAN_PASS);
      while (WiFi.status() != WL_CONNECTED) {
        delay(500);
      Serial.print(".");
      }
      Serial.println();
      Serial.println("WiFi connected");
      Serial.println("IP address: ");
      Serial.println(WiFi.localIP());

      client.setServer(mqtt_server, 1883);
      client.setCallback(callback);

    }
    void servo_move() {
      Serial.println("State Change. Rotating Servo");
      if ( dirc == 180) {
        client.publish(topic_state,"opened");
      }
      else if (dirc == 0) {
        client.publish(topic_state,"closed");
    }
      myservo.attach(servoPin);
      myservo.write(dirc);
      delay(spintime);
      myservo.detach();

      Serial.println("Returning to main loop");
      return;
    }

    void callback(char* topic, byte* payload, unsigned int length) {
      Serial.print("Message arrived: [");
      Serial.print(topic);
      Serial.print(" ]");
      char *blindcommand = (char *) payload; // convert mqtt byte array into char array
      blindcommand[length] ='\0';            // Must delimit with 0

      Serial.print(blindcommand);
      if (strcmp(blindcommand,"open") == 0) {
        Serial.println("OPEN COMMAND RECEIVED");
        dirc = 180; // direction for servo to run
        spintime = 20000; // << CHANGE TO WHATEVER TIME YOU NEED TO OPEN YOUR BLINDS
        state = 1; //sets current state
      }
      else if (strcmp(blindcommand,"close") == 0) {
        Serial.println("CLOSE COMMAND RECEIVED");
        dirc = 0;
        spintime = 18000; // << CHANGE TO WHATEVER TIME YOU NEED TO CLOSE YOUR BLINDS
        state = 2; //sets current state
      }
      if (state != prevstate) {
        Serial.println("State change!");
        servo_move();
      }
      prevstate = state;
    }

    void MQTT_connect() {
      while (!client.connected()) {  
    Serial.print("Attempting MQTT connection...");
        // Attempt to connect
        if (client.connect(SENSORNAME, mqtt_user, mqtt_password)) {
          Serial.println("MQTT connected");
        client.subscribe(topic_command);
      } else {
        Serial.print("failed, rc=");
      Serial.print(client.state());
      Serial.println(" try again in 5 seconds");
      delay(1000); // wait 5 seconds
      }
      }
    }


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

Error

Arduino: 1.8.2 (Windows 10), Board: "WeMos D1 R2 & mini, 80 MHz, 115200, 4M (3M SPIFFS)"

C:\Users\WinPC\Downloads\Compressed\esp8266MQTTBlinds-master\esp8266MQTTBlinds-master\mqttblinds\mqttblinds.ino: In function 'void setup()':

mqttblinds:56: error: 'WLAN_SSID' was not declared in this scope

   Serial.println(WLAN_SSID);

                  ^

mqttblinds:58: error: 'WLAN_PASS' was not declared in this scope

   WiFi.begin(WLAN_SSID, WLAN_PASS);

                         ^

C:\Users\WinPC\Downloads\Compressed\esp8266MQTTBlinds-master\esp8266MQTTBlinds-master\mqttblinds\mqttblinds.ino: In function 'void servo_move()':

mqttblinds:26: error: expected primary-expression before '=' token

 #define topic_state = "/troomblinds1/state";

                     ^

C:\Users\WinPC\Downloads\Compressed\esp8266MQTTBlinds-master\esp8266MQTTBlinds-master\mqttblinds\mqttblinds.ino:75:20: note: in expansion of macro 'topic_state'

     client.publish(topic_state,"opened");

                    ^

mqttblinds:75: error: expected primary-expression before ',' token

     client.publish(topic_state,"opened");

                               ^

mqttblinds:75: error: expected ';' before ')' token

     client.publish(topic_state,"opened");

                                        ^

mqttblinds:26: error: expected primary-expression before '=' token

 #define topic_state = "/troomblinds1/state";

                     ^

C:\Users\WinPC\Downloads\Compressed\esp8266MQTTBlinds-master\esp8266MQTTBlinds-master\mqttblinds\mqttblinds.ino:78:20: note: in expansion of macro 'topic_state'

     client.publish(topic_state,"closed");

                    ^

mqttblinds:78: error: expected primary-expression before ',' token

     client.publish(topic_state,"closed");

                               ^

mqttblinds:78: error: expected ';' before ')' token

     client.publish(topic_state,"closed");

                                        ^

C:\Users\WinPC\Downloads\Compressed\esp8266MQTTBlinds-master\esp8266MQTTBlinds-master\mqttblinds\mqttblinds.ino: In function 'void MQTT_connect()':

mqttblinds:120: error: 'SENSORNAME' was not declared in this scope

     if (client.connect(SENSORNAME, mqtt_user, mqtt_password)) {

                        ^

mqttblinds:27: error: expected primary-expression before '=' token

 #define topic_command = "/troomblinds1/command";

                       ^

C:\Users\WinPC\Downloads\Compressed\esp8266MQTTBlinds-master\esp8266MQTTBlinds-master\mqttblinds\mqttblinds.ino:122:22: note: in expansion of macro 'topic_command'

     client.subscribe(topic_command);

                      ^

mqttblinds:122: error: expected primary-expression before ')' token

     client.subscribe(topic_command);

                                   ^

mqttblinds:122: error: expected ';' before ')' token

Multiple libraries were found for "Servo.h"
 Used: C:\Program Files (x86)\Arduino\portable\packages\esp8266\hardware\esp8266\2.3.0\libraries\Servo
 Not used: C:\Program Files (x86)\Arduino\libraries\Servo
Multiple libraries were found for "PubSubClient.h"
 Used: C:\Program Files (x86)\Arduino\portable\sketchbook\libraries\PubSubClient
 Not used: C:\Program Files (x86)\Arduino\portable\sketchbook\libraries\ESP8266_Microgear
exit status 1
'WLAN_SSID' was not declared in this scope

The error shows exactly what is wrong. To start with;

'WLAN_SSID' was not declared in this scope
'WLAN_PASS' was not declared in this scope

You defined them as wifi_ssid and wifi_password

By the way, you published your wifi password on a public forum.

Thanks ! What is ‘WLAN_SSID’ Is it not same like wifi SSID.

Hi Smile, yes wlan is wireless lan, so please enter the ssid and password in the code for this to work :slight_smile:

1 Like

Hello friend,
can you help me to build same blind as yours, can you share your final code of your blind.
you help much appropriated