Internet de les coses amb ESP32 i ESP8266

Exemples Referència Plaques   Recursos CITCEA
Projectes Programació Perifèrics   Inici

Visualitzador de dades o avisos

Programa del grup 2

Aquest grup va fer un visualitzador que permet diverses opcions, com mostrar missatges que s'escriuen en una pàgina web, el temps que farà o un versicle que canvia cada dia.

El programa del microcontrolador és el següent:

#include <SPI.h>    // Carreguem la biblioteca SPI
#include <WiFiNINA.h>    // Carreguem la biblioteca WiFiNINA
#include <WiFiUdp.h>    // Farem servir UDP per llegir l'hora d'internet
#include <Adafruit_NeoPixel.h>
#include "ssd1306.h"
#define ARDUINOJSON_DECODE_UNICODE 1
#include <ArduinoJson.h>    // Carreguem la biblioteca json
#define LED 1    // pota on hem connectat el LED
#define LEDP 6    // pota on hem connectat el LED
#define pol 7
#define pol_dw 5
#define pol_ok 4
#define N_Do0     33
#define N_ReB0    35
#define N_Re0     37
#define N_MiB0    39
#define N_Mi0     41
#define N_Fa0     44
#define N_SolB0   46
#define N_Sol0    49
#define N_LaB0    52
#define N_La0     55
#define N_SiB0    58
#define N_Si0     62
#define N_Do1     65
#define N_ReB1    69
#define N_Re1     73
#define N_MiB1    78
#define N_Mi1     82
#define N_Fa1     87
#define N_SolB1   93
#define N_Sol1    98
#define N_LaB1   104
#define N_La1    110
#define N_SiB1   117
#define N_Si1    123
#define N_Do2    131
#define N_ReB2   139
#define N_Re2    147
#define N_MiB2   156
#define N_Mi2    165
#define N_Fa2    175
#define N_SolB2  185
#define N_Sol2   196
#define N_LaB2   208
#define N_La2    220
#define N_SiB2   233
#define N_Si2    247
#define N_Do3    262
#define N_ReB3   277
#define N_Re3    294
#define N_MiB3   311
#define N_Mi3    330
#define N_Fa3    349
#define N_SolB3  370
#define N_Sol3   392
#define N_LaB3   415
#define N_La3    440
#define N_SiB3   466
#define N_Si3    494
#define N_Do4    523
#define N_ReB4   554
#define N_Re4    587
#define N_MiB4   622
#define N_Mi4    659
#define N_Fa4    698
#define N_SolB4  740
#define N_Sol4   784
#define N_LaB4   831
#define N_La4    880
#define N_SiB4   932
#define N_Si4    988
#define N_Do5   1047
#define N_ReB5  1109
#define N_Re5   1175
#define N_MiB5  1245
#define N_Mi5   1319
#define N_Fa5   1397
#define N_SolB5 1480
#define N_Sol5  1568
#define N_LaB5  1661
#define N_La5   1760
#define N_SiB5  1865
#define N_Si5   1976
#define N_Do6   2093
#define N_ReB6  2217
#define N_Re6   2349
#define N_MiB6  2489
#define N_Mi6   2637
#define N_Fa6   2794
#define N_SolB6 2960
#define N_Sol6  3136
#define N_LaB6  3322
#define N_La6   3520
#define N_SiB6  3729
#define N_Si6   3951
#define N_Do7   4186
extern uint16_t hiScore;
const char idXarxa[] = "MOVISTAR-WIFI6";    // Nom del punt d'accés 
const char contrasenya[] = "BSdDAGXxAA";    // Contrasenya de connexió 
const char* SERVIDOR_VERSICLE = "discoverybiblestudy.org";
const char* PAGINA_VERSICLE = "/daily/api/";
const char* SERVIDOR_CLIMA = "api.open-meteo.com";
const char* PAGINA_CLIMA ="/v1/forecast?latitude=41.45&longitude=2.25&daily=weather_code,temperature_2m_max,wind_speed_10m_max&forecast_days=4&timezone=Europe%2FMadrid";
const char* server4 = SERVIDOR_VERSICLE;
const char* pagin = PAGINA_VERSICLE;
unsigned long darreraConnexio = 0;
const unsigned long periodeConnexio = 10000UL;   
String line = ""; 
byte valorLED = 0;    
byte R = 0;    
byte G = 0;   
byte B = 0;   
char TEXT1[50] = "";
char TEXT2[50] = "";
char TEXT3[50] = "";
String versiculo1 = "";
String ref = "";
int indexClima = 0;
String climaDia[4];
float climaTemp[4];
String climaCelTxt[4];
float climaVent[4];
int opcioWeb = 1;
SAppMenu menu;
const char *elements[] = {
    "VERSICLE",
    "CLIMA",
    "RECORDATORI 1",
    "RECORDATORI 2",
    "RECORDATORI 3"
};
int n = 0;
bool enviar = false;
int status = WL_IDLE_STATUS;
WiFiServer server(80);    // Creem un objecte de comunicació amb el port 80
                          // El port 80 és el de defecte per a http
