Supla 2 persianas

tecnica1
Mensajes: 15
Registrado: Dom Dic 17, 2017 11:29 pm

Hola @Maniek913, en referencia a tus consultas.
Aclaro que estoy utilizando una palaca Nodemcu 1.0

"Tengo un problema con este soft:
1. Los botones D4 y D8 no funcionan
2. durante el reset, las salidas D5 y D6 se activan brevemente
3. El led de configuración funciona en el puerto D4 en lugar de D3
4. el modo de configuración se inicia después de la primera pulsación de reiniciar
Todo funciona bien con la aplicación.
¿Alguien ha comprobado este sistema? ¿Es solo un problema?
Lo probé en 3 tipos diferentes de mosaicos, con el mismo resultado.
El pin D8 no se puede utilizar como entrada"

respuestas:
1- el botón D4 me funciona bien. El botón que estaba en D8 lo pasé a D6 y el relé a D8.
2- con el cambio anterior, solo quedaría solucionar D5, yo solo tengo Led en la placa y apenas enciende. Si tu relé funciona directamente con un transistor, prueba elevar la R de base.
3- El Led de configuración funciona en D3, ten presente que el anodo va con una R a + y el catodo a D3.
4- El modo de configuración entra con dos pulsaciones separadas en 1 segundo, si son muy rápidas solo hará reset.
y si funciona perfecto con la aplicación. Solo cambia D6 x D8 y todo irá bien.
Ten en cuenta de utilizar las versiones de soft indicadas por elmaya:
#define SUPLADEVICE_CPP // ----- V 1.6
#include <WiFiManager.h> //--------- https://github.com/tzapu/WiFiManager/tree/0.14 -------------
#include <ArduinoJson.h> //--------- https://github.com/bblanchon/ArduinoJson/tree/v5.13.2 ------
---- esp board manager 2.4.2 --- iwip Variant V2 higher Bandwidth en Arduino.


//#define D0 16 //no internal pullup resistor
//#define D1 5
//#define D2 4
//#define D3 0 //must not be pulled low during power on/reset, toggles value during boot
//#define D4 2 //must not be pulled low during power on/reset, toggles value during boot
//#define D5 14
//#define D6 12
//#define D7 13
//#define D8 15 //must not be pulled high during power on/reset

Ticker ticker;
#define relay_1 5
#define relay_2 4
#define relay_3 14
#define relay_4 15 //modificado
#define btn_1 2
#define btn_2 3
#define btn_3 12 //modificado
#define btn_4 13
#define status_led 0

Saludos a Todos, Feliz Año Nuevo desde Argentina.
Maniek913
Mensajes: 491
Registrado: Jue Feb 22, 2018 9:46 pm

Muchas gracias por su respuesta.
Usé un contenedor listo, pero intentaré aplicar tus consejos y compilar el suave.
Saludos cordiales y les deseo un Feliz Año Nuevo 2021
elmaya
Mensajes: 1482
Registrado: Mié Jun 27, 2018 5:48 pm
Ubicación: El Saucejo - Sevilla

tecnica1 escribió: Lun Dic 21, 2020 8:02 pm Hola @elmaya excelente, trabajo.
Ya hace un tiempo que lo ví, recién ahora lo implementé.
Me funcionó tanto la versión para cargar dede el IDE de Arduino, como el archivo compilado.
En función del Hardware que tengo, hice una modificacón de pines sin problema.
Pero necesito, si se puede, que el mismo dispositivo tenga Solo 1 PERSIANA y 1 VENTILADOR (o INTERRUPTOR DE LUZ).
Esto último no se como hacerlo, me podrás ayudar?
Si es así, necesito el archivo para poder editar los pines en caso de ser necesario.
De antemano muchas Gracias.
Supla 1 persianas + 1 relé
Basado en la nueva librería Supla dev.
3 relés + 3 pulsadores
Led de estado D4, giña 0.8s = no conectado – conectando, giña 0.3s = WiFiConfig, apagado = ok
WiFiConfig = pulsar D1 por al menos 5 segundos
El relé tiene dos modos de funcionamiento que se pueden seleccionar en WiFiConfig
“Relay Restore State” el relé recuerda el estado en caso de corte de alimentación
“Relay keep Turn On Duration” para temporizador de escaleras, el pulsador activa el relé con la misma duración que se haya establecido en la nube Supla, el relé apagado en caso de corte de alimentación
Captura de pantalla (114).png
Captura de pantalla (114).png (20.17 KiB) Visto 2787 veces

Código: Seleccionar todo

/*
Copyright (C) AC SOFTWARE SP. Z O.O.

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
*/
#define supla_lib_config_h_  // silences debug messages 
#include "LittleFS.h"   // ---- esp board manager 2.7.4 ---
#include <WiFiManager.h>
#include <ArduinoJson.h> //--------- V6 ------
#include <EEPROM.h>
#include <ESP8266WebServer.h>
#include <ESP8266HTTPUpdateServer.h>
#include <Ticker.h>      //for LED status
#include <ESP8266TrueRandom.h>
#include <SuplaDevice.h>
#include <supla/control/roller_shutter.h>
#include <supla/control/button.h>
#include <supla/control/relay.h>
#include <supla/network/esp_wifi.h>
Supla::ESPWifi wifi("", "");  //------ Do not change----wifimanager takes care------
#define STORAGE_OFFSET 512
#include <supla/storage/eeprom.h>
Supla::Eeprom eeprom(STORAGE_OFFSET);

extern "C"
{
#include "user_interface.h"
} 

