/*
/*Além de imprimir no console, agora, publicamos no LCD I2C*/
*/
#include <LiquidCrystal_I2C.h>
/*******************************************************************************/
#include "DHTesp.h" // Clique aqui para obter a biblioteca: http://librarymanager/All#DHTesp
#include <Ticker.h>

#ifndef ESP32
#pragma message(ESTE EXEMPLO É APENAS PARA ESP32!)
#error Selecione a placa ESP32.
#endif

/**************************************************************/
/* Exemplo de como ler sensores DHT de um ESP32 usando multi-*/
/* tarefa.                                                   */
/* Este exemplo depende da biblioteca Ticker para acordar */
/* a tarefa a cada 20 segundos                                  */
/**************************************************************/

DHTesp dht;

void tempTask(void *pvParameters);
bool getTemperature();
void triggerGetTemp();

/** Task handle for the light value read task */
TaskHandle_t tempTaskHandle = NULL;
/** Ticker para leitura de temperatura */ 
Ticker tempTicker;
/** Perfil de conforto */
ComfortState cf;
/** Flag se a tarefa deve executar */
bool tasksEnabled = false;
/** Número do pino para pino de dados DHT22 */
int dhtPin = 15;

LiquidCrystal_I2C lcd= LiquidCrystal_I2C(0x27, 16, 2);


/**
 * initTemp
 * Setup DHT library
 * Setup task and timer for repeated measurement
 * @return bool
 *    true if task and timer are started
 *    false if task or timer couldn't be started
 */
bool initTemp() {
  byte resultValue = 0;
  // Inicializa o Sensor de temperatura
	dht.setup(dhtPin, DHTesp::DHT22);
	Serial.println("DHT inicializado e tarefa tempTask no núcleo 1!!!");

  // Inicie a tarefa para obter temperatura
	xTaskCreatePinnedToCore(
			tempTask,                       /* Function to implement the task */
			"tempTask ",                    /* Name of the task */
			4000,                           /* Stack size in words */
			NULL,                           /* Task input parameter */
			5,                              /* Priority of the task */
			&tempTaskHandle,                /* Task handle. */
			1);                             /* Core where the task should run */

  if (tempTaskHandle == NULL) {
    Serial.println("Falha ao iniciar a tarefa para atualização de temperatura");
    return false;
  } else {
    //  Iniciar a atualização dos dados do ambiente a cada 20 segundos
    tempTicker.attach(4, triggerGetTemp);
  }
  return true;
}

/**
 * triggerGetTemp
 * Define o flag dhtUpdated para verdadeiro para manuseio em loop()
 * chamado porTicker getTempTimer
 */
void triggerGetTemp() {
  if (tempTaskHandle != NULL) {
	   xTaskResumeFromISR(tempTaskHandle);
  }
}

/**
 * Tarefa para ler a temperatura do sensor DHT22
 * @param pvParameters
 *    ponteiro para parâmetros de tarefa
 */
void tempTask(void *pvParameters) {
	Serial.println("Loop de execução das tarefas inicializado via tempTask");
	while (1) // tempTask loop
  {
    if (tasksEnabled) {
      // Get temperature values
			getTemperature();
		}
    // Got sleep again
		vTaskSuspend(NULL);
	}
}

/**
 * getTemperature
 * Leitura da temperatura do sensor DHT22
 * @return bool
 *    true if temperature could be aquired
 *    false if aquisition failed
*/
bool getTemperature() {
	// Reading temperature for humidity takes about 250 milliseconds!
	// Sensor readings may also be up to 2 seconds 'old' (it's a very slow sensor)
  TempAndHumidity newValues = dht.getTempAndHumidity();
	// Check if any reads failed and exit early (to try again).
	if (dht.getStatus() != 0) {
		Serial.println("DHT11 error status: " + String(dht.getStatusString()));
		return false;
	}
 //DÚVIDAS: https://github.com/beegee-tokyo/DHTesp
	float heatIndex = dht.computeHeatIndex(newValues.temperature, newValues.humidity);
  float dewPoint = dht.computeDewPoint(newValues.temperature, newValues.humidity);
  float cr = dht.getComfortRatio(cf, newValues.temperature, newValues.humidity);

  String comfortStatus;
  switch(cf) {
    case Comfort_OK:
      comfortStatus = "Comforto OK";
      break;
    case Comfort_TooHot:
      comfortStatus = "Muito quente";
      break;
    case Comfort_TooCold:
      comfortStatus = "Muito Frio";
      break;
    case Comfort_TooDry:
      comfortStatus = "Muito seco";
      break;
    case Comfort_TooHumid:
      comfortStatus = "Muito Umido";
      break;
    case Comfort_HotAndHumid:
      comfortStatus = "Quente e Umido";
      break;
    case Comfort_HotAndDry:
      comfortStatus = "Quente e Seco";
      break;
    case Comfort_ColdAndHumid:
      comfortStatus = "Frio e Umido";
      break;
    case Comfort_ColdAndDry:
      comfortStatus = "Frio e seco";
      break;
    default:
      comfortStatus = "Desconhecido:";
      break;
  };

  Serial.println(" T:" + String(newValues.temperature) + " H:" + String(newValues.humidity) + " I:" + String(heatIndex) + " D:" + String(dewPoint) + " " + comfortStatus);
  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print(String(comfortStatus));
  lcd.setCursor(0,1);
  lcd.print("T: ");
  lcd.setCursor(2,1);
  lcd.print(String(newValues.temperature));
  lcd.setCursor(8,1);
  lcd.print("U: ");
  lcd.setCursor(10,1);
  lcd.print(String(newValues.humidity));
  lcd.setCursor(15,1);
  lcd.print("%");
  
  return true;
}




void setup()
{
  Serial.begin(115200);
  lcd.init(); // initialize the lcd
  Serial.println();
  Serial.println("Exemplo DHT ESP32 com tarefas (tasks)");
  initTemp();
  // Fim do sinal de configuração() para tarefas
  tasksEnabled = true;

  /*************************LCD I2C**********************************/
 

lcd.backlight();

}

void loop() {
  if (!tasksEnabled) {
    // Espere 2 segundos para deixar o sistema se estabilizar
    delay(2000);
    // Habilite a tarefa que lerá valores do sensor DHT
    tasksEnabled = true;
    if (tempTaskHandle != NULL) {
			vTaskResume(tempTaskHandle);
		}
  }
  yield();//chamando para execução as tarefas em background nas temporizações
}