// Configuración Blynk
#define BLYNK_TEMPLATE_ID "TMPL2TNl1Gnuu"
#define BLYNK_TEMPLATE_NAME "A4 Telemed"
#define BLYNK_AUTH_TOKEN "sAxmoWtggtivhwqiLxZzaHwcVJ7K_dpk"

// Configuración WiFi
char ssid[] = "IZZI-632E";
char pass[] = "y9pze3yf";

// LIBRERÍAS
#include <WiFi.h>
#include <BlynkSimpleEsp32.h>
#include <Wire.h>
#include "MAX30105.h"
#include "spo2_algorithm.h"
#include "DHT.h"

// Configuración sensores
MAX30105 particleSensor;
#define DHTPIN 4
#define DHTTYPE DHT11
DHT dht(DHTPIN, DHTTYPE);

// Variables globales
uint32_t irBuffer[100];   // Buffer para datos IR
uint32_t redBuffer[100];  // Buffer para datos rojo
int32_t spo2;             // Valor de SpO2
int8_t validSPO2;         // Indicador de validez SpO2
int32_t heartRate;        // Frecuencia cardíaca
int8_t validHeartRate;    // Indicador de validez FC
float temperature;
unsigned long lastUpdate = 0;
const long updateInterval = 1000; // Actualizar cada segundo

void setup() {
  Serial.begin(115200);
  
  // Iniciar Blynk
  Blynk.begin(BLYNK_AUTH_TOKEN, ssid, pass);
  
  // Iniciar sensor DHT
  dht.begin();
  
  // Iniciar sensor MAX30102
  Wire.begin();
  if (!particleSensor.begin(Wire, I2C_SPEED_FAST)) {
    Serial.println("MAX30102 no encontrado");
    while (1);
  }

  // Configurar sensor MAX30102
  byte ledBrightness = 60; //Options: 0=Off to 255=50mA
  byte sampleAverage = 4;  //Options: 1, 2, 4, 8, 16, 32
  byte ledMode = 2;        //Options: 1 = Red only, 2 = Red + IR
  byte sampleRate = 100;   //Options: 50, 100, 200, 400, 800, 1000, 1600, 3200
  int pulseWidth = 411;    //Options: 69, 118, 215, 411
  int adcRange = 4096;     //Options: 2048, 4096, 8192, 16384
  
  particleSensor.setup(ledBrightness, sampleAverage, ledMode, sampleRate, pulseWidth, adcRange);
  
  Serial.println("Sistema listo. Coloque su dedo en el sensor...");
}

void loop() {
  Blynk.run(); // Mantener conexión Blynk
  
  if (millis() - lastUpdate >= updateInterval) {
    lastUpdate = millis();
    
    // Leer temperatura
    temperature = dht.readTemperature();
    
    // Tomar muestras del sensor óptico
    for (byte i = 0; i < 100; i++) {
      while (!particleSensor.available()) {
        particleSensor.check();
      }
      redBuffer[i] = particleSensor.getRed();
      irBuffer[i] = particleSensor.getIR();
      particleSensor.nextSample();
    }

    // Calcular SpO2 y frecuencia cardíaca
    maxim_heart_rate_and_oxygen_saturation(irBuffer, 100, redBuffer, &spo2, &validSPO2, &heartRate, &validHeartRate);

    // Mostrar datos por Serial
    displayData();
    
    // Enviar datos a Blynk
    sendToBlynk();
  }
}

void displayData() {
  Serial.println("\n--- Mediciones ---");
  
  // Temperatura
  if (!isnan(temperature)) {
    Serial.print("Temperatura: ");
    Serial.print(temperature);
    Serial.println(" °C");
  } else {
    Serial.println("Error lectura temperatura");
  }

  // SpO2
  Serial.print("SpO2: ");
  if (validSPO2) {
    Serial.print(spo2);
    Serial.println("%");
  } else {
    Serial.println("No válido");
  }

  // Frecuencia cardíaca
  Serial.print("Frecuencia Cardíaca: ");
  if (validHeartRate) {
    Serial.print(heartRate);
    Serial.println(" BPM");
  } else {
    Serial.println("No válida");
  }
  
  Serial.println("------------------");
}

void sendToBlynk() {
  // Enviar temperatura
  if (!isnan(temperature)) {
    Blynk.virtualWrite(V1, temperature);
  }
  
  // Enviar SpO2
  if (validSPO2) {
    Blynk.virtualWrite(V0, spo2);
  }
  
  // Enviar frecuencia cardíaca
  if (validHeartRate) {
    Blynk.virtualWrite(V2, heartRate);
  }
}
$abcdeabcde151015202530fghijfghij
max30102Breakout