//#define D0 16  //no internal pullup resistor
//#define D1  5
//#define D2  4
//#define D3  0  //must not be pulled low during power on/reset, toggles value during boot
//#define D4  2  //must not be pulled low during power on/reset, toggles value during boot
//#define D5 14
//#define D6 12
//#define D7 13
//#define D8 15  //must not be pulled high during power on/reset
//#define RX  3  //High at boot
//#define TX  1  //must not be pulled low during power on/reset

#define RS_RELAY_OPEN  12
#define RS_RELAY_CLOSE  13
#define RS_BUTTON_OPEN_PIN  0
#define RS_BUTTON_CLOSE_PIN 4
#define RELAY_PIN   14
#define BUTTON_PIN   5
int status_led = 2;         
int C_W_state = HIGH; 
int last_C_W_state = HIGH;
unsigned long time_last_C_W_change = 0; 
long C_W_delay = 5000;               // ---------------------- config delay 5 seconds ---------------------------
char Supla_server[81]=("Set server address");
char Email[81]=("set email address");
char Supla_name[81];
char Supla_status[51];
bool shouldSaveConfig = false;
bool initialConfig = false;
bool starting = true;
bool Tik = true;
int s;
char GUID[SUPLA_GUID_SIZE];
char AUTHKEY[SUPLA_AUTHKEY_SIZE];
byte uuidNumber[16]; // UUIDs in binary form are 16 bytes long
int customFieldLength = 40;
WiFiManagerParameter custom_field; // global param ( for non blocking w params )
static const char custom_radio_str[] PROGMEM = "<br><div style='text-align:center; width:100%; padding:0;'><label for='customfieldid'>Relay Restore State</label><input type='radio' name='customfieldid' value='0' checked>Relay keep Turn On Duration<input type='radio' name='customfieldid' value='1'></div>";
ESP8266WebServer httpServer(81);
ESP8266HTTPUpdateServer httpUpdater;
WiFiManager wifiManager;
Ticker ticker;

