Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // BSides Fortaleza 2026 — Portal do Crachá
- // Sobe uma rede WiFi própria (AP) com portal cativo e serve, via HTTP,
- // um site estático com a programação do evento, mais uma página de
- // configuração do Wi-Fi / funções dos botões / leitura do sensor SHTC3.
- // WiFi, WebServer, DNSServer e Preferences já vêm no core esp32 (sem
- // libs extras); só o sensor usa uma lib externa (Adafruit SHTC3).
- #include <WiFi.h>
- #include <WebServer.h>
- #include <DNSServer.h>
- #include <Preferences.h>
- #include <Wire.h>
- #include "Adafruit_SHTC3.h"
- #include "webpage.h"
- #include "config_page.h"
- #include "cronograma_img.h"
- #include "source_files.h" // gerado por gen_sources.py a cada build
- // ---- Hardware do crachá (pinos do sketch original example.ino) ----
- #define LED_RED 1
- #define LED_YELLOW 3
- #define LED_GREEN 5
- #define BTN_RED 4
- #define BTN_YELLOW 6
- #define BTN_GREEN 7
- #define BUZZER 11
- Adafruit_SHTC3 shtc3 = Adafruit_SHTC3();
- bool sensorOk = false;
- bool lastRed = HIGH, lastYellow = HIGH, lastGreen = HIGH;
- // ---- Config persistida em NVS (Preferences) ----
- // PLACA_NUM é injetado no build por `make upload PLACA=N` (ver Makefile).
- // Sem PLACA, o SSID padrão fica sem sufixo, igual antes.
- #ifndef PLACA_NUM
- #define PLACA_NUM 0
- #endif
- #define _STR(x) #x
- #define _XSTR(x) _STR(x)
- #if PLACA_NUM > 0
- const char* DEFAULT_SSID = "BSides Fortaleza 2026_" _XSTR(PLACA_NUM);
- #else
- const char* DEFAULT_SSID = "BSides Fortaleza 2026";
- #endif
- const char* DEFAULT_PASSWORD = ""; // "" = rede aberta
- Preferences prefs;
- String cfgSsid, cfgPass, cfgLblRed, cfgLblYellow, cfgLblGreen;
- const IPAddress AP_IP(192, 168, 4, 1);
- const IPAddress AP_GATEWAY(192, 168, 4, 1);
- const IPAddress AP_SUBNET(255, 255, 255, 0);
- const byte DNS_PORT = 53;
- DNSServer dnsServer;
- WebServer server(80);
- // ---------------- config: load / save / apply ----------------
- void loadConfig() {
- prefs.begin("badge", true);
- cfgSsid = prefs.getString("ssid", DEFAULT_SSID);
- cfgPass = prefs.getString("pass", DEFAULT_PASSWORD);
- cfgLblRed = prefs.getString("lblRed", "Vermelho");
- cfgLblYellow = prefs.getString("lblYellow", "Amarelo");
- cfgLblGreen = prefs.getString("lblGreen", "Verde");
- prefs.end();
- }
- void saveConfig() {
- prefs.begin("badge", false);
- prefs.putString("ssid", cfgSsid);
- prefs.putString("pass", cfgPass);
- prefs.putString("lblRed", cfgLblRed);
- prefs.putString("lblYellow", cfgLblYellow);
- prefs.putString("lblGreen", cfgLblGreen);
- prefs.end();
- }
- void applyAP() {
- WiFi.softAPdisconnect(true);
- delay(100);
- WiFi.softAPConfig(AP_IP, AP_GATEWAY, AP_SUBNET);
- if (cfgPass.length() > 0) {
- WiFi.softAP(cfgSsid.c_str(), cfgPass.c_str(), 1, 0, 8);
- } else {
- WiFi.softAP(cfgSsid.c_str(), nullptr, 1, 0, 8);
- }
- Serial.println("AP -> SSID: " + cfgSsid + (cfgPass.length() ? " (com senha)" : " (aberta)"));
- Serial.println("IP: " + WiFi.softAPIP().toString());
- }
- String jsonEscape(const String &s) {
- String out;
- out.reserve(s.length() + 4);
- for (size_t i = 0; i < s.length(); i++) {
- char c = s[i];
- if (c == '"' || c == '\\') out += '\\';
- out += c;
- }
- return out;
- }
- // ---------------- rotas HTTP ----------------
- void handleRoot() {
- server.send_P(200, "text/html", INDEX_HTML);
- }
- void handleConfigPage() {
- server.send_P(200, "text/html", CONFIG_HTML);
- }
- void handleDownloadIno() {
- server.sendHeader("Content-Disposition", "attachment; filename=\"code2026.ino\"");
- server.send_P(200, "text/plain", SRC_INO);
- }
- void handleDownloadWebpageH() {
- server.sendHeader("Content-Disposition", "attachment; filename=\"webpage.h\"");
- server.send_P(200, "text/plain", SRC_WEBPAGE_H);
- }
- void handleDownloadConfigH() {
- server.sendHeader("Content-Disposition", "attachment; filename=\"config_page.h\"");
- server.send_P(200, "text/plain", SRC_CONFIG_H);
- }
- void handleImage() {
- server.send_P(200, "image/jpeg", (PGM_P)CRONOGRAMA_JPG, CRONOGRAMA_JPG_LEN);
- }
- void handleApiConfigGet() {
- String json = "{";
- json += "\"ssid\":\"" + jsonEscape(cfgSsid) + "\",";
- json += "\"pass\":\"" + jsonEscape(cfgPass) + "\",";
- json += "\"lblRed\":\"" + jsonEscape(cfgLblRed) + "\",";
- json += "\"lblYellow\":\"" + jsonEscape(cfgLblYellow) + "\",";
- json += "\"lblGreen\":\"" + jsonEscape(cfgLblGreen) + "\"";
- json += "}";
- server.send(200, "application/json", json);
- }
- void handleApiConfigPost() {
- bool wantsApplyAP = false;
- if (server.hasArg("ssid")) {
- String newSsid = server.arg("ssid");
- newSsid.trim();
- if (newSsid.length() == 0) {
- server.send(400, "application/json", "{\"ok\":false,\"error\":\"SSID nao pode ser vazio\"}");
- return;
- }
- String newPass = server.hasArg("pass") ? server.arg("pass") : "";
- if (newPass.length() > 0 && newPass.length() < 8) {
- server.send(400, "application/json", "{\"ok\":false,\"error\":\"Senha precisa ter 8+ caracteres, ou vazia p/ rede aberta\"}");
- return;
- }
- cfgSsid = newSsid;
- cfgPass = newPass;
- wantsApplyAP = true;
- }
- if (server.hasArg("lblRed")) cfgLblRed = server.arg("lblRed");
- if (server.hasArg("lblYellow")) cfgLblYellow = server.arg("lblYellow");
- if (server.hasArg("lblGreen")) cfgLblGreen = server.arg("lblGreen");
- saveConfig();
- server.send(200, "application/json", "{\"ok\":true}");
- if (wantsApplyAP) {
- delay(300); // dá tempo da resposta HTTP sair antes de trocar de rede
- applyAP();
- }
- }
- void handleApiSensor() {
- String json;
- if (sensorOk) {
- sensors_event_t humidity, temp;
- if (shtc3.getEvent(&humidity, &temp)) {
- json = "{\"ok\":true,\"temp\":" + String(temp.temperature, 1) +
- ",\"hum\":" + String(humidity.relative_humidity, 1) + "}";
- } else {
- json = "{\"ok\":false}";
- }
- } else {
- json = "{\"ok\":false}";
- }
- server.send(200, "application/json", json);
- }
- // Qualquer host/caminho desconhecido volta pra home — é isso que faz o
- // celular detectar portal cativo e abrir a página sozinho.
- void handleNotFound() {
- server.sendHeader("Location", String("http://") + AP_IP.toString() + "/", true);
- server.send(302, "text/plain", "");
- }
- // ---------------- botões / LEDs / buzzer ----------------
- void beep(int ledPin, int vezes) {
- for (int i = 0; i < vezes; i++) {
- digitalWrite(ledPin, HIGH);
- tone(BUZZER, 2000);
- delay(100);
- digitalWrite(ledPin, LOW);
- noTone(BUZZER);
- delay(100);
- }
- }
- void pollButtons() {
- bool red = digitalRead(BTN_RED);
- bool yellow = digitalRead(BTN_YELLOW);
- bool green = digitalRead(BTN_GREEN);
- if (red == LOW && lastRed == HIGH) {
- delay(30);
- beep(LED_RED, 3);
- }
- if (yellow == LOW && lastYellow == HIGH) {
- delay(30);
- beep(LED_YELLOW, 2);
- }
- if (green == LOW && lastGreen == HIGH) {
- delay(30);
- beep(LED_GREEN, 1);
- }
- lastRed = red;
- lastYellow = yellow;
- lastGreen = green;
- }
- // ---------------- setup / loop ----------------
- void setup() {
- Serial.begin(115200);
- delay(200);
- pinMode(LED_RED, OUTPUT);
- pinMode(LED_YELLOW, OUTPUT);
- pinMode(LED_GREEN, OUTPUT);
- pinMode(BUZZER, OUTPUT);
- pinMode(BTN_RED, INPUT);
- pinMode(BTN_YELLOW, INPUT);
- pinMode(BTN_GREEN, INPUT);
- sensorOk = shtc3.begin();
- Serial.println(sensorOk ? "Sensor SHTC3 encontrado" : "Sensor SHTC3 nao encontrado");
- loadConfig();
- WiFi.mode(WIFI_AP);
- applyAP();
- dnsServer.start(DNS_PORT, "*", AP_IP);
- server.on("/", handleRoot);
- server.on("/config", handleConfigPage);
- server.on("/cronograma.jpg", handleImage);
- server.on("/api/config", HTTP_GET, handleApiConfigGet);
- server.on("/api/config", HTTP_POST, handleApiConfigPost);
- server.on("/api/sensor", HTTP_GET, handleApiSensor);
- server.on("/download/code2026.ino", handleDownloadIno);
- server.on("/download/webpage.h", handleDownloadWebpageH);
- server.on("/download/config_page.h", handleDownloadConfigH);
- // Endpoints de detecção de portal cativo dos principais sistemas.
- server.on("/generate_204", handleRoot); // Android
- server.on("/gen_204", handleRoot);
- server.on("/hotspot-detect.html", handleRoot); // iOS / macOS
- server.on("/library/test/success.html", handleRoot);
- server.on("/ncsi.txt", handleRoot); // Windows
- server.on("/connecttest.txt", handleRoot);
- server.onNotFound(handleNotFound);
- server.begin();
- Serial.println("=================================");
- Serial.print("SSID: "); Serial.println(cfgSsid);
- Serial.print("IP: "); Serial.println(WiFi.softAPIP());
- Serial.println("=================================");
- }
- void loop() {
- dnsServer.processNextRequest();
- server.handleClient();
- pollButtons();
- }
Advertisement
Add Comment
Please, Sign In to add comment