8 buttons and 8 relays in esp with hc595

elmaya
Posts: 1482
Joined: Wed Jun 27, 2018 5:48 pm
Location: El Saucejo - Sevilla

Post

8 buttons and 8 relays in esp with hc595
Wifi manager with double reset to get in Config
and restore of channels after restart (Eeprom)

Code: Select all

#include <FS.h>   //---- esp board manager 2.4.2 --- iwip Variant V2 higher Bandwidth
#include <ShiftRegister74HC595.h>
#include <ESP8266WiFi.h>
#define SUPLADEVICE_CPP
#include <SuplaDevice.h>
// create shift register object (number of shift registers, data pin 14 on 74595, clock pin 11 on 74595, latch pin 12 on 74595)
ShiftRegister74HC595 sr (1, 15, 16, 0); 

#include <ESP8266WebServer.h>
#include <DNSServer.h>
#include <WiFiManager.h> 
#include <ArduinoJson.h>
#include <EEPROM.h>
#include <DoubleResetDetector.h> 

#define DRD_TIMEOUT 30 // Number of seconds after reset during which a  subseqent reset will be considered a double reset.
#define DRD_ADDRESS 0 // RTC Memory Address for the DoubleResetDetector to use
DoubleResetDetector drd(DRD_TIMEOUT, DRD_ADDRESS);

bool eep = LOW;          //             ---------------- Eeprom ------------------
bool startEeprom = true; //             ---------------- Eeprom ------------------
int epr = 0;             //             ----------- Eepron read loops ------------
int s;                   //             ---------------- Status ------------------
unsigned long svr_update = 1800000; //mean time between update  30 minutes
unsigned long svr_update_lasttime;   //last time update
#define BEGIN_PIN 100

ADC_MODE(ADC_VCC);

#define BTN_COUNT 8

WiFiClient client;
//define your default values here, if there are different values in config.json, they are overwritten.
//length should be max size + 1 
char Supla_server[40];
char Location_id[15];
char Location_Pass[20];
byte mac[6];

//flag for saving data
bool shouldSaveConfig = false;
bool initialConfig = false;
int timeout           = 120; // seconds to run for wifi config

void saveConfigCallback () {                 //callback notifying us of the need to save config
  Serial.println("Should save config");
  shouldSaveConfig = true;
}
void ondemandwifiCallback () {
// The extra parameters to be configured (can be either global or just in the setup)
  // After connecting, parameter.getValue() will get you the configured value
  // id/name placeholder/prompt default length
  WiFiManagerParameter custom_Supla_server("server", "supla server", Supla_server, 40);
  WiFiManagerParameter custom_Location_id("ID", "Location_id", Location_id, 15);
  WiFiManagerParameter custom_Location_Pass("Password", "Location_Pass", Location_Pass, 20);

  //WiFiManager
  //Local intialization. Once its business is done, there is no need to keep it around
  WiFiManager wifiManager;
  wifiManager.setBreakAfterConfig(true);
  //set config save notify callback
  wifiManager.setSaveConfigCallback(saveConfigCallback);
  
  //add all your parameters here
  wifiManager.addParameter(&custom_Supla_server);
  wifiManager.addParameter(&custom_Location_id);
  wifiManager.addParameter(&custom_Location_Pass);

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

  //set minimu quality of signal so it ignores AP's under that quality
  //defaults to 8%
  wifiManager.setMinimumSignalQuality();

  // set configportal timeout
    wifiManager.setConfigPortalTimeout(timeout);

    if (!wifiManager.startConfigPortal("Supla AP")) {
      Serial.println("failed to connect and hit timeout");
      delay(3000);
      //reset and try again, or maybe put it to deep sleep
      ESP.restart();
      delay(5000);
    }
    //if you get here you have connected to the WiFi
    Serial.println("connected...yeey :)");
    
    //read updated parameters
    strcpy(Supla_server, custom_Supla_server.getValue());
    strcpy(Location_id, custom_Location_id.getValue());
    strcpy(Location_Pass, custom_Location_Pass.getValue());
    
  WiFi.softAPdisconnect(true);   //  close AP
}

// DS18B20 Sensor read implementation---------------------------------- Temp -------------------------------------------
double get_temperature(int channelNumber, double last_val) {  
    double t = -275;
     t = (ESP.getVcc()/1024.0);
     Eeprom_save() ;   //        ------------------------------Eepron save callback -----------------------------
                         //        ---- this happens every few seconds
      return t;  
}

typedef struct {  //------------------------------------------- BTN ----------------------------------------------------
  int pin;
  int relay_pin;
  int channel;
  char last_val;
  int ms;
  unsigned long last_time;
  bool mem;
} _btn_t;

_btn_t btn[BTN_COUNT];

