家庭自动化 / 家庭设备发布 内容更新

做一个桌面实体按钮:单击与长按切换 Home Assistant 场景

完整ESPHome按钮与HA演示包:区分短按/长按,离线本地提示,不把重启恢复状态当按键事件。

读完能做什么
把短按与长按分别转为HA事件及两个可见演示场景,能按本地计数、事件、Trace与helper逐层验收。
开始之前
已完成H01与F07,会核对GPIO5按钮、GPIO4限流LED和HA配置备份。
所需器材
DevKitC-1 v1.1 N8R8、USB数据线、常开按钮、面包板、导线、WP7113ID红LED、330Ω±5% 0.25W电阻、已有HA,使用包内helper与两个演示scene
版本组合
参考板:官方ESP32-S3-DevKitC-1 v1.1 / WROOM-1-N8R8ESPHome / Python:2026.9.1 / 3.12.13,macOS arm64实际环境设备框架:原生ESP-IDF toolchain / 5.5.5HA资料:Core2026.10.2,未在真实HA执行
适用范围

GPIO5常开按钮、GPIO4外接红LED;ESPHome2026.9.1/IDF5.5.5;HA事件/场景按Core2026.10.2源码核查,未运行。

这篇验证到了哪一步

资料核对已通过
docs/esp32-evidence/home-assistant-expanded.md验证日期:
构建 / 配置已通过
docs/esp32-evidence/home-expanded-builds.json:实际config/compile Exit0;HA与实板仍待验证对象:esp32-s3-devkitc-1 / ESP32S3 / 8MB Flash + OPI PSRAM版本:ESPHome2026.9.1 / Python3.12.13 / ESP-IDF5.5.5验证日期:
仿真不适用
未运行器件或HA仿真
本站实板待验证
未有本站指定实板/HA/无线或OLED运行记录,构建不替代物理验收

构建通过只说明指定环境中的代码或配置通过检查;实物功能、功耗和稳定性以对应的实板记录为准。

01 / 家庭设备

先用HA自己的helper验证场景链

按键事件、自动化匹配与场景执行是不同步骤。为避免需要先购买智能灯,本包创建input_boolean.hixinwu_h04_demo,两个演示场景把它设on/off;先完成可见基线,再替换成你的真实场景。

设备不会在本地直接驱动家里的场景实体。它识别手势并发事件,HA完成自动化与scene.turn_on;本站没有HA实际运行结果,下面每个检查点均需执行后记录。

参考:[3] HA Core2026.10.2:ESPHome管理器/事件处理[7] HA:Packages配置与合并规则[8] HA:场景定义与scene.turn_on[9] HA:事件触发器

02 / 家庭设备

GPIO5输入,GPIO4只作本地提示

断电接GPIO5/J1-5→常开按钮→GND,内部上拉,按下LOW。四脚按钮先断电确认按下才导通的两组;GPIO4/J1-4经330Ω接WP7113ID阳极、阴极回GND。只用桥USB供电,板载GPIO38 RGB不参与。

LED一闪表示本地走到了事件发送路径,三闪表示没有API状态订阅客户端。本灯不是HA执行回执,也没有实体场景光学反馈。

参考:[2] DevKitC-1 v1.1固定提交927ed7e:排针与USB[10] Kingbright WP7113ID V.14A

03 / 家庭设备

短按与长按互斥,留出无动作区

30ms双边滤波后,短按ON50–400ms并OFF至少250ms触发single;长按达到800ms即触发一次long,按住不重复,释放不补single。超过400但未达800ms不匹配;本例没有双击,短按之间建议释放至少约0.5秒。

trigger_on_initial_state=false跳过初态,HA自动化监听新事件而非计数初值或状态恢复。重启计数归零不是一次手势;按住按钮上电也必须实际验证不会发事件。 HA演示helper的initial=false会在HA重启时设默认值,这也不是场景触发;误触发需看事件与Trace。

参考:[4] ESPHome2026.9.1:binary_sensor timing与初始触发[5] ESPHome2026.9.1:api.connected与homeassistant.event schema[6] ESPHome2026.9.1:state subscriber连接条件

04 / 家庭设备

完整设备YAML:本地计数和离线路径

先按H01建立固定Python3.12.13/ESPHome2026.9.1环境和私有secrets,执行config/compile后再USB首刷。所有动作使用本地组件,不依赖额外库。

api.connected的state_subscription_only避免仅日志客户端就认为控制链就绪,但只证明有订阅客户端,不能证明HA自动化启用或特定客户端身份。无订阅时事件不缓存;恢复连接后不补旧按键。

