Boas práticas para automações no Home Assistant
Nos últimos meses, revisei uma a uma as automações da minha casa. O Home Assistant começou pequeno, com poucas luzes e um sensor aqui e outro ali, e foi crescendo até virar um sistema que controla luzes, tomadas, a geladeira, a TV e os botões espalhados pelos cômodos. Nesse caminho, dei de cara com dois tipos de problema que se repetiam.
O primeiro era abrir uma automação que eu mesmo tinha escrito e não entender mais o que ela fazia, nem por que tinha aquela condição estranha no meio. O segundo era mais irritante: luzes que ficavam acesas depois de um reinício do HA, ou que não voltavam ao estado certo quando um dispositivo Zigbee caía e voltava.
Cada problema virou uma regra, e hoje toda automação da casa segue as duas. É o que eu compartilho aqui:
- Nome e estrutura: escrever a automação de um jeito que você, ou outra pessoa, entenda o que ela faz daqui a seis meses.
- Gatilhos de ressincronização: fazer a automação se recuperar sozinha depois de um reinício, de uma edição ou da queda de um dispositivo.
Nome e estrutura
Toda automação da casa segue o mesmo esqueleto. Com 10 automações, qualquer nome serve. Com 80, a lista vira uma sopa de “Automação nova”, “Luz sala 2” e “teste final agora vai”. Um padrão fixo faz com que qualquer automação seja lida do mesmo jeito, seja ela a mais simples ou a mais complicada da casa.
- Nome no formato
Ambiente/Dispositivo | Função, por exemploLuz Cozinha | AcionamentoouGeladeira | Retomada Após Queda de Energia. Assim a lista de automações fica agrupada por ambiente, e você acha o que procura em segundos. - Uma descrição que explica o porquê das decisões menos óbvias. Aquele
for: 30 sou aquela condição esquisita existem por um motivo que você descobriu depois de horas olhando traces. Se ninguém escrever o motivo, o “você do futuro” apaga a linha achando que é sujeira, e o bug volta. - Um
idlegível em cada gatilho, no seu idioma e em snake_case: tudo em minúsculas, sem acentos nem espaços, com as palavras separadas por sublinhado (movimento,porta_aberta,tv_desligou). Esse formato é o padrão do Home Assistant para identificadores (é o mesmo dosentity_id) e evita problemas com espaços e caracteres especiais no YAML. Com IDs assim, umcondition: triggercomid: movimentose lê como uma frase. Com umid: "2", você precisa subir no YAML e contar os gatilhos. - Um único
choosecom um alias claro em cada ramo, e odefaultcuidando do estado oposto. Com isso, o trace mostra “Ligar Luz Por Movimento” em vez de “Option 2”, e fica claro o que acontece quando nenhum ramo se aplica. - Modo
restart, para que o evento mais recente sempre vença. Se a automação está esperando 30 segundos para apagar a luz e alguém entra no cômodo, o HA cancela a execução antiga e a nova assume. No modo padrão (single), o novo evento seria ignorado.
Veja a diferença na prática, com a mesma automação escrita das duas formas.
Antes:
alias: Automação nova
description: ""
triggers:
- trigger: state
entity_id: binary_sensor.presenca_corredor
to: "on"
- trigger: state
entity_id: binary_sensor.presenca_corredor
to: "off"
for:
seconds: 30
actions:
- choose:
- conditions:
- condition: state
entity_id: binary_sensor.presenca_corredor
state: "on"
sequence:
- action: light.turn_on
target:
entity_id: light.corredor
- conditions:
- condition: state
entity_id: binary_sensor.presenca_corredor
state: "off"
sequence:
- action: light.turn_off
target:
entity_id: light.corredor
mode: single
Depois:
alias: Luz Corredor | Acionamento
description: >-
Acende com presença e apaga 30 s depois que a presença some.
Os 30 s evitam que a luz pisque quando o sensor perde por um
instante uma pessoa parada.
triggers:
- trigger: state
entity_id: binary_sensor.presenca_corredor
to: "on"
id: movimento
- trigger: state
entity_id: binary_sensor.presenca_corredor
to: "off"
for:
seconds: 30
id: sem_movimento
actions:
- choose:
- alias: Ligar Luz Por Movimento
conditions:
- condition: trigger
id: movimento
sequence:
- action: light.turn_on
target:
entity_id: light.corredor
default:
- alias: Desligar Luz Após 30s Sem Movimento
action: light.turn_off
target:
entity_id: light.corredor
mode: restart
As duas fazem a mesma coisa, mas só a segunda explica a si mesma.
Gatilhos de ressincronização
As automações do Home Assistant reagem a mudanças: se nada muda, nada acontece. O problema aparece quando a mudança acontece enquanto ninguém está ouvindo. Imagine que você está no corredor, com a luz acesa, e o HA reinicia por causa de uma atualização. Nesse meio-tempo você sai, e o sensor vai para off. Quando o HA volta, o sensor já está em off, então a transição “on → off por 30 s” não acontece mais. A luz fica acesa até alguém passar pelo corredor de novo.
A solução é dar a toda automação que mantém um estado alguns gatilhos extras, cuja única função é mandar a automação olhar para a casa agora e colocar tudo no estado certo.
- Gatilho
inicio(homeassistant→start), que reavalia tudo quando o HA termina de iniciar. Ele cobre o caso do corredor: tudo o que mudou durante o reinício é corrigido assim que o sistema volta. - Gatilho
ativacao(a própria automação indo paraon), que reavalia tudo quando você reativa a automação. Isso resolve o caso clássico de desativar a automação para testar algo, mexer nas luzes na mão e esquecer que o mundo mudou. Além disso, cada edição recarrega a automação, que passa deunavailableparaon. Ou seja, a lógica nova é testada no instante em que você salva. - Gatilho
reconectou, listando todos os dispositivos envolvidos, e não só a luz: sensores, atuadores e, se a automação depende dela, a TV. Quando um dispositivo cai e volta, o estado dele pode ser diferente do que a automação imagina, e qualquer um deles pode ser a peça que mudou. fromem lista ([unavailable, unknown]) combinado comnot_tocom os mesmos valores. Dispositivos do Zigbee2MQTT costumam voltar em duas etapas:unavailable → unknown → estado real. Só comfrom: unavailable, o gatilho dispara na etapaunknown, quando o estado ainda não serve para nada, e não dispara de novo quando o estado real chega. Com a lista e onot_to, ele dispara uma única vez, no momento certo.- Ramos idempotentes, que conferem o estado atual em vez de confiar só no gatilho. Idempotente é uma palavra difícil para uma ideia simples: o ramo aplica o estado correto, não importa quantas vezes rode. “Se o gatilho foi
movimento, acenda” não serve para ressincronizar, porque noinicionão houve movimento nenhum. “Se tem alguém aqui agora, acenda; senão, apague” serve. - Ressincronização de acordo com o tipo da automação, porque colocar os três gatilhos em tudo cria problemas novos (aprendi isso errando):
- Mantém estado (luz, tomada):
inicio+ativacao+reconectou, porque existe um estado “certo” a recalcular. - Notificação de condição (“porta aberta há 10 min”, falta de energia): só
inicio+ativacao, com uminput_booleando tipo “já avisado” para não mandar o mesmo aviso duas vezes. Semreconectou, porque a reconexão de um sensor não é o problema que você quer avisar. - Evento puro (botão, campainha): nenhuma ressincronização, porque não há estado a recalcular. Um
toggledisparado noinicioinverteria a luz de alguém às 3 da manhã. Se o botão usa uma entidadeevent.*ou um gatilho de estado, adicionenot_from: [unavailable, unknown], para que a volta do dispositivo não pareça um clique. Aqui em casa os botões Zigbee usam um gatilhomqttno tópicozigbee2mqtt/<botão>/actioncom umpayloadfixo. Esse tópico só recebe mensagem quando alguém aperta o botão, então o problema nem existe.
- Mantém estado (luz, tomada):
Veja como fica a automação do corredor com essas regras aplicadas.
Antes (já organizada, mas sem ressincronização):
alias: Luz Corredor | Acionamento
description: >-
Acende com presença e apaga 30 s depois que a presença some.
Os 30 s evitam que a luz pisque quando o sensor perde por um
instante uma pessoa parada.
triggers:
- trigger: state
entity_id: binary_sensor.presenca_corredor
to: "on"
id: movimento
- trigger: state
entity_id: binary_sensor.presenca_corredor
to: "off"
for:
seconds: 30
id: sem_movimento
actions:
- choose:
- alias: Ligar Luz Por Movimento
conditions:
- condition: trigger
id: movimento
sequence:
- action: light.turn_on
target:
entity_id: light.corredor
default:
- alias: Desligar Luz Após 30s Sem Movimento
action: light.turn_off
target:
entity_id: light.corredor
mode: restart
Depois:
alias: Luz Corredor | Acionamento
description: >-
Acende com presença e apaga 30 s depois que a presença some.
Os 30 s evitam que a luz pisque quando o sensor perde por um
instante uma pessoa parada. Os gatilhos inicio, ativacao e reconectou
reavaliam o estado depois de um reinício, de uma edição ou da queda
de um dispositivo.
triggers:
# Funcionais
- trigger: state
entity_id: binary_sensor.presenca_corredor
to: "on"
id: movimento
- trigger: state
entity_id: binary_sensor.presenca_corredor
to: "off"
for:
seconds: 30
id: sem_movimento
# Ressincronização
- trigger: homeassistant
event: start
id: inicio
- trigger: state
entity_id: automation.luz_corredor_acionamento
to: "on"
id: ativacao
- trigger: state
entity_id:
- binary_sensor.presenca_corredor
- light.corredor
from: [unavailable, unknown]
not_to: [unavailable, unknown]
id: reconectou
actions:
- choose:
- alias: Ligar Luz Por Movimento Ou Ressincronização Com Presença
conditions:
- condition: trigger
id: [movimento, inicio, ativacao, reconectou]
- condition: state
entity_id: binary_sensor.presenca_corredor
state: "on"
sequence:
- action: light.turn_on
target:
entity_id: light.corredor
default:
- alias: Desligar Luz Sem Presença
action: light.turn_off
target:
entity_id: light.corredor
mode: restart
O ramo de “ligar” agora também responde aos gatilhos de ressincronização, mas só acende se o sensor confirmar presença. Se o HA reinicia com o corredor vazio, o default apaga a luz. Rodar isso uma vez ou dez vezes dá sempre o mesmo resultado.
Checklist para levar
Ao criar ou revisar uma automação, confira:
- ☐ O nome segue
Ambiente/Dispositivo | Função? - ☐ A descrição explica as decisões que não são óbvias?
- ☐ Todo gatilho tem um
idlegível, em snake_case? - ☐ Os ramos do
choosetêm alias, e odefaultcuida do estado oposto? - ☐ O modo é
restart? - ☐ Os gatilhos de ressincronização combinam com o tipo da automação (estado, notificação ou evento)?
- ☐ O
reconectoulista todos os dispositivos envolvidos, comfromem lista enot_to? - ☐ Os ramos que respondem a
inicio,ativacaoereconectouconferem o estado atual, em vez de confiar só no gatilho? - ☐ Você abriu o trace depois de salvar? A própria edição dispara o
ativacao, então o primeiro teste já aconteceu.
Resumindo
Nome e estrutura deixam a automação fácil de entender. Gatilhos de ressincronização deixam a automação difícil de quebrar. Nenhuma das duas práticas custa muito: são algumas linhas de YAML e um pouco de disciplina. Em troca, você não acorda mais com a luz do corredor acesa e perde o medo de abrir uma automação antiga.
Se você tem uma prática que funciona na sua casa, me conta nos comentários!