void supla_timer() {
  char v;
  unsigned long now = millis();
  {
  for(int a=0;a<BTN_COUNT;a++)
    if (btn[a].pin > 0) {
        v = digitalRead(btn[a].pin);
        if (v != btn[a].last_val && now - btn[a].last_time ) {
           btn[a].last_val = v;
           btn[a].last_time = now;
           if (v==0)
             {
              if ( btn[a].ms > 0 ) {
                     SuplaDevice.relayOn(btn[a].channel, btn[a].ms);
                     Serial.println(" monostable");
                 } else {
                 if ( (btn[a].mem) == 1 ) {   //   ----------------- == 1 if channel is false... == 0 if channel is true -----------------------
                  SuplaDevice.relayOff(btn[a].channel);
                  Serial.print("BTN Switsh off relay ");
                  Serial.println(btn[a].relay_pin);
                 } else {
                  SuplaDevice.relayOn(btn[a].channel, 0);
                  Serial.print("BTN Switsh on relay ");
                  Serial.println(btn[a].relay_pin);
                 }        
             }
             }}
      }
    }
    
}
void supla_btn_init() {
  for(int a=0;a<BTN_COUNT;a++)
    if (btn[a].pin > 0) {
        pinMode(btn[a].pin, INPUT_PULLUP);
        btn[a].last_val = digitalRead(btn[a].pin);
        btn[a].last_time = millis();
    }
}
int supla_DigitalRead(int channelNumber, uint8_t pin) {
   if (pin > 100) {
      if (pin == 101){
        if (btn[0].mem ==0) return 0;      
        else return 1;
      }
      if (pin == 102){
        if (btn[1].mem ==0) return 0;      
        else return 1;
      }
      if (pin == 103){
        if (btn[2].mem ==0) return 0;      
        else return 1;
      }
      if (pin == 104){
        if (btn[3].mem ==0) return 0;      
        else return 1;
      }
      if (pin == 105){
        if (btn[4].mem ==0) return 0;      
        else return 1;
      }
      if (pin == 106){
        if (btn[5].mem ==0) return 0;      
        else return 1;
      }
      if (pin == 107){
        if (btn[6].mem ==0) return 0;      
        else return 1;
      }
      if (pin == 108){
        if (btn[7].mem ==0) return 0;      
        else return 1;      
      }
      
   }
    return digitalRead(pin);
}
void suplaDigitalWrite(int channelNumber, uint8_t pin, uint8_t val) {  //------------------------------------------------  Virtual ----------------------------
    if (pin > 100) {
     if (pin == 101){
       btn[0].mem =val;
       sr.set(0, val); // set single pin 
     }
     if (pin == 102){
       btn[1].mem =val;
       sr.set(1, val); // set single pin 
     }
     if (pin == 103){
       btn[2].mem =val;
       sr.set(2, val); // set single pin 
     }
     if (pin == 104){
       btn[3].mem =val;
       sr.set(3, val); // set single pin 
     }
     if (pin == 105){
       btn[4].mem =val;
       sr.set(4, val); // set single pin 
     }
     if (pin == 106){
       btn[5].mem =val;
       sr.set(5, val); // set single pin 
     }
     if (pin == 107){
       btn[6].mem =val;
       sr.set(6, val); // set single pin 
     }
     if (pin == 108){
       btn[7].mem =val;
       sr.set(7, val); // set single pin 
     }
  return;
    }
   digitalWrite(pin, val);
  
  
}
void Eeprom_save() {                  //----------EEPROM write  ---------------------- EEprom
    if (startEeprom == true){             // ----- don't change memorized state until connected and restored all the channels

      return;
      }                        
      for(int i=0;i<BTN_COUNT;i++) {  //  ---check relay except it have delay (staircase)
         if ( btn[i].ms > 0 ) {
                     continue;
         } else {
        eep = (btn[i].mem);                    //  --- read relay state
        if (eep != EEPROM.read(i)){            //  --- compare relay state with memorized state
         EEPROM.write(i,eep);                  //  --- if different write memory
         Serial.print("EEPROM.");
         Serial.print(i);
         Serial.print(" write.");
         Serial.println((eep));
         Serial.print(" channel ");
         Serial.println((btn[i].channel));
         EEPROM.commit();
        }
      }
    }
}
void Eepron_read() {                  //----------EEPROM read  ---------------------- EEprom
                                
   // for(int i=0;i<BTN_COUNT;i++){      //  ---check relay except der have delay (staircase)
     //if ( (btn[i].ms) > 0 ) {
                //     continue;
        // } else {
        eep = EEPROM.read(epr);               //  ---read relay state
       
         Serial.print("EEPROM.");
         Serial.print(epr);
         Serial.print(" read.");
         Serial.println((eep));
         Serial.print(" channel ");
         Serial.println((btn[epr].channel));
       
        if (eep == HIGH){                    //  --- if 1 send relay on
          SuplaDevice.relayOn(epr, 0);       //  --- only one channel in each pass
          }
        
    if (epr == (BTN_COUNT-1)) {startEeprom = false;  }     //  --- once finished we do not need more
}
void status_func(int status, const char *msg) {     //    ------------------------ Status --------------------------
 s=status;                                          //    -- to check if we are registered and ready before restore from memory
}
void setup() {  //------------------------------------------------ Setup ----------------------------------------------

 // Serial.begin(115200);
  
  EEPROM.begin(512);

   if (drd.detectDoubleReset()) {
    Serial.println("Double Reset Detected");
    ondemandwifiCallback ();
  } else {
    Serial.println("No Double Reset Detected");
  }
  if (WiFi.SSID()==""){
    //Serial.println("We haven't got any access point credentials, so get them now");   
    initialConfig = true;
  } 
  //read configuration from FS json
  Serial.println("mounting FS...");
  
  if (SPIFFS.begin()) {
    Serial.println("mounted file system");
    if (SPIFFS.exists("/config.json")) {
      //file exists, reading and loading
      Serial.println("reading config file");
      File configFile = SPIFFS.open("/config.json", "r");
      if (configFile) {
        Serial.println("opened config file");
        size_t size = configFile.size();
        // Allocate a buffer to store contents of the file.
        std::unique_ptr<char[]> buf(new char[size]);

        configFile.readBytes(buf.get(), size);
        DynamicJsonBuffer jsonBuffer;         
        JsonObject& json = jsonBuffer.parseObject(buf.get());
        //json.printTo(Serial);   //print config data to serial on startup
        if (json.success()) {
          Serial.println("\nparsed json");

          strcpy(Supla_server, json["Supla_server"]);
          strcpy(Location_id, json["Location_id"]);
          strcpy(Location_Pass, json["Location_Pass"]);

        } else {
          Serial.println("failed to load json config");
          
        }
      }
    }
  } else {
    Serial.println("failed to mount FS");
  }
  WiFi.mode(WIFI_STA); // Force to station mode because if device was switched off while in access point mode it will start up next time in access point mode.

   uint8_t mac[WL_MAC_ADDR_LENGTH];
  WiFi.macAddress(mac);
  char GUID[SUPLA_GUID_SIZE] = {mac[WL_MAC_ADDR_LENGTH - 6], 
                                mac[WL_MAC_ADDR_LENGTH - 5], 
                                mac[WL_MAC_ADDR_LENGTH - 4], 
                                mac[WL_MAC_ADDR_LENGTH - 3], 
                                mac[WL_MAC_ADDR_LENGTH - 2], 
                                mac[WL_MAC_ADDR_LENGTH - 1]};
   
   
          
  SuplaDevice.addRelay(101, false);   
  SuplaDevice.addRelay(102, false);  
  SuplaDevice.addRelay(103, false); 
  SuplaDevice.addRelay(104, false);   
  SuplaDevice.addRelay(105, false);  
  SuplaDevice.addRelay(106, false); 
  SuplaDevice.addRelay(107, false);   
  SuplaDevice.addRelay(108, false);  
  // CHANNEL8 - Thermometer DS18B20
  SuplaDevice.addDS18B20Thermometer();

  memset(btn, 0, sizeof(btn));
  btn[0].pin =5;          // pin gpio buton  0 = no buton
  btn[0].relay_pin =101;  // pin gpio Relay
  btn[0].channel =0;      // channel
  btn[0].ms =0;           //  if = 0 Bistable -- if > 0 Monostable for X ms
  btn[0].mem =0;
  btn[1].pin =4;          // pin gpio buton  0 = no buton
  btn[1].relay_pin =102;  // pin gpio Relay
  btn[1].channel =1;      // channel
  btn[1].ms =0;           //  if = 0 Bistable -- if > 0 Monostable for X ms
  btn[1].mem =0;
  btn[2].pin =2;          // pin gpio buton  0 = no buton
  btn[2].relay_pin =103;  // pin gpio Relay
  btn[2].channel =2;      // channel
  btn[2].ms =0;           //  if = 0 Bistable -- if > 0 Monostable for X ms
  btn[2].mem =0;
  btn[3].pin =14;         // pin gpio buton  0 = no buton 
  btn[3].relay_pin =104;  // pin gpio Relay
  btn[3].channel =3;      // channel
  btn[3].ms =0;           //  if = 0 Bistable -- if > 0 Monostable for X ms
  btn[3].mem =0;
  btn[4].pin =12;         // pin gpio buton  0 = no buton
  btn[4].relay_pin =105;  // pin gpio Relay
  btn[4].channel =4;      // channel
  btn[4].ms =0;           //  if = 0 Bistable -- if > 0 Monostable for X ms
  btn[4].mem =0;
  btn[5].pin =13;         // pin gpio buton  0 = no buton
  btn[5].relay_pin =106;  // pin gpio Relay
  btn[5].channel =5;      // channel
  btn[5].ms =0;           //  if = 0 Bistable -- if > 0 Monostable for X ms
  btn[5].mem =0;
  btn[6].pin =3;         // pin gpio buton  0 = no buton
  btn[6].relay_pin =107;    // pin gpio Relay
  btn[6].channel =6;      // channel
  btn[6].ms =0;           //  if = 0 Bistable -- if > 0 Monostable for X ms
  btn[6].mem =0;
  btn[7].pin =1;          // pin gpio buton  0 = no buton
  btn[7].relay_pin =108;  // pin gpio Relay
  btn[7].channel =7;      // channel
  btn[7].ms =0;           //  if = 0 Bistable -- if > 0 Monostable for X ms
  btn[7].mem =0;
  supla_btn_init();

  SuplaDevice.setDigitalReadFuncImpl(&supla_DigitalRead);    //            ------Send Value to server -------
  SuplaDevice.setDigitalWriteFuncImpl(&suplaDigitalWrite);   //        -------  Read Value from server   -------
  SuplaDevice.setTimerFuncImpl(&supla_timer);
  SuplaDevice.setStatusFuncImpl(&status_func);    //   ----------------------------- Status -----------------------------
  SuplaDevice.setName("Supla 595");

  int LocationID = atoi(Location_id);
  SuplaDevice.begin(GUID,              // Global Unique Identifier 
                    mac,               // Ethernet MAC address
                    Supla_server,      // SUPLA server address
                    LocationID,        // Location ID 
                    Location_Pass);    // Location Password
// read_initial_relay_state();
}

void loop() {

  // Call the double reset detector loop method every so often,
  // so that it can recognise when the timeout expires.
  // You can also call drd.stop() when you wish to no longer
  // consider the next reset as a double reset.
  drd.loop();

  
  //save the custom parameters to FS
  if (shouldSaveConfig) {
    Serial.println("saving config");
    DynamicJsonBuffer jsonBuffer;
    JsonObject& json = jsonBuffer.createObject();
    json["Supla_server"] = Supla_server;
    json["Location_id"] = Location_id;
    json["Location_Pass"] = Location_Pass;

    File configFile = SPIFFS.open("/config.json", "w");
    if (!configFile) {
      Serial.println("failed to open config file for writing");
    }
    json.prettyPrintTo(Serial);
    json.printTo(configFile);
    configFile.close();
    Serial.println("config saved");
    shouldSaveConfig = false;
    WiFi.mode(WIFI_STA);
    ESP.restart();
    delay(5000); 
  }
  if (WiFi.status() != WL_CONNECTED) 
  {
    WiFi_up();
  } 
  
  SuplaDevice.iterate();
  SuplaDevice.setTemperatureCallback(&get_temperature);
  switch (s) {    //    ------------------------------------------------ Status ------------------------------------
  case 17:      // -----     STATUS_REGISTERED_AND_READY
  if (epr<BTN_COUNT){
  Serial.print("Eepron_read...");
  Serial.println(epr);
   Eepron_read() ;                // ------------------------------- Eeprom read callback -------------------------------
   epr = epr+1;                   // -------- 1 loop for each output 8 in total ----------
   
  }
   if (millis() > svr_update_lasttime + svr_update)  {
    epr = 0 ;
     startEeprom = true;
      Serial.println("svr update");
            svr_update_lasttime = millis(); 
    }
 }
}


// Supla.org ethernet layer
    int supla_arduino_tcp_read(void *buf, int count) {
        _supla_int_t size = client.available();
       
        if ( size > 0 ) {
            if ( size > count ) size = count;
            return client.read((uint8_t *)buf, size);
        };
    
        return -1;
    };
    
    int supla_arduino_tcp_write(void *buf, int count) {
        return client.write((const uint8_t *)buf, count);
    };
    
    bool supla_arduino_svr_connect(const char *server, int port) {
          return client.connect(server, 2015);
    }
    
    bool supla_arduino_svr_connected(void) {
          return client.connected();
    }
    
    void supla_arduino_svr_disconnect(void) {
         client.stop();
    }
    
    void supla_arduino_eth_setup(uint8_t mac[6], IPAddress *ip) {

       WiFi_up();
    }

SuplaDeviceCallbacks supla_arduino_get_callbacks(void) {
          SuplaDeviceCallbacks cb;
          
          cb.tcp_read = &supla_arduino_tcp_read;
          cb.tcp_write = &supla_arduino_tcp_write;
          cb.eth_setup = &supla_arduino_eth_setup;
          cb.svr_connected = &supla_arduino_svr_connected;
          cb.svr_connect = &supla_arduino_svr_connect;
          cb.svr_disconnect = &supla_arduino_svr_disconnect;
          cb.get_temperature = &get_temperature;
          cb.get_temperature_and_humidity = NULL;
          cb.get_rgbw_value = NULL;
          cb.set_rgbw_value = NULL;
          
          return cb;
}

void WiFi_up() // conect to wifi
{
  WiFi.begin(); 
  for (int x = 10; x > 0; x--) 
  {
    if (WiFi.status() == WL_CONNECTED) 
    {    
      break;                           
    }
    else                                 
    {
      Serial.print(".");                
      delay(500);                      
    }
  }

  if (WiFi.status() == WL_CONNECTED)
  {
    Serial.println("");
    Serial.println("CONNECTED");
    Serial.print("local IP: ");
    Serial.println(WiFi.localIP());
    Serial.print("subnetMask: ");
    Serial.println(WiFi.subnetMask());
    Serial.print("gatewayIP: ");
    Serial.println(WiFi.gatewayIP());
    long rssi = WiFi.RSSI();
    Serial.print("Signal Strength (RSSI): ");
    Serial.print(rssi);
    Serial.println(" dBm");
  }
  else    
  {
    Serial.println("");
    Serial.println("not connected");
  }
}
You do not have the required permissions to view the files attached to this post.
Last edited by elmaya on Thu Nov 14, 2019 9:29 am, edited 6 times in total.
elmaya
Posts: 1482
Joined: Wed Jun 27, 2018 5:48 pm
Location: El Saucejo - Sevilla

Post

Added temperature sensor "NTC 10Kohn"