代码 / 配置
esphome:
  name: esp32-scene-button
  friendly_name: ESP32 Scene Button
  min_version: 2026.9.1
  on_boot:
    priority: -100
    then:
      - logger.log: "H04-A booted; inspect real device logs"

esp32:
  board: esp32-s3-devkitc-1
  variant: ESP32S3
  flash_size: 8MB
  flash_mode: qio
  flash_frequency: 80MHz
  toolchain: esp-idf
  framework:
    type: esp-idf
    version: 5.5.5

psram:
  mode: octal
  speed: 80MHz

logger:
  baud_rate: 115200
  hardware_uart: UART0
  level: DEBUG

api:
  encryption:
    key: !secret api_key
  reboot_timeout: 0s

ota:
  - platform: esphome
    encryption:
      key: !secret api_key

wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_password
  reboot_timeout: 0s
  ap:
    ssid: "esp32-scene-button Recovery"
    password: !secret fallback_password
    ap_timeout: 90s

captive_portal:

globals:
  - id: single_count
    type: uint32_t
    restore_value: false
    initial_value: '0'
  - id: long_count
    type: uint32_t
    restore_value: false
    initial_value: '0'

switch:
  - platform: gpio
    id: indicator
    pin: GPIO4
    internal: true
    restore_mode: ALWAYS_OFF

script:
  - id: feedback
    mode: restart
    parameters:
      pulses: int
    then:
      - repeat:
          count: !lambda return pulses;
          then:
            - switch.turn_on: indicator
            - delay: 120ms
            - switch.turn_off: indicator
            - delay: 120ms

binary_sensor:
  - platform: gpio
    id: scene_button
    name: "Scene button physical"
    trigger_on_initial_state: false
    pin:
      number: GPIO5
      inverted: true
      mode:
        input: true
        pullup: true
    filters:
      - delayed_on_off: 30ms
    on_multi_click:
      - timing:
          - ON for 50ms to 400ms
          - OFF for at least 250ms
        invalid_cooldown: 250ms
        then:
          - lambda: ++id(single_count);
          - if:
              condition:
                api.connected:
                  state_subscription_only: true
              then:
                - homeassistant.event:
                    event: esphome.hixinwu_scene_button
                    data:
                      button: h04
                      gesture: single
                - logger.log: "H04 single event dispatched; this is not HA scene confirmation"
                - script.execute:
                    id: feedback
                    pulses: 1
              else:
                - logger.log: "H04 single local-only: no API state subscriber; event not buffered"
                - script.execute:
                    id: feedback
                    pulses: 3
      - timing:
          - ON for at least 800ms
        invalid_cooldown: 250ms
        then:
          - lambda: ++id(long_count);
          - if:
              condition:
                api.connected:
                  state_subscription_only: true
              then:
                - homeassistant.event:
                    event: esphome.hixinwu_scene_button
                    data:
                      button: h04
                      gesture: long
                - logger.log: "H04 long event dispatched; this is not HA scene confirmation"
                - script.execute:
                    id: feedback
                    pulses: 1
              else:
                - logger.log: "H04 long local-only: no API state subscriber; event not buffered"
                - script.execute:
                    id: feedback
                    pulses: 3

sensor:
  - platform: template
    name: "Single press count"
    accuracy_decimals: 0
    update_interval: 1s
    lambda: return id(single_count);
  - platform: template
    name: "Long press count"
    accuracy_decimals: 0
    update_interval: 1s
    lambda: return id(long_count);

参考:[1] ESPHome2026.9.1固定版本源码[4] ESPHome2026.9.1:binary_sensor timing与初始触发[5] ESPHome2026.9.1:api.connected与homeassistant.event schema[6] ESPHome2026.9.1:state subscriber连接条件

05 / 家庭设备

一份完整package装入helper、scene和自动化

下载的ha-package.yaml复制到HA配置目录packages/hixinwu_h04.yaml,在现有homeassistant映射中合并packages: !include_dir_named packages。保留既有packages,不能重复顶层键。按当前HA版本执行配置检查并重启,再确认helper和两个scene已加载。

在开发者工具记录实际scene ID;若名字冲突,修改包内自动化目标。先手动调用scene.turn_on分别观察helper on/off,再监听esphome.hixinwu_scene_button,最后看自动化Trace。本轮仅按Core2026.10.2源码/规则核对与YAML语法解析,没有HA配置或运行校验。