void tick() {
  int state = digitalRead(status_led);  
  digitalWrite(status_led, !state);     
}
void saveConfigCallback () {          
  Serial.println("Should save config");
  shouldSaveConfig = true;
}
void ondemandwifiCallback () {
   ticker.attach(0.3, tick);

   WiFiManagerParameter custom_Supla_server("server", "supla server", Supla_server, 81,"required");
   WiFiManagerParameter custom_Email("email", "Email", Email, 81,"required");
   WiFiManagerParameter custom_Supla_name("name", "Supla Device Name", Supla_name, 81,"required");
   WiFiManagerParameter custom_html_id21("<div><h4> - Supla State -   ");
   WiFiManagerParameter custom_html_id22( Supla_status);
   WiFiManagerParameter custom_html_id23( "</h4></div>");
   
   new (&custom_field) WiFiManagerParameter(custom_radio_str); // custom html input

   wifiManager.setBreakAfterConfig(true);
   wifiManager.setSaveConfigCallback(saveConfigCallback);
   wifiManager.setSaveParamsCallback(saveParamCallback);
  
   wifiManager.addParameter(&custom_Supla_server);
   wifiManager.addParameter(&custom_Email);
   wifiManager.addParameter(&custom_Supla_name);
   wifiManager.addParameter(&custom_html_id21);
   wifiManager.addParameter(&custom_html_id22);
   wifiManager.addParameter(&custom_html_id23);   

   wifiManager.addParameter(&custom_field);

   wifiManager.setCustomHeadElement("<style>html{ background-color: #01DF3A;}</style><div class='s'><svg version='1.1' id='l' x='0' y='0' viewBox='0 0 200 200' xml:space='preserve'><path d='M59.3,2.5c18.1,0.6,31.8,8,40.2,23.5c3.1,5.7,4.3,11.9,4.1,18.3c-0.1,3.6-0.7,7.1-1.9,10.6c-0.2,0.7-0.1,1.1,0.6,1.5c12.8,7.7,25.5,15.4,38.3,23c2.9,1.7,5.8,3.4,8.7,5.3c1,0.6,1.6,0.6,2.5-0.1c4.5-3.6,9.8-5.3,15.7-5.4c12.5-0.1,22.9,7.9,25.2,19c1.9,9.2-2.9,19.2-11.8,23.9c-8.4,4.5-16.9,4.5-25.5,0.2c-0.7-0.3-1-0.2-1.5,0.3c-4.8,4.9-9.7,9.8-14.5,14.6c-5.3,5.3-10.6,10.7-15.9,16c-1.8,1.8-3.6,3.7-5.4,5.4c-0.7,0.6-0.6,1,0,1.6c3.6,3.4,5.8,7.5,6.2,12.2c0.7,7.7-2.2,14-8.8,18.5c-12.3,8.6-30.3,3.5-35-10.4c-2.8-8.4,0.6-17.7,8.6-22.8c0.9-0.6,1.1-1,0.8-2c-2-6.2-4.4-12.4-6.6-18.6c-6.3-17.6-12.7-35.1-19-52.7c-0.2-0.7-0.5-1-1.4-0.9c-12.5,0.7-23.6-2.6-33-10.4c-8-6.6-12.9-15-14.2-25c-1.5-11.5,1.7-21.9,9.6-30.7C32.5,8.9,42.2,4.2,53.7,2.7c0.7-0.1,1.5-0.2,2.2-0.2C57,2.4,58.2,2.5,59.3,2.5z M76.5,81c0,0.1,0.1,0.3,0.1,0.6c1.6,6.3,3.2,12.6,4.7,18.9c4.5,17.7,8.9,35.5,13.3,53.2c0.2,0.9,0.6,1.1,1.6,0.9c5.4-1.2,10.7-0.8,15.7,1.6c0.8,0.4,1.2,0.3,1.7-0.4c11.2-12.9,22.5-25.7,33.4-38.7c0.5-0.6,0.4-1,0-1.6c-5.6-7.9-6.1-16.1-1.3-24.5c0.5-0.8,0.3-1.1-0.5-1.6c-9.1-4.7-18.1-9.3-27.2-14c-6.8-3.5-13.5-7-20.3-10.5c-0.7-0.4-1.1-0.3-1.6,0.4c-1.3,1.8-2.7,3.5-4.3,5.1c-4.2,4.2-9.1,7.4-14.7,9.7C76.9,80.3,76.4,80.3,76.5,81z M89,42.6c0.1-2.5-0.4-5.4-1.5-8.1C83,23.1,74.2,16.9,61.7,15.8c-10-0.9-18.6,2.4-25.3,9.7c-8.4,9-9.3,22.4-2.2,32.4c6.8,9.6,19.1,14.2,31.4,11.9C79.2,67.1,89,55.9,89,42.6z M102.1,188.6c0.6,0.1,1.5-0.1,2.4-0.2c9.5-1.4,15.3-10.9,11.6-19.2c-2.6-5.9-9.4-9.6-16.8-8.6c-8.3,1.2-14.1,8.9-12.4,16.6C88.2,183.9,94.4,188.6,102.1,188.6z M167.7,88.5c-1,0-2.1,0.1-3.1,0.3c-9,1.7-14.2,10.6-10.8,18.6c2.9,6.8,11.4,10.3,19,7.8c7.1-2.3,11.1-9.1,9.6-15.9C180.9,93,174.8,88.5,167.7,88.5z'/></svg>");
   wifiManager.setMinimumSignalQuality(8);
   //wifiManager.setShowStaticFields(true); // force show static ip fields
   //wifiManager.setShowDnsFields(true);    // force show dns field always
   wifiManager.setConfigPortalTimeout(180);

   if (!wifiManager.startConfigPortal("1RS-1V")) { Serial.println("Not connected to WiFi but continuing anyway.");} else { Serial.println("connected...yeey :)");}                
    strcpy(Supla_server, custom_Supla_server.getValue());
    strcpy(Email, custom_Email.getValue());
    strcpy(Supla_name, custom_Supla_name.getValue()); 
    if(strcmp(Supla_server, "get_new_guid_and_authkey") == 0){
      Serial.println("new guid & authkey.");
      EEPROM.write(300, 0);
      EEPROM.commit();
      ESP.reset(); 
    }

    WiFi.softAPdisconnect(true);   //  close AP
    Tik = true;
}
void status_func(int status, const char *msg) {    //    ------------------------ Status --------------------------

  if (s != status){
    s = status; 
      if (s != 10){
        strcpy(Supla_status, msg);
          Serial.print("Status: ");Serial.print(s);Serial.print(" ");Serial.println(Supla_status);
  }  }            
}
String getParam(String name){
  String value;
  if(wifiManager.server->hasArg(name)) {
    value = wifiManager.server->arg(name);
      if (value == "1"){ 
         EEPROM.write(381, 1);
          EEPROM.commit();
           Serial.println("----- Relay keep Turn On Duration -----");
         }else{
         EEPROM.write(381, 255);
          EEPROM.commit();
           Serial.println("----- Relay Restore State -----");          
         }
  }
  return value;
}
void saveParamCallback(){
  Serial.println("[CALLBACK] saveParamCallback fired");
  Serial.println("PARAM customfieldid = " + getParam("customfieldid"));
}
void guid_authkey(void) {
  if (EEPROM.read(300) != 60){
    int eep_gui = 301;

    ESP8266TrueRandom.uuid(uuidNumber);

    String uuidString = "";
    for (int i = 0; i < 16; i++) {
      int topDigit = uuidNumber[i] >> 4;
      int bottomDigit = uuidNumber[i] & 0x0f;
      uuidString += "0123456789abcdef"[topDigit];
      uuidString += "0123456789abcdef"[bottomDigit];
    }
    int length_uuid = uuidString.length();
    for (int i = 0; i < length_uuid; ++i) {
      EEPROM.put(eep_gui + i, uuidString[i]);
    }

    int eep_aut = 341;

    ESP8266TrueRandom.uuid(uuidNumber);

    String uuidString2 = "";
    for (int i = 0; i < 16; i++) {
      int topDigit = uuidNumber[i] >> 4;
      int bottomDigit = uuidNumber[i] & 0x0f;
      uuidString2 += "0123456789abcdef"[topDigit];
      uuidString2 += "0123456789abcdef"[bottomDigit];
    }
    int length_uuid2 = uuidString2.length();
    for (int i = 0; i < length_uuid2; ++i) {
      EEPROM.put(eep_aut + i, uuidString2[i]);
    }
    EEPROM.write(300, 60);
    EEPROM.commit();
  }
  read_guid();
  read_authkey();
  Serial.print("GUID : ");Serial.println(read_guid()); 
  Serial.print("AUTHKEY : ");Serial.println(read_authkey()); 
}