Code: Select all

#include <FS.h>  //---- esp board manager 2.4.2 --- iwip Variant V2 higher Bandwidth
#include <ShiftRegister74HC595.h>   //https://github.com/Simsso/ShiftRegister74HC595
#include <ESP8266WiFi.h>
#define SUPLADEVICE_CPP
#include <SuplaDevice.h>
// create shift register object (number of shift registers, data pin 14 on 74595, clock pin 11 on 74595, latch pin 12 on 74595)
ShiftRegister74HC595 sr (2, 15, 16, 0); 
#include <math.h>
#include <ESP8266WebServer.h>
#include <DNSServer.h>
#include <WiFiManager.h> 
#include <ArduinoJson.h>
#include <EEPROM.h>
#include <DoubleResetDetector.h> 

#define DRD_TIMEOUT 30 // Number of seconds after reset during which a  subseqent reset will be considered a double reset.
#define DRD_ADDRESS 0 // RTC Memory Address for the DoubleResetDetector to use
DoubleResetDetector drd(DRD_TIMEOUT, DRD_ADDRESS);

bool eep = LOW;          //             ---------------- Eeprom ------------------
bool startEeprom = true; //             ---------------- Eeprom ------------------
int epr = 0;             //             ----------- Eepron read loops ------------
int s;                   //             ---------------- Status ------------------
unsigned long svr_update = 1800000; //mean time between update  30 minutes
unsigned long svr_update_lasttime;   //last time update
unsigned long wifi_checkDelay = 60000;  // wifi reconect delay
unsigned long wifimilis;
#define BEGIN_PIN 100

unsigned int Rs = 100000;
double Vcc = 3.3;

#define BTN_COUNT 16

WiFiClient client;
//define your default values here, if there are different values in config.json, they are overwritten.
//length should be max size + 1 
char Supla_server[40];
char Location_id[15];
char Location_Pass[20];
byte mac[6];

//flag for saving data
bool shouldSaveConfig = false;
bool initialConfig = false;
int timeout           = 120; // seconds to run for wifi config

void saveConfigCallback () {                 //callback notifying us of the need to save config
  Serial.println("Should save config");
  shouldSaveConfig = true;
}
void ondemandwifiCallback () {
// The extra parameters to be configured (can be either global or just in the setup)
  // After connecting, parameter.getValue() will get you the configured value
  // id/name placeholder/prompt default length
  WiFiManagerParameter custom_Supla_server("server", "supla server", Supla_server, 40);
  WiFiManagerParameter custom_Location_id("ID", "Location_id", Location_id, 15);
  WiFiManagerParameter custom_Location_Pass("Password", "Location_Pass", Location_Pass, 20);

  //WiFiManager
  //Local intialization. Once its business is done, there is no need to keep it around
  WiFiManager wifiManager;

  //set config save notify callback
  wifiManager.setSaveConfigCallback(saveConfigCallback);
  
  //add all your parameters here
  wifiManager.addParameter(&custom_Supla_server);
  wifiManager.addParameter(&custom_Location_id);
  wifiManager.addParameter(&custom_Location_Pass);

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

  //set minimu quality of signal so it ignores AP's under that quality
  //defaults to 8%
  wifiManager.setMinimumSignalQuality();

  // set configportal timeout
    wifiManager.setConfigPortalTimeout(timeout);

    if (!wifiManager.startConfigPortal("Supla 595")) {
      Serial.println("failed to connect and hit timeout");
      delay(3000);
      //reset and try again, or maybe put it to deep sleep
      ESP.restart();
      delay(5000);
    }
    //if you get here you have connected to the WiFi
    Serial.println("connected...yeey :)");
    
    //read updated parameters
    strcpy(Supla_server, custom_Supla_server.getValue());
    strcpy(Location_id, custom_Location_id.getValue());
    strcpy(Location_Pass, custom_Location_Pass.getValue());
    
  WiFi.softAPdisconnect(true);   //  close AP
}
double get_temperature(int channelNumber, double last_val) {  // 10k Ntc Adc to Gnd and 100k Resistor Adc to +3,3v
    
      int val = 0;
      for(int i = 0; i < 10; i++) {
      val += analogRead(A0);
      delay(1);
      }
      val = val / 10;
      double V_NTC = (double)val / 1023;
      double R_NTC = (Rs * V_NTC) / (Vcc - V_NTC);
      R_NTC = log(R_NTC);
      double t = 1 / (0.001129148 + (0.000234125 + (0.0000000876741 * R_NTC * R_NTC ))* R_NTC );
      t = t - 273.15;
      
           Eeprom_save() ;   //        ------------------------------Eepron save callback -----------------------------
                             //        ---- this happens every few seconds

    
      return t;  
}

typedef struct {  //------------------------------------------- BTN ----------------------------------------------------
  int pin;
  int relay_pin;
  int channel;
  char last_val;
  int ms;
  unsigned long last_time;
  bool mem;
} _btn_t;

_btn_t btn[BTN_COUNT];

