Telemetria: guardar o que o sensor leu
Do pino ao banco, ao quadro e ao gráfico — e a decisão de quanto guardar.
Um sensor que não guarda nada responde "quanto é agora?". Guardar transforma isso em "o que aconteceu de madrugada?", que costuma ser a pergunta que importa.
Do pino para o banco#
adopt Arcane.IoT as IoT
adopt Arcane.Database as DB
adopt Arcane.OS as OS
adopt Arcane.IO as IO
pasta := $"{OS.temp_dir()}/df-doc-tel-{randint(100000, 999999)}"
IO.mkdir(pasta)
db := DB.connect($"{pasta}/estufa.db")
DB.execute(db, "CREATE TABLE leituras (quando TEXT, canal INTEGER, valor INTEGER)")
placa := IoT.conectar_simulada("uno")
placa.modo(14, "analogico")
placa.relatar_analogico(0)
cycle i from 1 to 5:
placa.simulador.definir_analogico(0, 400 + i * 30)
sleep(60)
DB.insert(db, "leituras", {"quando": $"t{i}", "canal": 0,
"valor": placa.analogico(0)})
linhas := DB.query(db, "SELECT * FROM leituras ORDER BY quando")
assert len(linhas) is 5
placa.fechar()
DB.close(db)
IO.remove_tree(pasta)O quadro, e a pergunta#
adopt Arcane.Quadro as Q
leituras := Q.de_vaults([
{"hora": 0, "canal": 0, "valor": 430},
{"hora": 1, "canal": 0, "valor": 460},
{"hora": 2, "canal": 0, "valor": 512},
{"hora": 0, "canal": 1, "valor": 210},
{"hora": 1, "canal": 1, "valor": 205},
])
por_canal := leituras >> agrupar "canal" >> resumir {"valor": "media"}
assert len(por_canal) is 2
out por_canal.para_vaults()Quanto guardar#
Um sensor a cada segundo dá 86.400 linhas por dia, e 31 milhões por ano. Quase sempre o que se quer é agregado: a média por minuto para a semana passada, o valor cru só para as últimas horas.
| Idade do dado | Resolução que costuma bastar |
|---|---|
| últimas 6 h | cru — é onde se investiga um incidente |
| últimos 7 dias | 1 minuto |
| últimos 6 meses | 1 hora, com mínimo e máximo |
| mais que isso | 1 dia, ou nada |
A agregação e a limpeza são trabalho de supabase-cron/pg_cron ou de um laço próprio — o ponto é decidir isso no começo. Um banco de sensor que cresce sem política sempre termina cheio, e a descoberta vem quando a escrita falha.
E se o painel some#
Um sensor que publica em MQTT com testamento avisa que caiu; um que grava direto no banco, não. Para saber que o dado parou de chegar, a pergunta é sobre a última linha:
adopt Arcane.IoT as IoT
ultima := 0
agora := 120
action saudavel(ultima_leitura, momento, prazo):
yield momento - ultima_leitura smaller prazo
assert saudavel(115, agora, 30) is yes
assert saudavel(40, agora, 30) is no // 80 s sem notícia: alerta