String read_guid(void) {
  String read_eeprom = "";
  int i, ii = 0;
  int eep_star = 301;
  int end_guid = eep_star + SUPLA_GUID_SIZE;
  String temp_read = "0x";
  for (i = eep_star; i < end_guid + 16;  i = i + 1) {
    temp_read += char(EEPROM.read(i));
    read_eeprom += char(EEPROM.read(i));
    if ( (i % 2) == 0) {
      char *_guid = strcpy((char*)malloc(temp_read.length() + 1), temp_read.c_str());
      GUID[ii] = strtoul( _guid, NULL, 16);
      temp_read = "0x";
      ii++;
    }
  }
  return read_eeprom;
}
String read_authkey(void) {
  String read_eeprom = "";
  int i, ii = 0;
  int eep_star = 341;
  int end_authkey = eep_star + SUPLA_AUTHKEY_SIZE;
  String temp_read = "0x";
  for (i = eep_star; i < end_authkey + 16;  i = i + 1) {
    temp_read += char(EEPROM.read(i));
    read_eeprom += char(EEPROM.read(i));
    if ( (i % 2) == 0) {
      char *_authkey = strcpy((char*)malloc(temp_read.length() + 1), temp_read.c_str());
      AUTHKEY[ii] = strtoul( _authkey, NULL, 16);
      temp_read = "0x";
      ii++;
    }
  }
  return read_eeprom;
}

void setup() {
  wifi_set_sleep_type(NONE_SLEEP_T);
  Serial.begin(115200, SERIAL_8N1, SERIAL_TX_ONLY, 15);
  Serial.println();
  EEPROM.begin(1024); 
  pinMode(status_led,OUTPUT);
  ticker.attach(0.8, tick); 
  guid_authkey();
    
  if (WiFi.SSID()==""){ initialConfig = true;} 

  if (LittleFS.begin()) {  // ------------------------- wificonfig read -----------------
    Serial.println("mounted file system");
    if (LittleFS.exists("/config.json")) {
      Serial.println("reading config file");
       File configFile = LittleFS.open("/config.json", "r");
      if (configFile) {
        Serial.println("opened config file");
         size_t size = configFile.size();
         std::unique_ptr<char[]> buf(new char[size]);
         configFile.readBytes(buf.get(), size);
        DynamicJsonDocument json(1024);
        DeserializationError deserializeError = deserializeJson(json, buf.get());
        serializeJsonPretty(json, Serial);
        if (!deserializeError) {Serial.println("\nparsed json");         
          if (json.containsKey("Supla_server")) strcpy(Supla_server, json["Supla_server"]);
          if (json.containsKey("Email")) strcpy(Email, json["Email"]);
          if (json.containsKey("Supla_name")) strcpy(Supla_name, json["Supla_name"]);       
        } else {
          Serial.println("failed to load json config");
           initialConfig = true;
        }
        configFile.close(); 
      }
    }
   } else {
    Serial.println("failed to mount FS");
  } 
   wifi_station_set_hostname(Supla_name);


  Supla::Control::RollerShutter *rs = new Supla::Control::RollerShutter(RS_RELAY_OPEN, RS_RELAY_CLOSE, true);  // Supla::Control::RollerShutter(PIN_UP, PIN_DOWN, invertLogic); "true" - for high state control, "false" - for low state control.
  Supla::Control::Button *buttonOpen = new Supla::Control::Button(RS_BUTTON_OPEN_PIN, true, true);  //  new Supla::Control::Button(pin, pullup, invertLogic);
  Supla::Control::Button *buttonClose = new Supla::Control::Button(RS_BUTTON_CLOSE_PIN, true, true);
  buttonOpen->addAction(Supla::OPEN_OR_STOP, *rs, Supla::ON_PRESS);
  buttonClose->addAction(Supla::CLOSE_OR_STOP, *rs, Supla::ON_PRESS);  

  auto relay_1 = new Supla::Control::Relay(RELAY_PIN, true);
  auto button_1 = new Supla::Control::Button(BUTTON_PIN, true, true);   
   if (EEPROM.read(381) > 1){ 
     relay_1->setDefaultStateRestore();
     Serial.println("----- Relay Restore State -----");
   }else{
     relay_1->setDefaultStateOff();
     relay_1->keepTurnOnDuration();
     Serial.println("----- Relay keep Turn On Duration -----"); 
   }
   button_1->addAction(Supla::TOGGLE, relay_1, Supla::ON_PRESS);
   button_1->setSwNoiseFilterDelay(50);
   
    eeprom.setStateSavePeriod(10000);  

    SuplaDevice.setName(Supla_name);
    SuplaDevice.setStatusFuncImpl(&status_func);
    wifi.enableSSL(false);
    SuplaDevice.begin(GUID,Supla_server,Email,AUTHKEY);

}

void loop() {
  if (initialConfig == true){ondemandwifiCallback();}

  int C_W_read = digitalRead(BUTTON_PIN);{  
   if (C_W_read != last_C_W_state) {  time_last_C_W_change = millis();}      
    if ((millis() - time_last_C_W_change) > C_W_delay) {     
     if (C_W_read != C_W_state) {     
       C_W_state = C_W_read;       
       if (C_W_state == LOW) {
        ondemandwifiCallback () ;} } }         
     last_C_W_state = C_W_read;            
   }

  if (shouldSaveConfig == true) { // ------------------------ wificonfig save --------------
    Serial.println(" config...");  
    DynamicJsonDocument json(1024);
    json["Supla_server"] = Supla_server;
    json["Email"] = Email;
    json["Supla_name"] = Supla_name;
    File configFile = LittleFS.open("/config.json", "w");
    if (!configFile) {Serial.println("failed to open config file for writing");}    
    serializeJsonPretty(json, Serial);
    serializeJson(json, configFile);
    configFile.close();
    Serial.println("Config written successfully");
    shouldSaveConfig = false;
    initialConfig = false; 
    WiFi.mode(WIFI_STA);   
    delay(5000);
    ESP.restart();     
  }
       
  SuplaDevice.iterate();
   delay(25);
    
  if (WiFi.status() == WL_CONNECTED){
    if (starting){
      httpUpdater.setup(&httpServer, "/update", "admin", "pass");
      httpServer.begin(); 
      starting = false;         
     }
     httpServer.handleClient();
     if ((Tik == true) && (s == 17)){ticker.detach();digitalWrite(status_led, HIGH);Tik = false;}
   }else{
    if (Tik == false) { ticker.attach(0.8, tick);Tik = true;Serial.println("ticker on  no 17"); } 
   }

}
tecnica1_1RS_1Relay_3Button_DOUT_16Mbit.rar
(574.3 KiB) Descargado 117 veces
tecnica1
Mensajes: 15
Registrado: Dom Dic 17, 2017 11:29 pm