void supla_timer() {
  char v;
  unsigned long now = millis();
  {
  for(int a=0;a<BTN_COUNT;a++)
    if (btn[a].pin > 0) {
        v = digitalRead(btn[a].pin);
        if (v != btn[a].last_val && now - btn[a].last_time ) {
           btn[a].last_val = v;
           btn[a].last_time = now;
           if (v==0)
             {
              if ( btn[a].ms > 0 ) {
                     SuplaDevice.relayOn(btn[a].channel, btn[a].ms);
                     Serial.println(" monostable");
                 } else {
                 if ( (btn[a].mem) == 1 ) {   //   ----------------- == 1 if channel is false... == 0 if channel is true -----------------------
                  SuplaDevice.relayOff(btn[a].channel);
                  Serial.print("BTN Switsh off relay ");
                  Serial.println(btn[a].relay_pin);
                 } else {
                  SuplaDevice.relayOn(btn[a].channel, 0);
                  Serial.print("BTN Switsh on relay ");
                  Serial.println(btn[a].relay_pin);
                 }        
             }
             }}
      }
    }
    
}
void supla_btn_init() {
  for(int a=0;a<BTN_COUNT;a++)
    if (btn[a].pin > 0) {
        pinMode(btn[a].pin, INPUT_PULLUP);
        btn[a].last_val = digitalRead(btn[a].pin);
        btn[a].last_time = millis();
    }
}
int supla_DigitalRead(int channelNumber, uint8_t pin) {
   
      if (channelNumber == 0){
        if (btn[0].mem ==0) return 0;      
        else return 1;
      }
      if (channelNumber == 1){
        if (btn[1].mem ==0) return 0;      
        else return 1;
      }
      if (channelNumber == 2){
        if (btn[2].mem ==0) return 0;      
        else return 1;
      }
      if (channelNumber == 3){
        if (btn[3].mem ==0) return 0;      
        else return 1;
      }
      if (channelNumber == 4){
        if (btn[4].mem ==0) return 0;      
        else return 1;
      }
      if (channelNumber == 5){
        if (btn[5].mem ==0) return 0;      
        else return 1;
      }
      if (channelNumber == 6){
        if (btn[6].mem ==0) return 0;      
        else return 1;
      }
      if (channelNumber == 7){
        if (btn[7].mem ==0) return 0;      
        else return 1;      
      }
      if (channelNumber == 8){
        if (btn[8].mem ==0) return 0;      
        else return 1;
      }
      if (channelNumber == 9){
        if (btn[9].mem ==0) return 0;      
        else return 1;
      }
      if (channelNumber == 10){
        if (btn[10].mem ==0) return 0;      
        else return 1;
      }
      if (channelNumber == 11){
        if (btn[11].mem ==0) return 0;      
        else return 1;
      }
      if (channelNumber == 12){
        if (btn[12].mem ==0) return 0;      
        else return 1;
      }
      if (channelNumber == 13){
        if (btn[13].mem ==0) return 0;      
        else return 1;
      }
      if (channelNumber == 14){
        if (btn[14].mem ==0) return 0;      
        else return 1;
      }
      if (channelNumber == 15){
        if (btn[15].mem ==0) return 0;      
        else return 1;      
      }
   
}
void suplaDigitalWrite(int channelNumber, uint8_t pin, uint8_t val) {  //------------------------------------------------  Virtual ----------------------------
  
     if (channelNumber == 0){
       btn[0].mem =val;
       sr.set(0, val); // set single pin 
     }
     if (channelNumber == 1){
       btn[1].mem =val;
       sr.set(1, val); // set single pin 
     }
     if (channelNumber == 2){
       btn[2].mem =val;
       sr.set(2, val); // set single pin 
     }
     if (channelNumber == 3){
       btn[3].mem =val;
       sr.set(3, val); // set single pin 
     }
     if (channelNumber == 4){
       btn[4].mem =val;
       sr.set(4, val); // set single pin 
     }
     if (channelNumber == 5){
       btn[5].mem =val;
       sr.set(5, val); // set single pin 
     }
     if (channelNumber == 6){
       btn[6].mem =val;
       sr.set(6, val); // set single pin 
     }
     if (channelNumber == 7){
       btn[7].mem =val;
       sr.set(7, val); // set single pin 
     }
     if (channelNumber == 8){
       btn[8].mem =val;
       sr.set(8, val); // set single pin 
     }
      if (channelNumber == 9){
       btn[9].mem =val;
       sr.set(9, val); // set single pin 
     }
     if (channelNumber == 10){
       btn[10].mem =val;
       sr.set(10, val); // set single pin 
     }
     if (channelNumber == 11){
       btn[11].mem =val;
       sr.set(11, val); // set single pin 
     }
     if (channelNumber == 12){
       btn[12].mem =val;
       sr.set(12, val); // set single pin 
     }
     if (channelNumber == 13){
       btn[13].mem =val;
       sr.set(13, val); // set single pin 
     }
     if (channelNumber == 14){
       btn[14].mem =val;
       sr.set(14, val); // set single pin 
     }
     if (channelNumber == 15){
       btn[15].mem =val;
       sr.set(15, val); // set single pin 
     }
     
  return;
    
  
  
}
void Eeprom_save() {                  //----------EEPROM write  ---------------------- EEprom
    if (startEeprom == true){             // ----- don't change memorized state until connected and restored all the channels

      return;
      }                        
      for(int i=0;i<BTN_COUNT;i++) {  //  ---check relay except it have delay (staircase)
         if ( btn[i].ms > 0 ) {
                     continue;
         } else {
        eep = (btn[i].mem);                    //  --- read relay state
        if (eep != EEPROM.read(i)){            //  --- compare relay state with memorized state
         EEPROM.write(i,eep);                  //  --- if different write memory
         Serial.print("EEPROM.");
         Serial.print(i);
         Serial.print(" write.");
         Serial.println((eep));
         Serial.print(" channel ");
         Serial.println((btn[i].channel));
         EEPROM.commit();
        }
      }
    }
}
void Eepron_read() {                  //----------EEPROM read  ---------------------- EEprom
                                
   // for(int i=0;i<BTN_COUNT;i++){      //  ---check relay except der have delay (staircase)
     //if ( (btn[i].ms) > 0 ) {
                //     continue;
        // } else {
        eep = EEPROM.read(epr);               //  ---read relay state
       
         Serial.print("EEPROM.");
         Serial.print(epr);
         Serial.print(" read.");
         Serial.println((eep));
         Serial.print(" channel ");
         Serial.println((btn[epr].channel));
       
        if (eep == HIGH){                    //  --- if 1 send relay on
          SuplaDevice.relayOn(epr, 0);       //  --- only one channel in each pass
          }
        
    if (epr == (BTN_COUNT-1)) {
      startEeprom = false;                //  --- once finished we do not need more
      }     
}
void status_func(int status, const char *msg) {     //    ------------------------ Status --------------------------
 s=status;                                          //    -- to check if we are registered and ready before restore from memory
}
void setup() {  //------------------------------------------------ Setup ----------------------------------------------

  Serial.begin(115200);
  
  EEPROM.begin(512);

   if (drd.detectDoubleReset()) {
    Serial.println("Double Reset Detected");
    ondemandwifiCallback ();
  } else {
    Serial.println("No Double Reset Detected");
  }
  if (WiFi.SSID()==""){
    //Serial.println("We haven't got any access point credentials, so get them now");   
    initialConfig = true;
  } 
  //read configuration from FS json
  Serial.println("mounting FS...");
  
  if (SPIFFS.begin()) {
    Serial.println("mounted file system");
    if (SPIFFS.exists("/config.json")) {
      //file exists, reading and loading
      Serial.println("reading config file");
      File configFile = SPIFFS.open("/config.json", "r");
      if (configFile) {
        Serial.println("opened config file");
        size_t size = configFile.size();
        // Allocate a buffer to store contents of the file.
        std::unique_ptr<char[]> buf(new char[size]);

        configFile.readBytes(buf.get(), size);
        DynamicJsonBuffer jsonBuffer;         
        JsonObject& json = jsonBuffer.parseObject(buf.get());
        //json.printTo(Serial);   //print config data to serial on startup
        if (json.success()) {
          Serial.println("\nparsed json");

          strcpy(Supla_server, json["Supla_server"]);
          strcpy(Location_id, json["Location_id"]);
          strcpy(Location_Pass, json["Location_Pass"]);

        } else {
          Serial.println("failed to load json config");
          
        }
      }
    }
  } else {
    Serial.println("failed to mount FS");
  }
  WiFi.mode(WIFI_STA); // Force to station mode because if device was switched off while in access point mode it will start up next time in access point mode.

   uint8_t mac[WL_MAC_ADDR_LENGTH];
  WiFi.macAddress(mac);
  char GUID[SUPLA_GUID_SIZE] = {mac[WL_MAC_ADDR_LENGTH - 6], 
                                mac[WL_MAC_ADDR_LENGTH - 5], 
                                mac[WL_MAC_ADDR_LENGTH - 4], 
                                mac[WL_MAC_ADDR_LENGTH - 3], 
                                mac[WL_MAC_ADDR_LENGTH - 2], 
                                mac[WL_MAC_ADDR_LENGTH - 1]};
   
   
          
  SuplaDevice.addRelay(101, false);   
  SuplaDevice.addRelay(102, false);  
  SuplaDevice.addRelay(103, false); 
  SuplaDevice.addRelay(104, false);   
  SuplaDevice.addRelay(105, false);  
  SuplaDevice.addRelay(106, false); 
  SuplaDevice.addRelay(107, false);   
  SuplaDevice.addRelay(108, false);
  SuplaDevice.addRelay(109, false);   
  SuplaDevice.addRelay(110, false);  
  SuplaDevice.addRelay(111, false); 
  SuplaDevice.addRelay(112, false);   
  SuplaDevice.addRelay(113, false);  
  SuplaDevice.addRelay(114, false); 
  SuplaDevice.addRelay(115, false);   
  SuplaDevice.addRelay(116, false);  
  // CHANNEL8 - Thermometer DS18B20
  SuplaDevice.addDS18B20Thermometer();

  memset(btn, 0, sizeof(btn));
  btn[0].pin =5;          // pin gpio buton  0 = no buton
  btn[0].relay_pin =101;  // pin gpio Relay
  btn[0].channel =0;      // channel
  btn[0].ms =0;           //  if = 0 Bistable -- if > 0 Monostable for X ms
  btn[0].mem =0;
  btn[1].pin =4;          // pin gpio buton  0 = no buton
  btn[1].relay_pin =102;  // pin gpio Relay
  btn[1].channel =1;      // channel
  btn[1].ms =0;           //  if = 0 Bistable -- if > 0 Monostable for X ms
  btn[1].mem =0;
  btn[2].pin =2;          // pin gpio buton  0 = no buton
  btn[2].relay_pin =103;  // pin gpio Relay
  btn[2].channel =2;      // channel
  btn[2].ms =0;           //  if = 0 Bistable -- if > 0 Monostable for X ms
  btn[2].mem =0;
  btn[3].pin =14;         // pin gpio buton  0 = no buton 
  btn[3].relay_pin =104;  // pin gpio Relay
  btn[3].channel =3;      // channel
  btn[3].ms =0;           //  if = 0 Bistable -- if > 0 Monostable for X ms
  btn[3].mem =0;
  btn[4].pin =12;         // pin gpio buton  0 = no buton
  btn[4].relay_pin =105;  // pin gpio Relay
  btn[4].channel =4;      // channel
  btn[4].ms =0;           //  if = 0 Bistable -- if > 0 Monostable for X ms
  btn[4].mem =0;
  btn[5].pin =13;         // pin gpio buton  0 = no buton
  btn[5].relay_pin =106;  // pin gpio Relay
  btn[5].channel =5;      // channel
  btn[5].ms =0;           //  if = 0 Bistable -- if > 0 Monostable for X ms
  btn[5].mem =0;
  btn[6].pin =3;         // pin gpio buton  0 = no buton
  btn[6].relay_pin =107;    // pin gpio Relay
  btn[6].channel =6;      // channel
  btn[6].ms =0;           //  if = 0 Bistable -- if > 0 Monostable for X ms
  btn[6].mem =0;
  btn[7].pin =1;          // pin gpio buton  0 = no buton
  btn[7].relay_pin =108;  // pin gpio Relay
  btn[7].channel =7;      // channel
  btn[7].ms =0;           //  if = 0 Bistable -- if > 0 Monostable for X ms
  btn[7].mem =0;
  btn[8].pin =22;          // pin gpio buton  0 = no buton
  btn[8].relay_pin =109;  // pin gpio Relay
  btn[8].channel =8;      // channel
  btn[8].ms =0;           //  if = 0 Bistable -- if > 0 Monostable for X ms
  btn[8].mem =0;
  btn[9].pin =22;          // pin gpio buton  0 = no buton
  btn[9].relay_pin =110;  // pin gpio Relay
  btn[9].channel =9;      // channel
  btn[9].ms =0;           //  if = 0 Bistable -- if > 0 Monostable for X ms
  btn[9].mem =0;
  btn[10].pin =22;          // pin gpio buton  0 = no buton
  btn[10].relay_pin =111;  // pin gpio Relay
  btn[10].channel =10;      // channel
  btn[10].ms =0;           //  if = 0 Bistable -- if > 0 Monostable for X ms
  btn[10].mem =0;
  btn[11].pin =22;         // pin gpio buton  0 = no buton 
  btn[11].relay_pin =112;  // pin gpio Relay
  btn[11].channel =11;      // channel
  btn[11].ms =0;           //  if = 0 Bistable -- if > 0 Monostable for X ms
  btn[11].mem =0;
  btn[12].pin =22;         // pin gpio buton  0 = no buton
  btn[12].relay_pin =113;  // pin gpio Relay
  btn[12].channel =12;      // channel
  btn[12].ms =0;           //  if = 0 Bistable -- if > 0 Monostable for X ms
  btn[12].mem =0;
  btn[13].pin =22;         // pin gpio buton  0 = no buton
  btn[13].relay_pin =114;  // pin gpio Relay
  btn[13].channel =13;      // channel
  btn[13].ms =0;           //  if = 0 Bistable -- if > 0 Monostable for X ms
  btn[13].mem =0;
  btn[14].pin =22;         // pin gpio buton  0 = no buton
  btn[14].relay_pin =115;    // pin gpio Relay
  btn[14].channel =14;      // channel
  btn[14].ms =0;           //  if = 0 Bistable -- if > 0 Monostable for X ms
  btn[14].mem =0;
  btn[15].pin =22;          // pin gpio buton  0 = no buton
  btn[15].relay_pin =116;  // pin gpio Relay
  btn[15].channel =15;      // channel
  btn[15].ms =0;           //  if = 0 Bistable -- if > 0 Monostable for X ms
  btn[15].mem =0;
  supla_btn_init();

  SuplaDevice.setDigitalReadFuncImpl(&supla_DigitalRead);    //            ------Send Value to server -------
  SuplaDevice.setDigitalWriteFuncImpl(&suplaDigitalWrite);   //        -------  Read Value from server   -------
  SuplaDevice.setTimerFuncImpl(&supla_timer);
  SuplaDevice.setStatusFuncImpl(&status_func);    //   ----------------------------- Status -----------------------------
  SuplaDevice.setName("Supla 8x16");

  int LocationID = atoi(Location_id);
  SuplaDevice.begin(GUID,              // Global Unique Identifier 
                    mac,               // Ethernet MAC address
                    Supla_server,      // SUPLA server address
                    LocationID,        // Location ID 
                    Location_Pass);    // Location Password
// read_initial_relay_state();
    for(int i=0;i<BTN_COUNT;i++){      //  ---check relay except der have delay (staircase)
     if ( (btn[i].ms) > 0 ) {
                     continue;
         } else {
        eep = EEPROM.read(i);               //  ---read relay state
       
         Serial.print("Recover.");
         Serial.print(i);
         Serial.print(" read.");
         Serial.println((eep));
         Serial.print(" channel ");
         Serial.println((btn[i].channel));
       
       // if (eep == HIGH){                    //  --- if 1 send relay on
          sr.set(btn[i].channel, eep); // set single pin 
          //SuplaDevice.relayOn(epr, 0);       //  --- only one channel in each pass
         // }
         }
    }         
}