WiFiSSLClient clientJSON;   
unsigned int localPortHora = 2390;
IPAddress timeServer(129, 6, 15, 28); 
const int NTP_PACKET_SIZE = 48;
byte packetBuffer[NTP_PACKET_SIZE];
WiFiUDP Udp;
int hora, minuts, segons;
const unsigned long DESFASAMENT_HORA = 7200UL;   
const unsigned long periodeHoraNTP = 60000UL;    
const unsigned long periodeReintentHora = 5000UL;
unsigned long darreraPeticioHora = 0;
unsigned long tempsBaseHora = 0;
unsigned long millisBaseHora = 0;
bool horaDisponible = false;
bool menuPrincipal = true;
int segonMostrat = -1;
bool op=false;
bool ntpyes = false;
bool jsonyes = false;
bool faseu = false;
bool climaDisponible = false;
Adafruit_NeoPixel cadena = Adafruit_NeoPixel(1, LED, NEO_GRB + NEO_KHZ800);
String Dades(String peti, String param){
    String valor = "";
    String sepa;
    int pos;
    if (peti.indexOf("?") != -1) {    
        peti = peti.substring(peti.indexOf("?")+1);
        if (peti.indexOf(param) != -1) {   
            peti = peti.substring(peti.indexOf(param)+param.length());
            sepa = peti.substring(0, 1);
            peti = peti.substring(1);
            pos = peti.indexOf("&");
            if (pos == -1) {
                pos = peti.indexOf(" ");
            }
            if ((pos != 0) && (sepa == "=")){
                valor = peti.substring(0, pos);
            }
        } 
    }
    return valor;
}
int posicioCentrada(String text) {
    int ampladaText = text.length() * 6;  
    int x = (128 - ampladaText) / 2;     
    if (x < 0) {
        x = 0;
    }
    return x;}
String netejaTextWeb(String txt) {
  String senseTags = "";
  bool dinsEtiqueta = false;
  for (int i = 0; i < txt.length(); i++) {
    char c = txt[i];
    if (c == '<') {
      dinsEtiqueta = true;
    } else if (c == '>') {
      dinsEtiqueta = false;
    } else if (!dinsEtiqueta) {
      senseTags += c;
    }
  }
  txt = senseTags;
  txt.replace("&quot;", "\"");
  txt.replace("&apos;", "'");
  txt.replace("&amp;", "&");
  txt.replace("&lt;", "<");
  txt.replace("&gt;", ">");
  txt.replace("&nbsp;", " ");
  txt.replace("&ndash;", "-");
  txt.replace("&mdash;", "-");
  txt.replace("&hellip;", "...");
  txt.replace("&iexcl;", "!");
  txt.replace("&iquest;", "?");
  String resultat = "";
  for (int i = 0; i < txt.length(); i++) {
    if (txt[i] == '&' && i + 2 < txt.length() && txt[i + 1] == '#') {
      int j = i + 2;
      bool esNumero = false;
      int valor = 0;
      while (j < txt.length() && isDigit(txt[j])) {
        esNumero = true;
        valor = valor * 10 + (txt[j] - '0');
        j++;
      }
      if (esNumero && j < txt.length() && txt[j] == ';') {
        if (valor >= 32 && valor <= 126) {
          resultat += char(valor);
        } else {
          resultat += "?";
        }
        i = j;
      } else {
        resultat += txt[i];
      }
    } else {
      resultat += txt[i];
    }
  }
  txt = resultat;
  txt.replace("\r", " ");
  txt.replace("\n", " ");
  txt.replace("\t", " ");
  while (txt.indexOf("  ") != -1) {
    txt.replace("  ", " ");
  }
  txt.trim();
  return txt;
}
void printCentrat(int y, String text) {
    int x = posicioCentrada(text);
    ssd1306_printFixed(x, y, text.c_str(), STYLE_NORMAL);
}
void printMissatgeCentrat(String text) {
    int maxCaracters = 21;
    int y = 24;
    if (text.length() <= maxCaracters) {
        printCentrat(32, text);
    } else {
        while (text.length() > 0 && y <= 56) {
            String tros = text.substring(0, maxCaracters);
            int espai = tros.lastIndexOf(' ');
            if (text.length() > maxCaracters && espai > 0) {
                tros = text.substring(0, espai);
                text = text.substring(espai + 1);
            } else {
                text = text.substring(tros.length());
            }
            tros.trim();
            printCentrat(y, tros);
            y += 8;
        }
    }
}
String agafaLinia(String text, int &posicio) {
    const int maxCaracters = 21;
    while ((posicio < text.length()) && (text.charAt(posicio) == ' ')) {
        posicio++;
    }
    if (posicio >= text.length()) {
        return "";
    }
    int finalLinia = posicio + maxCaracters;
    String linia;
    if (finalLinia >= text.length()) {
        linia = text.substring(posicio);
        posicio = text.length();
    } else {
        String tros = text.substring(posicio, finalLinia + 1);
        int espai = tros.lastIndexOf(' ');
        if (espai > 0) {
            linia = text.substring(posicio, posicio + espai);
            posicio = posicio + espai + 1;
        } else {
            linia = text.substring(posicio, finalLinia);
            posicio = finalLinia;
        }
    }
    linia.trim();
    return linia;}
int mostraPaginaVersicle(String text, int posicioInicial) {
    int posicio = posicioInicial;
    int y = 16;
    ssd1306_clearScreen();
    ssd1306_printFixed(0, 0, ref.c_str(), STYLE_NORMAL);
    for (int i = 0; i < 5; i++) {
        String linia = agafaLinia(text, posicio);
        ssd1306_printFixed(0, y, linia.c_str(), STYLE_NORMAL);
        y += 8;
    }
    return posicio;}