Feliz Año Nuevo
Referencia:
Supla 1 persianas + 1 relé
Basado en la nueva librería Supla dev.

Muchas Gracias #elmaya
Estoy Feliz, cargué el soft en la placa Nodemcu y funcionó de Primera.
Además aunque no te lo había pedido, cambiaste la configuración a D1, y así me queda como los otros módulos que instalé en mi casa.
Cambió la funcionalidad de los pulsadores, ahora la orden la ejecuta al presionar y no al soltarlo, eso es más lógico y por lo tanto amable al usuario.
Saludos desde Buenos Aires, Argentina.
tecnica1
Mensajes: 15
Registrado: Dom Dic 17, 2017 11:29 pm

Maniek913 escribió: Vie Ene 01, 2021 8:29 am Muchas gracias por su respuesta.
Usé un contenedor listo, pero intentaré aplicar tus consejos y compilar el suave.
Saludos cordiales y les deseo un Feliz Año Nuevo 2021
Hola, si lo necesitas te envío el archivo compilado.
Maniek913
Mensajes: 491
Registrado: Jue Feb 22, 2018 9:46 pm

Así que, por favor, tengo un Arduino con las últimas bibliotecas y tendría que cambiar un poco.
elmaya
Mensajes: 1482
Registrado: Mié Jun 27, 2018 5:48 pm
Ubicación: El Saucejo - Sevilla

Maniek913 escribió: Sab Ene 02, 2021 8:10 am Así que, por favor, tengo un Arduino con las últimas bibliotecas y tendría que cambiar un poco.
2 persianas 2 pulsadores:

En este diseño solo se necesita 1 pulsador por persiana ya que funciona en el modo paso a paso “ abre, para, cierra, para ”

Los Gpio:
Gpio14 D5 = relé apertura persiana 1
Gpio12 D6 = relé cierre persiana 1
Gpio13 D7 = relé apertura persiana 2
Gpio 5 D1 = relé cierre persiana 2
Gpio 0 D3 = pulsador persiana 1 + WiFiConfig “manteniendo pulsado durante al menos 5 segundos”
Gpio 4 D2 = pulsador persiana 2
Gpio 2 D4 = Led de estado “guiñando = no conectado/conectando, encendido = WiFiConfig, apagado = ok”

Código: Seleccionar todo

/*
Copyright (C) AC SOFTWARE SP. Z O.O.

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
*/
#define supla_lib_config_h_  // silences debug messages 
#include "LittleFS.h"   // ---- esp board manager 2.7.4 ---
#include <WiFiManager.h>
#include <ArduinoJson.h> //--------- V6 ------
#include <EEPROM.h>
#include <ESP8266WebServer.h>
#include <ESP8266HTTPUpdateServer.h>
#include <Ticker.h>      //for LED status
#include <ESP8266TrueRandom.h>
#include <SuplaDevice.h>
#include <supla/control/roller_shutter.h>
#include <supla/control/button.h>
#include <supla/control/relay.h>
#include <supla/network/esp_wifi.h>
Supla::ESPWifi wifi("", "");  //------ Do not edit----wifimanager takes care------
#define STORAGE_OFFSET 512
#include <supla/storage/eeprom.h>
Supla::Eeprom eeprom(STORAGE_OFFSET);

extern "C"
{
#include "user_interface.h"
} 

//#define D0 16  //no internal pullup resistor
//#define D1  5
//#define D2  4
//#define D3  0  //must not be pulled low during power on/reset, toggles value during boot
//#define D4  2  //must not be pulled low during power on/reset, toggles value during boot
//#define D5 14
//#define D6 12
//#define D7 13
//#define D8 15  //must not be pulled high during power on/reset
//#define RX  3  //High at boot
//#define TX  1  //must not be pulled low during power on/reset

