"use client"; import { useState, useMemo, useRef } from "react"; import Header from "@/components/Header"; import Footer from "@/components/Footer"; import PageHero from "@/components/PageHero"; import { categoriasDiagnostico, sintomasRapidos, errosCatalogo, regrasDecodificadorLog, } from "@/lib/diagnosticoData"; import { Activity, AlertTriangle, Check, CheckCircle2, ChevronDown, Copy, Cpu, ExternalLink, HelpCircle, Layers, LayoutGrid, RotateCcw, Search, ShieldAlert, Terminal, Wifi, Wrench, X, XCircle, Zap, } from "lucide-react"; /** Os rótulos dos sintomas vêm com emoji nos dados; a interface usa só texto e ícones. */ const semEmoji = (texto) => texto.replace(/^[\p{Extended_Pictographic}\uFE0F\s]+/u, ""); const ICONES = { Zap, Cpu, Layers, Activity, Terminal, Wifi }; const EXEMPLOS_LOG = [ ["Brownout", "Brownout detector was triggered\n\nrst:0xc (SW_CPU_RESET),boot:0x13"], ["LoadProhibited", "Guru Meditation Error: Core 0 panic'ed (LoadProhibited).\nEXCVADDR: 0x00000000"], ["Task watchdog", "Task watchdog got triggered. The following tasks/users did not reset the watchdog: - IDLE0"], ["Handshake TLS", "mbedtls_ssl_handshake returned -0x2700\nThe certificate is not yet valid"], ]; const GRAVIDADE = { "Crítica": "text-danger", Alta: "text-gold", }; const CHECKLISTS = [ { icon: Zap, titulo: "Hardware e alimentação", itens: [ "Capacitor de 10 µF a 100 µF de baixo ESR no VCC, mais um cerâmico de 100 nF junto ao chip.", "LDO dimensionado para picos de 600 mA a 1 A, com folga térmica.", "Nenhum periférico forçando nível lógico nos pinos de strapping durante o boot.", "Capacitor de 10 µF ou 1 µF no pino EN (RST) para auto-reset estável na gravação.", ], }, { icon: Layers, titulo: "Firmware e FreeRTOS", itens: [ "Toda tarefa FreeRTOS cede a CPU com vTaskDelay, filas ou semáforos.", "Toda ISR marcada com IRAM_ATTR e sem chamadas bloqueantes.", "Sem uso contínuo de String do Arduino em laços, para evitar fragmentação do heap.", "Horário sincronizado por SNTP antes de abrir conexões TLS/HTTPS.", ], }, ]; export default function DiagnosticoPage() { const [termoBusca, setTermoBusca] = useState(""); const [categoriaAtiva, setCategoriaAtiva] = useState("todos"); const [sintomaAtivo, setSintomaAtivo] = useState(null); const [cardAberto, setCardAberto] = useState(null); const [linguagemCodigo, setLinguagemCodigo] = useState({}); // { [id]: 'arduino' | 'espidf' } const [copiadoId, setCopiadoId] = useState(null); const searchInputRef = useRef(null); // Estado do Analisador de Logs const [logInput, setLogInput] = useState(""); const [resultadoLog, setResultadoLog] = useState(null); // Função de Análise do Log const analisarLog = (texto) => { setLogInput(texto); if (!texto || texto.trim() === "") { setResultadoLog(null); return; } for (const regra of regrasDecodificadorLog) { if (regra.padrao.test(texto)) { setResultadoLog(regra); return; } } setResultadoLog({ titulo: "Padrão de erro não categorizado automaticamente", tipo: "Desconhecido", explicacao: "Não identificamos uma assinatura clássica de Guru Meditation ou Brownout neste trecho. Verifique se a taxa de baud rate (ex: 115200) está correta e se o cabeçalho 'rst:' ou 'panic' está presente.", acaoRecomendada: "Procure por palavras-chave como 'Guru Meditation', 'rst:', 'LoadProhibited', 'watchdog' ou 'panic' no console serial.", }); }; const copiarParaClipboard = (texto, id) => { navigator.clipboard.writeText(texto); setCopiadoId(id); setTimeout(() => setCopiadoId(null), 2000); }; // Filtragem dos erros const errosFiltrados = useMemo(() => { const termo = termoBusca.toLowerCase().trim(); return errosCatalogo.filter((erro) => { const matchCategoria = categoriaAtiva === "todos" || erro.categoria === categoriaAtiva; const matchSintoma = !sintomaAtivo || erro.sintomas.includes(sintomaAtivo); const matchBusca = !termo || erro.titulo.toLowerCase().includes(termo) || erro.resumo.toLowerCase().includes(termo) || erro.causaRaiz.toLowerCase().includes(termo) || erro.logSerial.toLowerCase().includes(termo); return matchCategoria && matchSintoma && matchBusca; }); }, [categoriaAtiva, sintomaAtivo, termoBusca]); const temFiltroAtivo = termoBusca.trim() !== "" || categoriaAtiva !== "todos" || sintomaAtivo !== null; const limparTodosFiltros = () => { setTermoBusca(""); setCategoriaAtiva("todos"); setSintomaAtivo(null); searchInputRef.current?.focus(); }; const toggleCard = (id) => { setCardAberto((prev) => (prev === id ? null : id)); }; const setLang = (id, lang) => { setLinguagemCodigo((prev) => ({ ...prev, [id]: lang })); }; const totalFiltros = (termoBusca.trim() ? 1 : 0) + (categoriaAtiva !== "todos" ? 1 : 0) + (sintomaAtivo ? 1 : 0); return (
Baseado no artigo do Ciência Embarcada

Cole o log e veja a causa

Copie o trecho do monitor serial. O diagnóstico aparece na hora.

Testar com {EXEMPLOS_LOG.map(([rotulo, texto]) => ( ))}