void loop() {

  // Call the double reset detector loop method every so often,
  // so that it can recognise when the timeout expires.
  // You can also call drd.stop() when you wish to no longer
  // consider the next reset as a double reset.
  drd.loop();

  
  //save the custom parameters to FS
  if (shouldSaveConfig) {
    Serial.println("saving config");
    DynamicJsonBuffer jsonBuffer;
    JsonObject& json = jsonBuffer.createObject();
    json["Supla_server"] = Supla_server;
    json["Location_id"] = Location_id;
    json["Location_Pass"] = Location_Pass;

    File configFile = SPIFFS.open("/config.json", "w");
    if (!configFile) {
      Serial.println("failed to open config file for writing");
    }
    json.prettyPrintTo(Serial);
    json.printTo(configFile);
    configFile.close();
    Serial.println("config saved");
    shouldSaveConfig = false;
    //end save
  }
  if (WiFi.status() != WL_CONNECTED) { 
    WiFi_up();
    } 
  
  SuplaDevice.iterate();
  SuplaDevice.setTemperatureCallback(&get_temperature);
  switch (s) {    //    ------------------------------------------------ Status ------------------------------------
  case 17:      // -----     STATUS_REGISTERED_AND_READY
  if (epr<BTN_COUNT){
  Serial.print("Eepron_read...");
  Serial.println(epr);
   Eepron_read() ;                // ------------------------------- Eeprom read callback -------------------------------
   epr = epr+1;                   // -------- 1 loop for each output 8 in total ----------
   
  }
  if (millis() > svr_update_lasttime + svr_update)  {
    epr = 0 ;
     startEeprom = true;
      Serial.println("svr update");
        svr_update = 1800000;
            svr_update_lasttime = millis(); 
  }
    break;
    case 9:      // --------------------- DISCONNECTED  ----------------------
    svr_update = 5000;
    break;
    case 10:      // --------------------- REGISTER_IN_PROGRESS  ----------------------
    svr_update = 5000;
    break;
  }
 
}


// Supla.org ethernet layer
    int supla_arduino_tcp_read(void *buf, int count) {
        _supla_int_t size = client.available();
       
        if ( size > 0 ) {
            if ( size > count ) size = count;
            return client.read((uint8_t *)buf, size);
        };
    
        return -1;
    };
    
    int supla_arduino_tcp_write(void *buf, int count) {
        return client.write((const uint8_t *)buf, count);
    };
    
    bool supla_arduino_svr_connect(const char *server, int port) {
          return client.connect(server, 2015);
    }
    
    bool supla_arduino_svr_connected(void) {
          return client.connected();
    }
    
    void supla_arduino_svr_disconnect(void) {
         client.stop();
    }
    
    void supla_arduino_eth_setup(uint8_t mac[6], IPAddress *ip) {

       WiFi_up();
    }

SuplaDeviceCallbacks supla_arduino_get_callbacks(void) {
          SuplaDeviceCallbacks cb;
          
          cb.tcp_read = &supla_arduino_tcp_read;
          cb.tcp_write = &supla_arduino_tcp_write;
          cb.eth_setup = &supla_arduino_eth_setup;
          cb.svr_connected = &supla_arduino_svr_connected;
          cb.svr_connect = &supla_arduino_svr_connect;
          cb.svr_disconnect = &supla_arduino_svr_disconnect;
          cb.get_temperature = &get_temperature;
          cb.get_temperature_and_humidity = NULL;
          cb.get_rgbw_value = NULL;
          cb.set_rgbw_value = NULL;
          
          return cb;
}

void WiFi_up() // conect to wifi
{ 
  if (millis() > wifimilis)  {
  WiFi.begin(); 
  for (int x = 10; x > 0; x--) 
  {
    if (x == 1){
    wifimilis = (millis() + wifi_checkDelay) ; 
    }
    if (WiFi.status() == WL_CONNECTED) 
    {    
     return; // break;                           
    }
    else                              
    {
     yield();
     delay(500);   
      Serial.print(".");                
                         
    }
    
  }

  if (WiFi.status() == WL_CONNECTED)
  {
    Serial.println("");
    Serial.println("CONNECTED");
    Serial.print("local IP: ");
    Serial.println(WiFi.localIP());
    Serial.print("subnetMask: ");
    Serial.println(WiFi.subnetMask());
    Serial.print("gatewayIP: ");
    Serial.println(WiFi.gatewayIP());
    long rssi = WiFi.RSSI();
    Serial.print("Signal Strength (RSSI): ");
    Serial.print(rssi);
    Serial.println(" dBm");
  }
  else    
  {
    Serial.println("");
    Serial.println("not connected");
  }
  }
}
Image
You do not have the required permissions to view the files attached to this post.
Last edited by elmaya on Wed Nov 13, 2019 1:07 pm, edited 3 times in total.
elmaya
Posts: 1482
Joined: Wed Jun 27, 2018 5:48 pm
Location: El Saucejo - Sevilla

Post

It is fascinating
More than 5000 visits and not even a comment
User avatar
QLQ
Posts: 2279
Joined: Sun Sep 03, 2017 9:13 am
Location: Koszalin

Post

nice Job but I have Errors:
8 buttons and 8 relays in esp with hc595 :
line 424:

Code: Select all

DynamicJsonBuffer jsonBuffer;
error:

Code: Select all

C:\Documents and Settings\RK\Moje dokumenty\Arduino\Wemos_8_przek\Wemos_8_przek.ino: In function 'void setup()':

Wemos_8_przek:311: error: 'DynamicJsonBuffer' was not declared in this scope

         DynamicJsonBuffer jsonBuffer;         

         ^

C:\Documents and Settings\RK\Moje dokumenty\Arduino\Wemos_8_przek\Wemos_8_przek.ino:311:9: note: suggested alternative:

In file included from K:\SUPLA_PRJ\arduino\arduino\arduino180\libraries\ArduinoJson\src/ArduinoJson/DynamicJsonDocument.hpp:10:0,

                 from K:\SUPLA_PRJ\arduino\arduino\arduino180\libraries\ArduinoJson\src/ArduinoJson.hpp:9,

                 from K:\SUPLA_PRJ\arduino\arduino\arduino180\libraries\ArduinoJson\src/ArduinoJson.h:9,

                 from C:\Documents and Settings\RK\Moje dokumenty\Arduino\Wemos_8_przek\Wemos_8_przek.ino:12:

K:\SUPLA_PRJ\arduino\arduino\arduino180\libraries\ArduinoJson\src/ArduinoJson/Memory/DynamicJsonBuffer.hpp:159:5: note:   'ArduinoJson::Internals::DynamicJsonBuffer'

     DynamicJsonBuffer;

     ^

Wemos_8_przek:311: error: expected ';' before 'jsonBuffer'

         DynamicJsonBuffer jsonBuffer;         

                           ^

Wemos_8_przek:312: error: 'jsonBuffer' was not declared in this scope

         JsonObject& json = jsonBuffer.parseObject(buf.get());

                            ^

Wemos_8_przek:314: error: 'class ArduinoJson::JsonObject' has no member named 'success'

         if (json.success()) {

                  ^

C:\Documents and Settings\RK\Moje dokumenty\Arduino\Wemos_8_przek\Wemos_8_przek.ino: In function 'void loop()':

Wemos_8_przek:424: error: 'DynamicJsonBuffer' was not declared in this scope

     DynamicJsonBuffer jsonBuffer;

     ^

C:\Documents and Settings\RK\Moje dokumenty\Arduino\Wemos_8_przek\Wemos_8_przek.ino:424:5: note: suggested alternative:

In file included from K:\SUPLA_PRJ\arduino\arduino\arduino180\libraries\ArduinoJson\src/ArduinoJson/DynamicJsonDocument.hpp:10:0,

                 from K:\SUPLA_PRJ\arduino\arduino\arduino180\libraries\ArduinoJson\src/ArduinoJson.hpp:9,

                 from K:\SUPLA_PRJ\arduino\arduino\arduino180\libraries\ArduinoJson\src/ArduinoJson.h:9,

                 from C:\Documents and Settings\RK\Moje dokumenty\Arduino\Wemos_8_przek\Wemos_8_przek.ino:12:

K:\SUPLA_PRJ\arduino\arduino\arduino180\libraries\ArduinoJson\src/ArduinoJson/Memory/DynamicJsonBuffer.hpp:159:5: note:   'ArduinoJson::Internals::DynamicJsonBuffer'

     DynamicJsonBuffer;

     ^

Wemos_8_przek:424: error: expected ';' before 'jsonBuffer'

     DynamicJsonBuffer jsonBuffer;

                       ^

Wemos_8_przek:425: error: 'jsonBuffer' was not declared in this scope

     JsonObject& json = jsonBuffer.createObject();

                        ^

Wemos_8_przek:434: error: 'class ArduinoJson::JsonObject' has no member named 'prettyPrintTo'

     json.prettyPrintTo(Serial);

          ^

Wemos_8_przek:435: error: 'class ArduinoJson::JsonObject' has no member named 'printTo'

     json.printTo(configFile);

          ^

exit status 1
'DynamicJsonBuffer' was not declared in this scope

]
EDIT:
the problem was the json library. It must be in ver 5.13.3 . Not higher
jak coś nie działa to włącz zasilanie.....
User avatar
QLQ
Posts: 2279
Joined: Sun Sep 03, 2017 9:13 am
Location: Koszalin