void esperaBotoDret() {
    while (digitalRead(pol_dw)) {
        actualitzaHoraInternet();
        delay(50);
    }
    while (!digitalRead(pol_dw)) {
        delay(50);
    }
}
void mostraVersiclePaginat() {
    int posicioPagina = 0;
    int properaPosicio = mostraPaginaVersicle(versiculo1, posicioPagina);
    while (!digitalRead(pol_ok)) {
        delay(50);
    }
    while (digitalRead(pol_dw)) { 
        actualitzaHoraInternet();
        if (!digitalRead(pol_ok)) {  
            while (!digitalRead(pol_ok)) {
                delay(50);
            }
            if (properaPosicio < versiculo1.length()) {
                posicioPagina = properaPosicio;
            } else {
                posicioPagina = 0;
            }
            properaPosicio = mostraPaginaVersicle(versiculo1, posicioPagina);
        }
        delay(50);
    }
    while (!digitalRead(pol_dw)) {
        delay(50);
    }
}
void calculHora(unsigned long Segs) {
    Segs = Segs % 86400UL;
    hora = Segs / 3600;
    Segs = Segs % 3600;
    minuts = Segs / 60;
    segons = Segs % 60;}
String dosDigitsString(int valor) {
    if (valor < 10) {
        return "0" + String(valor);
    }
    return String(valor);
}
String textHora() {
    if (!horaDisponible) {
        return "--.--";
    }
    unsigned long tempsActual = tempsBaseHora + ((millis() - millisBaseHora) / 1000UL);
    calculHora(tempsActual);
    return dosDigitsString(hora) + "." + dosDigitsString(minuts) ;
}
void demanaHoraInternet() {
    for (int k = 0; k < NTP_PACKET_SIZE; k++) {
        packetBuffer[k] = 0;
    }
    packetBuffer[0] = 0b11100011;
    packetBuffer[1] = 0;
    packetBuffer[2] = 6;
    packetBuffer[3] = 0xEC;
    packetBuffer[12] = 49;
    packetBuffer[13] = 0x4E;
    packetBuffer[14] = 49;
    packetBuffer[15] = 52;
    Serial.println("Enviant petició NTP...");
    Udp.beginPacket(timeServer, 123);
    if (Udp.parsePacket() | ntpyes==true)  {
        Serial.println("Resposta NTP OK");
        jsonyes = false; 
    } else if (ntpyes == false){
        Serial.println("No hi ha resposta NTP");}
        Udp.write(packetBuffer, NTP_PACKET_SIZE);
        Udp.endPacket();
        darreraPeticioHora = millis();
}
void llegeixRespostaHora() {
    if (Udp.parsePacket()) {
        if (ntpyes == false){ 
            Serial.println("?? Resposta NTP rebuda");
            ntpyes = true;
        }
        Udp.read(packetBuffer, NTP_PACKET_SIZE);
        unsigned long Word1 = packetBuffer[40];
        unsigned long Word2 = packetBuffer[41];
        unsigned long Word3 = packetBuffer[42];
        unsigned long Word4 = packetBuffer[43];
        unsigned long Temps1900 = Word1 << 24;
        Temps1900 |= Word2 << 16;
        Temps1900 |= Word3 << 8;
        Temps1900 |= Word4;
        tempsBaseHora = Temps1900 + DESFASAMENT_HORA;
        millisBaseHora = millis();
        horaDisponible = true;
    }
}
void actualitzaHoraInternet() {
    llegeixRespostaHora();
    if (!horaDisponible) {
        if (millis() - darreraPeticioHora > periodeReintentHora) {
            demanaHoraInternet();
        }
    } else if (millis() - darreraPeticioHora > periodeHoraNTP) {
        demanaHoraInternet();
    }
}
void dibuixaHoraMenu() {
    if (!menuPrincipal) {
        return;
    }
    String text = textHora();
    int x = 128 - text.length() * 6;
    ssd1306_printFixed(x, 56, "        ", STYLE_NORMAL);
    ssd1306_printFixed(x, 56, text.c_str(), STYLE_NORMAL);
}
void mostrarMenuPrincipal() {
    menuPrincipal = true;
    ssd1306_showMenu(&menu);
    dibuixaHoraMenu();
}
void actualitzaRellotgeMenu() {
    actualitzaHoraInternet();
    if (!menuPrincipal) {
        return;
    }
    if (!horaDisponible) {
        if (segonMostrat != -2) {
            segonMostrat = -2;
            dibuixaHoraMenu();
        }
        return;
    }
    unsigned long tempsActual = tempsBaseHora + ((millis() - millisBaseHora) / 1000UL);
    int segonActual = tempsActual % 60;
    if (segonActual != segonMostrat) {
        segonMostrat = segonActual;
        dibuixaHoraMenu();
    }
}
String tradueixCel(int codi) {
    if (codi == 0) return "Sol";
    if (codi == 1) return "Poc nuvol";
    if (codi == 2) return "Mig nuvol";
    if (codi == 3) return "Nuvol";
    if (codi == 45 || codi == 48) return "Boira";
    if (codi == 51 || codi == 53 || codi == 55) return "Plugim";
    if (codi == 61 || codi == 63 || codi == 65) return "Pluja";
    if (codi == 66 || codi == 67) return "Pluja gelada";
    if (codi == 71 || codi == 73 || codi == 75) return "Neu";
    if (codi == 77) return "Neu granulada";
    if (codi == 80 || codi == 81 || codi == 82) return "Ruixats";
    if (codi == 95) return "Tempesta";
    if (codi == 96 || codi == 99) return "Tempesta forta";
    return "Desconegut";
}
void mostraDiaClima(int i) {
    ssd1306_clearScreen();
    if (i < 0 || i >= 4) return;
    String linia1 = "Dia: " + climaDia[i];
    String linia2 = "Temp: " + String(climaTemp[i], 1) + " deg. C";
    String linia3 = "Clima: " + climaCelTxt[i];
    String linia4 = "Vent: " + String(climaVent[i], 1) + " km/h";
    printCentrat(8, linia1);
    printCentrat(24, linia2);
    printCentrat(40, linia3);
    printCentrat(56, linia4);
}
void mostraClimaPaginat() {
    indexClima = 0;
    ssd1306_clearScreen();
    mostraDiaClima(indexClima);
    while (!digitalRead(pol_dw)) {
        delay(50);
    }
    bool sortir = false;
    while (!sortir) {
        actualitzaHoraInternet();
        if (!digitalRead(pol_ok)) {
            while (!digitalRead(pol_ok)) delay(50);
            indexClima++;
            if (indexClima >= 4) indexClima = 0;
            ssd1306_clearScreen();
            mostraDiaClima(indexClima);
        }
        if (!digitalRead(pol_dw)) {
            while (!digitalRead(pol_dw)) delay(50);
            sortir = true;
        }
        delay(50);
    }
    while (!digitalRead(pol_dw)) delay(50);
}
void setup() {
    ssd1306_128x64_i2c_init();
    ssd1306_fillScreen(0);
    ssd1306_setFixedFont(ssd1306xled_font6x8);
    pinMode(pol_dw, INPUT_PULLUP); // El polsador és una entrada    
    pinMode(pol_ok, INPUT_PULLUP); // El polsador és una entrada
    pinMode(pol, INPUT_PULLUP); // El polsador és una entrada
    ssd1306_createMenu(&menu, elements, sizeof(elements)/sizeof(elements[0]));
    mostrarMenuPrincipal();
    Serial.begin(9600);    // Monitor sèrie
    pinMode(LEDP, OUTPUT);    // La pota del LED és sortida
    analogWrite(LEDP, 0);    // Comencem amb el LED apagat
    TEXT1[0] = '\0';
    TEXT2[0] = '\0';
    TEXT3[0] = '\0';
    cadena.begin();  // Inicialitza els NeoPixels
    R = 0;
    G = 0;
    B = 0;
    cadena.clear();
    cadena.setPixelColor(0, R, G, B);        
    cadena.show();
    delay(200);
    cadena.setPixelColor(0, 0, 0, 0);
    cadena.show();
    delay(1000);            // Petita pausa per assegurar la transmissió
    if (WiFi.status() == WL_NO_MODULE) {
        Serial.println("No s'ha trobat el dispositiu Wi-Fi");
        while (true);    // Bloquegem el programa
    }
    String versio = WiFi.firmwareVersion();
    if (versio < "1.0.0") {
        Serial.println("Convindria actualitzar el firmware");
    }
    while (status != WL_CONNECTED) {
        Serial.print("Connectant a la xarxa ");
        Serial.println(idXarxa);
        status = WiFi.begin(idXarxa, contrasenya);
        delay(10000);    // Ho tornarem a intentar passats 10 s
    }
    server.begin();    // Posem en marxa el servidor
    Serial.print("Connectat a "); 
    Serial.println(WiFi.SSID());
    Serial.print("Estat de la connexió: ");
    Serial.println(WiFi.status()); 
    Serial.print("Adreça IP del dispositiu: ");
    Serial.println(WiFi.localIP()); 
    Serial.print("Intensitat del senyal: ");
    Serial.print(WiFi.RSSI()); 
    Serial.println(" dBm");
    Serial.println(); 
    Serial.print("Ja pots fer la teva connexió al dispositiu ");
    Serial.println(WiFi.localIP());
    Udp.begin(localPortHora);
    Serial.println("DEBUG 9: UDP iniciat");
    demanaHoraInternet();
    mostrarMenuPrincipal();
}
void loop() {    // Programa que es repeteix indefinidament
    actualitzaRellotgeMenu();
    if (n==0) n = 1;
    if (millis() < 50) {
        cadena.setPixelColor(0, 0,0,0);
        cadena.show();
    }
    if (n==0) {
      delay(200);
      ssd1306_clearScreen();
      mostrarMenuPrincipal();
    }
    if (status != WiFi.status()) {    // Mirem si ha canviat l'estat de la connexió
        status = WiFi.status();
        if (status == WL_AP_CONNECTED) {
            Serial.println("Dispositiu connectat al punt d'accés");
        } else {
            Serial.println("El dispositiu s'ha desconnectat del punt d'accés");
        }
    }
    if (!digitalRead(pol)) {         
        while (!digitalRead(pol)) delay(50);  
        if (opcioWeb == 1) {         
            menuPrincipal = false;
            waitForStart();
            gameLoop(hiScore);
            delay(200);               
            ssd1306_clearScreen();
            mostrarMenuPrincipal();
        } else if (opcioWeb == 2) {   
            tone(3, N_La2, 450);
            delay(450);
            tone(3, N_Si2, 150);
            delay(150);
            tone(3, N_Do3, 900);
            delay(900);
            tone(3, N_Re3, 300);
            delay(300);
            tone(3, N_Si2, 300);
            delay(300);
            tone(3, N_Do3, 300);
            delay(300);
            tone(3, N_La2, 1200);
            delay(1200);
            tone(3, N_Do3, 450);
            delay(450);
            tone(3, N_Re3, 150);
            delay(150);
            tone(3, N_Mi3, 900);
            delay(900);
            tone(3, N_Mi3, 300);
            delay(300);
            tone(3, N_Sol3, 300);
            delay(300);
            tone(3, N_Mi3, 300);
            delay(300);
            tone(3, N_Re3, 600);
            delay(600);
            tone(3, N_Do3, 600);
            delay(600);
        }
        else if (opcioWeb == 3) {
            delay(600);
            tone(3, N_Do4, 300);
            delay(300);
            tone(3, N_LaB4, 300);
            delay(300);
            tone(3, N_LaB4, 300);
            delay(300);
            tone(3, N_Sol4, 1500);
            delay(1500);
            tone(3, N_Re4, 300);
            delay(300);
            tone(3, N_Re4, 300);
            delay(300);
            tone(3, N_Sol4, 300);
            delay(300);
            tone(3, N_Sol4, 1800);
            delay(1800);
            tone(3, N_Re4, 600);
            delay(600);
            tone(3, N_Re4, 300);
            delay(300);
            tone(3, N_Sol4, 1200);
            delay(1200);
            tone(3, N_Re4, 600);
            delay(600);
            tone(3, N_SiB3, 300);
            delay(300);
            tone(3, N_MiB4, 300);
            delay(300);
            tone(3, N_Do4, 1200);
            delay(1200);
            tone(3, N_Do4, 300);
            delay(300);
            tone(3, N_LaB4, 300);
            delay(300);
            tone(3, N_LaB4, 300);
            delay(300);
            tone(3, N_Sol4, 1500);
            delay(1500);
            tone(3, N_Re4, 300);
            delay(300);
            tone(3, N_Re4, 300);
            delay(300);
            tone(3, N_Sol4, 300);
            delay(300);
            tone(3, N_Sol4, 1800);
            delay(1800);
            tone(3, N_Re4, 300);
            delay(300);
            tone(3, N_Re4, 300);
            delay(300);
            tone(3, N_Re4, 300);
            delay(300);
            tone(3, N_Sol4, 1200);
            delay(1200);
            tone(3, N_Re4, 600);
            delay(600);
            tone(3, N_SiB3, 300);
            delay(300);
            tone(3, N_MiB4, 300);
            delay(300);
            tone(3, N_Do4, 1200);
            delay(1200);
            tone(3, N_Do4, 300);
            delay(300);
            tone(3, N_Do5, 300);
            delay(300);
            tone(3, N_Do5, 300);
            delay(300);
            tone(3, N_SiB4, 1500);
            delay(1500);
            tone(3, N_Sol4, 300);
            delay(300);
            tone(3, N_Sol4, 300);
            delay(300);
            tone(3, N_SiB4, 300);
            delay(300);
            tone(3, N_SiB4, 1800);
            delay(1800);
            tone(3, N_Sol4, 300);
            delay(300);
            tone(3, N_Sol4, 300);
            delay(300);
            tone(3, N_Sol4, 300);
            delay(300);
            tone(3, N_MiB5, 1200);
            delay(1200);
            tone(3, N_Re5, 1200);
            delay(1200);
            tone(3, N_Do5, 1200);
            delay(1200);
            tone(3, N_Do4, 300);
            delay(300);
            tone(3, N_Do5, 300);
            delay(300);
            tone(3, N_Do5, 300);
            delay(300);
            tone(3, N_SiB4, 1500);
            delay(1500);
            tone(3, N_Sol4, 300);
            delay(300);
            tone(3, N_Sol4, 300);
            delay(300);
            tone(3, N_SiB4, 300);
            delay(300);
            tone(3, N_SiB4, 1800);
            delay(1800);
            tone(3, N_Sol4, 300);
            delay(300);
            tone(3, N_Sol4, 300);
            delay(300);
            tone(3, N_Sol4, 300);
            delay(300);
            tone(3, N_MiB5, 1200);
            delay(1200);
            tone(3, N_Re5, 1200);
            delay(1200);
            tone(3, N_Do5, 2700);
            delay(300);
        }
    }
    if (!digitalRead(pol_dw)){
        ssd1306_menuDown(&menu);
        mostrarMenuPrincipal();
        while (!digitalRead(pol_dw)){
            ;
        }
    }
    if (!digitalRead(pol_ok)){
        menuPrincipal = false;
        ssd1306_clearScreen();
        printMissatgeCentrat("\n\n");
        if(ssd1306_menuSelection(&menu) == 2){
            if (TEXT1[0] == '\0') {
                printMissatgeCentrat("Recordatori Buit");
                cadena.setPixelColor(0, 125, 0, 0);
                cadena.show();
                tone(3, N_Do3, 300);
                delay(300);
                tone(3, N_SiB2, 300);
                delay(300);
                tone(3, N_Do3, 300);
                delay(300);
                tone(3, N_MiB3, 600);
                delay(600);
                tone(3, N_Sol2, 300);
                delay(300);
                tone(3, N_SiB2, 300);
                delay(300);
                tone(3, N_Do3, 600);
                delay(600);
            } else {
                printMissatgeCentrat(TEXT1);
                cadena.setPixelColor(0, 0, 125, 0);
                cadena.show();
                tone(3, N_SiB3, 300);
                delay(300);
                tone(3, N_La3, 150);
                delay(150);
                tone(3, N_Fa3, 150);
                delay(150);
                tone(3, N_Sol3, 150);
                delay(150);
                tone(3, N_Re4, 150);
                delay(150);
                tone(3, N_Do4, 600);
                delay(600);
                cadena.setPixelColor(0, 0, 0, 0);
                cadena.show();
                esperaBotoDret();
            }
        }
        if (ssd1306_menuSelection(&menu) == 3){
            if (TEXT2[0] == '\0') {
                printMissatgeCentrat("Recordatori Buit");
                cadena.setPixelColor(0, 125, 0, 0);
                cadena.show();
                tone(3, N_Do3, 300);
                delay(300);
                tone(3, N_SiB2, 300);
                delay(300);
                tone(3, N_Do3, 300);
                delay(300);
                tone(3, N_MiB3, 600);
                delay(600);
                tone(3, N_Sol2, 300);
                delay(300);
                tone(3, N_SiB2, 300);
                delay(300);
                tone(3, N_Do3, 600);
                delay(600);
            } else {
                printMissatgeCentrat(TEXT2);
                cadena.setPixelColor(0, 0, 125, 0);
                cadena.show();
                tone(3, N_SiB3, 300);
                delay(300);
                tone(3, N_La3, 150);
                delay(150);
                tone(3, N_Fa3, 150);
                delay(150);
                tone(3, N_Sol3, 150);
                delay(150);
                tone(3, N_Re4, 150);
                delay(150);
                tone(3, N_Do4, 600);
                delay(600);
                cadena.setPixelColor(0, 0, 0, 0);
                cadena.show();
                esperaBotoDret();
            }
        }
        if (ssd1306_menuSelection(&menu) == 4){
            if (TEXT3[0] == '\0') {
                printMissatgeCentrat("Recordatori Buit");
                cadena.setPixelColor(0, 125, 0, 0);
                cadena.show();
                tone(3, N_Do3, 300);
                delay(300);
                tone(3, N_SiB2, 300);
                delay(300);
                tone(3, N_Do3, 300);
                delay(300);
                tone(3, N_MiB3, 600);
                delay(600);
                tone(3, N_Sol2, 300);
                delay(300);
                tone(3, N_SiB2, 300);
                delay(300);
                tone(3, N_Do3, 600);
                delay(600);
            } else {
                printMissatgeCentrat(TEXT3);
                cadena.setPixelColor(0, 0, 125, 0);
                cadena.show();
                tone(3, N_SiB3, 300);
                delay(300);
                tone(3, N_La3, 150);
                delay(150);
                tone(3, N_Fa3, 150);
                delay(150);
                tone(3, N_Sol3, 150);
                delay(150);
                tone(3, N_Re4, 150);
                delay(150);
                tone(3, N_Do4, 600);
                delay(600);
                cadena.setPixelColor(0, 0, 0, 0);
                cadena.show();
                esperaBotoDret();
            }
        }
        if (ssd1306_menuSelection(&menu) == 0){
            if (versiculo1.length() == 0) {
                printMissatgeCentrat("Cap Versicle Rebut");
                cadena.setPixelColor(0, 125, 0, 0);
                cadena.show();
                tone(3, N_Do3, 300);
                delay(300);
                tone(3, N_SiB2, 300);
                delay(300);
                tone(3, N_Do3, 300);
                delay(300);
                tone(3, N_MiB3, 600);
                delay(600);
                tone(3, N_Sol2, 300);
                delay(300);
                tone(3, N_SiB2, 300);
                delay(300);
                tone(3, N_Do3, 600);
                delay(600);
            } else {
                printMissatgeCentrat("Obrint Versicle");
                cadena.setPixelColor(0, 0, 125, 0);
                cadena.show();
                tone(3, N_SiB3, 300);
                delay(300);
                tone(3, N_La3, 150);
                delay(150);
                tone(3, N_Fa3, 150);
                delay(150);
                tone(3, N_Sol3, 150);
                delay(150);
                tone(3, N_Re4, 150);
                delay(150);
                tone(3, N_Do4, 600);
                delay(600);
                cadena.setPixelColor(0, 0, 0, 0);
                cadena.show();
                mostraVersiclePaginat();
            }
        }
        if (ssd1306_menuSelection(&menu) == 1){
            if (!climaDisponible) {
                printMissatgeCentrat("Registre Climatic No Rebut");
                cadena.setPixelColor(0, 125, 0, 0);
                cadena.show();
                tone(3, N_Do3, 300);
                delay(300);
                tone(3, N_SiB2, 300);
                delay(300);
                tone(3, N_Do3, 300);
                delay(300);
                tone(3, N_MiB3, 600);
                delay(600);
                tone(3, N_Sol2, 300);
                delay(300);
                tone(3, N_SiB2, 300);
                delay(300);
                tone(3, N_Do3, 600);
                delay(600);
            } else {
                printMissatgeCentrat("Obrint Registre Climatic");
                cadena.setPixelColor(0, 0, 125, 0);
                cadena.show();
                tone(3, N_SiB3, 300);
                delay(300);
                tone(3, N_La3, 150);
                delay(150);
                tone(3, N_Fa3, 150);
                delay(150);
                tone(3, N_Sol3, 150);
                delay(150);
                tone(3, N_Re4, 150);
                delay(150);
                tone(3, N_Do4, 600);
                delay(600);
                cadena.setPixelColor(0, 0, 0, 0);
                cadena.show();
                mostraClimaPaginat();
            }
        }
        while (!digitalRead(pol_ok)){
            ;
        }
        delay(1000);
        cadena.setPixelColor(0, 0, 0, 0);
        cadena.show();
        ssd1306_clearScreen( );
        mostrarMenuPrincipal();
    }
    delay(500);
    WiFiClient client = server.available();    // Mirem si hi ha clients
    if (client) {                             // Si hi ha un client...
        Serial.println("Nou client");
        String peticio = "";                // Aquí guardarem una línia de la petició del client
        while (client.connected()) {            // Mentre el client estigui connectat
            if (client.available()) {             // Si hi ha dades disponibles
                char c = client.read();             // Llegim un byte
                Serial.write(c);
                if (c == '\n') {                    // Mirem si és un salt de línia
                    if (peticio.length() == 0) {
                        enviar = true;    // Llestos per enviar la resposta
                        break;    // Sortim del while
                    } else {      // Si hem rebut un salt de línia
                        if (peticio.indexOf("GET") != -1) {    // Si no ho troba torna -1
                            if (Dades(peticio, "R") != "") {    // Hi havia el paràmetre R?
                                R = Dades(peticio, "R").toInt();
                            } 
                            if (Dades(peticio, "G") != "") {    // Hi havia el paràmetre G?
                                G = Dades(peticio, "G").toInt();
                            } 
                            if (Dades(peticio, "B") != "") {    // Hi havia el paràmetre B?
                                B = Dades(peticio, "B").toInt();
                            }
                            cadena.setPixelColor(0, R, G, B);
                            cadena.show();
                        }
                        if (peticio.indexOf("GET") != -1) {    // Si no ho troba torna -1
                            if (Dades(peticio, "LED") != "") {    // Hi havia el paràmetre?
                                valorLED = Dades(peticio, "LED").toInt();
                            } 
                            analogWrite(LEDP, valorLED);    // Enviem el valor al LED
                        }
                        if (peticio.indexOf("GET") != -1) {    // Si no ho troba torna -1
                            if (Dades(peticio, "MISSATGE1") != "") {    // Hi havia el paràmetre?
                                if (Dades(peticio, "MISSATGE1") == "Cap" || Dades(peticio, "MISSATGE1") == "cap") {
                                    strcpy(TEXT1, "");
                                } else strcpy(TEXT1, Dades(peticio, "MISSATGE1").c_str());
                            }
                            for (int i = 0; TEXT1[i] != '\0'; i++) {
                                if (TEXT1[i] == '+') TEXT1[i] = ' ';
                            }
                        }
                        if (peticio.indexOf("GET") != -1) {    // Si no ho troba torna -1
                            if (Dades(peticio, "MISSATGE2") != "") {    // Hi havia el paràmetre?
                                if (Dades(peticio, "MISSATGE2") == "Cap" || Dades(peticio, "MISSATGE2") == "cap") {
                                    strcpy(TEXT2, "");
                                } else strcpy(TEXT2, Dades(peticio, "MISSATGE2").c_str());
                            }
                            for (int i = 0; TEXT2[i] != '\0'; i++) {
                                if (TEXT2[i] == '+') TEXT2[i] = ' ';
                            }
                        }
                        if (peticio.indexOf("GET") != -1) {    // Si no ho troba torna -1
                            if (Dades(peticio, "MISSATGE3") != "") {    // Hi havia el paràmetre?
                                if (Dades(peticio, "MISSATGE3") == "Cap" || Dades(peticio, "MISSATGE3") == "cap") {
                                    strcpy(TEXT3, "");
                                } else strcpy(TEXT3, Dades(peticio, "MISSATGE3").c_str());
                            } 
                            for (int i = 0; TEXT3[i] != '\0'; i++) {
                                if (TEXT3[i] == '+') TEXT3[i] = ' ';
                            }
                        }
                        if (peticio.indexOf("GET") != -1) {    // Si no ho troba torna -1
                            if (Dades(peticio, "OPCIO") != "") {
                                opcioWeb = Dades(peticio, "OPCIO").toInt();
                            }
                        }
                        peticio = "";    // Comencem línia amb una línia buida
                    }
                } else if (c != '\r') {    // Si el caràcter no és un retorn
                    peticio += c;      // Afegim el caràcter rebut
                }
            }
        }
        if (enviar) {
            // Resposta al client
            client.println("HTTP/1.1 200 OK");
            client.println();    
            client.println("<!DOCTYPE HTML>");
            client.println("<meta charset='UTF-8'>");
            client.println("<html>");
            client.print("<h1>El LED està a (");                 
            client.print(R);  
            client.print(", ");  
            client.print(G);  
            client.print(", ");  
            client.print(B);  
            client.println(")</h1>");
            client.println("<form action='/' method='get'>");
            client.println("<p>R: <span id='valorR'>");
            client.print(R);
            client.println("</span></p>");
            client.print("<input type='range' id='sliderR' name='R' min='0' max='255' value='");
            client.print(R);
            client.println("' oninput='actualitzaRGB()'>");
            client.println("<p>G: <span id='valorG'>");
            client.print(G);
            client.println("</span></p>");
            client.print("<input type='range' id='sliderG' name='G' min='0' max='255' value='");
            client.print(G);
            client.println("' oninput='actualitzaRGB()'>");
            client.println("<p>B: <span id='valorB'>");
            client.print(B);
            client.println("</span></p>");
            client.print("<input type='range' id='sliderB' name='B' min='0' max='255' value='");
            client.print(B);
            client.println("' oninput='actualitzaRGB()'>");
            client.println("<p>Previsualització:</p>");
            client.println("<div id='preview' style='width:120px;height:120px;border:1px solid black;'></div>");
            client.println("<br>");
            client.println("<input type='submit' value='Enviar RGB'>");
            client.println("</form>");
            client.print("<h1>El LED està a ");                 
            client.print(valorLED);  
            client.println("</h1>");
            client.println("<form action='/' method='get'>");
            client.println("<p></p>");
            client.println("<p></p>");
            client.println("<input type='text' name='LED'>");
            client.println("<p></p>");
            client.println("<p></p>");
            client.print("<h1>VERSICLE: ");
            client.print("<p>");
            if (versiculo1.length() == 0) {
                client.print("Cap versicle rebut");
            } else {
                client.print(versiculo1);
            }
            client.print("<h1>CLIMA D'AVUI: ");
            client.print("<p>");
            if (!climaDisponible) {
                client.print("Cap clima rebut");
            } else {
                client.print(climaDia[0]);
                client.print(" - ");
                client.print(climaTemp[0]);
                client.print("°C - ");
                client.print(climaCelTxt[0]);
                client.print(" - Vent ");
                client.print(climaVent[0]);
                client.print(" km/h");
            }
            client.print("<h1>RECORDATORI 1: ");
            if(TEXT1[0] == '\0') {
                client.print("Cap");
            } else {
                client.print(TEXT1);
            }
            client.println("</h1>");
            client.println("<form action='/' method='get'>");
            client.println("<p></p>");
            client.println("<p></p>");
            client.println("<input type='text' name='MISSATGE1' maxlength='50'>");
            client.print("<h1>RECORDATORI 2: ");
            if(TEXT2[0] == '\0') {
                client.print("Cap");
            } else {
                client.print(TEXT2);
            }
            client.println("</h1>");
            client.println("<form action='/' method='get'>");
            client.println("<p></p>");
            client.println("<p></p>");
            client.println("<input type='text' name='MISSATGE2' maxlength='50'>");
            client.print("<h1>RECORDATORI 3: ");
            if(TEXT3[0] == '\0') {
                client.print("Cap");
            } else {
                client.print(TEXT3);
            }
            client.println("</h1>");
            client.println("<form action='/' method='get'>");
            client.println("<p></p>");
            client.println("<p></p>");
            client.println("<input type='text' name='MISSATGE3' maxlength='50'>");
            client.println("</p>");
            client.print("<h1>OPCIÓ D'ACCIÓ: ");
            if(opcioWeb == 2){
                client.print("Segadors");
            }
            else if(opcioWeb == 3){
                client.print("TITANIUM");
            } else {
                client.print("Cap");
            }
            client.println("</h1>");
            client.println("<form action='/' method='get'>");
            client.println("<p>Escull una opció:</p>");
            client.println("<select name='OPCIO'>");
            client.print("<option value='1'");
            client.print("<option value='2'");
            if(opcioWeb == 2) client.print(" selected");
            client.println(">Segadors</option>");
            client.print("<option value='3'");
            if(opcioWeb == 3) client.print(" selected");
            client.println(">TITANIUM</option>");
            client.println("</select>");
            client.println("<input type='submit'>");
            client.println("</form>");
            client.println("<script>");
            client.println("function actualitzaRGB(){");
            client.println("let r=document.getElementById('sliderR').value;");
            client.println("let g=document.getElementById('sliderG').value;");
            client.println("let b=document.getElementById('sliderB').value;");
            client.println("document.getElementById('valorR').innerHTML=r;");
            client.println("document.getElementById('valorG').innerHTML=g;");
            client.println("document.getElementById('valorB').innerHTML=b;");
            client.println("document.getElementById('preview').style.backgroundColor='rgb('+r+','+g+','+b+')';");
            client.println("}");
            client.println("actualitzaRGB();");
            client.println("</script>");
            client.println("</html>"); 
            delay(1);
            enviar = false;
        }
        client.stop();    // Tanquem la connexió
        Serial.println("Fi de la connexió amb el client");
    }
    if (millis() - darreraConnexio > periodeConnexio) {
        if (jsonyes==false) {
            Serial.println("Fent petició JSON...");
        }
        clientJSON.stop();
        if (faseu == false) {
            server4 = SERVIDOR_VERSICLE;
            pagin = PAGINA_VERSICLE;
        } else {
            server4 = SERVIDOR_CLIMA;
            pagin = PAGINA_CLIMA;
        }
        if (clientJSON.connect(server4, 443)) {
            if (jsonyes == false) {
                Serial.println("S'ha fet la connexió al servidor");
                jsonyes = true;
            }
            clientJSON.print("GET ");
            clientJSON.print(pagin);
            clientJSON.println(" HTTP/1.1");
            clientJSON.print("Host: ");
            clientJSON.println(server4);
            clientJSON.println("Connection: close");
            clientJSON.println();
            darreraConnexio = millis();
        } else {
            Serial.println("Ha fallat la connexió");
        }
    }   
    while (clientJSON.available()) {
        line = clientJSON.readStringUntil('\r');
        if (line.indexOf('{')>=0) {
            if (op==false){
                Serial.println("Tractem les dades");
                op=true;  
            } 
            DynamicJsonDocument json_doc(8000);
            DeserializationError json_error = deserializeJson(json_doc, line);

            if (json_error) {
                if (jsonyes == false) {
                    Serial.println("JSON No Rebut");
                }
            } else if (jsonyes == false) {
                Serial.println("JSON Rebut");
                jsonyes = true;
            } else {
                if (faseu==false){
                    String versiculo = json_doc["text"];
                    String refe = json_doc["ref"];
                    ref = netejaTextWeb(refe);
                    versiculo1 = netejaTextWeb(versiculo);
                    faseu=true;
                    server4 = SERVIDOR_CLIMA;
                    pagin = PAGINA_CLIMA;
                    climaDisponible = true;
                } else {
                    for (int i = 0; i < 4; i++) {
                        String dia = json_doc["daily"]["time"][i] | "";
                        float temperatura = json_doc["daily"]["temperature_2m_max"][i] | 0.0;
                        int codiCel = json_doc["daily"]["weather_code"][i] | -1;
                        float velocitatVent = json_doc["daily"]["wind_speed_10m_max"][i] | 0.0;
                        if (dia.length() >= 10) {
                            dia = dia.substring(5);
                        }
                        climaDia[i] = dia;
                        climaTemp[i] = temperatura;
                        climaCelTxt[i] = tradueixCel(codiCel);
                        climaVent[i] = velocitatVent;
                    }
                    faseu = false;
                    server4 = SERVIDOR_VERSICLE;
                    pagin = PAGINA_VERSICLE;
                } 
            }
        }
    }
}

 

 

Llicència de Creative Commons
Aquesta obra d'Oriol Boix està llicenciada sota una llicència no importada Reconeixement-NoComercial-SenseObraDerivada 3.0.