ESP32 Projeleri
#19İleri

WebSocket ile Çoklu İstemci Senkronize Canlı Kontrol Paneli

~2 saatWebSocket kavramına temel aşinalık

Proje Amacı

Birden fazla tarayıcının aynı anda açık kalıcı bir WebSocket bağlantısıyla bir RGB LED'in rengini canlı kontrol edip, bir istemcideki değişikliğin tüm diğer istemcilerde anında (polling olmadan) görünmesini sağlamayı öğretir. ESP32'nin ikinci çekirdeği, her biri açık kalan onlarca WebSocket bağlantısını sensör okuma döngüsünü hiç bloklamadan yönetebilecek yeterli RAM ve async ağ yığınına sahiptir. Bu eşzamanlı bağlantı yönetimi Arduino Uno'da kurulamaz: WiFi donanımı yoktur; olsaydı bile kalıcı, çift yönlü (full-duplex) birden fazla soket bağlantısını aynı anda açık tutmak 2KB RAM'i fazlasıyla aşar.

Gerekli Malzemeler

  • ESP32 DevKit V1 (38 pin)
  • RGB LED (ortak katot)
  • 3x 330Ω direnç
  • Breadboard
  • Jumper kablolar

Gerekli Kütüphaneler

ESPAsyncWebServer + AsyncTCP (me-no-dev, GitHub'dan zip kurulum — bkz. proje #06). AsyncWebSocket sınıfı ESPAsyncWebServer paketiyle birlikte gelir, ayrı kurulum gerekmez.

Pin Bağlantıları

Bileşen PiniBağlantı
RGB LED Kırmızı (330Ω üzerinden)
GPIO4
RGB LED Yeşil (330Ω üzerinden)
GPIO16
RGB LED Mavi (330Ω üzerinden)
GPIO17
RGB LED Katot (ortak)
GND

Devre Şeması

ESP32 Kodu

esp32-19-websocket-ile-coklu-istemci-senkronize-canli-kontrol-paneli.ino
1#include <WiFi.h>
2#include <ESPAsyncWebServer.h>
3#include <AsyncWebSocket.h>
4
5const char* ssid = "WIFI_ADINIZ";
6const char* password = "WIFI_SIFRENIZ";
7const int PIN_R = 4, PIN_G = 16, PIN_B = 17;
8
9AsyncWebServer server(80);
10AsyncWebSocket soket("/ws");
11
12const char anaSayfaHtml[] PROGMEM = R"HTML(
13<!DOCTYPE html><html><body style="font-family:sans-serif;text-align:center;padding-top:30px">
14<h2>Canlı RGB Kontrol Paneli</h2>
15<input type="color" id="renk" value="#00d4ff" style="width:120px;height:60px">
16<script>
17 var ws = new WebSocket('ws://' + location.host + '/ws');
18 document.getElementById('renk').oninput = function(e) {
19 ws.send(e.target.value); // örn: "#ff0000"
20 };
21 ws.onmessage = function(e) {
22 document.getElementById('renk').value = e.data; // başka istemciden gelen değişikliği yansıt
23 };
24</script></body></html>
25)HTML";
26
27void renkUygula(String hex) {
28 long deger = strtol(hex.substring(1).c_str(), NULL, 16);
29 int kirmizi = (deger >> 16) & 0xFF, yesil = (deger >> 8) & 0xFF, mavi = deger & 0xFF;
30 analogWrite(PIN_R, kirmizi); // ESP32 core >= 3.0'da analogWrite PWM'i otomatik yönetir
31 analogWrite(PIN_G, yesil);
32 analogWrite(PIN_B, mavi);
33}
34
35void soketOlay(AsyncWebSocket* sunucu, AsyncWebSocketClient* istemci, AwsEventType tur,
36 void* arg, uint8_t* veri, size_t uzunluk) {
37 if (tur == WS_EVT_DATA) {
38 String hex = String((char*)veri).substring(0, uzunluk);
39 renkUygula(hex);
40 // KRİTİK: gelen değişikliği GÖNDEREN HARİÇ tüm diğer istemcilere anında
41 // yay — senkronizasyonun kalbi burasıdır.
42 sunucu->textAll(hex);
43 }
44}
45
46void setup() {
47 Serial.begin(115200);
48 pinMode(PIN_R, OUTPUT); pinMode(PIN_G, OUTPUT); pinMode(PIN_B, OUTPUT);
49
50 WiFi.begin(ssid, password);
51 while (WiFi.status() != WL_CONNECTED) { delay(400); Serial.print("."); }
52 Serial.println("\nBağlandı: " + WiFi.localIP().toString());
53
54 soket.onEvent(soketOlay);
55 server.addHandler(&soket);
56 server.on("/", [](AsyncWebServerRequest* istek) {
57 istek->send_P(200, "text/html", anaSayfaHtml);
58 });
59 server.begin();
60}
61
62void loop() {
63 soket.cleanupClients(); // kopan bağlantıları düzenli temizler, bellek sızıntısını önler
64 delay(1000);
65}

Çalışma Açıklaması

