diff --git a/src/bot/handler.js b/src/bot/handler.js index 66c372a..16da289 100644 --- a/src/bot/handler.js +++ b/src/bot/handler.js @@ -1045,6 +1045,8 @@ Digite /help para ver todos os comandos disponíveis! const nomePlano = servico.descricao || servico.nome || 'N/A'; const endereco = servico.instalacao_endereco || servico.end_rua || null; const cidade = servico.instalacao_cidade || null; + // Campo base/AP usado para rotear para a OLT correta + const baseInfo = servico.base || (servico.id_ap ? `AP ${servico.id_ap}` : null); // Executar consultas em paralelo: Juniper + ONU const [juniperResult, onuResult] = await Promise.all([ @@ -1052,7 +1054,7 @@ Digite /help para ver todos os comandos disponíveis! ? this.ssh.getJuniperSubscriberInfo('juniper', pppoeLogin).catch(e => ({ success: false, error: e.message })) : Promise.resolve({ success: false, skipped: true }), serial - ? this._diagnosticarONU(serial).catch(e => ({ success: false, error: e.message })) + ? this._diagnosticarONU(serial, baseInfo).catch(e => ({ success: false, error: e.message })) : Promise.resolve({ success: false, skipped: true }) ]); @@ -1106,7 +1108,7 @@ Digite /help para ver todos os comandos disponíveis! msg += '\n'; if (onuResult.portaEthernet) { - const ethOk = /forward|up|1gbit|100mbit/i.test(onuResult.portaEthernet); + const ethOk = /forward|up|active|1gbit|100mbit/i.test(onuResult.portaEthernet); msg += ` ${ethOk ? '🟢' : '🔴'} Porta Ethernet: ${onuResult.portaEthernet}\n`; } } @@ -1120,37 +1122,66 @@ Digite /help para ver todos os comandos disponíveis! } /** - * Diagnóstico de ONU: detecta tipo (Datacom/FiberHome) e retorna dados estruturados + * Mapeia o campo base/AP do TopSapp para o ID da OLT Datacom (ou 'fiberhome') */ - async _diagnosticarONU(serial) { - const serialUpper = serial.toUpperCase(); - - if (serialUpper.startsWith('DACM')) { - return await this._diagnosticarONUDatacom(serial); - } else { - return await this._diagnosticarONUFiberhome(serial); - } + _resolverOLTporBase(baseInfo) { + if (!baseInfo) return null; + const b = String(baseInfo).toUpperCase(); + if (/INTERNET\s+FIBRA\s+OPTICA/i.test(b)) return 'fiberhome'; + if (/COLMEIA/i.test(b)) return 'olt_colmeia'; + if (/DITO/i.test(b)) return 'olt_dito'; + if (/CANAA\s*2/i.test(b)) return 'olt_canaa2'; + if (/CANAA/i.test(b)) return 'olt_canaa'; + return null; } - async _diagnosticarONUDatacom(serial) { - const olts = this.ssh.listOLTs(); - if (olts.length === 0) { - return { success: false, error: 'Nenhuma OLT Datacom configurada' }; + /** + * Diagnóstico de ONU: detecta tipo (Datacom/FiberHome) e retorna dados estruturados + * @param {string} serial - Serial da ONU + * @param {string|null} baseInfo - Campo base/AP do TopSapp para rotear para OLT correta + */ + async _diagnosticarONU(serial, baseInfo) { + const serialUpper = serial.toUpperCase(); + const oltHint = this._resolverOLTporBase(baseInfo); + + // Usar base description para decidir se é FiberHome + if (oltHint === 'fiberhome' || + (!serialUpper.startsWith('DACM') && (serialUpper.startsWith('FHTT') || serialUpper.startsWith('FHGT')))) { + return await this._diagnosticarONUFiberhome(serial); } - // Buscar ONU em todas as OLTs em paralelo - const searches = olts.map(olt => - this.ssh.findOnuBySerial(olt.id, serial) - .then(r => ({ ...r, oltId: olt.id, oltName: olt.name })) - .catch(() => ({ success: false })) - ); - const results = await Promise.allSettled(searches); + return await this._diagnosticarONUDatacom(serial, oltHint); + } + async _diagnosticarONUDatacom(serial, oltIdHint) { let found = null; - for (const r of results) { - if (r.status === 'fulfilled' && r.value.success) { - found = r.value; - break; + + // 1. Tentar na OLT indicada pelo campo base/AP do cadastro + if (oltIdHint && this.ssh.equipamentos.has(oltIdHint)) { + const r = await this.ssh.findOnuBySerial(oltIdHint, serial).catch(() => null); + if (r && r.success) { + const olt = this.ssh.equipamentos.get(oltIdHint); + found = { ...r, oltId: oltIdHint, oltName: olt.name }; + } + } + + // 2. Fallback: buscar em todas as OLTs Datacom + if (!found) { + const olts = this.ssh.listOLTs(); + if (olts.length === 0) { + return { success: false, error: 'Nenhuma OLT Datacom configurada' }; + } + const searches = olts.map(olt => + this.ssh.findOnuBySerial(olt.id, serial) + .then(r => ({ ...r, oltId: olt.id, oltName: olt.name })) + .catch(() => ({ success: false })) + ); + const results = await Promise.allSettled(searches); + for (const r of results) { + if (r.status === 'fulfilled' && r.value.success) { + found = r.value; + break; + } } } @@ -1207,21 +1238,34 @@ Digite /help para ver todos os comandos disponíveis! return { success: false, error: resultado.error || 'ONU não encontrada na FiberHome' }; } - const portaPrincipal = resultado.portasEthernet && resultado.portasEthernet.length > 0 - ? resultado.portasEthernet[0] - : null; + // Preferir porta com dados reais de velocidade; cair para primeira disponível + const portas = resultado.portasEthernet || []; + const portaComDados = portas.find(p => p.status !== 'unknown' && p.speed); + const portaAtiva = portas.find(p => p.status === 'active'); + const portaBase = portaComDados || portaAtiva || (portas.length > 0 ? portas[0] : null); + + let portaEthernetStr = null; + if (portaBase && portaBase.status !== 'unknown') { + const statusLabel = portaBase.status === 'active' ? 'up' : 'down'; + portaEthernetStr = portaBase.speed + ? `${statusLabel} — ${portaBase.speed}` + : statusLabel; + } + + // rxPower: retornar null se for 'N/A' para que a UI mostre 'N/A' via fallback + const rxPower = resultado.rxPower && resultado.rxPower !== 'N/A' ? resultado.rxPower : null; return { success: true, type: 'fiberhome', - oltName: 'FiberHome', + oltName: 'FiberHome AN5516', slot: resultado.slot, pon: resultado.pon, onuId: resultado.onuId, online: resultado.online, - rxPower: resultado.rxPower, - txPower: resultado.txPower, - portaEthernet: portaPrincipal ? `${portaPrincipal.status}` : null + rxPower, + txPower: resultado.txPower !== 'N/A' ? resultado.txPower : null, + portaEthernet: portaEthernetStr }; } diff --git a/src/fiberhome/manager.js b/src/fiberhome/manager.js index 71074e8..ada89f0 100644 --- a/src/fiberhome/manager.js +++ b/src/fiberhome/manager.js @@ -723,18 +723,62 @@ class FiberhomeManager { // Processar LST-ONULANINFO (portas ethernet) if (resposta.comando && resposta.comando.includes('LST-ONULANINFO')) { - // Extrair informações das portas - const portMatches = dados.matchAll(/PORT\s*=\s*(\d+).*?STATUS\s*=\s*(\w+)/gi); - for (const match of portMatches) { - const portNum = parseInt(match[1]); - const status = match[2].toLowerCase(); - - if (portNum >= 1 && portNum <= 4) { - if (!resultado.portasEthernet[portNum-1]) { - resultado.portasEthernet[portNum-1] = { porta: portNum, status: 'unknown' }; + const linhasLan = dados.split(/[\r\n]+/); + // Detectar linha de cabeçalho (formato tabular TL1) + const headerLan = linhasLan.find(l => + /ONUPORT/i.test(l) || (/SPEED/i.test(l) && /ONUNO/i.test(l)) + ); + + if (headerLan) { + // Formato TL1 tab-separado + const headerFields = headerLan.trim().split(/\t/).map(f => f.trim().toUpperCase()); + const idxPort = headerFields.findIndex(h => h === 'ONUPORT'); + const idxState = headerFields.findIndex(h => h === 'ADMINSTATE' || h === 'CURSTATE' || h === 'STATUS'); + const idxSpeed = headerFields.findIndex(h => h === 'CURRNEGOTYPE' || h === 'SPEED'); + const idxDuplex = headerFields.findIndex(h => h === 'DUPLEXMODE' || h === 'DUPLEX'); + + for (const linha of linhasLan) { + if (linha === headerLan || !linha.trim() || + /---+|COMPLD|total_blocks/i.test(linha)) continue; + const campos = linha.trim().split(/\t/).map(f => f.trim()); + if (campos.length < 4) continue; + + // ONUPORT formato: NA-NA-slot-pon-portnum + const portField = idxPort >= 0 ? campos[idxPort] : ''; + const portMatch = portField.match(/[^-](\d+)$/); + if (!portMatch) continue; + const portNum = parseInt(portMatch[1]); + if (portNum < 1 || portNum > 8) continue; + + const stateVal = idxState >= 0 ? campos[idxState] : ''; + const speedVal = idxSpeed >= 0 ? campos[idxSpeed] : ''; + const duplexVal = idxDuplex >= 0 ? campos[idxDuplex] : ''; + + const isUp = /up|enable|active/i.test(stateVal); + const speedClean = speedVal && !/^(?:auto|--)$/i.test(speedVal) ? speedVal : null; + const duplexClean = duplexVal && !/^(?:auto|--)$/i.test(duplexVal) ? duplexVal : null; + const speedLabel = speedClean + ? (duplexClean ? `${speedClean} ${duplexClean}` : speedClean) + : null; + + resultado.portasEthernet[portNum - 1] = { + porta: portNum, + status: isUp ? 'active' : 'inactive', + speed: speedLabel + }; + } + } else { + // Fallback: formato key=value legado + const portMatches = dados.matchAll(/PORT\s*[=:]\s*(\d+).*?STATUS\s*[=:]\s*(\w+)/gis); + for (const match of portMatches) { + const portNum = parseInt(match[1]); + const status = match[2].toLowerCase(); + if (portNum >= 1 && portNum <= 4) { + resultado.portasEthernet[portNum - 1] = { + porta: portNum, + status: status === 'up' ? 'active' : status === 'down' ? 'inactive' : 'unknown' + }; } - resultado.portasEthernet[portNum-1].status = status === 'up' ? 'active' : - status === 'down' ? 'inactive' : 'unknown'; } } }