#define RS_RELAY_OPEN_1  14
#define RS_RELAY_CLOSE_1 12
#define RS_RELAY_OPEN_2  13
#define RS_RELAY_CLOSE_2  5
#define RS_BUTTON_1_PIN   0
#define RS_BUTTON_2_PIN   4 
int status_led = 2;         
int C_W_state = HIGH; 
int last_C_W_state = HIGH;
unsigned long time_last_C_W_change = 0; 
long C_W_delay = 5000;               // ---------------------- config delay 5 seconds ---------------------------
char Supla_server[81]=("svr?.supla.org");
char Email[81]=("your@email");
char Supla_name[81];
char Supla_status[51];
char Router_SSID [32];
char Router_Pass[64];
bool shouldSaveConfig = false;
bool initialConfig = false;
bool starting = true;
bool Tik = true;
int s;
char GUID[SUPLA_GUID_SIZE];
char AUTHKEY[SUPLA_AUTHKEY_SIZE];
byte uuidNumber[16]; // UUIDs in binary form are 16 bytes long
static const char logo[] PROGMEM = "<style>html{ background-color: #01DF3A;}</style><div class='s'><svg version='1.1' id='l' x='0' y='0' viewBox='0 0 200 200' xml:space='preserve'><path d='M59.3,2.5c18.1,0.6,31.8,8,40.2,23.5c3.1,5.7,4.3,11.9,4.1,18.3c-0.1,3.6-0.7,7.1-1.9,10.6c-0.2,0.7-0.1,1.1,0.6,1.5c12.8,7.7,25.5,15.4,38.3,23c2.9,1.7,5.8,3.4,8.7,5.3c1,0.6,1.6,0.6,2.5-0.1c4.5-3.6,9.8-5.3,15.7-5.4c12.5-0.1,22.9,7.9,25.2,19c1.9,9.2-2.9,19.2-11.8,23.9c-8.4,4.5-16.9,4.5-25.5,0.2c-0.7-0.3-1-0.2-1.5,0.3c-4.8,4.9-9.7,9.8-14.5,14.6c-5.3,5.3-10.6,10.7-15.9,16c-1.8,1.8-3.6,3.7-5.4,5.4c-0.7,0.6-0.6,1,0,1.6c3.6,3.4,5.8,7.5,6.2,12.2c0.7,7.7-2.2,14-8.8,18.5c-12.3,8.6-30.3,3.5-35-10.4c-2.8-8.4,0.6-17.7,8.6-22.8c0.9-0.6,1.1-1,0.8-2c-2-6.2-4.4-12.4-6.6-18.6c-6.3-17.6-12.7-35.1-19-52.7c-0.2-0.7-0.5-1-1.4-0.9c-12.5,0.7-23.6-2.6-33-10.4c-8-6.6-12.9-15-14.2-25c-1.5-11.5,1.7-21.9,9.6-30.7C32.5,8.9,42.2,4.2,53.7,2.7c0.7-0.1,1.5-0.2,2.2-0.2C57,2.4,58.2,2.5,59.3,2.5z M76.5,81c0,0.1,0.1,0.3,0.1,0.6c1.6,6.3,3.2,12.6,4.7,18.9c4.5,17.7,8.9,35.5,13.3,53.2c0.2,0.9,0.6,1.1,1.6,0.9c5.4-1.2,10.7-0.8,15.7,1.6c0.8,0.4,1.2,0.3,1.7-0.4c11.2-12.9,22.5-25.7,33.4-38.7c0.5-0.6,0.4-1,0-1.6c-5.6-7.9-6.1-16.1-1.3-24.5c0.5-0.8,0.3-1.1-0.5-1.6c-9.1-4.7-18.1-9.3-27.2-14c-6.8-3.5-13.5-7-20.3-10.5c-0.7-0.4-1.1-0.3-1.6,0.4c-1.3,1.8-2.7,3.5-4.3,5.1c-4.2,4.2-9.1,7.4-14.7,9.7C76.9,80.3,76.4,80.3,76.5,81z M89,42.6c0.1-2.5-0.4-5.4-1.5-8.1C83,23.1,74.2,16.9,61.7,15.8c-10-0.9-18.6,2.4-25.3,9.7c-8.4,9-9.3,22.4-2.2,32.4c6.8,9.6,19.1,14.2,31.4,11.9C79.2,67.1,89,55.9,89,42.6z M102.1,188.6c0.6,0.1,1.5-0.1,2.4-0.2c9.5-1.4,15.3-10.9,11.6-19.2c-2.6-5.9-9.4-9.6-16.8-8.6c-8.3,1.2-14.1,8.9-12.4,16.6C88.2,183.9,94.4,188.6,102.1,188.6z M167.7,88.5c-1,0-2.1,0.1-3.1,0.3c-9,1.7-14.2,10.6-10.8,18.6c2.9,6.8,11.4,10.3,19,7.8c7.1-2.3,11.1-9.1,9.6-15.9C180.9,93,174.8,88.5,167.7,88.5z'/></svg>";

Supla::Control::RollerShutter *RS_1 = nullptr;
Supla::Control::RollerShutter *RS_2 = nullptr;

ESP8266WebServer httpServer(81);
ESP8266HTTPUpdateServer httpUpdater;
Ticker ticker;