Post

Compiles, uploads the firmware. after reboot the diode will flash twice, SuplaAP appears but does not give an IP address.
jak coś nie działa to włącz zasilanie.....
elmaya
Posts: 1482
Joined: Wed Jun 27, 2018 5:48 pm
Location: El Saucejo - Sevilla

Post

User avatar
QLQ
Posts: 2279
Joined: Sun Sep 03, 2017 9:13 am
Location: Koszalin

Post

OK. IT work . BUT !: You have to manually set the computer's wifi card IP address: 192.168.4.2 and the mask 255.255.255.0

Automatically, the ESP module will not do it.
It works great.
jak coś nie działa to włącz zasilanie.....
elmaya
Posts: 1482
Joined: Wed Jun 27, 2018 5:48 pm
Location: El Saucejo - Sevilla

Post

Compiled firmware
Image
You do not have the required permissions to view the files attached to this post.
elmaya
Posts: 1482
Joined: Wed Jun 27, 2018 5:48 pm
Location: El Saucejo - Sevilla

Post

16 push button, 16 relay

PORTS SETTINGS:

GPIO5 /D1 Switching_Relay_Button Channel 1- On the port must be pull-up. Active - connect to GND

GPIO4 /D2 Switching_Relay_Button Channel 2- On the port must be pull-up. Active - connect to GND

GPIO2 /D4 Switching_Relay_Button Channel 3- On the port must be pull-up. Active - connect to GND

GPI14 /D5 Switching_Relay_Button Channel 4- On the port must be pull-up. Active - connect to GND

GPIO12/D6 Switching_Relay_Button Channel 5- On the port must be pull-up. Active - connect to GND

GPIO13/D7 Switching_Relay_Button Channel 6- On the port must be pull-up. Active - connect to GND

GPIO3 /RX Switching_Relay_Button Channel 7- On the port must be pull-up. Active - connect to GND

GPIO1 /TX Switching_Relay_Button Channel 8- On the port must be pull-up. Active - connect to GND

Channel 9 to 16 A0 with resistive divider 8 x 1kohm

GPIO15/D8 shift registers, data pin 14 on 74595

GPIO16/D0 shift registers, clock pin 11 on 74595

GPIO0 /D3 shift registers, latch pin 12 on 74595

fisrt shift registers Q7´pin 9 ,to second shift registers data pin 14

Image

Code: Select all

#include <FS.h>       // ---- esp board manager 2.4.2 --- iwip Variant V2 higher Bandwidth
#include <ShiftRegister74HC595.h>   //https://github.com/Simsso/ShiftRegister74HC595
#include <ESP8266WiFi.h>
#define SUPLADEVICE_CPP
#include <SuplaDevice.h>
ShiftRegister74HC595 sr (2, 15, 16, 0); // create shift register object (number of shift registers, data pin 14 on 74595, clock pin 11 on 74595, latch pin 12 on 74595)
#include <math.h>
#include <ESP8266WebServer.h>
#include <DNSServer.h>
#include <WiFiManager.h> //--------- https://github.com/tzapu/WiFiManager/tree/0.14 -------------
#include <ArduinoJson.h> //--------- https://github.com/bblanchon/ArduinoJson/tree/v5.13.2 ------
#include <EEPROM.h>
#include <DoubleResetDetector.h> 
extern "C"
{
#include "user_interface.h"
}
#define DRD_TIMEOUT 30 // Number of seconds after reset during which a  subseqent reset will be considered a double reset.
#define DRD_ADDRESS 0 // RTC Memory Address for the DoubleResetDetector to use
DoubleResetDetector drd(DRD_TIMEOUT, DRD_ADDRESS);
int uno = 1;
bool eep = LOW;          //             ---------------- Eeprom ------------------
bool startEeprom = true; //             ---------------- Eeprom ------------------
int epr = 0;             //             ----------- Eepron read loops ------------
int s;                   //             ---------------- Status ------------------
int an;
int buttonValue = 0;
unsigned long svr_update = 1800000; //mean time between update  30 minutes
unsigned long svr_update_lasttime;   //last time update
unsigned long wifi_checkDelay = 60000;  // wifi reconect delay
unsigned long wifimilis;
unsigned long eep_milis;
unsigned long an_milis;
#define BEGIN_PIN 100
#define BTN_COUNT 16

WiFiClient client;
char Supla_server[40];
char Location_id[15];
char Location_Pass[20];
byte mac[6];

//flag for saving data
bool shouldSaveConfig = false;
bool initialConfig = false;
int timeout           = 120; // seconds to run for wifi config

void saveConfigCallback () {                 //callback notifying us of the need to save config
  Serial.println("Should save config");
  shouldSaveConfig = true;
}
void ondemandwifiCallback () {

  WiFiManagerParameter custom_Supla_server("server", "supla server", Supla_server, 40);
  WiFiManagerParameter custom_Location_id("ID", "Location_id", Location_id, 15);
  WiFiManagerParameter custom_Location_Pass("Password", "Location_Pass", Location_Pass, 20);

  WiFiManager wifiManager;

  wifiManager.setSaveConfigCallback(saveConfigCallback);
 
  wifiManager.addParameter(&custom_Supla_server);
  wifiManager.addParameter(&custom_Location_id);
  wifiManager.addParameter(&custom_Location_Pass);

  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();

    wifiManager.setConfigPortalTimeout(timeout);

    if (!wifiManager.startConfigPortal("Supla16x16")) {
      Serial.println("failed to connect and hit timeout");
      delay(3000);
      ESP.restart();
      delay(5000);
    }
    Serial.println("connected...yeey :)");

    strcpy(Supla_server, custom_Supla_server.getValue());
    strcpy(Location_id, custom_Location_id.getValue());
    strcpy(Location_Pass, custom_Location_Pass.getValue());
    
  WiFi.softAPdisconnect(true);   //  close AP
}

typedef struct {  //------------------------------------------- BTN ----------------------------------------------------
  int pin;
  int relay_pin;
  int channel;
  char last_val;
  int ms;
  unsigned long last_time;
  bool mem;
} _btn_t;

_btn_t btn[BTN_COUNT];

