Relay 5V control+Butto

Relay 5V control+Butto

Esphome Relay 5V control+ButtoRelay_Video

############## https://github.com/esphome/esphome-flasher/releases ###############################
################################################################################################
# 4 路繼電器控制系統 - 完整範例(含逐項詳細註解)
# 說明:
#  - 本檔整合:按鍵 (4)、4 路繼電器、每路開機預設 (select)、全開/全關 switch、
#    WiFi 自動重連機制、WiFi 訊號與 uptime 顯示等。
#  - 註解以中文為主,盡量逐行說明用途與注意事項,方便維護。
################################################################################################
# substitutions:可重複使用變數設定
# 用途:避免在檔案多處重複寫同一字串,維護更容易(改一次全域生效)
# 範例:若要更改設備名稱,只需修改此處 device_name 即可
################################################################################################
substitutions:
  device_name: relay-control-system  # 設備名稱(會用在 entity name、AP SSID 等)
################################################################################################
# esphome:ESPHome 主節點設定
# - name: 裝置內部識別名稱(不可含空白或特殊字元)
# - friendly_name: 顯示於 Home Assistant 的友好名稱(可含空白)
# - on_boot: 開機時要執行的動作,這裡我們依照 select 的設定決定每一路 relay 的開機行為
################################################################################################
esphome:
  name: ${device_name}                          # 裝置內部識別名稱(在 ESPHome UI 與網路上使用)
  friendly_name: 4路按鍵開關切換relay           # 在 Home Assistant 中顯示的名稱(友好名稱)
  name_add_mac_suffix: true
################################################################################################
  # on_boot:設備上電或軟體重啟時會執行
  # priority:執行優先權,數值越高代表越晚執行(確保其他元件先初始化)
  # then:執行內容,這裡使用 lambda(C++)直接存取 select 與 switch 的 state
  on_boot:
    priority: 300  # 建議 200~300,確保 sensor / switch 基本初始化完成
    then:
      - lambda: |-
          // apply_default: 小工具函式,用來判斷 select 的 state,並對應操作 relay
          // 備註:select 的 state 會是 "ON"、"OFF" 或 "RESTORE"(字串)
          auto apply_default = [](const std::string &state, auto relay_id) {
            // 如果 state == "ON",則強制打開該繼電器
            if (state == "ON") relay_id->turn_on();
            // 如果 state == "OFF",則強制關閉該繼電器
            else if (state == "OFF") relay_id->turn_off();
            // 如果 state == "RESTORE",什麼也不做(保持繼電器自己 restore 的狀態)
          };
          // 依序將 select 狀態套用到四個 relay 上
          apply_default(id(default_relay_state1).state, id(relay1));
          apply_default(id(default_relay_state2).state, id(relay2));
          apply_default(id(default_relay_state3).state, id(relay3));
          apply_default(id(default_relay_state4).state, id(relay4));
################################################################################################
# esp8266:指定硬體平台與板型
# board: d1_mini 表示使用 Wemos D1 mini(常見 ESP8266 開發板)
# framework.version: 使用哪個核心框架版本,使用 latest 可取得 ESPHome 內建可用版本
################################################################################################
esp8266:
  board: d1_mini            # 開發板型
  framework:
    version: latest        # 使用最新可用的 arduino/esp8266 框架(依 ESPHome 版本而定)