void tick() {
  int state = digitalRead(status_led);  
  digitalWrite(status_led, !state);     
}
void saveConfigCallback () {          
  Serial.println("Should save config");
  shouldSaveConfig = true;
}
void ondemandwifiCallback () {
   ticker.detach();
   digitalWrite(status_led, LOW);
   WiFiManager wifiManager;
   
   WiFiManagerParameter custom_Supla_server("server", "supla server", Supla_server, 81,"required");
   WiFiManagerParameter custom_Email("email", "Email", Email, 81,"required");
   WiFiManagerParameter custom_Supla_name("name", "Supla Device Name", Supla_name, 81,"required");
   WiFiManagerParameter custom_html_id21("<div><h4> - Supla State -   ");
   WiFiManagerParameter custom_html_id22( Supla_status);
   WiFiManagerParameter custom_html_id23( "</h4></div>");

   wifiManager.setBreakAfterConfig(true);
   wifiManager.setSaveConfigCallback(saveConfigCallback);
  
   wifiManager.addParameter(&custom_Supla_server);
   wifiManager.addParameter(&custom_Email);
   wifiManager.addParameter(&custom_Supla_name);
   wifiManager.addParameter(&custom_html_id21);
   wifiManager.addParameter(&custom_html_id22);
   wifiManager.addParameter(&custom_html_id23);   

   wifiManager.setCustomHeadElement(logo);
   wifiManager.setMinimumSignalQuality(8);
   //wifiManager.setShowStaticFields(true); // force show static ip fields
   //wifiManager.setShowDnsFields(true);    // force show dns field always
   wifiManager.setConfigPortalTimeout(180);

   if (!wifiManager.startConfigPortal("2RS-2B")) { Serial.println("Not connected to WiFi but continuing anyway.");} else { Serial.println("connected...yeey :)");}                
    strcpy(Supla_server, custom_Supla_server.getValue());
    strcpy(Email, custom_Email.getValue());
    strcpy(Supla_name, custom_Supla_name.getValue());
    wifiManager.getWiFiSSID().toCharArray(Router_SSID, 33);
    wifiManager.getWiFiPass().toCharArray(Router_Pass, 65); 
    if(strcmp(Supla_server, "get_new_guid_and_authkey") == 0){
      Serial.println("new guid & authkey.");
      EEPROM.write(300, 0);
      EEPROM.commit();
      ESP.reset(); 
    }
  if (shouldSaveConfig == true) { // ------------------------ wificonfig save --------------
    Serial.println(" config...");  
    DynamicJsonDocument json(1024);
    json["Supla_server"] = Supla_server;
    json["Email"] = Email;
    json["Supla_name"] = Supla_name;
    json["Router_SSID"] = Router_SSID;
    json["Router_Pass"] = Router_Pass; 
    File configFile = LittleFS.open("/config.json", "w");
    if (!configFile) {Serial.println("failed to open config file for writing");}    
    serializeJsonPretty(json, Serial);
    serializeJson(json, configFile);
    configFile.close();
    Serial.println("Config written successfully");
    shouldSaveConfig = false;
    initialConfig = false; 
    WiFi.mode(WIFI_STA);   
    delay(5000);
    ESP.restart();     
  }
    WiFi.softAPdisconnect(true);   //  close AP
    Tik = true;
}
void status_func(int status, const char *msg) {    //    ------------------------ Status --------------------------

  if (s != status){
    s = status; 
      if (s != 10){
        strcpy(Supla_status, msg);
          Serial.print("Status: ");Serial.print(s);Serial.print(" ");Serial.println(Supla_status);
  }  }            
}

void guid_authkey(void) {
  if (EEPROM.read(300) != 60){
    int eep_gui = 301;

    ESP8266TrueRandom.uuid(uuidNumber);

    String uuidString = "";
    for (int i = 0; i < 16; i++) {
      int topDigit = uuidNumber[i] >> 4;
      int bottomDigit = uuidNumber[i] & 0x0f;
      uuidString += "0123456789abcdef"[topDigit];
      uuidString += "0123456789abcdef"[bottomDigit];
    }
    int length_uuid = uuidString.length();
    for (int i = 0; i < length_uuid; ++i) {
      EEPROM.put(eep_gui + i, uuidString[i]);
    }

    int eep_aut = 341;

    ESP8266TrueRandom.uuid(uuidNumber);

    String uuidString2 = "";
    for (int i = 0; i < 16; i++) {
      int topDigit = uuidNumber[i] >> 4;
      int bottomDigit = uuidNumber[i] & 0x0f;
      uuidString2 += "0123456789abcdef"[topDigit];
      uuidString2 += "0123456789abcdef"[bottomDigit];
    }
    int length_uuid2 = uuidString2.length();
    for (int i = 0; i < length_uuid2; ++i) {
      EEPROM.put(eep_aut + i, uuidString2[i]);
    }
    EEPROM.write(300, 60);
    EEPROM.commit();
  }
  read_guid();
  read_authkey();
  Serial.print("GUID : ");Serial.println(read_guid()); 
  Serial.print("AUTHKEY : ");Serial.println(read_authkey()); 
}

String read_guid(void) {
  String read_eeprom = "";
  int i, ii = 0;
  int eep_star = 301;
  int end_guid = eep_star + SUPLA_GUID_SIZE;
  String temp_read = "0x";
  for (i = eep_star; i < end_guid + 16;  i = i + 1) {
    temp_read += char(EEPROM.read(i));
    read_eeprom += char(EEPROM.read(i));
    if ( (i % 2) == 0) {
      char *_guid = strcpy((char*)malloc(temp_read.length() + 1), temp_read.c_str());
      GUID[ii] = strtoul( _guid, NULL, 16);
      temp_read = "0x";
      ii++;
    }
  }
  return read_eeprom;
}
String read_authkey(void) {
  String read_eeprom = "";
  int i, ii = 0;
  int eep_star = 341;
  int end_authkey = eep_star + SUPLA_AUTHKEY_SIZE;
  String temp_read = "0x";
  for (i = eep_star; i < end_authkey + 16;  i = i + 1) {
    temp_read += char(EEPROM.read(i));
    read_eeprom += char(EEPROM.read(i));
    if ( (i % 2) == 0) {
      char *_authkey = strcpy((char*)malloc(temp_read.length() + 1), temp_read.c_str());
      AUTHKEY[ii] = strtoul( _authkey, NULL, 16);
      temp_read = "0x";
      ii++;
    }
  }
  return read_eeprom;
}

