Opening & Closing blinds mixing ESP enabled remotes & Zwave

Hi,

Wanted to share a full scene open / close system for blinds. Mixing various remotes & zwave devices.

My scene.yaml :

- name: open_all_blinds
  entities:
    cover.somfy_blinds: "open"
    cover.frontdoor_blinds: "open"
    cover.small_shutter_level: "open"
    cover.small_shutter_switch: "open"
    cover.big_shutter_level: "open"
  icon: mdi:blinds-open

- name: close_all_blinds
  entities:
    cover.somfy_blinds: "closed"
    cover.frontdoor_blinds: "closed"
    cover.small_shutter_level: "closed"
    cover.big_shutter_level: "closed"
  icon: mdi:blinds

My frontend integration:

type: horizontal-stack
cards:
  - type: button
    tap_action:
      action: call-service
      service: scene.turn_on
      service_data:
        entity_id: scene.open_all_blinds
    entity: scene.open_all_blinds
    name: Open blinds
    icon: 'mdi:blinds-open'
  - type: button
    tap_action:
      action: call-service
      service: scene.turn_on
      service_data:
        entity_id: scene.close_all_blinds
    entity: scene.close_all_blinds
    name: Close blinds
    icon: 'mdi:blinds'

The Home assistant config:

- platform: mqtt
  name: "Somfy Blinds"
  command_topic:      "homeassistant/ESP-Somfy/cmd"
  state_topic:              "homeassistant/ESP-Somfy/state"
  availability_topic:     "homeassistant/ESP-Somfy/status"
  qos: 0
  retain: false
  payload_open: "OPEN"
  payload_close: "CLOSE"
  state_open: "open"
  state_closed: "closed"
  payload_available: "online"
  payload_not_available: "offline"

Btw, if you are interested with the smart remote, my Somfy telis 4 is linked to an ESP8266. The remote buttons are just putting the left part of the push button to the GND (right). So basically, pressing the button just put it to the Ground. Wire the part that is not GND to any I/O port of the ESP8266, the GND of the remote to GND of ESP8266 and VCC to VCC. I used this wiring diagram. The Arduino code is a mashup I made based on several source code and some of mine:

#include <PubSubClient.h>
#include <WiFiUdp.h>
#include <ArduinoOTA.h>
#include <EEPROM.h>

#ifdef ESP32
    #include <WiFi.h>
#elif ESP8266
    #include <ESP8266WiFi.h>
#endif
#ifdef ESP32
    #include <ESPmDNS.h>
#elif ESP8266
    #include <ESP8266mDNS.h>
#endif

int                  OTAport = 8266;
const char*      OTApassword = "xxxxxxx";
uint8_t                 OPEN = 2;
uint8_t                 STOP = 0;
uint8_t                CLOSE = 4;
const char*        cmd_topic = "homeassistant/ESP-Somfy/cmd";
const char*      state_topic = "homeassistant/ESP-Somfy/state";
const char*      status_topic = "homeassistant/ESP-Somfy/status";
const char*        wifi_ssid = "xxxxxx";
const char*    wifi_password = "xxxxxxxxx";
const unsigned int mqtt_port = 1883;
const char*          mqtt_id = "ESP1";
const char*      device_name = "ESP-Somfy";
long                     tps = 0;
long                       i = 0;
const char*      mqtt_server = "xxxxx";
const char*        mqtt_user = "xxxxxxx"; 
const char*    mqtt_password = "xxxxxxxx";
String                        state_shutter;

void Wifi_init();
void OTA_init();
void Button_press(char* button);
void mqttconnect();
void receivedCallback(char* topic, byte* payload, unsigned int length);
void EEwrite(char add,String data);
String EEread(char add);

WiFiClient wifiClient;
PubSubClient client(wifiClient);

void Wifi_init()
{
  long logrssi = 0 ;
  if (WiFi.SSID() != wifi_ssid) 
  {
    Serial.printf("[Connecting to %s                  ]\n", wifi_ssid);
    WiFi.mode(WIFI_STA);
    WiFi.begin(wifi_ssid, wifi_password);
    Serial.printf("[");
    WiFi.persistent(true);
    WiFi.setAutoConnect(true);
    WiFi.setAutoReconnect(true);
  }
  while (WiFi.status() != WL_CONNECTED) 
  {
     Serial.print(".");
     delay(1000);
  }
  Serial.println("]");
  for (size_t i = 0; i < 10; i++)
  {
    long rssi = WiFi.RSSI();
    logrssi = logrssi + rssi;
    delay(200);
  }
  #ifdef ESP32
     WiFi.setHostname(device_name);
  #elif ESP8266
     WiFi.hostname(device_name);
  #endif
  Serial.printf("[MAC: %s IP: %s]\n", WiFi.macAddress().c_str(), 
  WiFi.localIP().toString().c_str());
  Serial.printf("[Mean rssi = %0.1d dBm                    ]\n", logrssi / 10);
  delay(1000);
}