################################################################################################
# wifi:Wi-Fi 設定
# - ssid / password:連線資訊(建議透過 secrets.yaml 儲存)
# - fast_connect:若使用固定 SSID,可加快連線速度(跳過 AP 掃描)
# - reboot_timeout:若連不上網路,等待多少時間後自動重啟(此處設定 120s)
# - ap:若連不上 Wi-Fi,會啟用臨時 AP(可用於初次設定或修復)
################################################################################################
wifi:
#  ssid: !secret wifi_ssid            # 建議把敏感資訊放 secrets.yaml
#  password: !secret wifi_password
#  fast_connect: true                 # 若使用固定 router,建議啟用
#  reboot_timeout: 120s               # 若 Wi-Fi 連線失敗,等待多少秒後自動重啟(可防止卡住)
################################################################################################  
  ap:
    ssid: "${device_name}_AP"        # 當主 Wi-Fi 失敗時,會開一個 AP(Wi-Fi 名稱)
    password: !secret ap_password   # AP 密碼(至少 8 字元)
    ap_timeout: 120s                # AP 模式持續時間(超時後再嘗試連線主網路)
################################################################################################
# logger:日誌設定
# - level:日誌等級(NONE/ERROR/WARN/INFO/DEBUG/VERBOSE)
# - baud_rate:序列埠速度,若使用 RX/D1 等腳位作為按鍵,建議關閉序列(baud_rate: 0)
################################################################################################
logger:    # level #選項控制日誌詳細程度,可選值:
  level: WARN  # 輸出警告和錯誤
#  level: DEBUG   #調試資訊詳細輸出
#  level: NONE     #- 不輸出任何日誌
#  level: ERROR    #- 只輸出錯誤訊息
#  level: INFO     #- 輸出常規訊息(預設)
#  level: DEBUG    #- 輸出詳細訊息,包含內部狀態
#  level: VERBOSE  #- 輸出最詳細訊息,包含所有事件、感測器值變化、內部處理細節
  baud_rate: 0     # 設為 0 會禁用 UART,避免與 RX 腳衝突(若使用 RX 讀按鍵很重要)
################################################################################################
# api:ESPHome 與 Home Assistant 的通訊設定
# - reboot_timeout: 若 API 斷線需要多久沒恢復就觸發重啟(0 表示不自動重啟)
################################################################################################
api:
  reboot_timeout: 0s   # API 斷線不自動重啟(由 wifi 自動重連機制處理)
################################################################################################
# ota、web_server、time、captive_portal:額外服務
# - ota: 支援 Over-the-air 更新
# - web_server: 提供內建 HTTP 管理頁面(可查看 logs)
# - time: 同步 Home Assistant 的時間(用於時間相關 automations)
# - captive_portal: 當 AP 啟用時提供簡易設定頁面
################################################################################################
ota:
  - platform: esphome    # 支援原生 OTA 更新
################################################################################################
web_server:
  port: 80               # Web 管理頁面(瀏覽器開啟裝置 IP 即可)
################################################################################################
time:
  - platform: homeassistant  # 使用 Home Assistant 的時間作為時間來源
    id: esptime
################################################################################################
captive_portal:            # 啟用 captive portal(AP 模式下會導向設定頁)
################################################################################################
# globals:全域變數設定
# - 可用來在 lambda 與條件中保存跨週期的狀態
# - restore_value: 是否在重啟時保留該值(yes/no)
################################################################################################
globals:
  - id: wifi_disconnected_secs    # 用來記錄 Wi-Fi 斷線累積秒數
    type: int
    restore_value: no            # 重啟後不保留(通常為 0)
    initial_value: '0'           # 初始值為 0(字串或數字皆可)
################################################################################################
# number:可在 Home Assistant 中顯示並修改的數字(範例:WiFi 重連超時)
# - 此處定義了 wifi_reconnect_timeout(秒數)
# - on_value: 當數值改變時要執行的動作(此處重置 wifi_disconnected_secs 並記 log)
################################################################################################
number:
  - platform: template
    name: "WiFi Reconnect Timeout"    # 在 HA 顯示的名稱
    id: wifi_reconnect_timeout
    unit_of_measurement: "s"          # 單位:秒
    min_value: 60                     # 最小值(1 分鐘)
    max_value: 3600                   # 最大值(1 小時)
    step: 10                          # 調整步階
    restore_value: true               # 重啟後保留使用者選擇
    initial_value: 300                # 初始預設 300 秒(5 分鐘)
    optimistic: true                  # 變更後立刻在 HA 顯示(不需等待 ESP 回報)
    on_value:
      then:
        - logger.log:
            format: "Reconnect timeout changed to %.0f seconds. Resetting disconnect counter."
            args: [x]
        - globals.set:
            id: wifi_disconnected_secs
            value: '0'               # 當使用者更改超時值時,重置計時器
