5

Como construí um dashboard de energia solar embutido na parede da minha casa

Moro numa casa off-grid no alto de uma montanha e trabalho remoto. Nesse cenário, monitorar o consumo de energia é necessidade constante: no verão os painéis solares recebem sol a partir das 6-7h da manhã, mas no inverno isso só acontece por volta das 9-10h. A decisão de "assistir mais um episódio antes de dormir" ou "guardar energia" é literalmente a diferença entre ter ou não energia elétrica para trabalhar nos próximos dias nublados.

Para tomar essa decisão eu precisava consultar o aplicativo da bateria e a previsão do tempo — dois aplicativos, várias telas e atenção dividida. Então construí um dashboard que consulta os dados da bateria e uma API de previsão do tempo e exibe tudo em um display embutido na parede:

Display embutido na parede mostrando a carga da bateria e a previsão do tempo

Neste write-up, conto o processo por trás do projeto: as limitações que guiaram cada decisão de arquitetura, as semanas de engenharia reversa para conseguir os dados da bateria e a solução para responder o "e amanhã, vai ter sol?".

Se quiser o contexto completo (o problema que motivou tudo isso), leia o post anterior no meu blog.

As limitações do cenário off-grid

A maior restrição do projeto pode ser resumida em uma frase: não tenho internet disponível 24 horas por dia. Essa é uma limitação derivada de não ter geração de energia constante — e é justamente o problema que este projeto busca quantificar e deixar visível.

Consequência direta: todo o sistema precisava funcionar com ou sem acesso à internet.

Onde comecei

Meu ponto de partida foi ver o que eu já tinha em mãos:

  • dados da bateria via aplicativo mobile do fabricante
  • APIs públicas de previsão do tempo
  • hardware barato e de baixo consumo de energia (um CYD — placa ESP32 com tela TFT de 2.8" soldada)

O primeiro problema: eu sempre usei o próprio roteador da Starlink. Com ela desligada, eu ficava não só sem internet, mas também sem rede nenhuma — os dispositivos não conseguiam nem se falar entre si.

A solução foi adicionar um roteador wifi simples (Intelbras), que funciona 24h por dia independente da Starlink. Ele disponibiliza uma rede exclusiva para a bateria e o display, e se conecta via cabo ethernet à Starlink para dar acesso à internet quando ela está online.

Os dados: o capítulo da engenharia reversa

Conseguir os dados da bateria foi um longo processo de exploração que levou algumas semanas. Eu sabia que deveria haver algum modo de acessá-los, afinal a bateria enviava os dados para o aplicativo do fabricante.

Na primeira exploração, identifiquei a bateria na rede, mas não encontrei nenhum serviço aberto no IP dela. Descompilei o aplicativo, fiz engenharia reversa, monitorando o tráfego da minha rede — dias de frustração e nenhum caminho à frente.

Esgotadas minhas ideias, decidi fazer o caminho inverso: pegar os dados do aplicativo em vez da bateria. Não era o que eu queria, pois eu só teria acesso aos dados com internet, mas não ia deixar o projeto travar antes de sair do papel. Com isso, implementei a v0: a tela mostrava o estado de carga da bateria e uma estimativa de carga/descarga.

Satisfeito com a vitória e usando o dashboard há algumas semanas, decidi fazer um segundo round de exploração. Afinal, não faz sentido acessar um servidor na China para ler os dados de um dispositivo que está a 20 metros de mim, na mesma rede local.

Depois de muita pesquisa e leitura de várias versões de manuais, encontrei uma funcionalidade escondida no aplicativo: ele consegue acessar os dados da bateria sem internet, conectando-se diretamente a ela na rede local. Descoberta promissora.

A partir daí, instalei aplicativos de monitoramento de rede no celular e gravei o tráfego enquanto usava o aplicativo da bateria. Rede não é meu forte, e analisar aqueles logs manualmente levaria muito tempo, com risco de deixar algo passar. Então usei o Claude Code para analisar os logs, informando quais ações eu tinha feito durante a gravação — e ele identificou exatamente quais requests traziam os dados que eu via no app. Com alguns scripts Python, passei a replicar essas requests sem depender do aplicativo.

Para quem tem uma bateria da Felicity ou quer entender o protocolo por baixo dos panos, documentei tudo no repositório do projeto.

Com isso, a v1 estava de pé: dados da bateria sem nenhuma dependência de internet.

Temos o hoje, mas e amanhã?

Com a situação atual resolvida, faltava responder: vai ter sol amanhã? Posso esbanjar ou preciso economizar?

Depois de comparar APIs, escolhi a Open-Meteo. Melhor que previsão do tempo, ela disponibiliza a previsão de radiação solar — uma métrica muito mais precisa para o meu problema do que "nublado", "sol" ou "chuva".

Aqui esbarrei de novo na limitação de internet, e também na do hardware do display. A solução mais simples seria o próprio display consultar a API, mas isso significaria implementar em C uma série de redundâncias e caches para falhas de internet ou da API. Optei por uma solução um pouco mais complexa, porém mais simples de manter:

  • um serviço em Go rodando na VPS busca os dados na Open-Meteo de hora em hora, aplica cache e cálculos, e sobrescreve um arquivo JSON estático
  • o serviço nunca fica exposto na internet: se a API retornar erro, ele simplesmente não faz nada — o próprio arquivo vira a camada de cache
  • o display faz uma requisição para esse arquivo: se der erro, continua mostrando os últimos dados que tinha; se voltar, compara a data e atualiza o que está na tela
  • para falhas de conexão não passarem despercebidas, a tela mostra há quantas horas foi a última atualização bem-sucedida

Detalhe da tela: carga, tensão, corrente, previsão de geração e histórico das últimas 24h

Instalação

Para simplificar, aproveitei uma tomada com adaptador USB: liguei os fios 220v na tomada e o CYD na saída USB, tudo em uma única peça. Removi as outras entradas da tomada, aumentei o buraco do espelho e embuti o CYD dentro da caixa — instalar ficou simples como instalar qualquer outra tomada.

Parte de trás do display: placa ESP32 com tela TFT integrada, encaixada na caixa

Interior da caixa embutida na parede, com a fonte e a fiação

O sistema completo

               wifi                      ethernet
Bateria Felicity <-----> Roteador Intelbras <-----> Starlink (internet)
       ^                      ^
       |                      |
       +---- wifi ------------+
                     |
                     v
            +--------------+
            |  CYD (tela)  |
            +--------------+
                     ^
                     | http (arquivo JSON)
                     |
Open-Meteo --https--> Serviço Go (VPS) --sobrescreve--> JSON estático

Componentes: bateria Felicity, roteador Intelbras, CYD (ESP32 + tela), serviço Go na VPS, API Open-Meteo, tomada USB.

Código do firmware e do serviço: github.com/marcosvpj/felicity-cyd

Conclusão

Não é porque moro off-grid, no alto de uma montanha, que não posso usar tecnologia para melhorar minha vida. A principal questão é entender as limitações vigentes e trabalhar com elas — e ao redor delas.

E isso serve para tudo: muitas vezes queremos fazer as coisas do melhor modo possível, com a melhor arquitetura possível, quando simplesmente disponibilizar um arquivo JSON estático já resolve.

Carregando publicação patrocinada...
2