void OTA_init()
{
  ArduinoOTA.setPort(OTAport);
  ArduinoOTA.setHostname(device_name);
  ArduinoOTA.setPassword((const char *)OTApassword);
  ArduinoOTA.onStart([]() { Serial.println("Starting"); });
  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();
}

void EEwrite(char add,String data)
{
  int _size = data.length();
  int i;
  for(i=0;i<_size;i++)
  {
    EEPROM.write(add+i,data[i]);
  }
  EEPROM.write(add+_size,'\0');   //Add termination null character for String Data
  EEPROM.commit();
}

String EEread(char add)
{
  char data[10]; //Max 10 Bytes
  int i=0;
  unsigned char k;
  k=EEPROM.read(add);
  for(i=0;i<9;i++)
  {    
    k=EEPROM.read(add+i);
    data[i]=k;
    i++;
  }
  data[i]='\0';
  return String(data);
}

void mqttconnect() {
    while ( !client.connected() ) {
        Serial.print("[Connecting to MQTT server: ");
        if (client.connect(mqtt_id, mqtt_user, mqtt_password, status_topic, 1, 1, "offline", 1)) {
            Serial.println("connected   ]");
            client.subscribe(cmd_topic, 1);
            Serial.println("[Subscribed to cmd topics               ]");
            client.publish(status_topic, "online", false);
        }
        else {
            Serial.print("*** MQTT broker connexion failed, status code=");
            Serial.print(client.state());
            Serial.print(" ***");
            Serial.println("[Retrying in 5 seconds]");
            delay(5000);
        }
    }
}

void receivedCallback(char* topic, byte* payload, unsigned int length) {
  payload[length]='\0';
  if(strcmp((char *)payload, "OPEN") == 0) {
     Serial.println("- Shutter up cmd received");
     Button_press(OPEN);
     state_shutter = "open";
     EEwrite(0,state_shutter);
  }
  if(strcmp((char *)payload, "STOP") == 0) {
     Serial.println("- Shutter stop cmd received");
     Button_press(STOP);
     state_shutter = "unkown";
     EEwrite(0,state_shutter);
  }
  if(strcmp((char *)payload, "CLOSE") == 0) {
     Serial.print("- Shutter down cmd received");
     Serial.println("off");
     Button_press(CLOSE);
     state_shutter = "closed";
     EEwrite(0,state_shutter);
  }
  client.publish(state_topic, state_shutter.c_str(), false);
}

void Button_press(uint8_t button) {
  Serial.print("-- Pressing button: ");
  Serial.println(button);
  digitalWrite(button,LOW); 
  delay(1000);
  Serial.println("-- Releasing button");
  digitalWrite(button, HIGH);
}

void setup()
{
  String previous_state;
  Serial.begin(115200);
  Serial.printf("[<<<<<<<<<Booting up %s>>>>>>>>>>]\n", device_name);
  Wifi_init();
  Serial.println("[Setting up I/O                         ]");
  pinMode(OPEN,OUTPUT);
  pinMode(STOP,OUTPUT);
  pinMode(CLOSE,OUTPUT);
  digitalWrite(OPEN,HIGH);   // Set IN and OUT HIGH so the remote doesn't activate on start IN
  digitalWrite(STOP,HIGH);
  digitalWrite(CLOSE,HIGH);
  Serial.println("[Setting up OTA                         ]");
  OTA_init();  
  Serial.println("[Setting up MQTT                        ]");
  client.setKeepAlive(60);
  client.setServer(mqtt_server, mqtt_port);
  client.setCallback(receivedCallback);
  Serial.println("[Getting state pre-reboot from EEPROM   ]");
  EEPROM.begin(10);
  previous_state = EEread(0);
  Serial.println("[Connecting to MQTT                     ]");
  mqttconnect();
  delay(2000);
  if ( client.connected() ) {
     Serial.println("[Updating MQTT with pre-reboot state    ]");
     client.publish(state_topic, previous_state.c_str(), false);
  }                  
  Serial.println("[<<<<<<Init completed successfully>>>>>>]");
}

void loop()
{
  ArduinoOTA.handle();   
  if (WiFi.status() != WL_CONNECTED) {
     Serial.println("*** Wifi disconnected: reconnecting ***");
     Wifi_init();
  } 
  if ( !client.connected() ) {
     Serial.println("*** MQTT disconnected: reconnecting ***");
     mqttconnect();
  }
  client.loop();
  delay(200);
  if (millis()-tps>55000){
     tps=millis();
     client.publish(status_topic, "online", false);
  }