################################################################################################
# binary_sensor:實體按鍵(GPIO)與狀態監控(status)
# - 每個按鍵使用 INPUT_PULLUP 與 inverted: true(常態為 HIGH,按下變 LOW)
# - filters: delayed_on / delayed_off 用於去抖(Debounce)
# - on_press: 按下時會 toggle 對應的 template switch(fakebuttonX)
################################################################################################
binary_sensor:
  - platform: gpio
    id: button1
    name: "Button1_Red"
    icon: "mdi:button-pointer"                 # 這裡可以換成任何 MDI 圖示
    pin:
      number: GPIO5                        # D1(實際接到繼電器模組的輸出腳)
      mode: INPUT_PULLUP # 啟用內部上拉電阻,按鍵接地時會被偵測到
      inverted: true     # 反相:按下為 true(active)
    filters:
      - delayed_on: 50ms  # 防抖:按下有效需持續 50ms
      - delayed_off: 50ms # 防抖:放開有效需持續 50 ms
    on_press:
      - switch.toggle: fakebutton1   # 切換 template switch(會由 template switch 發動真實 relay)
#-----------------------------------------------------------------------------------------------
  - platform: gpio
    id: button2
    name: "Button2_Blue"
    icon: "mdi:button-pointer"                 # 這裡可以換成任何 MDI 圖示    
    pin:
      number: GPIO4                        # D2
      mode: INPUT_PULLUP
      inverted: true
    filters:
      - delayed_on: 50ms
      - delayed_off: 50ms
    on_press:
      - switch.toggle: fakebutton2
#-----------------------------------------------------------------------------------------------
  - platform: gpio
    id: button3
    name: "Button3_Green"
    icon: "mdi:button-pointer"                 # 這裡可以換成任何 MDI 圖示    
    pin:
      number: GPIO0                        # D3(注意:部分板子此腳位在啟動時影響引導模式,請確認接法)
      mode: INPUT_PULLUP
      inverted: true
    filters:
      - delayed_on: 50ms
      - delayed_off: 50ms
    on_press:
      - switch.toggle: fakebutton3
#-----------------------------------------------------------------------------------------------
  - platform: gpio
    id: button4
    name: "Button4_Yellow"
    icon: "mdi:button-pointer"                 # 這裡可以換成任何 MDI 圖示    
    pin:
      number: GPIO2                        # D4(注意:部分板子此腳位在啟動時影響引導模式,請確認接法)
      mode: INPUT_PULLUP
      inverted: true
    filters:
      - delayed_on: 50ms
      - delayed_off: 50ms
    on_press:
      - switch.toggle: fakebutton4
################################################################################################
# status binary_sensor:告訴 Home Assistant 裝置是否 online(內建)
  - platform: status
    name: "${device_name} WiFi Status"   # 若裝置離線,HA 會顯示為 unavailable
##########################################################
################################################################################################
         #$$$$$$$$$$$$$  此版本使用高電平觸發繼電器  $$$$$$$$$$$$$$$