soket.cleanupClients() düzenli çağrılmazsa, tarayıcı sekmesi kapatılıp da düzgün 'disconnect' göndermeyen istemcilerin bıraktığı bağlantı nesneleri bellekte birikip zamanla cihazı yavaşlatabilir veya çökertebilir. sunucu->textAll(hex) ile tüm istemcilere (gönderen dahil) yayın yapan bu basit yaklaşım tercih edilmiştir çünkü tarayıcı zaten kendi input değerini biliyor, kendine geri gelen mesaj bir sorun yaratmaz.

Test Bilgisi

Kodu yükleyin, IP adresini tarayıcıda açın (birden fazla sekmede veya farklı cihazlarda). Bir sekmedeki renk seçiciyi değiştirin; RGB LED anında değişmeli ve açık olan diğer tüm sekmelerdeki renk seçici de otomatik güncellenmeli — bu, klasik 'sayfayı yenile' (polling) yaklaşımından temel farkıdır ve birden fazla cihazla test edildiğinde çok daha etkileyici gözlemlenir.

Olası Sorunlar ve Çözümleri

WebSocket bağlantısı hiç kurulamıyorsa (tarayıcı konsolunda hata): 'ws://' önekinin (wss:// değil, bu proje TLS kullanmıyor) doğru yazıldığından ve location.host'un doğru IP:port ürettiğinden emin olun. Renk değişimi gecikmeli veya takılarak geliyorsa: aynı anda çok fazla istemci bağlıysa (10'dan fazla) ESP32'nin RAM'i zorlanabilir, gerçekçi bir üst sınır (örn. 5-6 istemci) koyun. analogWrite derleme hatası veriyorsa: kullandığınız ESP32 Arduino core sürümünü kontrol edin (core >= 3.0'da yerleşiktir, daha eski sürümlerde ledcWrite + ledcAttachPin API'si kullanılmalıdır).

Alternatif Çözümler

Renk yayınına ek olarak bir 'canlı sıcaklık grafiği' yayınlanarak sensör verisi de tüm istemcilere anlık push edilebilir. Kimlik doğrulama olmadan herkesin kontrol edebildiği bu basit modele, bağlantı anında bir token veya parola kontrolü eklenerek yetkisiz erişim engellenebilir. textAll yerine binary WebSocket mesajları kullanılarak (örn. RGB için 3 byte) veri boyutu ve gecikme daha da azaltılabilir.

Bu projenin kodunu AI ile özelleştir

Farklı pin, ek özellik ya da başka bir sensör mü istiyorsun?

Benzer Projeler

İleri

FreeRTOS Dual-Core Görev Paylaşımlı Veri Toplama

xTaskCreatePinnedToCore() ile iki farklı sensör okuma görevini ESP32'nin iki fiziksel çekirdeğine (Core 0 ve Core 1) sabitleyerek tamamen paralel çalıştırmayı öğretir — biri yavaş ve bloklayıcı DHT22'yi okurken diğeri hızlı analog LDR okumaya kesintisiz devam eder, ikisi birbirini beklemez. ESP32, iki bağımsız Xtensa LX6 çekirdeğine sahiptir; Arduino sketch'i normalde sadece Core 1'de çalışır, Core 0 ise bilinçli olarak görev atanarak devreye alınabilir. Bu paralellik Arduino Uno'da kurulamaz: ATmega328P tek çekirdekli 8-bit bir mikrodenetleyicidir, ikinci bir çekirdeğe görev atamak donanımsal olarak mümkün değildir ve kart FreeRTOS gibi bir RTOS da çalıştıramaz.

İleri

ESPAsyncWebServer ile Bloklamayan Çoklu İstemci REST API

Birden fazla tarayıcı veya istemcinin aynı anda, birbirini bloklamadan bağlanıp iki rölenin durumunu okuyup değiştirebildiği asenkron (event-driven) bir REST API sunmayı öğretir — akıllı ev panelleri ve endüstriyel kontrol arayüzlerinde tercih edilen mimarinin küçük ölçekli bir örneğidir. ESPAsyncWebServer, gelen her isteği ayrı ayrı bekletmeden (non-blocking) LwIP ağ yığınıyla doğrudan çalışır; bunun için ESP32'nin ikinci çekirdeği ve yeterli RAM'i (520KB SRAM) devreye girer. Bu mimari Arduino Uno'da kurulamaz: WiFi donanımı yoktur; harici bir WiFi shield eklense bile klasik senkron 'WiFiServer' modeli her isteği sırayla işler ve 2KB RAM, birden fazla eşzamanlı bağlantı arabelleğini aynı anda tutmaya yetmez.

İleri

Şifreli BLE ile Kimlik Doğrulamalı Akıllı Kilit

BLE (Bluetooth Low Energy) bonding/pairing ile bir telefonun kimliğini bir kez eşleştirip, sonraki bağlantılarda ESP32'nin donanımsal AES şifrelemesiyle korunan bir kanaldan 'kilidi aç' komutunu doğrulamayı ve bir servo ile fiziksel kilidi açmayı öğretir. ESP32'nin dahili BLE radyosu, Secure Connections (LE Secure Connections) ile şifreli eşleştirme yapabilecek donanımsal kripto desteğine sahiptir. Bu güvenlik düzeyi Arduino Uno'da kurulamaz: kart hiçbir Bluetooth radyosu (Classic veya BLE) içermez ve kripto hızlandırma donanımı da yoktur; harici bir BLE modülü (HM-10 gibi) eklense bile bu modüller genelde bonding/güvenli eşleştirmeyi tam desteklemez.