ESP8266 ve Servo Motor ile Akıllı Sunucu Güç Tetikleyicisi (Home Assistant) Akıllı Parmak
📌 Projenin Amacı
Kişisel sunucumuz (eski bir laptop vb.) elektrik kesintilerinde veya işletim sistemi (HAOS) çöktüğünde fiziksel bir müdahaleye ihtiyaç duyar. Bu proje; bir ESP8266 (NodeMCU) ve SG90 Servo Motor kullanarak bilgisayarın güç tuşuna fiziksel olarak basan, ancak bunu yaparken yanlış alarmları ve gereksiz yeniden başlatmaları (reboot loop) önlemek için akıllı ağ kontrolleri yapan bir sistemdir.
🚀 Öne Çıkan Özellikler (Neden Akıllı?)
- Çift Katmanlı Durum Kontrolü: Sadece Home Assistant arayüzünü (8123) değil, donanım katmanını da (Observer - 4357) denetler. Arayüz çökse bile sunucu fiziksel olarak çalışıyorsa körleme tuşa basmaz.
- Yedekli Ağ (Fallback) Sistemi: Sunucunun Ethernet (Kablolu) bağlantısı kopsa bile, Wi-Fi IP'si üzerinden ikincil bir ping atar. Ağlardan birinden cevap gelirse tetiklemeyi iptal eder.
- Soğuk Başlangıç ve Modem Koruması: Elektrik kesintisi sonrası sistem geri geldiğinde, modemin internete bağlanması ve sunucunun boot edilmesi için 5 dakika (300 saniye) sabırla bekler, gereksiz panik yapmaz.
- 24 Saatlik Bakım Modu: Fiziksel sunucu bakımı yaparken sistemin tuşa basmasını ve Telegram'a mesaj atmasını tek tuşla 24 saatliğine (veya manuel kapatana kadar) donduran entegre anahtar.
- Akıllı Telegram Bildirimleri: Manuel tetiklemelerde mesaj atarak rahatsızlık vermez. Sadece sistem kritik bir kararla otomatik müdahale yaptığında veya elektrik gidip/geldiğinde haber verir.
🛠️ Kullanılan Donanımlar
- Mikrodenetleyici: NodeMCU V2 (ESP8266)
- Motor: SG90 Servo Motor (D2 pinine bağlı)
- Sunucu: Hometech Alfa 400C Laptop (veya herhangi bir PC)
- Montaj: 3M VHB Akrilik Çift Taraflı Bant (Motoru kasaya sabitlemek için en güvenli yöntem) (Ama ben japonla yapıştırdım kemik gibi)
⚙️ Fiziksel Kurulum ve Kalibrasyon İpuçları
Servo motoru bilgisayara yapıştırmadan önce sıfır noktasını doğru ayarlamak çok önemlidir:
1. ESPHome kodunu karta yükleyin ve karta elektrik verin. Motor -1.0 (bekleme) konumuna gelip kilitlenecektir.
2. Elektriği kesin ve servo motorun ucundaki beyaz plastik kolu çıkartın.
3. Plastik kolu, güç tuşunun sadece 2-3 milimetre üzerinde havada kalacak şekilde dişliye tekrar takın.
4. Çift taraflı bandı kullanarak servoyu kasaya sabitleyin.
5. (Eğer basma kuvveti çok/az gelirse kod içerisindeki level: -0.7 değerini 0.0 ile -1.0 arasında değiştirerek hassas ayar yapabilirsiniz.)
💻 ESPHome Kodunun Tamamı (YAML)
[!info] Not Kodu kopyalamadan önce
192.168.1.110(Ethernet) ve192.168.1.149(Wi-Fi) IP adreslerini ile Telegram Bot bilgilerinizi kendi sisteminize göre güncellemeyi unutmayın.
esphome:
name: sunucu-tetikleyici
friendly_name: sunucu-tetikleyici
on_boot:
priority: -100
then:
- wait_until:
wifi.connected
- servo.write:
id: guc_servosu
level: -1.0
# Elektrik kesintisi sonrası modemin ve HAOS'un toparlanması için 5 dakika bekle
- delay: 5min
- script.execute: sunucu_kontrol
esp8266:
board: nodemcuv2
logger:
api:
encryption:
key: "KENDI_API_SIFRENIZ"
ota:
- platform: esphome
wifi:
ssid: !secret wifi_ssid
password: !secret wifi_password
ap:
ssid: "sunucu-tetikleyici"
password: "AP_SIFRENIZ"
web_server:
port: 80
http_request:
id: telegram_istegi
verify_ssl: false
timeout: 5s
globals:
- id: sunucu_core_erisilebilir
type: bool
restore_value: no
initial_value: "true"
- id: sunucu_donanim_erisilebilir
type: bool
restore_value: no
initial_value: "true"
- id: otomatik_kilit
type: bool
restore_value: no
initial_value: "false"
- id: bakim_modu
type: bool
restore_value: no
initial_value: "false"
# Durum Hafızası: 0=İlk Açılış, 1=Sorunsuz, 2=Sadece Donanım Var, 3=Tamamen Kapalı
- id: sistem_durumu
type: int
restore_value: no
initial_value: "0"
output:
- platform: esp8266_pwm
id: pwm_output
pin: D2
frequency: 50 Hz
servo:
- id: guc_servosu
output: pwm_output
switch:
- platform: template
name: "Bakim Modu (24 Saat)"
id: bakim_modu_anahtari
icon: mdi:tools
optimistic: true
lambda: |-
return id(bakim_modu);
turn_on_action:
- lambda: 'id(bakim_modu) = true;'
- script.execute:
id: telegram_gonder
mesaj: "🛠️ Bakım Modu AKTİF. 24 saat boyunca otomatik takipler ve tetiklemeler tamamen durduruldu."
- script.execute: bakim_modu_zamanlayici
turn_off_action:
- lambda: 'id(bakim_modu) = false;'
- script.stop: bakim_modu_zamanlayici
- script.execute:
id: telegram_gonder
mesaj: "✅ Bakım Modu KAPATILDI. Sistem takibi tekrar devrede."
- script.execute: sunucu_kontrol
button:
- platform: template
name: "Sistemi Baslat (1 sn)"
icon: mdi:power
on_press:
- servo.write:
id: guc_servosu
level: -0.7
- delay: 1s
- servo.write:
id: guc_servosu
level: -1.0
- platform: template
name: "Uzun Bas (3 sn)"
icon: mdi:power-sleep
on_press:
- servo.write:
id: guc_servosu
level: -0.7
- delay: 3s
- servo.write:
id: guc_servosu
level: -1.0
- platform: template
name: "Zorla Kapat (10 sn)"
icon: mdi:power-plug-off
on_press:
- servo.write:
id: guc_servosu
level: -0.7
- delay: 10s
- servo.write:
id: guc_servosu
level: -1.0
script:
- id: telegram_gonder
parameters:
mesaj: string
then:
- http_request.post:
url: "[https://api.telegram.org/botTOKEN/sendMessage](https://api.telegram.org/botTOKEN/sendMessage)"
request_headers:
Content-Type: "application/json"
body: !lambda |-
return "{\"chat_id\": \"KENDI_CHAT_ID_NIZ\", \"text\": \"" + mesaj + "\"}";
- id: bakim_modu_zamanlayici
mode: restart
then:
- delay: 24h
- switch.turn_off: bakim_modu_anahtari
- id: kilit_ac
then:
- delay: 15min
- lambda: 'id(otomatik_kilit) = false;'
- id: servo_bas
mode: single
then:
- lambda: 'id(otomatik_kilit) = true;'
- script.execute:
id: telegram_gonder
mesaj: "🟠 Sunucu iki ağda da erişilemiyor ve süre doldu. Açma işlemi başlatılıyor."
- servo.write:
id: guc_servosu
level: -0.7
- delay: 1s
- servo.write:
id: guc_servosu
level: -1.0
- script.execute: kilit_ac
- id: sunucu_kontrol
mode: single
then:
- if:
condition:
lambda: 'return !id(bakim_modu);'
then:
# 1. Donanım Katmanı (HA Observer) Kontrolü (Ethernet)
- http_request.get:
url: "[http://192.168.1.110:4357](http://192.168.1.110:4357)"
on_response:
then:
- lambda: 'id(sunucu_donanim_erisilebilir) = true;'
on_error:
then:
- lambda: 'id(sunucu_donanim_erisilebilir) = false;'
- delay: 2s
# 1.1 Eğer Ethernet (110) cevap vermezse Wi-Fi (149) dene
- if:
condition:
lambda: 'return !id(sunucu_donanim_erisilebilir);'
then:
- http_request.get:
url: "[http://192.168.1.149:4357](http://192.168.1.149:4357)"
on_response:
then:
- lambda: 'id(sunucu_donanim_erisilebilir) = true;'
on_error:
then:
- lambda: 'id(sunucu_donanim_erisilebilir) = false;'
- delay: 2s
# 2. Yazılım Katmanı (HA Core) Kontrolü (Ethernet)
- http_request.get:
url: "[http://192.168.1.110:8123](http://192.168.1.110:8123)"
on_response:
then:
- lambda: 'id(sunucu_core_erisilebilir) = true;'
on_error:
then:
- lambda: 'id(sunucu_core_erisilebilir) = false;'
- delay: 2s
# 2.1 Eğer Ethernet (110) cevap vermezse Wi-Fi (149) dene
- if:
condition:
lambda: 'return !id(sunucu_core_erisilebilir);'
then:
- http_request.get:
url: "[http://192.168.1.149:8123](http://192.168.1.149:8123)"
on_response:
then:
- lambda: 'id(sunucu_core_erisilebilir) = true;'
on_error:
then:
- lambda: 'id(sunucu_core_erisilebilir) = false;'
- delay: 2s
# ANALİZ VE KARAR
- if:
condition:
lambda: 'return id(sunucu_core_erisilebilir);'
then:
# Her Şey Yolunda
- if:
condition:
lambda: 'return id(sistem_durumu) != 1;'
then:
- if:
condition:
lambda: 'return id(sistem_durumu) == 0;'
then:
- script.execute:
id: telegram_gonder
mesaj: "⚡ Elektrik/Sistem devreye girdi. 5 dakikalık test süresi bitti, sunucu aktif olarak izleniyor."
else:
- script.execute:
id: telegram_gonder
mesaj: "🔵 Sunucu tekrar erişilebilir oldu. Sistem normale döndü."
- lambda: 'id(sistem_durumu) = 1;'
else:
- if:
condition:
lambda: 'return id(sunucu_donanim_erisilebilir);'
then:
# Makine Açık, Arayüz Çökmüş
- if:
condition:
lambda: 'return id(sistem_durumu) != 2;'
then:
- script.execute:
id: telegram_gonder
mesaj: "🟣 Kritik Uyarı: HAOS arayüzüne ulaşılamıyor ancak sunucu donanımı çalışıyor. Otomatik müdahale yapılmıyor."
- lambda: 'id(sistem_durumu) = 2;'
else:
# Tamamen Kapalı veya Yeniden Başlıyor veya Modem Gitti
- if:
condition:
lambda: 'return id(sistem_durumu) != 3;'
then:
- script.execute:
id: telegram_gonder
mesaj: "🟡 Sunucuya ulaşılamıyor. Sunucu kapalı veya modem yeniden başlıyor olabilir. 5 dakika (300 sn) beklenecek."
- lambda: 'id(sistem_durumu) = 3;'
- if:
condition:
lambda: 'return !id(otomatik_kilit);'
then:
- delay: 300s
# 300 Saniye Sonrası Son Ethernet (110) Kontrolü
- http_request.get:
url: "[http://192.168.1.110:4357](http://192.168.1.110:4357)"
on_response:
then:
- lambda: 'id(sunucu_donanim_erisilebilir) = true;'
on_error:
then:
- lambda: 'id(sunucu_donanim_erisilebilir) = false;'
- delay: 2s
# 300 Saniye Sonrası Son Wi-Fi (149) Kontrolü
- if:
condition:
lambda: 'return !id(sunucu_donanim_erisilebilir);