void supla_timer() {
  char v;
  unsigned long now = millis();
  {
  for(int a=0;a<BTN_COUNT;a++)
    if (btn[a].pin > 0) {
        v = digitalRead(btn[a].pin);
        if (v != btn[a].last_val && now - btn[a].last_time ) {
           btn[a].last_val = v;
           btn[a].last_time = now;
           if (v==0)
             {
              if ( btn[a].ms > 0 ) {
                     SuplaDevice.relayOn(btn[a].channel, btn[a].ms);
                     Serial.println(" monostable");
                 } else {
                 if ( (btn[a].mem) == 1 ) {   //   ----------------- == 1 if channel is false... == 0 if channel is true -----------------------
                  SuplaDevice.relayOff(btn[a].channel);
                  Serial.print("BTN Switsh off relay ");
                  Serial.println(btn[a].relay_pin);
                 } else {
                  SuplaDevice.relayOn(btn[a].channel, 0);
                  Serial.print("BTN Switsh on relay ");
                  Serial.println(btn[a].relay_pin);
                 }        
             }
             }}
      }
    }
    
}
void supla_btn_init() {
  for(int a=0;a<BTN_COUNT;a++)
    if (btn[a].pin > 0) {
        pinMode(btn[a].pin, INPUT_PULLUP);
        btn[a].last_val = digitalRead(btn[a].pin);
        btn[a].last_time = millis();
    }
}
int supla_DigitalRead(int channelNumber, uint8_t pin) {
   
      if (channelNumber == 0){
        if (btn[0].mem ==0) return 0;      
        else return 1;
      }
      if (channelNumber == 1){
        if (btn[1].mem ==0) return 0;      
        else return 1;
      }
      if (channelNumber == 2){
        if (btn[2].mem ==0) return 0;      
        else return 1;
      }
      if (channelNumber == 3){
        if (btn[3].mem ==0) return 0;      
        else return 1;
      }
      if (channelNumber == 4){
        if (btn[4].mem ==0) return 0;      
        else return 1;
      }
      if (channelNumber == 5){
        if (btn[5].mem ==0) return 0;      
        else return 1;
      }
      if (channelNumber == 6){
        if (btn[6].mem ==0) return 0;      
        else return 1;
      }
      if (channelNumber == 7){
        if (btn[7].mem ==0) return 0;      
        else return 1;      
      }
      if (channelNumber == 8){
        if (btn[8].mem ==0) return 0;      
        else return 1;
      }
      if (channelNumber == 9){
        if (btn[9].mem ==0) return 0;      
        else return 1;
      }
      if (channelNumber == 10){
        if (btn[10].mem ==0) return 0;      
        else return 1;
      }
      if (channelNumber == 11){
        if (btn[11].mem ==0) return 0;      
        else return 1;
      }
      if (channelNumber == 12){
        if (btn[12].mem ==0) return 0;      
        else return 1;
      }
      if (channelNumber == 13){
        if (btn[13].mem ==0) return 0;      
        else return 1;
      }
      if (channelNumber == 14){
        if (btn[14].mem ==0) return 0;      
        else return 1;
      }
      if (channelNumber == 15){
        if (btn[15].mem ==0) return 0;      
        else return 1;      
      }      
}
void suplaDigitalWrite(int channelNumber, uint8_t pin, uint8_t val) {  //------------------------------------------------  Virtual ----------------------------
  
     if (channelNumber == 0){
       btn[0].mem =val;
       sr.set(0, val); // set single pin 
     }
     if (channelNumber == 1){
       btn[1].mem =val;
       sr.set(1, val); // set single pin 
     }
     if (channelNumber == 2){
       btn[2].mem =val;
       sr.set(2, val); // set single pin 
     }
     if (channelNumber == 3){
       btn[3].mem =val;
       sr.set(3, val); // set single pin 
     }
     if (channelNumber == 4){
       btn[4].mem =val;
       sr.set(4, val); // set single pin 
     }
     if (channelNumber == 5){
       btn[5].mem =val;
       sr.set(5, val); // set single pin 
     }
     if (channelNumber == 6){
       btn[6].mem =val;
       sr.set(6, val); // set single pin 
     }
     if (channelNumber == 7){
       btn[7].mem =val;
       sr.set(7, val); // set single pin 
     }
     if (channelNumber == 8){
       btn[8].mem =val;
       sr.set(8, val); // set single pin 
     }
      if (channelNumber == 9){
       btn[9].mem =val;
       sr.set(9, val); // set single pin 
     }
     if (channelNumber == 10){
       btn[10].mem =val;
       sr.set(10, val); // set single pin 
     }
     if (channelNumber == 11){
       btn[11].mem =val;
       sr.set(11, val); // set single pin 
     }
     if (channelNumber == 12){
       btn[12].mem =val;
       sr.set(12, val); // set single pin 
     }
     if (channelNumber == 13){
       btn[13].mem =val;
       sr.set(13, val); // set single pin 
     }
     if (channelNumber == 14){
       btn[14].mem =val;
       sr.set(14, val); // set single pin 
     }
     if (channelNumber == 15){
       btn[15].mem =val;
       sr.set(15, val); // set single pin 
     }
     
  return;
        
}
void Eeprom_save() {                  //----------EEPROM write  ---------------------- EEprom
    if (startEeprom == true){             // ----- don't change memorized state until connected and restored all the channels

      return;
      }                        
      for(int i=0;i<BTN_COUNT;i++) {  //  ---check relay except it have delay (staircase)
         if ( btn[i].ms > 0 ) {
                     continue;
         } else {
        eep = (btn[i].mem);                    //  --- read relay state
        if (eep != EEPROM.read(i)){            //  --- compare relay state with memorized state
         EEPROM.write(i,eep);                  //  --- if different write memory
         Serial.print("EEPROM.");
         Serial.print(i);
         Serial.print(" write.");
         Serial.println((eep));
         Serial.print(" channel ");
         Serial.println((btn[i].channel));
         EEPROM.commit();
        }
      }
    }
}
void Eepron_read() {                  //----------EEPROM read  ---------------------- EEprom
                                
   // for(int i=0;i<BTN_COUNT;i++){      //  ---check relay except der have delay (staircase)
     //if ( (btn[i].ms) > 0 ) {
                //     continue;
        // } else {
        eep = EEPROM.read(epr);               //  ---read relay state
       
         Serial.print("EEPROM.");
         Serial.print(epr);
         Serial.print(" read.");
         Serial.println((eep));
         Serial.print(" channel ");
         Serial.println((btn[epr].channel));
       
        if (eep == HIGH){                    //  --- if 1 send relay on
          SuplaDevice.relayOn(epr, 0);       //  --- only one channel in each pass
          }
        
    if (epr == (BTN_COUNT-1)) {
      startEeprom = false;                //  --- once finished we do not need more
      }     
}
void status_func(int status, const char *msg) {     //    ------------------------ Status --------------------------
 s=status;                                          //    -- to check if we are registered and ready before restore from memory
}
void setup() {  //------------------------------------------------ Setup ----------------------------------------------

  wifi_set_sleep_type(NONE_SLEEP_T);

  Serial.begin(115200); 
  EEPROM.begin(512);

   if (drd.detectDoubleReset()) {
    Serial.println("Double Reset Detected");
    ondemandwifiCallback ();
  } else {
    Serial.println("No Double Reset Detected");
  }
  if (WiFi.SSID()==""){  //Serial.println("We haven't got any access point credentials, so get them now");       
    initialConfig = true;
  } 
  Serial.println("mounting FS...");  
  if (SPIFFS.begin()) {
    Serial.println("mounted file system");
    if (SPIFFS.exists("/config.json")) {
      Serial.println("reading config file");
      File configFile = SPIFFS.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);
        DynamicJsonBuffer jsonBuffer;         
        JsonObject& json = jsonBuffer.parseObject(buf.get());
        //json.printTo(Serial);   //print config data to serial on startup
        if (json.success()) {
          Serial.println("\nparsed json");
          strcpy(Supla_server, json["Supla_server"]);
          strcpy(Location_id, json["Location_id"]);
          strcpy(Location_Pass, json["Location_Pass"]);
        } else {
          Serial.println("failed to load json config");         
            }
          }
        }
      } else {
        Serial.println("failed to mount FS");
      }
  
   WiFi.mode(WIFI_STA); 

   uint8_t mac[WL_MAC_ADDR_LENGTH];
   WiFi.macAddress(mac);
   char GUID[SUPLA_GUID_SIZE] = {mac[WL_MAC_ADDR_LENGTH - 6], mac[WL_MAC_ADDR_LENGTH - 5], mac[WL_MAC_ADDR_LENGTH - 4], mac[WL_MAC_ADDR_LENGTH - 3],                                
                                 mac[WL_MAC_ADDR_LENGTH - 2], mac[WL_MAC_ADDR_LENGTH - 1], mac[WL_MAC_ADDR_LENGTH - 1], mac[WL_MAC_ADDR_LENGTH - 2], 
                                 mac[WL_MAC_ADDR_LENGTH - 3], mac[WL_MAC_ADDR_LENGTH - 4], mac[WL_MAC_ADDR_LENGTH - 5], mac[WL_MAC_ADDR_LENGTH - 6]};
          
  SuplaDevice.addRelay(101, false);   
  SuplaDevice.addRelay(102, false);  
  SuplaDevice.addRelay(103, false); 
  SuplaDevice.addRelay(104, false);   
  SuplaDevice.addRelay(105, false);  
  SuplaDevice.addRelay(106, false); 
  SuplaDevice.addRelay(107, false);   
  SuplaDevice.addRelay(108, false);
  SuplaDevice.addRelay(109, false);   
  SuplaDevice.addRelay(110, false);  
  SuplaDevice.addRelay(111, false); 
  SuplaDevice.addRelay(112, false);   
  SuplaDevice.addRelay(113, false);  
  SuplaDevice.addRelay(114, false); 
  SuplaDevice.addRelay(115, false);   
  SuplaDevice.addRelay(116, false);       

  memset(btn, 0, sizeof(btn));
  btn[0].pin =5;          // pin gpio buton  0 = no buton
  btn[0].relay_pin =101;  // pin gpio Relay
  btn[0].channel =0;      // channel
  btn[0].ms =0;           //  if = 0 Bistable -- if > 0 Monostable for X ms
  btn[0].mem =0;
  btn[1].pin =4;          // pin gpio buton  0 = no buton
  btn[1].relay_pin =102;  // pin gpio Relay
  btn[1].channel =1;      // channel
  btn[1].ms =0;           //  if = 0 Bistable -- if > 0 Monostable for X ms
  btn[1].mem =0;
  btn[2].pin =2;          // pin gpio buton  0 = no buton
  btn[2].relay_pin =103;  // pin gpio Relay
  btn[2].channel =2;      // channel
  btn[2].ms =0;           //  if = 0 Bistable -- if > 0 Monostable for X ms
  btn[2].mem =0;
  btn[3].pin =14;         // pin gpio buton  0 = no buton 
  btn[3].relay_pin =104;  // pin gpio Relay
  btn[3].channel =3;      // channel
  btn[3].ms =0;           //  if = 0 Bistable -- if > 0 Monostable for X ms
  btn[3].mem =0;
  btn[4].pin =12;         // pin gpio buton  0 = no buton
  btn[4].relay_pin =105;  // pin gpio Relay
  btn[4].channel =4;      // channel
  btn[4].ms =0;           //  if = 0 Bistable -- if > 0 Monostable for X ms
  btn[4].mem =0;
  btn[5].pin =13;         // pin gpio buton  0 = no buton
  btn[5].relay_pin =106;  // pin gpio Relay
  btn[5].channel =5;      // channel
  btn[5].ms =0;           //  if = 0 Bistable -- if > 0 Monostable for X ms
  btn[5].mem =0;
  btn[6].pin =3;          // pin gpio buton  0 = no buton
  btn[6].relay_pin =107;  // pin gpio Relay
  btn[6].channel =6;      // channel
  btn[6].ms =0;           //  if = 0 Bistable -- if > 0 Monostable for X ms
  btn[6].mem =0;
  btn[7].pin =1;          // pin gpio buton  0 = no buton
  btn[7].relay_pin =108;  // pin gpio Relay
  btn[7].channel =7;      // channel
  btn[7].ms =0;           //  if = 0 Bistable -- if > 0 Monostable for X ms
  btn[7].mem =0;
  btn[8].pin =22;          // pin gpio buton  0 = no buton
  btn[8].relay_pin =109;  // pin gpio Relay
  btn[8].channel =8;      // channel
  btn[8].ms =0;           //  if = 0 Bistable -- if > 0 Monostable for X ms
  btn[8].mem =0;
  btn[9].pin =22;         // pin gpio buton  0 = no buton
  btn[9].relay_pin =110;  // pin gpio Relay
  btn[9].channel =9;      // channel
  btn[9].ms =0;           //  if = 0 Bistable -- if > 0 Monostable for X ms
  btn[9].mem =0;
  btn[10].pin =22;         // pin gpio buton  0 = no buton
  btn[10].relay_pin =111;  // pin gpio Relay
  btn[10].channel =10;     // channel
  btn[10].ms =0;           //  if = 0 Bistable -- if > 0 Monostable for X ms
  btn[10].mem =0;
  btn[11].pin =22;         // pin gpio buton  0 = no buton 
  btn[11].relay_pin =112;  // pin gpio Relay
  btn[11].channel =11;     // channel
  btn[11].ms =0;           //  if = 0 Bistable -- if > 0 Monostable for X ms
  btn[11].mem =0;
  btn[12].pin =22;         // pin gpio buton  0 = no buton
  btn[12].relay_pin =113;  // pin gpio Relay
  btn[12].channel =12;     // channel
  btn[12].ms =0;           //  if = 0 Bistable -- if > 0 Monostable for X ms
  btn[12].mem =0;
  btn[13].pin =22;         // pin gpio buton  0 = no buton
  btn[13].relay_pin =114;  // pin gpio Relay
  btn[13].channel =13;     // channel
  btn[13].ms =0;           //  if = 0 Bistable -- if > 0 Monostable for X ms
  btn[13].mem =0;
  btn[14].pin =22;         // pin gpio buton  0 = no buton
  btn[14].relay_pin =115;  // pin gpio Relay
  btn[14].channel =14;     // channel
  btn[14].ms =0;           //  if = 0 Bistable -- if > 0 Monostable for X ms
  btn[14].mem =0;
  btn[15].pin =22;         // pin gpio buton  0 = no buton
  btn[15].relay_pin =116;  // pin gpio Relay
  btn[15].channel =15;     // channel
  btn[15].ms =0;           //  if = 0 Bistable -- if > 0 Monostable for X ms
  btn[15].mem =0;
  supla_btn_init();

  SuplaDevice.setDigitalReadFuncImpl(&supla_DigitalRead);    //            ------Send Value to server -------
  SuplaDevice.setDigitalWriteFuncImpl(&suplaDigitalWrite);   //        -------  Read Value from server   -------
  SuplaDevice.setTimerFuncImpl(&supla_timer);
  SuplaDevice.setStatusFuncImpl(&status_func);    //   ----------------------------- Status -----------------------------
  SuplaDevice.setName("Supla16x16");

  int LocationID = atoi(Location_id);
  SuplaDevice.begin(GUID,              // Global Unique Identifier 
                    mac,               // Ethernet MAC address
                    Supla_server,      // SUPLA server address
                    LocationID,        // Location ID 
                    Location_Pass);    // Location Password