代码 / 配置
# Home Assistant Core 2026.10.2 source-checked only; live HA validation is pending.
# Load as packages/hixinwu_h04.yaml using !include_dir_named packages.
input_boolean:
  hixinwu_h04_demo:
    name: "Hixinwu H04 demo flag"
    initial: false
scene:
  - id: hixinwu_h04_focus_demo_v1
    name: "Hixinwu H04 focus demo"
    entities:
      input_boolean.hixinwu_h04_demo: "on"
  - id: hixinwu_h04_rest_demo_v1
    name: "Hixinwu H04 rest demo"
    entities:
      input_boolean.hixinwu_h04_demo: "off"
automation:
  - id: hixinwu_h04_single_v1
    alias: "Hixinwu H04 single to focus"
    triggers:
      - trigger: event
        event_type: esphome.hixinwu_scene_button
        event_data:
          button: h04
          gesture: single
    actions:
      - action: scene.turn_on
        target:
          entity_id: scene.hixinwu_h04_focus_demo
    mode: single
  - id: hixinwu_h04_long_v1
    alias: "Hixinwu H04 long to rest"
    triggers:
      - trigger: event
        event_type: esphome.hixinwu_scene_button
        event_data:
          button: h04
          gesture: long
    actions:
      - action: scene.turn_on
        target:
          entity_id: scene.hixinwu_h04_rest_demo
    mode: single

参考:[3] HA Core2026.10.2:ESPHome管理器/事件处理[7] HA:Packages配置与合并规则[8] HA:场景定义与scene.turn_on[9] HA:事件触发器

06 / 家庭设备

用事件数量检查重复,不能只看最终状态

正常做30次约0.2秒短按并各释放0.5秒;本地计数、HA事件与Trace应一一对应。长按2秒10次,每次只一条long且无single;再试中间区和按住上电、RESET。

helper已经on时再次设on看起来不变,所以最终状态不能证明动作只发一次。feedback脚本为restart,快速新手势会重启灯闪,灯的次数也不是精确事件计数器;必须保留日志与事件记录。

参考:[4] ESPHome2026.9.1:binary_sensor timing与初始触发[5] ESPHome2026.9.1:api.connected与homeassistant.event schema[8] HA:场景定义与scene.turn_on[9] HA:事件触发器

07 / 家庭设备

停止HA后先看本地提示,再确认恢复不补发

保持设备供电停止HA,再按键应继续计数并走无订阅三闪路径;恢复后先确认没有旧事件,再新按一次。Wi-Fi断开可作为另一故障单独测,不能同时改按钮线路来混淆原因。

无计数先查GPIO5与按钮组;有计数无事件查API订阅;有事件无Trace查event_type/data过滤和自动化启用;有Trace无helper变化查场景实际ID。恢复固定YAML、USB重刷与原HA配置备份,不以擦Flash/eFuse作为首步。

参考:[2] DevKitC-1 v1.1固定提交927ed7e:排针与USB[3] HA Core2026.10.2:ESPHome管理器/事件处理[4] ESPHome2026.9.1:binary_sensor timing与初始触发[5] ESPHome2026.9.1:api.connected与homeassistant.event schema[7] HA:Packages配置与合并规则[9] HA:事件触发器

08 / 家庭设备

当前通过的是软件,场景结果仍待执行

设备配置与固件实际检查写入独立证据;HA package只做语法与固定来源核对,不冒称已在HA加载。串口、LED、手势重复、HA离线与重启场景都保留待验证。

改真实家居场景前先保存helper演示的事件与Trace基线,记录每次目标和实际结果。公开下载不含私有Wi-Fi/API密钥,观察表保持空白。

参考:[1] ESPHome2026.9.1固定版本源码[3] HA Core2026.10.2:ESPHome管理器/事件处理[7] HA:Packages配置与合并规则[8] HA:场景定义与scene.turn_on[9] HA:事件触发器

BACK TO THE SOURCE

资料来源与版本说明

本文依据下列官方文档与上游资料独立整理,适用范围与版本以本文所列组合为准。资料核对日期:。资料核对、程序构建与实板测试分别记录,不互相替代。

  1. ESPHome2026.9.1固定版本源码
  2. DevKitC-1 v1.1固定提交927ed7e:排针与USB
  3. HA Core2026.10.2:ESPHome管理器/事件处理
  4. ESPHome2026.9.1:binary_sensor timing与初始触发
  5. ESPHome2026.9.1:api.connected与homeassistant.event schema
  6. ESPHome2026.9.1:state subscriber连接条件
  7. HA:Packages配置与合并规则
  8. HA:场景定义与scene.turn_on
  9. HA:事件触发器
  10. Kingbright WP7113ID V.14A