132 lines
2.9 KiB
YAML
132 lines
2.9 KiB
YAML
substitutions:
|
|
device_name: fdm-exhaust-fan-control
|
|
friendly_name: "FDM Exhaust Fan Control"
|
|
|
|
esphome:
|
|
name: ${device_name}
|
|
friendly_name: ${friendly_name}
|
|
|
|
esp32:
|
|
board: seeed_xiao_esp32c3
|
|
framework:
|
|
type: esp-idf
|
|
|
|
# Enable logging
|
|
logger:
|
|
|
|
# Enable Home Assistant API
|
|
api:
|
|
encryption:
|
|
key: !secret api_encryption_key
|
|
|
|
ota:
|
|
- platform: esphome
|
|
password: !secret ota_password
|
|
|
|
wifi:
|
|
ssid: !secret wifi_iot_ssid
|
|
password: !secret wifi_password
|
|
manual_ip:
|
|
static_ip: 192.168.69.110
|
|
gateway: 192.168.69.1
|
|
subnet: 255.255.255.0
|
|
ap:
|
|
ssid: "${friendly_name} Fallback"
|
|
password: !secret fallback_password
|
|
|
|
# Prevents aggressive reconnection attempts
|
|
power_save_mode: none # Use 'light' for battery devices
|
|
|
|
# Slower but more reliable connection
|
|
fast_connect: true
|
|
|
|
# Handle connection failures gracefully
|
|
on_connect:
|
|
- logger.log: "Wi-Fi connected!"
|
|
on_disconnect:
|
|
- logger.log: "Wi-Fi disconnected!"
|
|
|
|
# Reduce mDNS traffic
|
|
mdns:
|
|
disabled: true # Set to true if you use static IPs and don't need discovery
|
|
|
|
captive_portal:
|
|
web_server:
|
|
port: 80
|
|
|
|
# GPIO Outputs for fan control
|
|
# IMPORTANT: inverted: true because NPN transistor driver inverts the logic
|
|
# GPIO HIGH -> NPN ON -> Gate LOW -> Fan OFF
|
|
# GPIO LOW -> NPN OFF -> Gate HIGH (5V via pull-up) -> Fan ON
|
|
output:
|
|
- platform: gpio
|
|
pin:
|
|
number: GPIO3 # D1 on XIAO
|
|
inverted: true
|
|
id: fan_80mm_output
|
|
|
|
- platform: gpio
|
|
pin:
|
|
number: GPIO4 # D2 on XIAO
|
|
inverted: true
|
|
id: fan_120mm_output
|
|
|
|
# Fan entities for Home Assistant
|
|
fan:
|
|
- platform: binary
|
|
name: "80mm Exhaust Fan"
|
|
id: fan_80mm
|
|
output: fan_80mm_output
|
|
|
|
- platform: binary
|
|
name: "120mm Exhaust Fan"
|
|
id: fan_120mm
|
|
output: fan_120mm_output
|
|
|
|
# Optional: Add a switch to control both fans together
|
|
switch:
|
|
- platform: template
|
|
name: "All Fans"
|
|
id: all_fans
|
|
turn_on_action:
|
|
- fan.turn_on: fan_80mm
|
|
- fan.turn_on: fan_120mm
|
|
turn_off_action:
|
|
- fan.turn_off: fan_80mm
|
|
- fan.turn_off: fan_120mm
|
|
lambda: |-
|
|
return id(fan_80mm).state && id(fan_120mm).state;
|
|
|
|
# Diagnostic sensors
|
|
sensor:
|
|
- platform: wifi_signal
|
|
name: "${device_name} WiFi Signal"
|
|
update_interval: 60s
|
|
|
|
- platform: uptime
|
|
name: "${device_name} Uptime"
|
|
update_interval: 60s
|
|
|
|
text_sensor:
|
|
- platform: wifi_info
|
|
ip_address:
|
|
name: "${device_name} IP Address"
|
|
ssid:
|
|
name: "${device_name} Connected SSID"
|
|
bssid:
|
|
name: "${device_name} BSSID"
|
|
|
|
# Watchdog to auto-reboot if things go wrong
|
|
interval:
|
|
- interval: 5min
|
|
then:
|
|
- if:
|
|
condition:
|
|
and:
|
|
- lambda: 'return millis() > 300000;' # >5 min uptime
|
|
- not:
|
|
wifi.connected:
|
|
then:
|
|
- logger.log: "Wi-Fi not connected for 5 min, rebooting..."
|
|
- delay: 10s
|
|
- lambda: 'App.safe_reboot();' |