Este componente personalizado para o Home Assistant busca e exibe os preços de combustíveis a partir dos dados publicados pela Agência Nacional do Petróleo, Gás Natural e Biocombustíveis (ANP). Ele extrai informações de um arquivo XLSX disponibilizado no site oficial e cria sensores que mostram os preços mínimo, médio e máximo para cada tipo de combustível, filtrando os dados pelo estado e município configurados.
-
Extração Automática:
Busca automaticamente a URL do arquivo XLSX mais recente com os dados de preços semanais. -
Suporte a Múltiplos Combustíveis:
Extrai informações para os seguintes combustíveis:- Etanol Hidratado
- Gasolina Comum
- Gasolina Aditivada
- GLP
- GNV
- Óleo Diesel
- Óleo Diesel S10
-
Preços Mínimo, Médio e Máximo:
Para cada combustível, o componente extrai e disponibiliza três valores:- Mínimo
- Médio
- Máximo
-
Filtragem por Estado e Município:
Os dados são filtrados de acordo com os parâmetros de estado e município configurados na integração.
Por padrão, se não forem informados, os valores padrão são:- Estado:
SANTA CATARINA - Município:
TUBARAO
- Estado:
-
Home Assistant:
Versão 2024.11.0 ou superior. -
HACS:
É recomendado instalar o componente via HACS. -
Dependências Python:
Instaladas automaticamente pelo Home Assistant a partir domanifest.json:openpyxlbeautifulsoup4
-
Abra o HACS no Home Assistant:
No menu lateral do Home Assistant, clique em "HACS". -
Adicionar Repositório Personalizado:
- Clique em "Integrations".
- Clique nos três pontos no canto superior direito e selecione "Custom repositories".
- Adicione o repositório do componente (
https://github.com/dougbaptista/ha_fuel_prices) e selecione "Integration" como tipo. - Clique em "Add".
-
Instalar o Componente:
Após adicionar o repositório, volte à lista de integrações em HACS, localize "Fuel Prices" e clique em "Install". -
Reinicie o Home Assistant:
Após a instalação, reinicie o Home Assistant para que o componente seja carregado.
Ou adicione o repositório com um clique:
- Procure por Fuel Prices em Configurações > Dispositivos e Serviços.
- O fluxo tem três passos: estado, município e combustíveis.
As listas são montadas a partir da planilha da ANP, então só aparece o que ela realmente publica — atualmente 388 municípios em todo o país. Se a sua cidade não estiver na lista, é porque a ANP não coleta preços nela; escolha o município pesquisado mais próximo.
No último passo, os combustíveis já vêm marcados conforme o que existe naquele município (nem todos têm GNV, por exemplo). Cada combustível selecionado gera três sensores: mínimo, médio e máximo.
Para mudar qualquer coisa depois, use Configurar na integração. As entidades e o histórico são preservados; combustíveis desmarcados têm suas entidades removidas.
Contribuições são bem-vindas! Se você tiver sugestões, encontrar bugs ou desejar melhorias, sinta-se à vontade para abrir uma issue ou enviar um pull request no repositório.
- Escolha quais combustíveis acompanhar. Antes eram sempre os 7, gerando 21 entidades mesmo para quem só queria gasolina. O fluxo ganhou um terceiro passo, e a lista já vem marcada com os combustíveis que a ANP realmente publica para o município — nem todo lugar tem GNV, por exemplo.
- Desmarcar um combustível remove as entidades dele do registro, em vez de deixá-las órfãs e indisponíveis para sempre.
- Quem já tinha a integração instalada continua com os 7, sem mudança.
- Estado e município viram listas de seleção. Os dois campos eram texto livre. A ANP pesquisa apenas 388 municípios dos 5.570 do país (Santa Catarina, por exemplo, tem 16), então digitar uma cidade não pesquisada instalava a integração normalmente e ela simplesmente nunca trazia dado. Agora o fluxo tem dois passos — estado e depois município — e as opções vêm da própria planilha da ANP, mostrando só o que existe de fato.
- Se a ANP estiver inacessível no momento da configuração, o formulário cai automaticamente para entrada livre, com aviso.
- Precisão de exibição por unidade. Combustível por litro continua com 3
casas, como nas bombas (
6,299), mas GLP e GNV passam a usar 2 — o botijão aparecia como112,140 BRL/13kg, que se lê como 112 mil.
Correções de bugs:
-
Unidades corrigidas para GLP e GNV. O GLP era exibido como preço por litro (e depois por quilo), mas a ANP o cota por botijão de 13 kg — daí valores como
R$ 112. O GNV era exibido por litro, mas é cotado por m³. A unidade agora é lida da colunaUNIDADE DE MEDIDAda própria planilha, em vez de ser presumida. -
O fluxo de opções passa a ter efeito. As opções eram salvas em
entry.options, mas o código só liaentry.data— editar estado/município não mudava nada. A configuração efetiva agora édata + optionse a integração se recarrega automaticamente ao salvar. -
unique_idsem colisão. O identificador eracombustível_tipo_município, que colidia entre municípios homônimos de estados diferentes. Agora é derivado doentry_id. A migração é automática e preserva o histórico das entidades existentes.
Desempenho:
- O event loop não trava mais.
load_workbook, a varredura das ~40 mil linhas e o parsing HTML rodavam direto na corrotina, congelando todo o Home Assistant por segundos a cada atualização. Agora rodam em executor. - Normalização de texto com cache e filtro pelo município antes do estado, reduzindo drasticamente o trabalho por linha.
- Logging preguiçoso (
%s), eliminando formatação de string dentro do laço principal mesmo com DEBUG desligado.
Segurança:
- Teto de download de 50 MB, verificado por
Content-Lengthe durante a leitura em blocos, evitando exaustão de memória por arquivo anômalo. - Validação do link extraído da página: resolução correta com
urljoin, exigência de HTTPS e restrição ao domíniogov.br. - Dependências fixadas no
manifest.json;aiohttpremovido de lá, já que é dependência do próprio core (declará-la sem versão permitia atualizar a biblioteca de rede do Home Assistant durante a instalação).
Qualidade e diagnóstico:
- Cada falha (rede, HTTP, layout do site, aba ausente, coluna ausente, município inexistente) agora produz uma mensagem específica. Antes, todas apareciam como "Nenhum dado retornado", apontando para a causa errada.
- Dados obsoletos são sinalizados. O último valor válido continua sendo
preservado durante falhas passageiras, mas após 14 dias as entidades ficam
indisponíveis em vez de publicar um preço antigo como se fosse atual. A idade
é medida pelo período de referência publicado na planilha (
period_start/period_end), não pela hora do download. - Novos atributos:
surveyed_stations(quantos postos a ANP pesquisou — amostra pequena significa preço menos representativo),period_start,period_end,last_successful_updateestale. - Normalização defensiva de estado, município e produto. A ANP hoje publica
esses campos sem acento; a normalização garante que a integração continue
funcionando caso isso mude, e aceita entrada acentuada do usuário
(
Tubarão,Criciúma) na configuração. state_class: measurementenative_unit_of_measurement, habilitando estatísticas de longo prazo (gráficos históricos).- Todos os sensores agrupados sob um dispositivo por município.
- Fluxo de configuração valida a entrada e impede cadastrar o mesmo município duas vezes.
- Traduções completas (
en+pt-BR), incluindo o fluxo de opções. - CI deixou de mascarar falhas com
|| truee ganhou validaçãohassfeste HACS; a suíte de testes agora cobre o parsing real da planilha.
O diretório da integração foi renomeado de custom_components/ha_fuel_prices
para custom_components/fuel_prices, para coincidir com o domínio declarado no
manifest.json — requisito do Home Assistant e do hassfest.
Suas configurações e o histórico são preservados (o domínio fuel_prices não
mudou). Se você instalou via HACS, atualize normalmente e remova a pasta
antiga custom_components/ha_fuel_prices caso ela permaneça, antes de
reiniciar o Home Assistant.
Melhorias de desempenho e estabilidade:
-
Coordenador centralizado (DataUpdateCoordinator): Os dados da ANP agora são buscados uma única vez e compartilhados entre todos os sensores. Antes, cada sensor (21 no total) fazia seu próprio download e processamento do arquivo — agora é apenas 1 requisição por ciclo.
-
Intervalo de atualização otimizado: Atualização a cada 6 horas (os dados da ANP são semanais, não faz sentido consultar com mais frequência).
-
Remoção do pandas: Substituído por leitura direta com
openpyxlem modoread_only. Reduz significativamente o consumo de memória e o tempo de inicialização, especialmente em dispositivos como Raspberry Pi. -
Leitura em memória do XLSX: O arquivo XLSX agora é processado em memória (
BytesIO) evitando gravação em disco temporário. -
Preservação do histórico: O sensor agora mantém o último valor válido quando os dados estão indisponíveis (erro de rede, arquivo corrompido, valor inválido). Isso evita "buracos" no histórico com estados
unknown/unavailable. -
Sessão HTTP reutilizável e timeouts: Usa a sessão HTTP do Home Assistant (
async_get_clientsession) com timeout, melhorando estabilidade e integração. -
Edição pós-instalação: Adicionado
Options Flowpara permitir editarestadoemunicípiodepois da criação da integração.
- Versão inicial com busca de preços da ANP por município.
Se você deseja contribuir ou rodar verificações locais, siga estas instruções recomendadas.
- Instale Python 3.12 (mesma versão usada pelo CI).
- Crie e ative um ambiente virtual:
python -m venv .venv
.\.venv\Scripts\Activate.ps1- Atualize o pip e instale dependências de desenvolvimento:
python -m pip install --upgrade pip
pip install -r requirements.txt -r requirements-dev.txt
python -m pip install pre-commit- Rode os hooks do pre-commit (formatação e lint):
pre-commit install
pre-commit run --all-files- Rode os testes:
pytest -qObservações:
- O CI do repositório roda em Python 3.12 e reprova o build em qualquer erro de
black,isort,flake8oupytest. - Toda a lógica de scraping e parsing vive em
custom_components/fuel_prices/parser.py, que não importa nada do Home Assistant. Isso permite testá-la diretamente, com planilhas XLSX geradas em memória pelos testes. - Não é necessário instalar
homeassistantpara rodar a suíte:tests/conftest.pyinstala stubs mínimos apenas se o pacote não estiver presente, então instalar o HA de verdade (ou opytest-homeassistant-custom-component) continua funcionando.
custom_components/fuel_prices/
├── __init__.py # setup/unload da entrada, listener de opções, migração de unique_id
├── config_flow.py # fluxos de configuração e opções
├── const.py # constantes e limites
├── coordinator.py # I/O HTTP, timeouts, teto de download, ponte com o executor
├── parser.py # lógica pura: scraping, parsing do XLSX, normalização
└── sensor.py # entidades