# switch:各類開關定義
# - 我們使用 template switch 作為「邏輯層」(供 UI / 按鍵切換)
# - gpio switch 為實際驅動繼電器的硬體層
# - 每個 gpio switch 使用 restore_mode 保留上次狀態(若需要)
# - 另外新增:WiFi Auto Reconnect、All ON、All OFF 等輔助開關
################################################################################################
switch:
  # WiFi 自動重連開關(控制是否啟用自動重啟行為)
  - platform: template
    name: "WiFi Auto Reconnect"
    id: wifi_auto_reconnect
    optimistic: true                # 在 HA UI 上立刻顯示切換結果(不等待 ESP 回報)
    restore_mode: RESTORE_DEFAULT_ON  # 裝置重啟後此開關預設為 ON(可改)
  ##################################################################
  # Relay 1:template switch (fakebutton1) + gpio switch (relay1)
  # - template switch 供按鍵與 HA 控制,並回傳實體狀態(lambda)
  # - gpio switch 為真實驅動腳位,inverted: true 表示繼電器為低電位觸發(common for relay modules)
  # @@@@@@@“Relay只能定義D5-D8,不能定義D1-D4,因為D3與D4板子此腳位在啟動時影響引導模式會當掉
  # https://esphome.io/components/binary_sensor/index.html#binary-sensor-automation
  ##################################################################
  - platform: template
    id: fakebutton1                  # template switch 的 id(內部參考用)
    name: "Relay1_Red"               # 在 Home Assistant 顯示的名稱
    icon: "mdi:power"                # 這裡可以換成任何 MDI 圖示
    lambda: |-
      return id(relay1).state;       // 讀取實體 relay 的狀態並回傳(同步 UI)
    turn_on_action:
      - switch.turn_on: relay1       #  // template switch turn_on 時觸發 gpio relay1 on
    turn_off_action:
      - switch.turn_off: relay1     
#-----------------------------------------------------------------------------------------------
  - platform: gpio
    pin: GPIO14     # D5(Wemos D1 mini 腳位編號)
    id: relay1
    inverted: false                   # 若你的繼電器為低電位觸發(常見),保留 true;若高電位觸發改為 false
    restore_mode: RESTORE_DEFAULT_OFF # 裝置重啟時繼電器預設 (若沒有 select 指定 RESTORE) → 可為 OFF 或 ON
  ##################################################################
  # Relay 2
  ##################################################################
  - platform: template
    id: fakebutton2                   # template switch 的 id(內部參考用)
    name: "Relay2_Blue"               # 在 Home Assistant 顯示的名稱
    icon: "mdi:power"                 # 這裡可以換成任何 MDI 圖示
    lambda: |-
      return id(relay2).state;      // 讀取實體 relay 的狀態並回傳(同步 UI)
    turn_on_action:
      - switch.turn_on: relay2
    turn_off_action:
      - switch.turn_off: relay2
#-----------------------------------------------------------------------------------------------
  - platform: gpio
    pin: GPIO12     # D6
    id: relay2
    inverted: false
    restore_mode: RESTORE_DEFAULT_OFF
  ##################################################################
  # Relay 3
  ##################################################################
  - platform: template
    id: fakebutton3            # template switch 的 id(內部參考用)
    name: "Relay3_Green"       # 在 Home Assistant 顯示的名稱
    icon: "mdi:power"          # 這裡可以換成任何 MDI 圖示
    lambda: |-
      return id(relay3).state;      // 讀取實體 relay 的狀態並回傳(同步 UI)
    turn_on_action:
      - switch.turn_on: relay3
    turn_off_action:
      - switch.turn_off: relay3
#-----------------------------------------------------------------------------------------------
  - platform: gpio
    pin: GPIO15     # D7
    id: relay3
    inverted: false
    restore_mode: RESTORE_DEFAULT_OFF
  ##################################################################
  # Relay 4
  ##################################################################
  - platform: template
    id: fakebutton4            # template switch 的 id(內部參考用)
    name: "Relay4_Yellow"      # 在 Home Assistant 顯示的名稱       
    icon: "mdi:power"          # 這裡可以換成任何 MDI 圖示
    lambda: |-
      return id(relay4).state;      // 讀取實體 relay 的狀態並回傳(同步 UI)
    turn_on_action:
      - switch.turn_on: relay4
    turn_off_action:
      - switch.turn_off: relay4
