

//-------- Con este programa controlaremos un motor de persiana real a 230 V -------//

///////  Poderemos empregar os pulsadores de entrada e tamén os canais MQTT   /////////

///////         O controlador que empregaremos será o ESP32                    ////////


/* Librerías que precisamos */
#include <WiFi.h>
#include <PubSubClient.h>


/* Datos da nosa wifi ssid-password */
const char* ssid = "vodafoneA218";
const char* password = "3GRKRF4E5TGHI7";
/* Datos do noso servidor MQTT, instalado neste caso na raspberry */
const char* mqtt_server = "192.168.0.156";



/* Conectámonos con PubSubClient client */
WiFiClient espClient;
PubSubClient client(espClient);

/*Definimos pins*/
const char in_subir = 32;
const char in_baixar = 33;
const char ou_subir = 12;
const char ou_baixar = 13;

/*Definimos topics */

#define PERSIANASUBIR_TOPIC     "controlpersianas/salon/subir" /* 1=on, 0=off */
#define PERSIANABAIXAR_TOPIC     "controlpersianas/salon/baixar" /* 1=on, 0=off */

long lastMsg = 0;
char msg[20];

void receivedCallback(char* topic, byte* payload, unsigned int length) {
  Serial.print("Message received: ");
  Serial.println(topic);

  
   Serial.print("payload: ");
  if (strcmp(topic, "controlpersianas/salon/subir") == 0) {
    String mensaxe = func_payloadtostring(payload, length);
    Serial.println(mensaxe);
    if (mensaxe == "ON")
      digitalWrite(ou_subir, HIGH);
      digitalWrite(ou_baixar, LOW); // Isto fago como seguridade extra
    if (mensaxe == "OFF")
      digitalWrite(ou_subir, LOW); 
  }

  if (strcmp(topic, "controlpersianas/salon/baixar") == 0) {
    String mensaxe = func_payloadtostring(payload, length);
    Serial.println(mensaxe);
    if (mensaxe == "ON")
      digitalWrite(ou_baixar, HIGH);
      digitalWrite(ou_subir, LOW); // Isto fago como seguridade extra
    if (mensaxe == "OFF")
      digitalWrite(ou_baixar, LOW); 
  }

}

//----- función payloadtostring -----------//  // Esta función existe para ser chamada á súa vez por callback

String func_payloadtostring (byte* payload, unsigned int length) {
  int i = 0;
  char buff[length + 1];
  for (i = 0; i < length; i++) {
    buff[i] = payload[i];
  }
  buff[i] = '\0';
  String mensaxe = String(buff);
  return mensaxe;
}
  
//  ---------------------------------------------//  
  
 

void mqttconnect() {
  /* Loop until reconnected */
  while (!client.connected()) {
    Serial.print("MQTT connecting ...");
    /* client ID */
    String clientId = "ESP32Client";
    /* connect now */
    if (client.connect(clientId.c_str())) {
      Serial.println("connected");
      /* subscribe topic with default QoS 0*/
      client.subscribe(PERSIANASUBIR_TOPIC);
      client.subscribe(PERSIANABAIXAR_TOPIC);
    } else {
      Serial.print("failed, status code =");
      Serial.print(client.state());
      Serial.println("try again in 5 seconds");
      /* Wait 5 seconds before retrying */
      delay(5000);
    }
  }
}


//-----------------------------------------------------------------------------------------------------------------------------------//
bool value_subir = true;                 // Variables empregadas polas funcións para controlar o estado dos pulsadores.
bool lastvalue_subir = true;             // Nos nosos vinilos temos relés para calefacción con disparo baixo por iso inicializamos esas saídas en 1

bool value_baixar = true;                 
bool lastvalue_baixar = true;             



////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

void setup() {
  Serial.begin(115200);
  // We start by connecting to a WiFi network
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);

  WiFi.begin(ssid, password);

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  /* Declaramos os pulsadores como entradas pullup e as conexións do motor como saídas */
  pinMode(in_subir, INPUT_PULLUP);
  pinMode(in_baixar, INPUT_PULLUP);
  pinMode(ou_subir, OUTPUT);
  pinMode(ou_baixar, OUTPUT);

  Serial.println("");
  Serial.println("WiFi connected");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());

  /* Configuaramos o porto do servidor MQTT */
  client.setServer(mqtt_server, 1883);
  /* this receivedCallback function will be invoked 
  when client received subscribed topic */
  client.setCallback(receivedCallback);
 
}



//----- Función subir --------------------------------------------------------------------------------------------//

void func_subir() {
  value_subir = digitalRead(in_subir);
  if (value_subir != lastvalue_subir) {
    if (value_subir == HIGH) {
      digitalWrite(ou_subir, HIGH);
      client.publish(PERSIANASUBIR_TOPIC,"OFF");
      Serial.println("Non subimos");
    } else {
        digitalWrite(ou_subir, LOW);
        client.publish(PERSIANASUBIR_TOPIC,"ON");
        //client.publish(PERSIANABAIXAR_TOPIC,"OFF"); // Isto fago como seguridade extra, pero corto o topic do sentido contrario
        Serial.println("Subimos");
      }
      delay(200);
  } 
    lastvalue_subir = value_subir;
}


//----- Función baixar --------------------------------------------------------------------------------------------//

void func_baixar() {
  value_baixar = digitalRead(in_baixar);
  if (value_baixar != lastvalue_baixar) {
    if (value_baixar == HIGH) {
      digitalWrite(ou_baixar, HIGH);
      client.publish(PERSIANABAIXAR_TOPIC,"OFF");
      Serial.println("Non baixamos");
    } else {
        digitalWrite(ou_baixar, LOW);
        client.publish(PERSIANABAIXAR_TOPIC,"ON");
        //client.publish(PERSIANASUBIR_TOPIC,"OFF"); // Isto fago como seguridade extra, pero corto o topic do sentido contrario
        Serial.println("Baixamos");
      }
      delay(50);
  } 
    lastvalue_baixar = value_baixar;
}


//////////////////////////////////////////////////////////////////////////////////////////////


void loop() {
  
  /* if client was disconnected then try to reconnect again */
  if (!client.connected()) {
    mqttconnect();
  }

  func_subir();
  delay(10);

  func_baixar();
  delay(10);
  
  /* this function will listen for incomming 
  subscribed topic-process-invoke receivedCallback */
  client.loop();

  
  delay (1000);
 
}
