diff --git a/src/bot/handler.js b/src/bot/handler.js index 747b69a..cea71ce 100644 --- a/src/bot/handler.js +++ b/src/bot/handler.js @@ -2,6 +2,7 @@ const NLPProcessor = require('../nlp/processor'); const SSHManager = require('../ssh/manager'); const { TopSappManager } = require('../topsapp'); const FiberhomeManager = require('../fiberhome/manager'); +const FiberhomeTL1Manager = require('../fiberhome/manager_tl1'); const config = require('../config/config'); const logger = require('../utils/logger'); const DateProcessor = require('../utils/dateProcessor'); @@ -13,6 +14,7 @@ class BotHandler { this.ssh = new SSHManager(); this.topsapp = new TopSappManager(); this.fiberhome = new FiberhomeManager(); + this.fiberhomeTL1 = new FiberhomeTL1Manager(); this.dateProcessor = new DateProcessor(); this.userSessions = new Map(); // Armazena sessões de usuário this.suporteSessions = new Map(); // Armazena sessões de suporte em andamento @@ -895,10 +897,14 @@ Digite /help para ver todos os comandos disponíveis! const result = await this.ssh.checkOnuSignalBySerial(oltId, serialNumber); if (result.success) { - let message = `📡 *Sinal da ONU ${serialNumber}*\n\n`; - message += `🏢 **OLT:** ${olt.name} (${olt.host})\n`; - message += `📍 **Localização:** Slot ${result.slot}, ONU ${result.onuId}\n\n`; - message += `📊 **Informações do Sinal:**\n`; + // Escapar caracteres especiais do Markdown + const oltNameEscaped = olt.name.replace(/_/g, '\\_'); + const serialEscaped = serialNumber.replace(/_/g, '\\_'); + + let message = `📡 *Sinal da ONU ${serialEscaped}*\n\n`; + message += `🏢 *OLT:* ${oltNameEscaped} (${olt.host})\n`; + message += `📍 *Localização:* Slot ${result.slot}, ONU ${result.onuId}\n\n`; + message += `📊 *Informações do Sinal:*\n`; message += `\`\`\`\n${result.signalOutput}\n\`\`\``; await this.bot.sendMessage(chatId, message, { parse_mode: 'Markdown' }); @@ -975,8 +981,11 @@ Digite /help para ver todos os comandos disponíveis! { text: '❌ Cancelar', callback_data: 'cancel_action' } ]); + // Escapar caracteres especiais do serial + const serialEscaped = serialNumber.replace(/_/g, '\\_'); + await this.bot.sendMessage(chatId, - `🗑️ **Remover ONU ${serialNumber}**\n\n` + + `🗑️ *Remover ONU ${serialEscaped}*\n\n` + '🏢 Selecione a OLT onde a ONU está configurada:', { reply_markup: keyboard, @@ -1013,8 +1022,11 @@ Digite /help para ver todos os comandos disponíveis! { text: '❌ Cancelar', callback_data: 'cancel_action' } ]); + // Escapar caracteres especiais + const serialEscaped = serialNumber.replace(/_/g, '\\_'); + await this.bot.sendMessage(chatId, - `➕ **Adicionar ONU ${serialNumber}**\n\n` + + `➕ *Adicionar ONU ${serialEscaped}*\n\n` + '🏢 Selecione a OLT onde deseja adicionar a ONU:', { reply_markup: keyboard, @@ -1056,10 +1068,13 @@ Digite /help para ver todos os comandos disponíveis! { text: '❌ Cancelar', callback_data: 'cancel_action' } ]); + // Escapar caracteres especiais + const serialEscaped = serialNumber.replace(/_/g, '\\_'); + await this.bot.sendMessage(chatId, - `➕ **Adicionar ONU com VLAN Customizada**\n\n` + - `📱 **Serial:** ${serialNumber}\n` + - `🏷️ **VLAN:** ${vlanId}\n\n` + + `➕ *Adicionar ONU com VLAN Customizada*\n\n` + + `📱 *Serial:* ${serialEscaped}\n` + + `🏷️ *VLAN:* ${vlanId}\n\n` + '🏢 Selecione a OLT onde deseja adicionar a ONU:', { reply_markup: keyboard, @@ -1081,6 +1096,8 @@ Digite /help para ver todos os comandos disponíveis! return; } + console.log(`📝 Criando sessão para usuário ${userId}, serial: ${serialNumber}`); + // Criar sessão para coletar informações this.userSessions.set(userId, { action: 'adicionar_onu_fiberhome_step1', @@ -1088,12 +1105,17 @@ Digite /help para ver todos os comandos disponíveis! timestamp: Date.now() }); + console.log(`✅ Sessão criada. Sessões ativas:`, this.userSessions.size); + + // Escapar caracteres especiais + const serialEscaped = serialNumber.replace(/_/g, '\\_'); + // Perguntar o alias/nome do usuário await this.bot.sendMessage(chatId, - `➕ **Adicionar ONU Fiberhome**\n\n` + - `📱 **Serial:** ${serialNumber}\n` + + `➕ *Adicionar ONU Fiberhome*\n\n` + + `📱 *Serial:* ${serialEscaped}\n` + `🔍 A porta PON será descoberta automaticamente\n\n` + - '👤 Digite o **nome/alias** do usuário:', + '👤 Digite o *nome/alias* do usuário:', { parse_mode: 'Markdown' } ); } @@ -1103,57 +1125,77 @@ Digite /help para ver todos os comandos disponíveis! */ async handleUserSessionInput(chatId, text, userId, session) { try { - switch (session.action) { - case 'adicionar_onu_fiberhome_step1': - // Recebeu o nome do usuário, agora perguntar pelo tipo da ONU - session.usuario = text.trim(); - session.action = 'adicionar_onu_fiberhome_step2'; - this.userSessions.set(userId, session); + console.log(`🔄 Processando input de sessão. Action: ${session.action}, Type: ${session.type}, Text: ${text}`); + + // Verificar se é sessão baseada em action (Fiberhome ONU) + if (session.action) { + switch (session.action) { + case 'adicionar_onu_fiberhome_step1': + // Recebeu o nome do usuário, adicionar sufixo e perguntar pelo tipo da ONU + const usuarioBase = text.trim(); + session.usuario = usuarioBase.includes('@') ? usuarioBase : `${usuarioBase}@clicknetguarai.com.br`; + session.action = 'adicionar_onu_fiberhome_step2'; + this.userSessions.set(userId, session); - const keyboard = { - inline_keyboard: [ - [{ text: '🔌 AN5506-02-B (2 portas)', callback_data: 'fh_onu_type_AN5506-02-B' }], - [{ text: '🔌 AN5506-01-A (1 porta)', callback_data: 'fh_onu_type_AN5506-01-A' }], - [{ text: '❌ Cancelar', callback_data: 'cancel_action' }] - ] - }; + const keyboard = { + inline_keyboard: [ + [{ text: '🔌 AN5506-02-B (2 portas)', callback_data: 'fh_onu_type_AN5506-02-B' }], + [{ text: '🔌 AN5506-01-A (1 porta)', callback_data: 'fh_onu_type_AN5506-01-A' }], + [{ text: '❌ Cancelar', callback_data: 'cancel_action' }] + ] + }; - await this.bot.sendMessage(chatId, - `📡 **Porta PON:** ${session.portAlias}\n\n` + - '🔌 Selecione o **tipo da ONU**:', - { reply_markup: keyboard, parse_mode: 'Markdown' } - ); - break; + await this.bot.sendMessage(chatId, + `👤 **Usuário:** ${session.usuario}\n\n` + + '🔌 Selecione o **tipo da ONU**:', + { reply_markup: keyboard, parse_mode: 'Markdown' } + ); + return; - case 'adicionar_onu_fiberhome_step5': - // Recebeu confirmação de VLAN customizada - const vlanInput = text.trim(); - - if (vlanInput && !isNaN(vlanInput)) { - const vlan = parseInt(vlanInput); - if (vlan >= 1 && vlan <= 4094) { - session.vlan = vlan; + case 'adicionar_onu_fiberhome_step3': + // Recebeu confirmação de VLAN customizada + const vlanInput = text.trim(); + + if (vlanInput && !isNaN(vlanInput)) { + const vlan = parseInt(vlanInput); + if (vlan >= 1 && vlan <= 4094) { + session.vlan = vlan; + } else { + await this.bot.sendMessage(chatId, '❌ VLAN inválida. Usando VLAN padrão 1002.'); + session.vlan = 1002; + } } else { - await this.bot.sendMessage(chatId, '❌ VLAN inválida. Usando VLAN padrão 1002.'); session.vlan = 1002; } - } else { - session.vlan = 1002; - } - // Limpar sessão - this.userSessions.delete(userId); + // Limpar sessão + this.userSessions.delete(userId); - // Executar adição da ONU - await this.executarAdicaoOnuFiberhome(chatId, session); - break; - - default: - // Sessão desconhecida, limpar - this.userSessions.delete(userId); - await this.bot.sendMessage(chatId, '❌ Sessão expirada. Por favor, comece novamente.'); - break; + // Executar adição da ONU + await this.executarAdicaoOnuFiberhome(chatId, session); + return; + } } + + // Verificar se é sessão baseada em type (outros fluxos) + if (session.type) { + switch (session.type) { + case 'waiting_custom_command': + await this.executeCustomCommand(chatId, session.connectionId, text); + this.userSessions.delete(userId); + return; + + case 'waiting_username_disconnect': + await this.handleDisconnectUser(chatId, text.trim()); + this.userSessions.delete(userId); + return; + } + } + + // Estado desconhecido + console.log(`❓ Estado de sessão desconhecido: action=${session.action}, type=${session.type}`); + this.userSessions.delete(userId); + await this.bot.sendMessage(chatId, '❓ Estado de sessão desconhecido. Tente novamente.'); } catch (error) { console.error('❌ Erro ao processar input da sessão:', error); this.userSessions.delete(userId); @@ -1168,18 +1210,21 @@ Digite /help para ver todos os comandos disponíveis! try { const { serial, usuario, vlan, onuType } = session; + // Escapar caracteres especiais + const serialEscaped = serial.replace(/_/g, '\\_'); + await this.bot.sendMessage(chatId, `⏳ Adicionando ONU Fiberhome...\n\n` + `🔍 Descobrindo porta PON automaticamente...\n` + - `👤 **Usuário:** ${usuario}\n` + - `📱 **Serial:** ${serial}\n` + - `🔌 **Tipo:** ${onuType}\n` + - `🏷️ **VLAN:** ${vlan}`, + `👤 *Usuário:* ${usuario}\n` + + `📱 *Serial:* ${serialEscaped}\n` + + `🔌 *Tipo:* ${onuType}\n` + + `🏷️ *VLAN:* ${vlan}`, { parse_mode: 'Markdown' } ); // Executar comando TL1 via Fiberhome Manager - const resultado = await this.fiberhome.adicionarOnuFiberhome( + const resultado = await this.fiberhomeTL1.adicionarOnuFiberhome( serial, usuario, vlan, @@ -1187,22 +1232,26 @@ Digite /help para ver todos os comandos disponíveis! ); if (resultado.success) { + // Escapar caracteres especiais do Markdown + const oltEscaped = resultado.details.olt.replace(/_/g, '\\_'); + const serialEscaped = serial.replace(/_/g, '\\_'); + await this.bot.sendMessage(chatId, - `✅ **ONU Fiberhome Adicionada com Sucesso!**\n\n` + - `👤 **Usuário:** ${usuario}\n` + - `🏢 **OLT:** ${resultado.details.olt}\n` + - `📡 **Porta descoberta:** Slot ${resultado.details.slot}, PON ${resultado.details.ponPort}\n` + - `📱 **Serial:** ${serial}\n` + - `🔌 **Tipo:** ${onuType}\n` + - `🏷️ **VLAN:** ${vlan}\n` + - `⚙️ **Portas configuradas:** ${resultado.details.portas}\n\n` + - `🔐 **Login Web:** admin / clicknet10\n\n` + + `✅ *ONU Fiberhome Adicionada com Sucesso!*\n\n` + + `👤 *Usuário:* ${usuario}\n` + + `🏢 *OLT:* ${oltEscaped}\n` + + `📡 *Porta descoberta:* Slot ${resultado.details.slot}, PON ${resultado.details.ponPort}\n` + + `📱 *Serial:* ${serialEscaped}\n` + + `🔌 *Tipo:* ${onuType}\n` + + `🏷️ *VLAN:* ${vlan}\n` + + `⚙️ *Portas configuradas:* ${resultado.details.portas}\n\n` + + `🔐 Login Web: \`admin / clicknet10\`\n\n` + `⚡ A ONU foi reiniciada e estará disponível em alguns instantes.`, { parse_mode: 'Markdown' } ); } else { await this.bot.sendMessage(chatId, - `❌ **Erro ao adicionar ONU Fiberhome**\n\n` + + `❌ *Erro ao adicionar ONU Fiberhome*\n\n` + `⚠️ ${resultado.error}`, { parse_mode: 'Markdown' } ); @@ -1211,7 +1260,7 @@ Digite /help para ver todos os comandos disponíveis! } catch (error) { console.error('❌ Erro ao executar adição de ONU Fiberhome:', error); await this.bot.sendMessage(chatId, - `❌ **Erro ao adicionar ONU Fiberhome**\n\n` + + `❌ *Erro ao adicionar ONU Fiberhome*\n\n` + `⚠️ ${error.message}`, { parse_mode: 'Markdown' } ); @@ -1548,25 +1597,8 @@ Digite /help para ver todos os comandos disponíveis! } /** - * Lida com input de usuário durante sessões específicas + * MÉTODO REMOVIDO - handleUserSessionInput duplicado foi mesclado acima */ - async handleUserSessionInput(chatId, text, userId, session) { - switch (session.type) { - case 'waiting_custom_command': - await this.executeCustomCommand(chatId, session.connectionId, text); - break; - - case 'waiting_username_disconnect': - await this.handleDisconnectUser(chatId, text.trim()); - break; - - default: - await this.bot.sendMessage(chatId, '❓ Estado de sessão desconhecido. Tente novamente.'); - } - - // Limpar sessão - this.userSessions.delete(userId); - } /** * Executa comando personalizado em uma conexão SSH @@ -1635,7 +1667,10 @@ Digite /help para ver todos os comandos disponíveis! * Executa verificação de sinal na OLT Fiberhome */ async handleCheckSignalFiberhome(chatId, serialNumber) { - await this.bot.sendMessage(chatId, `🔍 Procurando ONU ${serialNumber} na OLT Fiberhome...`); + // Escapar caracteres especiais + const serialEscaped = serialNumber.replace(/_/g, '\\_'); + + await this.bot.sendMessage(chatId, `🔍 Procurando ONU ${serialEscaped} na OLT Fiberhome...`); try { // Usar a mesma lógica do handleStatusONU @@ -1650,26 +1685,26 @@ Digite /help para ver todos os comandos disponíveis! if (resultado.success) { // Formatar resposta similar às OLTs Datacom - let message = `📡 *Sinal da ONU ${serialNumber}*\n\n`; - message += `🏢 **OLT:** Fiberhome UNM2000 (131.0.192.9)\n`; - message += `📍 **Localização:** Slot ${resultado.slot}, PON ${resultado.pon}, ONU ${resultado.onuId}\n`; - message += `🔌 **Status:** ${resultado.online ? '🟢 Online' : '🔴 Offline'}\n\n`; + let message = `📡 *Sinal da ONU ${serialEscaped}*\n\n`; + message += `🏢 *OLT:* Fiberhome UNM2000 (131.0.192.9)\n`; + message += `📍 *Localização:* Slot ${resultado.slot}, PON ${resultado.pon}, ONU ${resultado.onuId}\n`; + message += `🔌 *Status:* ${resultado.online ? '🟢 Online' : '🔴 Offline'}\n\n`; - message += `📊 **Informações do Sinal:**\n`; - message += `📡 **RX Power:** ${resultado.rxPower}\n`; - message += `📤 **TX Power:** ${resultado.txPower}\n`; - message += `📏 **Distância:** ${resultado.distance}\n\n`; + message += `📊 *Informações do Sinal:*\n`; + message += `📡 *RX Power:* ${resultado.rxPower}\n`; + message += `📤 *TX Power:* ${resultado.txPower}\n`; + message += `📏 *Distância:* ${resultado.distance}\n\n`; // Status das portas Ethernet (resumido) if (resultado.portasEthernet.length > 0) { const portasAtivas = resultado.portasEthernet.filter(p => p.status === 'active' || p.status === 'up').length; - message += `🔗 **Portas Ethernet:** ${portasAtivas}/${resultado.portasEthernet.length} ativas\n`; + message += `🔗 *Portas Ethernet:* ${portasAtivas}/${resultado.portasEthernet.length} ativas\n`; } // Serviços WAN if (resultado.servicosWAN.length > 0) { const servicosAtivos = resultado.servicosWAN.filter(s => s.status === 'active').length; - message += `🌐 **Serviços WAN:** ${servicosAtivos} ativo(s)\n`; + message += `🌐 *Serviços WAN:* ${servicosAtivos} ativo(s)\n`; } await this.bot.sendMessage(chatId, message, { parse_mode: 'Markdown' }); @@ -2639,7 +2674,7 @@ Digite /help para ver todos os comandos disponíveis! // Recuperar sessão const session = this.userSessions.get(userId); - if (!session || session.action !== 'adicionar_onu_fiberhome_step4') { + if (!session || session.action !== 'adicionar_onu_fiberhome_step2') { await this.bot.answerCallbackQuery(callbackQuery.id, '❌ Sessão expirada'); await this.bot.sendMessage(chatId, '❌ Sessão expirada. Por favor, comece novamente.'); this.userSessions.delete(userId); @@ -2647,6 +2682,8 @@ Digite /help para ver todos os comandos disponíveis! } session.onuType = onuType; + session.action = 'adicionar_onu_fiberhome_step3'; + this.userSessions.set(userId, session); await this.bot.answerCallbackQuery(callbackQuery.id); @@ -2681,7 +2718,7 @@ Digite /help para ver todos os comandos disponíveis! // Recuperar sessão const session = this.userSessions.get(userId); - if (!session || session.action !== 'adicionar_onu_fiberhome_step2') { + if (!session || session.action !== 'adicionar_onu_fiberhome_step3') { await this.bot.answerCallbackQuery(callbackQuery.id, '❌ Sessão expirada'); await this.bot.sendMessage(chatId, '❌ Sessão expirada. Por favor, comece novamente.'); this.userSessions.delete(userId); @@ -2701,10 +2738,7 @@ Digite /help para ver todos os comandos disponíveis! await this.executarAdicaoOnuFiberhome(chatId, session); } else if (data === 'fh_vlan_custom') { - // Pedir VLAN customizada - session.action = 'adicionar_onu_fiberhome_step3'; - this.userSessions.set(userId, session); - + // Pedir VLAN customizada - manter sessão no step3 para receber input do usuário await this.bot.editMessageText( `🏷️ **VLAN Customizada**\n\n` + `Digite o número da VLAN que deseja usar (1-4094):`, diff --git a/src/fiberhome/manager_tl1.js b/src/fiberhome/manager_tl1.js index ffb7a37..cc3ab4a 100644 --- a/src/fiberhome/manager_tl1.js +++ b/src/fiberhome/manager_tl1.js @@ -56,10 +56,12 @@ class FiberhomeManager { async conectarUNM2000() { try { if (this.tl1Connection && !this.tl1Connection.destroyed) { + console.log('✅ Conexão TL1 já existe e está ativa'); this.logger.debug('Conexão TL1 já existe e está ativa'); return true; } + console.log('🔌 Conectando ao UNM2000 via TL1:', this.config.unm2000); this.logger.debug('Conectando ao UNM2000 via TL1', this.config.unm2000); return new Promise((resolve, reject) => { @@ -72,43 +74,55 @@ class FiberhomeManager { // Handler para dados recebidos this.tl1Connection.on('data', (data) => { dataBuffer += data.toString(); + console.log('📥 TL1 dados recebidos:', dataBuffer); this.logger.debug('TL1 dados recebidos:', dataBuffer); // Verificar se login foi bem-sucedido if (!authenticated && dataBuffer.includes('COMPLD')) { authenticated = true; + console.log('✅ Login TL1 bem-sucedido!'); this.logger.info('Login TL1 bem-sucedido'); resolve(true); + } else if (!authenticated && dataBuffer.includes('DENY')) { + console.log('❌ Login TL1 negado!'); + this.logger.error('Login TL1 negado'); + reject(new Error('Login TL1 negado')); } }); this.tl1Connection.connect(this.config.unm2000.port, this.config.unm2000.host, () => { + console.log('🔗 Socket TL1 conectado, enviando comando de login'); this.logger.debug('Socket TL1 conectado, enviando comando de login'); - // Comando de login TL1 - const loginCommand = `ACT-USER::${this.config.unm2000.username}:${this.commandId++}::${this.config.unm2000.password};`; + // Comando de login TL1 - formato correto: LOGIN:::CTAG::UN=username,PWD=password; + const loginCommand = `LOGIN:::${this.commandId++}::UN=${this.config.unm2000.username},PWD=${this.config.unm2000.password};`; + console.log('📤 Enviando login:', loginCommand); this.tl1Connection.write(loginCommand + '\r\n'); // Timeout para autenticação setTimeout(() => { if (!authenticated) { - this.logger.error('Timeout na autenticação TL1'); + console.log('⏱️ Timeout na autenticação TL1 (10s). DataBuffer:', dataBuffer); + this.logger.error('Timeout na autenticação TL1', { dataBuffer }); reject(new Error('Timeout na autenticação TL1')); } }, 10000); }); this.tl1Connection.on('error', (error) => { + console.log('❌ Erro na conexão TL1:', error.message); this.logger.error('Erro na conexão TL1', error); reject(error); }); this.tl1Connection.on('timeout', () => { + console.log('⏱️ Timeout do socket TL1'); this.logger.error('Timeout na conexão TL1'); reject(new Error('Timeout na conexão TL1')); }); this.tl1Connection.on('close', () => { + console.log('🔌 Conexão TL1 fechada'); this.logger.debug('Conexão TL1 fechada'); this.tl1Connection = null; }); @@ -386,6 +400,7 @@ class FiberhomeManager { */ async descobrirPortaPON(serial) { try { + console.log('🔍 Descobrindo porta PON para ONU:', serial); this.logger.debug('Descobrindo porta PON para ONU', { serial }); // Conectar ao UNM2000 @@ -394,18 +409,89 @@ class FiberhomeManager { throw new Error('Não foi possível conectar ao UNM2000'); } - // Buscar em todas as portas PON possíveis (slots 1-20, portas 1-16) - for (let slot = 1; slot <= 20; slot++) { - for (let porta = 1; porta <= 16; porta++) { + let tentativas = 0; + const maxTentativas = 320; // Máximo de tentativas (20 slots x 16 portas) + + // Primeiro, tentar listar dispositivos para descobrir o nome correto da OLT + console.log('📋 Listando dispositivos OLT...'); + const listarCmd = `LST-DEVICE:::${this.commandId++}::;`; + const dispositivos = await this.executarComandoTL1(listarCmd); + + let oltName = this.config.olt.name; // Fallback para o IP configurado + + if (dispositivos.success && dispositivos.data) { + console.log('📋 Resposta LST-DEVICE:', dispositivos.data); + + // Extrair DEVNAME da resposta (formato: AN5516-06_172.16.10.6) + const match = dispositivos.data.match(/^([^\s]+)\s+[\d\.]+\s+AN5516/m); + if (match && match[1]) { + oltName = match[1]; + console.log(`✅ Nome da OLT descoberto: ${oltName}`); + // Atualizar configuração para uso futuro + this.config.olt.name = oltName; + } else { + console.log('⚠️ Não foi possível extrair DEVNAME, usando IP como fallback'); + } + } else { + console.log('⚠️ Não foi possível listar dispositivos:', dispositivos.error); + } + + // Listar placas PON instaladas para saber quais slots existem + console.log('📋 Listando placas PON instaladas...'); + const listarBoardsCmd = `LST-BOARD::OLTID=${oltName}:${this.commandId++}::;`; + const boards = await this.executarComandoTL1(listarBoardsCmd); + + let slotsDisponiveis = []; + if (boards.success && boards.data) { + console.log('📋 Placas encontradas:', boards.data); + + // Extrair slots das placas GPON (formato BOARDID: 1-1-slot, tipo: GCOB ou GC8B) + // Exemplo: "1-1-12 GCOB GPON 16" + const ponLines = boards.data.split('\n'); + for (const line of ponLines) { + // Verificar se a linha contém placa GPON + if (line.includes('GPON')) { + // Extrair BOARDID no formato rack-shelf-slot (ex: 1-1-12) + const boardMatch = line.match(/(\d+)-(\d+)-(\d+)\s+(GCOB|GC8B)\s+GPON/); + if (boardMatch) { + const slot = parseInt(boardMatch[3]); // Pegar o terceiro número (slot) + const numPortas = parseInt(line.match(/GPON\s+(\d+)/)[1]); // Número de portas + if (!slotsDisponiveis.find(s => s.slot === slot)) { + slotsDisponiveis.push({ slot, portas: numPortas }); + } + } + } + } + + slotsDisponiveis.sort((a, b) => a.slot - b.slot); + console.log(`✅ Slots PON disponíveis:`, slotsDisponiveis.map(s => `${s.slot} (${s.portas} portas)`).join(', ')); + } + + if (slotsDisponiveis.length === 0) { + console.log('⚠️ Nenhuma placa GPON encontrada, tentando slots 1-20'); + // Fallback: tentar todos os slots de 1 a 20 com 16 portas + slotsDisponiveis = Array.from({length: 20}, (_, i) => ({ slot: i + 1, portas: 16 })); + } + + // Buscar em todas as portas PON dos slots disponíveis + for (const slotInfo of slotsDisponiveis) { + if (tentativas >= maxTentativas) break; + + const { slot, portas } = slotInfo; + + for (let porta = 1; porta <= portas && tentativas < maxTentativas; porta++) { + tentativas++; const ponId = `NA-NA-${slot}-${porta}`; - const comando = `LST-UNREGONU::OLTID=${this.config.olt.name},PONID=${ponId}:${this.commandId++}::;`; + const comando = `LST-UNREGONU::OLTID=${oltName},PONID=${ponId}:${this.commandId++}::;`; - this.logger.debug('Consultando porta PON', { ponId }); + console.log(`🔎 Consultando porta PON ${ponId} (slot ${slot}, porta ${porta}/${portas})`); + this.logger.debug('Consultando porta PON', { ponId, tentativa: tentativas, oltName }); const resultado = await this.executarComandoTL1(comando); if (resultado.success && resultado.data) { // Verificar se a ONU está na resposta if (resultado.data.toUpperCase().includes(serial.toUpperCase())) { + console.log(`✅ Porta PON descoberta: ${ponId}`); this.logger.info('Porta PON descoberta', { serial, ponId }); return { success: true, @@ -414,21 +500,30 @@ class FiberhomeManager { porta }; } + } else if (!resultado.success) { + console.log(`⚠️ Erro ao consultar porta ${ponId}: ${resultado.error}`); + // Se o erro for de formato, provavelmente todas as portas vão falhar + if (resultado.error && resultado.error.includes('invalid parameter format')) { + console.log('❌ Formato de comando inválido, interrompendo busca'); + throw new Error('Formato de comando LST-UNREGONU inválido. Verifique configuração da OLT.'); + } } // Pequeno delay entre consultas para não sobrecarregar - await new Promise(resolve => setTimeout(resolve, 100)); + await new Promise(resolve => setTimeout(resolve, 200)); } } // ONU não encontrada - this.logger.warn('ONU não encontrada em nenhuma porta PON', { serial }); + console.log(`❌ ONU ${serial} não encontrada após ${tentativas} tentativas`); + this.logger.warn('ONU não encontrada em nenhuma porta PON', { serial, tentativas }); return { success: false, error: 'ONU não encontrada em nenhuma porta PON. Verifique se a ONU está ligada e descoberta pela OLT.' }; } catch (error) { + console.log('❌ Erro ao descobrir porta PON:', error.message); this.logger.error('Erro ao descobrir porta PON', { serial, error: error.message }); return { success: false,