{"id":379,"date":"2026-09-28T09:56:25","date_gmt":"2026-09-28T12:56:25","guid":{"rendered":"https:\/\/www.bernabauer.com\/blog\/boas-praticas-para-automacoes-no-home-assistant\/"},"modified":"2026-09-28T09:56:25","modified_gmt":"2026-09-28T12:56:25","slug":"boas-praticas-para-automacoes-no-home-assistant","status":"publish","type":"post","link":"https:\/\/www.bernabauer.com\/blog\/boas-praticas-para-automacoes-no-home-assistant\/","title":{"rendered":"Boas pr\u00e1ticas para automa\u00e7\u00f5es no Home Assistant"},"content":{"rendered":"<p>Nos \u00faltimos meses, revisei uma a uma as automa\u00e7\u00f5es da minha casa. O Home Assistant come\u00e7ou pequeno, com poucas luzes e um sensor aqui e outro ali, e foi crescendo at\u00e9 virar um sistema que controla luzes, tomadas, a geladeira, a TV e os bot\u00f5es espalhados pelos c\u00f4modos. Nesse caminho, dei de cara com dois tipos de problema que se repetiam.<\/p>\n<p>O primeiro era abrir uma automa\u00e7\u00e3o que eu mesmo tinha escrito e n\u00e3o entender mais o que ela fazia, nem por que tinha aquela condi\u00e7\u00e3o estranha no meio. O segundo era mais irritante: luzes que ficavam acesas depois de um rein\u00edcio do HA, ou que n\u00e3o voltavam ao estado certo quando um dispositivo Zigbee ca\u00eda e voltava.<\/p>\n<p>Cada problema virou uma regra, e hoje toda automa\u00e7\u00e3o da casa segue as duas. \u00c9 o que eu compartilho aqui:<\/p>\n<ul>\n<li><strong>Nome e estrutura<\/strong>: escrever a automa\u00e7\u00e3o de um jeito que voc\u00ea, ou outra pessoa, entenda o que ela faz daqui a seis meses.<\/li>\n<li><strong>Gatilhos de ressincroniza\u00e7\u00e3o<\/strong>: fazer a automa\u00e7\u00e3o se recuperar sozinha depois de um rein\u00edcio, de uma edi\u00e7\u00e3o ou da queda de um dispositivo.<\/li>\n<\/ul>\n<h2>Nome e estrutura<\/h2>\n<p>Toda automa\u00e7\u00e3o da casa segue o mesmo esqueleto. Com 10 automa\u00e7\u00f5es, qualquer nome serve. Com 80, a lista vira uma sopa de &#8220;Automa\u00e7\u00e3o nova&#8221;, &#8220;Luz sala 2&#8221; e &#8220;teste final agora vai&#8221;. Um padr\u00e3o fixo faz com que qualquer automa\u00e7\u00e3o seja lida do mesmo jeito, seja ela a mais simples ou a mais complicada da casa.<\/p>\n<ul>\n<li><strong>Nome no formato <code>Ambiente\/Dispositivo | Fun\u00e7\u00e3o<\/code><\/strong>, por exemplo <code>Luz Cozinha | Acionamento<\/code> ou <code>Geladeira | Retomada Ap\u00f3s Queda de Energia<\/code>. Assim a lista de automa\u00e7\u00f5es fica agrupada por ambiente, e voc\u00ea acha o que procura em segundos.<\/li>\n<li><strong>Uma descri\u00e7\u00e3o que explica o porqu\u00ea das decis\u00f5es menos \u00f3bvias.<\/strong> Aquele <code>for: 30 s<\/code> ou aquela condi\u00e7\u00e3o esquisita existem por um motivo que voc\u00ea descobriu depois de horas olhando traces. Se ningu\u00e9m escrever o motivo, o &#8220;voc\u00ea do futuro&#8221; apaga a linha achando que \u00e9 sujeira, e o bug volta.<\/li>\n<li><strong>Um <code>id<\/code> leg\u00edvel em cada gatilho<\/strong>, no seu idioma e em <em>snake_case<\/em>: tudo em min\u00fasculas, sem acentos nem espa\u00e7os, com as palavras separadas por sublinhado (<code>movimento<\/code>, <code>porta_aberta<\/code>, <code>tv_desligou<\/code>). Esse formato \u00e9 o padr\u00e3o do Home Assistant para identificadores (\u00e9 o mesmo dos <code>entity_id<\/code>) e evita problemas com espa\u00e7os e caracteres especiais no YAML. Com IDs assim, um <code>condition: trigger<\/code> com <code>id: movimento<\/code> se l\u00ea como uma frase. Com um <code>id: \"2\"<\/code>, voc\u00ea precisa subir no YAML e contar os gatilhos.<\/li>\n<li><strong>Um \u00fanico <code>choose<\/code> com um alias claro em cada ramo<\/strong>, e o <code>default<\/code> cuidando do estado oposto. Com isso, o trace mostra &#8220;Ligar Luz Por Movimento&#8221; em vez de &#8220;Option 2&#8221;, e fica claro o que acontece quando nenhum ramo se aplica.<\/li>\n<li><strong>Modo <code>restart<\/code><\/strong>, para que o evento mais recente sempre ven\u00e7a. Se a automa\u00e7\u00e3o est\u00e1 esperando 30 segundos para apagar a luz e algu\u00e9m entra no c\u00f4modo, o HA cancela a execu\u00e7\u00e3o antiga e a nova assume. No modo padr\u00e3o (<code>single<\/code>), o novo evento seria ignorado.<\/li>\n<\/ul>\n<p>Veja a diferen\u00e7a na pr\u00e1tica, com a mesma automa\u00e7\u00e3o escrita das duas formas.<\/p>\n<p><strong>Antes:<\/strong><\/p>\n<pre>alias: Automa\u00e7\u00e3o nova\ndescription: \"\"\ntriggers:\n  - trigger: state\n    entity_id: binary_sensor.presenca_corredor\n    to: \"on\"\n  - trigger: state\n    entity_id: binary_sensor.presenca_corredor\n    to: \"off\"\n    for:\n      seconds: 30\nactions:\n  - choose:\n      - conditions:\n          - condition: state\n            entity_id: binary_sensor.presenca_corredor\n            state: \"on\"\n        sequence:\n          - action: light.turn_on\n            target:\n              entity_id: light.corredor\n      - conditions:\n          - condition: state\n            entity_id: binary_sensor.presenca_corredor\n            state: \"off\"\n        sequence:\n          - action: light.turn_off\n            target:\n              entity_id: light.corredor\nmode: single<\/pre>\n<p><strong>Depois:<\/strong><\/p>\n<pre>alias: Luz Corredor | Acionamento\ndescription: &gt;-\n  Acende com presen\u00e7a e apaga 30 s depois que a presen\u00e7a some.\n  Os 30 s evitam que a luz pisque quando o sensor perde por um\n  instante uma pessoa parada.\ntriggers:\n  - trigger: state\n    entity_id: binary_sensor.presenca_corredor\n    to: \"on\"\n    id: movimento\n  - trigger: state\n    entity_id: binary_sensor.presenca_corredor\n    to: \"off\"\n    for:\n      seconds: 30\n    id: sem_movimento\nactions:\n  - choose:\n      - alias: Ligar Luz Por Movimento\n        conditions:\n          - condition: trigger\n            id: movimento\n        sequence:\n          - action: light.turn_on\n            target:\n              entity_id: light.corredor\n    default:\n      - alias: Desligar Luz Ap\u00f3s 30s Sem Movimento\n        action: light.turn_off\n        target:\n          entity_id: light.corredor\nmode: restart<\/pre>\n<p>As duas fazem a mesma coisa, mas s\u00f3 a segunda explica a si mesma.<\/p>\n<h2>Gatilhos de ressincroniza\u00e7\u00e3o<\/h2>\n<p>As automa\u00e7\u00f5es do Home Assistant reagem a <strong>mudan\u00e7as<\/strong>: se nada muda, nada acontece. O problema aparece quando a mudan\u00e7a acontece enquanto ningu\u00e9m est\u00e1 ouvindo. Imagine que voc\u00ea est\u00e1 no corredor, com a luz acesa, e o HA reinicia por causa de uma atualiza\u00e7\u00e3o. Nesse meio-tempo voc\u00ea sai, e o sensor vai para <code>off<\/code>. Quando o HA volta, o sensor <strong>j\u00e1 est\u00e1<\/strong> em <code>off<\/code>, ent\u00e3o a transi\u00e7\u00e3o &#8220;on \u2192 off por 30 s&#8221; n\u00e3o acontece mais. A luz fica acesa at\u00e9 algu\u00e9m passar pelo corredor de novo.<\/p>\n<p>A solu\u00e7\u00e3o \u00e9 dar a toda automa\u00e7\u00e3o que mant\u00e9m um estado alguns gatilhos extras, cuja \u00fanica fun\u00e7\u00e3o \u00e9 mandar a automa\u00e7\u00e3o <strong>olhar para a casa agora e colocar tudo no estado certo<\/strong>.<\/p>\n<ul>\n<li><strong>Gatilho <code>inicio<\/code> (<code>homeassistant<\/code> \u2192 <code>start<\/code>)<\/strong>, que reavalia tudo quando o HA termina de iniciar. Ele cobre o caso do corredor: tudo o que mudou durante o rein\u00edcio \u00e9 corrigido assim que o sistema volta.<\/li>\n<li><strong>Gatilho <code>ativacao<\/code> (a pr\u00f3pria automa\u00e7\u00e3o indo para <code>on<\/code>)<\/strong>, que reavalia tudo quando voc\u00ea reativa a automa\u00e7\u00e3o. Isso resolve o caso cl\u00e1ssico de desativar a automa\u00e7\u00e3o para testar algo, mexer nas luzes na m\u00e3o e esquecer que o mundo mudou. Al\u00e9m disso, cada edi\u00e7\u00e3o recarrega a automa\u00e7\u00e3o, que passa de <code>unavailable<\/code> para <code>on<\/code>. Ou seja, a l\u00f3gica nova \u00e9 testada no instante em que voc\u00ea salva.<\/li>\n<li><strong>Gatilho <code>reconectou<\/code>, listando todos os dispositivos envolvidos<\/strong>, e n\u00e3o s\u00f3 a luz: sensores, atuadores e, se a automa\u00e7\u00e3o depende dela, a TV. Quando um dispositivo cai e volta, o estado dele pode ser diferente do que a automa\u00e7\u00e3o imagina, e qualquer um deles pode ser a pe\u00e7a que mudou.<\/li>\n<li><strong><code>from<\/code> em lista (<code>[unavailable, unknown]<\/code>) combinado com <code>not_to<\/code> com os mesmos valores.<\/strong> Dispositivos do Zigbee2MQTT costumam voltar em duas etapas: <code>unavailable \u2192 unknown \u2192 estado real<\/code>. S\u00f3 com <code>from: unavailable<\/code>, o gatilho dispara na etapa <code>unknown<\/code>, quando o estado ainda n\u00e3o serve para nada, e n\u00e3o dispara de novo quando o estado real chega. Com a lista e o <code>not_to<\/code>, ele dispara uma \u00fanica vez, no momento certo.<\/li>\n<li><strong>Ramos idempotentes, que conferem o estado atual em vez de confiar s\u00f3 no gatilho.<\/strong> Idempotente \u00e9 uma palavra dif\u00edcil para uma ideia simples: o ramo aplica o estado correto, n\u00e3o importa quantas vezes rode. &#8220;Se o gatilho foi <code>movimento<\/code>, acenda&#8221; n\u00e3o serve para ressincronizar, porque no <code>inicio<\/code> n\u00e3o houve movimento nenhum. &#8220;<strong>Se tem algu\u00e9m aqui agora<\/strong>, acenda; sen\u00e3o, apague&#8221; serve.<\/li>\n<li><strong>Ressincroniza\u00e7\u00e3o de acordo com o tipo da automa\u00e7\u00e3o<\/strong>, porque colocar os tr\u00eas gatilhos em tudo cria problemas novos (aprendi isso errando):\n<ul>\n<li><em>Mant\u00e9m estado<\/em> (luz, tomada): <code>inicio<\/code> + <code>ativacao<\/code> + <code>reconectou<\/code>, porque existe um estado &#8220;certo&#8221; a recalcular.<\/li>\n<li><em>Notifica\u00e7\u00e3o de condi\u00e7\u00e3o<\/em> (&#8220;porta aberta h\u00e1 10 min&#8221;, falta de energia): s\u00f3 <code>inicio<\/code> + <code>ativacao<\/code>, com um <code>input_boolean<\/code> do tipo &#8220;j\u00e1 avisado&#8221; para n\u00e3o mandar o mesmo aviso duas vezes. Sem <code>reconectou<\/code>, porque a reconex\u00e3o de um sensor n\u00e3o \u00e9 o problema que voc\u00ea quer avisar.<\/li>\n<li><em>Evento puro<\/em> (bot\u00e3o, campainha): nenhuma ressincroniza\u00e7\u00e3o, porque n\u00e3o h\u00e1 estado a recalcular. Um <code>toggle<\/code> disparado no <code>inicio<\/code> inverteria a luz de algu\u00e9m \u00e0s 3 da manh\u00e3. Se o bot\u00e3o usa uma entidade <code>event.*<\/code> ou um gatilho de estado, adicione <code>not_from: [unavailable, unknown]<\/code>, para que a volta do dispositivo n\u00e3o pare\u00e7a um clique. Aqui em casa os bot\u00f5es Zigbee usam um gatilho <code>mqtt<\/code> no t\u00f3pico <code>zigbee2mqtt\/&lt;bot\u00e3o&gt;\/action<\/code> com um <code>payload<\/code> fixo. Esse t\u00f3pico s\u00f3 recebe mensagem quando algu\u00e9m aperta o bot\u00e3o, ent\u00e3o o problema nem existe.<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<p>Veja como fica a automa\u00e7\u00e3o do corredor com essas regras aplicadas.<\/p>\n<p><strong>Antes<\/strong> (j\u00e1 organizada, mas sem ressincroniza\u00e7\u00e3o):<\/p>\n<pre>alias: Luz Corredor | Acionamento\ndescription: &gt;-\n  Acende com presen\u00e7a e apaga 30 s depois que a presen\u00e7a some.\n  Os 30 s evitam que a luz pisque quando o sensor perde por um\n  instante uma pessoa parada.\ntriggers:\n  - trigger: state\n    entity_id: binary_sensor.presenca_corredor\n    to: \"on\"\n    id: movimento\n  - trigger: state\n    entity_id: binary_sensor.presenca_corredor\n    to: \"off\"\n    for:\n      seconds: 30\n    id: sem_movimento\nactions:\n  - choose:\n      - alias: Ligar Luz Por Movimento\n        conditions:\n          - condition: trigger\n            id: movimento\n        sequence:\n          - action: light.turn_on\n            target:\n              entity_id: light.corredor\n    default:\n      - alias: Desligar Luz Ap\u00f3s 30s Sem Movimento\n        action: light.turn_off\n        target:\n          entity_id: light.corredor\nmode: restart<\/pre>\n<p><strong>Depois:<\/strong><\/p>\n<pre>alias: Luz Corredor | Acionamento\ndescription: &gt;-\n  Acende com presen\u00e7a e apaga 30 s depois que a presen\u00e7a some.\n  Os 30 s evitam que a luz pisque quando o sensor perde por um\n  instante uma pessoa parada. Os gatilhos inicio, ativacao e reconectou\n  reavaliam o estado depois de um rein\u00edcio, de uma edi\u00e7\u00e3o ou da queda\n  de um dispositivo.\ntriggers:\n  # Funcionais\n  - trigger: state\n    entity_id: binary_sensor.presenca_corredor\n    to: \"on\"\n    id: movimento\n  - trigger: state\n    entity_id: binary_sensor.presenca_corredor\n    to: \"off\"\n    for:\n      seconds: 30\n    id: sem_movimento\n  # Ressincroniza\u00e7\u00e3o\n  - trigger: homeassistant\n    event: start\n    id: inicio\n  - trigger: state\n    entity_id: automation.luz_corredor_acionamento\n    to: \"on\"\n    id: ativacao\n  - trigger: state\n    entity_id:\n      - binary_sensor.presenca_corredor\n      - light.corredor\n    from: [unavailable, unknown]\n    not_to: [unavailable, unknown]\n    id: reconectou\nactions:\n  - choose:\n      - alias: Ligar Luz Por Movimento Ou Ressincroniza\u00e7\u00e3o Com Presen\u00e7a\n        conditions:\n          - condition: trigger\n            id: [movimento, inicio, ativacao, reconectou]\n          - condition: state\n            entity_id: binary_sensor.presenca_corredor\n            state: \"on\"\n        sequence:\n          - action: light.turn_on\n            target:\n              entity_id: light.corredor\n    default:\n      - alias: Desligar Luz Sem Presen\u00e7a\n        action: light.turn_off\n        target:\n          entity_id: light.corredor\nmode: restart<\/pre>\n<p>O ramo de &#8220;ligar&#8221; agora tamb\u00e9m responde aos gatilhos de ressincroniza\u00e7\u00e3o, mas s\u00f3 acende se o sensor confirmar presen\u00e7a. Se o HA reinicia com o corredor vazio, o <code>default<\/code> apaga a luz. Rodar isso uma vez ou dez vezes d\u00e1 sempre o mesmo resultado.<\/p>\n<h2>Checklist para levar<\/h2>\n<p>Ao criar ou revisar uma automa\u00e7\u00e3o, confira:<\/p>\n<ul>\n<li>\u2610 O nome segue <code>Ambiente\/Dispositivo | Fun\u00e7\u00e3o<\/code>?<\/li>\n<li>\u2610 A descri\u00e7\u00e3o explica as decis\u00f5es que n\u00e3o s\u00e3o \u00f3bvias?<\/li>\n<li>\u2610 Todo gatilho tem um <code>id<\/code> leg\u00edvel, em snake_case?<\/li>\n<li>\u2610 Os ramos do <code>choose<\/code> t\u00eam alias, e o <code>default<\/code> cuida do estado oposto?<\/li>\n<li>\u2610 O modo \u00e9 <code>restart<\/code>?<\/li>\n<li>\u2610 Os gatilhos de ressincroniza\u00e7\u00e3o combinam com o tipo da automa\u00e7\u00e3o (estado, notifica\u00e7\u00e3o ou evento)?<\/li>\n<li>\u2610 O <code>reconectou<\/code> lista <strong>todos<\/strong> os dispositivos envolvidos, com <code>from<\/code> em lista e <code>not_to<\/code>?<\/li>\n<li>\u2610 Os ramos que respondem a <code>inicio<\/code>, <code>ativacao<\/code> e <code>reconectou<\/code> conferem o estado atual, em vez de confiar s\u00f3 no gatilho?<\/li>\n<li>\u2610 Voc\u00ea abriu o trace depois de salvar? A pr\u00f3pria edi\u00e7\u00e3o dispara o <code>ativacao<\/code>, ent\u00e3o o primeiro teste j\u00e1 aconteceu.<\/li>\n<\/ul>\n<h2>Resumindo<\/h2>\n<p>Nome e estrutura deixam a automa\u00e7\u00e3o <strong>f\u00e1cil de entender<\/strong>. Gatilhos de ressincroniza\u00e7\u00e3o deixam a automa\u00e7\u00e3o <strong>dif\u00edcil de quebrar<\/strong>. Nenhuma das duas pr\u00e1ticas custa muito: s\u00e3o algumas linhas de YAML e um pouco de disciplina. Em troca, voc\u00ea n\u00e3o acorda mais com a luz do corredor acesa e perde o medo de abrir uma automa\u00e7\u00e3o antiga.<\/p>\n<p>Se voc\u00ea tem uma pr\u00e1tica que funciona na sua casa, me conta nos coment\u00e1rios!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Aprenda a nomear e estruturar automa\u00e7\u00f5es no Home Assistant para que sejam f\u00e1ceis de entender e resistentes a rein\u00edcios e quedas de dispositivos.<\/p>\n","protected":false},"author":2,"featured_media":378,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_kad_post_transparent":"","_kad_post_title":"","_kad_post_layout":"","_kad_post_sidebar_id":"","_kad_post_content_style":"","_kad_post_vertical_padding":"","_kad_post_feature":"","_kad_post_feature_position":"","_kad_post_header":false,"_kad_post_footer":false,"_kad_post_classname":"","_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_feature_clip_id":0,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_post_was_ever_published":false},"categories":[6],"tags":[13,113,76,124],"class_list":["post-379","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-automacao","tag-automacao","tag-dicas","tag-home-assistant","tag-yaml"],"jetpack_sharing_enabled":true,"jetpack_featured_media_url":"https:\/\/www.bernabauer.com\/blog\/wp-content\/uploads\/2026\/09\/boas-praticas-para-automacoes-no-home-assistant-featured.jpg","_links":{"self":[{"href":"https:\/\/www.bernabauer.com\/blog\/wp-json\/wp\/v2\/posts\/379","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.bernabauer.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.bernabauer.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.bernabauer.com\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.bernabauer.com\/blog\/wp-json\/wp\/v2\/comments?post=379"}],"version-history":[{"count":0,"href":"https:\/\/www.bernabauer.com\/blog\/wp-json\/wp\/v2\/posts\/379\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.bernabauer.com\/blog\/wp-json\/wp\/v2\/media\/378"}],"wp:attachment":[{"href":"https:\/\/www.bernabauer.com\/blog\/wp-json\/wp\/v2\/media?parent=379"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.bernabauer.com\/blog\/wp-json\/wp\/v2\/categories?post=379"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.bernabauer.com\/blog\/wp-json\/wp\/v2\/tags?post=379"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}