// read_initial_relay_state
    for(int i=0;i<BTN_COUNT;i++){      //  ---check relay except der have delay (staircase)
     if ( (btn[i].ms) > 0 ) {
                     continue;
         } else {
        eep = EEPROM.read(i);               //  ---read relay state
       if (eep > uno ){
         EEPROM.write(i,uno);                  
         Serial.println("epp correct");
         EEPROM.commit();
       }
         Serial.print("Recover.");
         Serial.print(i);
         Serial.print(" read.");
         Serial.println((eep));
         Serial.print(" channel ");
         Serial.println((btn[i].channel));
             
         sr.set(btn[i].channel, eep); // set single pin 
          
         }
    }         
}

void loop() {

  drd.loop();

  if (initialConfig){
    for(int i=0;i<BTN_COUNT;i++){      
        EEPROM.write(i,0);    
   } 
    ondemandwifiCallback () ;
    initialConfig = false; 
  }

  if (shouldSaveConfig) {
    Serial.println("saving config");
    DynamicJsonBuffer jsonBuffer;
    JsonObject& json = jsonBuffer.createObject();
    json["Supla_server"] = Supla_server;
    json["Location_id"] = Location_id;
    json["Location_Pass"] = Location_Pass;
    File configFile = SPIFFS.open("/config.json", "w");
    if (!configFile) {
      Serial.println("failed to open config file for writing");
    }
    json.prettyPrintTo(Serial);
    json.printTo(configFile);
    configFile.close();
    Serial.println("config saved");
    shouldSaveConfig = false;
    WiFi.mode(WIFI_STA);
    ESP.restart();
    delay(5000); 
  }
  
  if (WiFi.status() != WL_CONNECTED) { 
    WiFi_up();
  } 
  
  SuplaDevice.iterate();
  //if (millis() > an_milis){
   analog_switch();
    //an_milis = an_milis + 200;
  //}
  if (millis() > eep_milis){
     Eeprom_save() ;   //        ------------------------------Eepron save callback -----------------------------
     eep_milis = eep_milis + 5000 ;
     }
  
  switch (s) {    //    ------------------------------------------------ Status ------------------------------------
  case 17:      // -----     STATUS_REGISTERED_AND_READY
  if (epr<BTN_COUNT){
  Serial.print("Eepron_read...");
  Serial.println(epr);
   Eepron_read() ;                // ------------------------------- Eeprom read callback -------------------------------
   epr = epr+1;                   // -------- 1 loop for each output 8 in total ----------
   
  } 
    break;

    case 10:      // --------------------- REGISTER_IN_PROGRESS  ----------------------
    epr = 0 ;
     startEeprom = true;
    break;
  }
}

    int supla_arduino_tcp_read(void *buf, int count) {
        _supla_int_t size = client.available();       
        if ( size > 0 ) {
            if ( size > count ) size = count;
            return client.read((uint8_t *)buf, size);
        };    
        return -1;
    };   
    int supla_arduino_tcp_write(void *buf, int count) {
        return client.write((const uint8_t *)buf, count);
    };    
    bool supla_arduino_svr_connect(const char *server, int port) {
          return client.connect(server, 2015);
    }    
    bool supla_arduino_svr_connected(void) {
          return client.connected();
    }    
    void supla_arduino_svr_disconnect(void) {
         client.stop();
    }    
    void supla_arduino_eth_setup(uint8_t mac[6], IPAddress *ip) {
       WiFi_up();
    }

SuplaDeviceCallbacks supla_arduino_get_callbacks(void) {
          SuplaDeviceCallbacks cb;
          
          cb.tcp_read = &supla_arduino_tcp_read;
          cb.tcp_write = &supla_arduino_tcp_write;
          cb.eth_setup = &supla_arduino_eth_setup;
          cb.svr_connected = &supla_arduino_svr_connected;
          cb.svr_connect = &supla_arduino_svr_connect;
          cb.svr_disconnect = &supla_arduino_svr_disconnect;
          cb.get_temperature = NULL;
          cb.get_temperature_and_humidity = NULL;
          cb.get_rgbw_value = NULL;
          cb.set_rgbw_value = NULL;          
          return cb;
}

void WiFi_up(){ // conect to wifi
 
  if (millis() > wifimilis)  {
  WiFi.begin(); 
  for (int x = 10; x > 0; x--) 
  {
    if (x == 1){
    wifimilis = (millis() + wifi_checkDelay) ; 
    }
    if (WiFi.status() == WL_CONNECTED) 
    {    
     break;                           
    }
    else                              
    {
     yield();
     delay(500);   
      Serial.print(".");                                         
    }    
  }

  if (WiFi.status() == WL_CONNECTED){  
    Serial.println("");
    Serial.println("CONNECTED");
    Serial.print("local IP: ");
    Serial.println(WiFi.localIP());
    Serial.print("subnetMask: ");
    Serial.println(WiFi.subnetMask());
    Serial.print("gatewayIP: ");
    Serial.println(WiFi.gatewayIP());
    long rssi = WiFi.RSSI();
    Serial.print("Signal Strength (RSSI): ");
    Serial.print(rssi);
    Serial.println(" dBm");
  }
  else    
  {
    Serial.println("");
    Serial.println("not connected");
  }
  }
}

void analog_switch(){
   
  buttonValue = analogRead(A0); //Read analog value from A0 pin
  
  if (buttonValue<=50){   //For no button:
  delay (100);
  return;
  }
  else
  {
   delay (50);
   buttonValue = analogRead(A0);
   Serial.print ("analog read: ");
   Serial.println(buttonValue);
   
  if (buttonValue>=113 && buttonValue<=153){ //For 1st button:
    Serial.println("read: 9 ");
    an = 8;
    analogRelay() ;
    delay (500);
    return;
  }  
  else if (buttonValue>=256 && buttonValue<=296){//For 2nd button:
    Serial.println("read: 10 ");
    an = 9;
    analogRelay() ;
    delay (500);
    return;
  }  
  else if (buttonValue>=389  && buttonValue<=429){//For 3rd button:
    Serial.println("read: 11 ");
    an = 10;
    analogRelay() ;
    delay (500);
    return;
  }  
  else if (buttonValue>=525  && buttonValue<=565){//For 4th button:
    Serial.println("read: 12 ");
    an = 11;
    analogRelay() ;
    delay (500);
    return;
  }    
  else if (buttonValue>=654  && buttonValue<=694){//For 5rd button:
    Serial.println("read: 13 ");
    an = 12;
    analogRelay() ;
    delay (500);
    return;
  }  
  else if (buttonValue>=796  && buttonValue<=836){//For 6th button:
    Serial.println("read: 14 ");
    an = 13;
    analogRelay() ;
    delay (500);
    return;
  }  
  else if (buttonValue>=930  && buttonValue<=970){//For 7rd button:
    Serial.println("read: 15 ");
    an = 14;
    analogRelay() ;
    delay (500);
    return;
  }  
  else if (buttonValue>=1000 ){//For 8th button:
    Serial.println("read: 16 ");
    an = 15;
    analogRelay() ;
    delay (500);
    return;
  } 
 }  
}
void analogRelay(){
  
   if ( btn[an].ms > 0 ) {
                     SuplaDevice.relayOn(btn[an].channel, btn[an].ms);
                     Serial.println(" monostable");
                 } else {
                 if ( (btn[an].mem) == 1 ) {   //   ----------------- == 1 if channel is false... == 0 if channel is true -----------------------
                  SuplaDevice.relayOff(btn[an].channel);
                  Serial.print("BTN Switsh off relay ");
                  Serial.println(btn[an].relay_pin);
                 } else {
                  SuplaDevice.relayOn(btn[an].channel, 0);
                  Serial.print("BTN Switsh on relay ");
                  Serial.println(btn[an].relay_pin);
                 }        
             } 
             delay (500);
}
Initial parameters for "ESP Falsh Download Tool":

CreystalFreq 26M
SPI SPEED 40 MHz
SPI MODE QIO
BAUDRATE 11520
FLASH SIZE 32Mbit (4MByte)

supla_595_reset_to_Config16_x16.bin ------------> 0x00000


// CFG MODE - SWITCH

To bring the device into configuration mode, in this case press Reset_Button 2 times
When in configuration mode, the device goes into Access Point mode.

In order to enter or change the settings, you need to:

- Sign in at https://cloud.supla.org (registration is free of charge)
- Connect to WiFi called (Supla16x16) from any computer with a wireless network card and Internet browser.
- Open access page: http://192.168.4.1
- Enter user name and password to the WiFi through which the device will get Internet access.
- Enter Server address, Location ID and Location Password, which will be provided once you sign in at cloud.supla.org
You do not have the required permissions to view the files attached to this post.
Last edited by elmaya on Thu Oct 31, 2019 12:51 am, edited 1 time in total.
selo
Posts: 9
Joined: Mon Mar 04, 2019 1:31 am

Post

Thanks for this.
How can i use it for roller shutters?

Return to “Ideas and concepts”