#-----------------------------------------------------------------------------------------------
  - platform: gpio
    pin: GPIO13     # D8
    id: relay4
    inverted: false
    restore_mode: RESTORE_DEFAULT_OFF
  ##################################################################
  # All Relays ON(全開)
  # - template switch,按下後依序打開所有 relay
  # - 可搭配 Home Assistant 的 automation 或用於 UI 的快速按鍵
  ##################################################################
  - platform: template
    id: all_on
    name: "All Relays ON"
    icon: "mdi:power-plug"
    turn_on_action:
      - switch.turn_on: relay1
      - switch.turn_on: relay2
      - switch.turn_on: relay3
      - switch.turn_on: relay4
  ##################################################################
  # All Relays OFF(全關)
  # - template switch,按下後依序關閉所有 relay
  ##################################################################
  - platform: template
    id: all_off
    name: "All Relays OFF"
    icon: "mdi:power-plug-off"
    turn_on_action:
      - switch.turn_off: relay1
      - switch.turn_off: relay2
      - switch.turn_off: relay3
      - switch.turn_off: relay4
################################################################################################
# select:每個繼電器的開機預設狀態(ON / OFF / RESTORE)
# - restore_value: true 表示在設備重啟時記住使用者上次在 HA UI 選的選項
# - initial_option: 初次 flash 時的預設值(建議設為 RESTORE,使系統保持上次實際狀態)
# - 在 on_boot 中,會讀取此 select 的狀態並執行相對應動作(see above on_boot)
################################################################################################
select:
  - platform: template
    name: "${device_name} Default Relay State1"
    id: default_relay_state1
    optimistic: true
    restore_value: true
    options: ["ON", "OFF", "RESTORE"]  # 三個選項
    initial_option: "RESTORE"          # 初次上傳時預設為 RESTORE(保持目前繼電器的 restore 狀態]
#-----------------------------------------------------------------------------------------------
  - platform: template
    name: "${device_name} Default Relay State2"
    id: default_relay_state2
    optimistic: true
    restore_value: true
    options: ["ON", "OFF", "RESTORE"]
    initial_option: "RESTORE"
#-----------------------------------------------------------------------------------------------
  - platform: template
    name: "${device_name} Default Relay State3"
    id: default_relay_state3
    optimistic: true
    restore_value: true
    options: ["ON", "OFF", "RESTORE"]
    initial_option: "RESTORE"
#-----------------------------------------------------------------------------------------------
  - platform: template
    name: "${device_name} Default Relay State4"
    id: default_relay_state4
    optimistic: true
    restore_value: true
    options: ["ON", "OFF", "RESTORE"]
    initial_option: "RESTORE"
################################################################################################
# sensor:各種監控感測器(WiFi 訊號、uptime、WiFi 重連倒數)
# - wifi_signal: 直接回傳 RSSI(dBm),template sensor 將其轉換為百分比顯示
################################################################################################
sensor:
  ##################################################################
  # WiFi 訊號(原始 RSSI)
  # - id: wifi_1 用於其他 template sensor 參考
  ##################################################################
  - platform: wifi_signal
    id: wifi_1
    update_interval: 60s
  ##################################################################
  # Wifi signal(百分比顯示)
  # - 由 wifi_1 的 dBm 值換算為百分比
  # - 公式為二次多項式近似,僅供參考
  ##################################################################
  - platform: template
    name: "${device_name} Wifi signal"
    unit_of_measurement: '%'
    accuracy_decimals: 0
    icon: "mdi:wifi"
    lambda: |-
      if (id(wifi_1).state >= -50.0)
        return 100.0;
      else if (id(wifi_1).state <= -100.0)
        return 0.0;
      else
        return (2 * (id(wifi_1).state + 100));
    update_interval: 60s
  ##################################################################
  # Uptime(系統上線時間)
  # - 若想以秒為單位可改設定;此處預設回傳小時數
  ##################################################################
  - platform: uptime
    name: "${device_name} Uptime"
  ##################################################################
  # WiFi Reconnect Countdown(倒數秒數)
  # - 顯示距離自動重啟還剩多少秒(以 wifi_reconnect_timeout 與 wifi_disconnected_secs 計算)
  ##################################################################
  - platform: template
    name: "WiFi Reconnect Countdown"
    id: wifi_reconnect_countdown
    unit_of_measurement: "s"
    accuracy_decimals: 0
    lambda: |-
      int remaining = (int)id(wifi_reconnect_timeout).state - id(wifi_disconnected_secs);
      if (remaining < 0) remaining = 0;
      return remaining;
    update_interval: 10s