void setup() {
  wifi_set_sleep_type(NONE_SLEEP_T);
  Serial.begin(115200, SERIAL_8N1, SERIAL_TX_ONLY, 15);
  Serial.println();
  EEPROM.begin(1024); 
  pinMode(status_led,OUTPUT);
  ticker.attach(0.8, tick); 
  guid_authkey();
    
  if (WiFi.SSID()==""){ initialConfig = true;} 

  if (LittleFS.begin()) {  // ------------------------- wificonfig read -----------------
    Serial.println("mounted file system");
    if (LittleFS.exists("/config.json")) {
      Serial.println("reading config file");
       File configFile = LittleFS.open("/config.json", "r");
      if (configFile) {
        Serial.println("opened config file");
         size_t size = configFile.size();
         std::unique_ptr<char[]> buf(new char[size]);
         configFile.readBytes(buf.get(), size);
        DynamicJsonDocument json(1024);
        DeserializationError deserializeError = deserializeJson(json, buf.get());
        serializeJsonPretty(json, Serial);
        if (!deserializeError) {Serial.println("\nparsed json");         
          if (json.containsKey("Supla_server")) strcpy(Supla_server, json["Supla_server"]);
          if (json.containsKey("Email")) strcpy(Email, json["Email"]);
          if (json.containsKey("Supla_name")) strcpy(Supla_name, json["Supla_name"]);
          if (json.containsKey("Router_SSID")) strcpy(Router_SSID, json["Router_SSID"]);
          if (json.containsKey("Router_Pass")) strcpy(Router_Pass, json["Router_Pass"]);       
        } else {
          Serial.println("failed to load json config");
           initialConfig = true;
        }
        configFile.close(); 
      }
    }
   } else {
    Serial.println("failed to mount FS");
  } 
   wifi_station_set_hostname(Supla_name);
   wifi.setSsid(Router_SSID);
   wifi.setPassword(Router_Pass);

  RS_1 = new Supla::Control::RollerShutter(RS_RELAY_OPEN_1, RS_RELAY_CLOSE_1, true);  // Supla::Control::RollerShutter(PIN_UP, PIN_DOWN, invertLogic); "true" - for high state control, "false" - for low state control.
  auto buttonOne = new Supla::Control::Button(RS_BUTTON_1_PIN, true, true);  //  new Supla::Control::Button(pin, pullup, invertLogic);
  RS_2 = new Supla::Control::RollerShutter(RS_RELAY_OPEN_2, RS_RELAY_CLOSE_2, true);  // Supla::Control::RollerShutter(PIN_UP, PIN_DOWN, invertLogic); "true" - for high state control, "false" - for low state control.
  auto buttonTwo = new Supla::Control::Button(RS_BUTTON_2_PIN, true, true);  //  new Supla::Control::Button(pin, pullup, invertLogic);

  buttonOne->addAction(Supla::STEP_BY_STEP, RS_1, Supla::ON_PRESS);
  buttonTwo->addAction(Supla::STEP_BY_STEP, RS_2, Supla::ON_PRESS);
  
    eeprom.setStateSavePeriod(10000);  

    SuplaDevice.setName(Supla_name);
    SuplaDevice.setStatusFuncImpl(&status_func);
    wifi.enableSSL(false);
    SuplaDevice.begin(GUID,Supla_server,Email,AUTHKEY);

}

void loop() {
  if (initialConfig == true){ondemandwifiCallback();}

  int C_W_read = digitalRead(RS_BUTTON_1_PIN);{  
   if (C_W_read != last_C_W_state) {  time_last_C_W_change = millis();}      
    if ((millis() - time_last_C_W_change) > C_W_delay) {     
     if (C_W_read != C_W_state) {     
       C_W_state = C_W_read;       
       if (C_W_state == LOW) {
        RS_1->stop();
        RS_2->stop();
        ondemandwifiCallback () ;} } }         
     last_C_W_state = C_W_read;            
   }
       
  SuplaDevice.iterate();
   delay(25);
    
  if (WiFi.status() == WL_CONNECTED){
    if (starting){
      httpUpdater.setup(&httpServer, "/update", "admin", "pass");
      httpServer.begin(); 
      starting = false;         
     }
     httpServer.handleClient();
     if ((Tik == true) && (s == 17)){ticker.detach();digitalWrite(status_led, HIGH);Tik = false;}
   }else{
    if (Tik == false) { ticker.attach(0.8, tick);Tik = true;Serial.println("ticker on  no 17"); } 
   }

}

2RS_2Button_DOUT_16Mbit.rar
(573.79 KiB) Descargado 112 veces
Maniek913
Mensajes: 491
Registrado: Jue Feb 22, 2018 9:46 pm

Muchas gracias, el software funciona, pero todavía hay una operación temporal de D5, D6 y D7 durante el reinicio, inicio. Esto no es un gran problema, pero aún así hace que se aplique voltaje a ambos terminales del motor simultáneamente.
Desafortunadamente, ya tengo botones dobles para persianas enrollables y preferiría tener 4 botones para el control.
elmaya
Mensajes: 1482
Registrado: Mié Jun 27, 2018 5:48 pm
Ubicación: El Saucejo - Sevilla

Maniek913 escribió: Sab Ene 02, 2021 6:11 pm Muchas gracias, el software funciona, pero todavía hay una operación temporal de D5, D6 y D7 durante el reinicio, inicio. Esto no es un gran problema, pero aún así hace que se aplique voltaje a ambos terminales del motor simultáneamente.
Desafortunadamente, ya tengo botones dobles para persianas enrollables y preferiría tener 4 botones para el control.
¡Estoy seguro de que ninguna de las salidas se activa durante el reinicio!
Por favor mandar una foto de tus relés, para ver como son.
Maniek913
Mensajes: 491
Registrado: Jue Feb 22, 2018 9:46 pm

Enlace a la película:
https://youtu.be/L3f-EsWp60I
Estas entradas realmente funcionan. Conecté los leds para mostrarlo, pero también ocurre en los relés.
¿No lo tienes?
Responder

Volver a “Ideas y conceptos”