/*
websocket(pred mDNS):
let ws = new WebSocket("ws://ip:port/");
ws.onopen = () => console.log("Připojeno k ESP32 WebSocket");
ws.onmessage = (msg) => console.log("Lux:", msg.data);
ws.onclose = () => console.log("Odpojeno");
+ mDNS
+ wifi manager
*/
#include <Wire.h> // pro I2C komunikaci s BH1750
#include <BH1750.h> // knihovna pro BH1750 senzor
#include <WiFi.h> // Wi-Fi funkcionalita ESP32
#include <WiFiManager.h> // WiFiManager – konfigurace Wi-Fi přes AP
#include <ESPmDNS.h> // mDNS – umožní přístup přes "esp32.local"
#include <WebSocketsServer.h> // WebSocket server pro komunikaci s dashboardem
#include <SPI.h> // pro SPI komunikaci s SD kartou
#include <SD.h> // knihovna pro SD kartu
#include <time.h> // knihovna pro čas
#define LED_BUILTIN 2 // vestavěná LED ESP32 (většinou pin 2)
#define WSS_PORT 81 // port WebSocket serveru
#define READ_SPD 200 // rychlost čtení senzoru (ms)
#define SD_CS 5 // pin pro SD CS
#define CSV_FILE "/lux_data.csv" // soubor pro zápis dat
BH1750 lightMeter; // BH1750 senzor
WiFiManager wifiManager; // WiFiManager pro dynamické nastavení Wi-Fi
WebSocketsServer webSocket = WebSocketsServer(WSS_PORT); // WebSocket server
File dataFile; // soubor pro zápis dat
bool sdReady = false; // stav SD karty
// callback při připojení/odpojení WebSocket klienta
void webSocketEvent(uint8_t num, WStype_t type, uint8_t * payload, size_t length) {
if(type == WStype_CONNECTED){
Serial.printf("WebSocket klient připojen: %u\n", num);
}
else if(type == WStype_DISCONNECTED){
Serial.printf("WebSocket klient odpojen: %u\n", num);
}
}
void setup() {
// wifiManager.resetSettings(); // testovani nove site (SMAZAT)
// ESP.restart(); // taky SMAZAT
Serial.begin(115200);
Wire.begin(21, 22); // inicializace I2C (SDA/SCL default 21/22)
pinMode(LED_BUILTIN, OUTPUT);
// inicializace BH1750
if(lightMeter.begin(BH1750::CONTINUOUS_HIGH_RES_MODE, 0x5C)){
Serial.println("BH1750 inicializován");
} else {
Serial.println("ERROR: Nelze najít BH1750");
}
// pokus o připojení k ulozene Wi-Fi nebo spuštění AP
if (wifiManager.autoConnect("ESP32_BH1750_AP")) {
digitalWrite(LED_BUILTIN, HIGH);
Serial.print("Připojeno k Wi-Fi, IP: ");
Serial.println(WiFi.localIP());
} else {
Serial.println("ERROR: Nepodařilo se připojit k Wi-Fi");
}
// inicializace mDNS (umožní přístup k ESP32 přes "esp32.local")
if (MDNS.begin("esp32")) {
Serial.println("mDNS server běží: esp32.local");
} else {
Serial.println("ERROR: mDNS se nespustil");
}
// inicializace WebSocket serveru
webSocket.begin();
webSocket.onEvent(webSocketEvent);
Serial.print("WebSocket server běží, port: ");
Serial.println(WSS_PORT);
// inicializace SD karty
if (SD.begin(SD_CS)) {
Serial.println("SD karta OK");
sdReady = true;
if (!SD.exists(CSV_FILE)) { // vytvorneni souboru pro zapis, pokud neexistuje
dataFile = SD.open(CSV_FILE, FILE_WRITE);
if (dataFile) {
dataFile.println("Datum,Čas,Lux");
dataFile.close();
Serial.println("CSV hlavička vytvořena");
}
}
} else {
Serial.println("ERROR: SD karta nenalezena");
}
}
void loop() {
// obsluha WebSocket serveru
webSocket.loop();
// odesílání a zápis dat z BH1750 podle READ_SPD
static unsigned long lastSend = 0;
if(millis() - lastSend > READ_SPD){
lastSend = millis();
float lux = lightMeter.readLightLevel(); // čtení intenzity světla
if(lux < 0) lux = 0; // kontrola chybového čtení
String message = String(lux, 2); // převod na String s 2 desetinnými místy
webSocket.broadcastTXT(message); // odeslání všem WebSocket klientům
Serial.println("Odesláno lux: " + message);
// aktualni cas
struct tm timeinfo;
getLocalTime(&timeinfo);
char dateStr[11];
char timeStr[9];
strftime(dateStr, sizeof(dateStr), "%d/%m/%Y", &timeinfo); // formát: DD/MM/YYYY
strftime(timeStr, sizeof(timeStr), "%H:%M:%S", &timeinfo); // formát: HH:MM:SS
// zapis na sd
if (sdReady) {
dataFile = SD.open(CSV_FILE, FILE_APPEND);
if (dataFile) {
dataFile.print(dateStr);
dataFile.print(",");
dataFile.print(timeStr);
dataFile.print(",");
dataFile.println(String(lux, 2));
dataFile.close();
}
}
// debug
Serial.printf("%s %s → %.2f lux\n", dateStr, timeStr, lux);
}
}