################################################################################################
# button:軟體按鍵(例如 restart)
# - platform: restart:會觸發 ESP 重啟(可由 automation 或 interval 呼叫)
################################################################################################
button:
  - platform: restart
    name: "Restart Button"
    id: restart_button   # 可在 automations 或 lambda 中以 button.press 呼叫以重啟裝置
################################################################################################
# text_sensor:顯示文字資訊(WiFi IP、SSID、MAC、ESPHome 版本)
# - platform: wifi_info 與 platform: version 皆為流程內建選項
################################################################################################
text_sensor:        
  - platform: wifi_info
    ip_address:
      name: "${device_name} IP Address"
      icon: "mdi:ip-network"
    ssid:
      name: "${device_name} Connected SSID"
      icon: "mdi:signal-variant"
    mac_address:
      name: "${device_name} MAC Address"
      icon: "mdi:wifi-marker"
################################################################################################
  - platform: version
    name: "ESPHome Version"

################################################################################################
# interval:週期性任務(用於 WiFi 自動重連邏輯)
# - 我們每 30s 檢查一次 wifi.connected
# - 若未連線,則累加 wifi_disconnected_secs
# - 若累計超過 wifi_reconnect_timeout 且 wifi_auto_reconnect 開啟,則觸發 restart_button(軟體重啟)
################################################################################################
interval:
  - interval: 30s
    then:
      - if:
          condition:
            wifi.connected
          then:
            # WiFi 正常:重置斷線計時器
            - globals.set:
                id: wifi_disconnected_secs
                value: '0'
          else:
            # WiFi 不連線:累計斷線秒數
            - lambda: |-
                id(wifi_disconnected_secs) += 30;
            # 若開啟自動重連且超時,則紀錄 log、重啟設備(透過 button.press)
            - if:
                condition:
                  and:
                    - switch.is_on: wifi_auto_reconnect
                    - lambda: 'return id(wifi_disconnected_secs) >= (int)id(wifi_reconnect_timeout).state;'
                then:
                  - logger.log: "WiFi disconnected too long, restarting..."
                  - globals.set:
                      id: wifi_disconnected_secs
                      value: '0'
                  - button.press: restart_button
################################################################################################
# 額外提示與注意事項(非 YAML 內容)
# 1. 引導腳位 (GPIO0, GPIO2, GPIO15 等) 在某些開發板會影響啟動模式,若繼電器接法會改變 boot 行為,
#    請在硬體接線上特別注意:避免在開機時有拉到錯誤電位。
# 2. 若使用 RX (GPIO3) 做按鍵,必須關閉 UART(baud_rate: 0),否則可能干擾序列輸出。
# 3. restore_mode: RESTORE_DEFAULT_OFF 表示若無其他恢復機制,重啟預設關閉,可視需求改為 RESTORE_DEFAULT_ON。
# 4. 若不使用 DHT22,可刪除 sensor: dht 那段以節省資源。
# 5. 若希望按鍵支援長按做「全開/全關」,我可以把 long_press or on_multi_click 加到 binary_sensor 的 on_press 中,
#    例如 on_multi_click 或 on_long_press 可觸發 all_on / all_off。
################################################################################################