fix TopSapp

This commit is contained in:
rodrigo committed 2025-08-10 13:54:46 -03:00
1 parent 8dc6c594c9
commit bae6adefcb
42 files changed
+43645 -105

No files matched your search

+961
View File
@@ -0,0 +1,961 @@
const net = require('net');
class FiberhomeManager {
constructor() {
this.tl1Connection = null;
this.commandId = 1;
// Configuração apenas para UNM2000 via TL1
this.config = {
unm2000: {
host: '131.0.192.9',
port: 3337,
username: '1',
password: '1',
timeout: 15000,
defaultOLT: 'AN5516-06_172.16.10.6' // Nome correto da OLT no sistema
}
};
this.logger = require('../utils/logger');
}
/**
* Testar conectividade de rede com um host
*/
async testarConectividade(host, port, timeout = 5000) {
return new Promise((resolve) => {
const socket = new net.Socket();
socket.setTimeout(timeout);
socket.connect(port, host, () => {
this.logger.debug(`Conectividade OK: ${host}:${port}`);
socket.destroy();
resolve(true);
});
socket.on('error', (error) => {
this.logger.debug(`Erro de conectividade ${host}:${port}:`, error.message);
resolve(false);
});
socket.on('timeout', () => {
this.logger.debug(`Timeout de conectividade ${host}:${port}`);
socket.destroy();
resolve(false);
});
});
}
/**
* Conectar ao UNM2000 via TL1
*/
async conectarUNM2000() {
try {
this.logger.debug('=== INICIO CONEXAO UNM2000 ===');
this.logger.debug('Configuração:', this.config.unm2000);
if (this.tl1Connection && !this.tl1Connection.destroyed) {
this.logger.debug('Conexão TL1 já existe e está ativa');
return true;
}
this.logger.debug('Conectando ao UNM2000 via TL1', this.config.unm2000);
// Primeiro testar conectividade básica
this.logger.debug('Testando conectividade básica...');
const conectividade = await this.testarConectividade(
this.config.unm2000.host,
this.config.unm2000.port,
5000
);
if (!conectividade) {
this.logger.error(`Host ${this.config.unm2000.host}:${this.config.unm2000.port} não acessível`);
throw new Error(`Host ${this.config.unm2000.host}:${this.config.unm2000.port} não acessível`);
}
this.logger.debug('Conectividade básica OK, iniciando conexão TL1...');
return new Promise((resolve, reject) => {
this.tl1Connection = new net.Socket();
let authenticated = false;
let dataBuffer = '';
this.tl1Connection.setTimeout(this.config.unm2000.timeout);
// Handler para dados recebidos
this.tl1Connection.on('data', (data) => {
const receivedData = data.toString();
dataBuffer += receivedData;
this.logger.debug('TL1 dados recebidos:', {
raw: receivedData,
buffer: dataBuffer
});
// Verificar padrões de sucesso no login TL1 Fiberhome
if (!authenticated) {
if (dataBuffer.includes('COMPLD') ||
dataBuffer.includes('M COMPLD') ||
dataBuffer.includes('IP') ||
dataBuffer.includes('>')) {
authenticated = true;
this.logger.info('Login TL1 Fiberhome bem-sucedido');
resolve(true);
}
// Padrões de erro
else if (dataBuffer.includes('DENY') ||
dataBuffer.includes('FAIL') ||
dataBuffer.includes('ERROR')) {
this.logger.error('Login TL1 negado:', dataBuffer);
reject(new Error('Login TL1 negado pelo equipamento'));
}
}
});
this.tl1Connection.connect(this.config.unm2000.port, this.config.unm2000.host, () => {
this.logger.debug('Socket TL1 conectado, enviando login Fiberhome');
// Aguardar um pouco para receber prompt inicial
setTimeout(() => {
// Comando de login TL1 formato Fiberhome
const loginCommand = `LOGIN:::CTAG::UN=${this.config.unm2000.username},PWD=${this.config.unm2000.password};`;
this.logger.debug('Enviando comando login TL1 Fiberhome:', loginCommand);
this.tl1Connection.write(loginCommand + '\r\n');
}, 1000);
// Timeout para autenticação
setTimeout(() => {
if (!authenticated) {
this.logger.error('Timeout na autenticação TL1 - dados recebidos:', dataBuffer);
reject(new Error(`Timeout na autenticação TL1. Dados: ${dataBuffer.substring(0, 200)}`));
}
}, 12000);
});
this.tl1Connection.on('error', (error) => {
this.logger.error('Erro na conexão TL1', error);
reject(error);
});
this.tl1Connection.on('timeout', () => {
this.logger.error('Timeout na conexão TL1');
reject(new Error('Timeout na conexão TL1'));
});
this.tl1Connection.on('close', () => {
this.logger.debug('Conexão TL1 fechada');
this.tl1Connection = null;
});
});
} catch (error) {
this.logger.error('=== ERRO NA CONEXAO UNM2000 ===');
this.logger.error('Erro detalhado:', {
message: error.message,
code: error.code,
errno: error.errno,
syscall: error.syscall,
address: error.address,
port: error.port
});
this.logger.error('Erro ao conectar UNM2000', error);
return false;
}
}
/**
* Método de teste para verificar comandos TL1 básicos
*/
async testarComandoTL1(comando) {
try {
this.logger.debug('=== TESTE TL1 ===');
this.logger.debug('Comando:', comando);
const conectado = await this.conectarUNM2000();
if (!conectado) {
throw new Error('Não foi possível conectar ao UNM2000');
}
const resultado = await this.executarComandoTL1(comando);
this.logger.debug('=== RESULTADO TESTE TL1 ===');
this.logger.debug('Success:', resultado.success);
this.logger.debug('Error:', resultado.error);
this.logger.debug('Data length:', resultado.data ? resultado.data.length : 0);
this.logger.debug('Data:', resultado.data);
this.logger.debug('=== FIM TESTE TL1 ===');
return resultado;
} catch (error) {
this.logger.error('Erro no teste TL1:', error.message);
return { success: false, error: error.message };
}
}
/**
* Executar comando TL1
*/
async executarComandoTL1(comando) {
try {
this.logger.debug('Executando comando TL1', { comando });
if (!this.tl1Connection || this.tl1Connection.destroyed) {
const conectado = await this.conectarUNM2000();
if (!conectado) {
throw new Error('Não foi possível conectar ao UNM2000');
}
}
return new Promise((resolve, reject) => {
let dataBuffer = '';
let responseReceived = false;
// Handler temporário para esta consulta
const dataHandler = (data) => {
dataBuffer += data.toString();
this.logger.debug('Resposta TL1 acumulada:', {
comando,
responseLength: dataBuffer.length,
response: dataBuffer
});
// Verificar se a resposta está completa (formato Fiberhome)
if ((dataBuffer.includes('COMPLD') ||
dataBuffer.includes('M COMPLD') ||
dataBuffer.includes('DENY') ||
dataBuffer.includes(';')) && !responseReceived) {
responseReceived = true;
this.tl1Connection.removeListener('data', dataHandler);
if (dataBuffer.includes('COMPLD') || dataBuffer.includes('M COMPLD')) {
this.logger.debug('Comando TL1 executado com sucesso');
resolve({
success: true,
data: dataBuffer
});
} else if (dataBuffer.includes('DENY')) {
this.logger.warn('Comando TL1 negado pelo equipamento');
resolve({
success: false,
error: 'Comando negado pelo equipamento',
data: dataBuffer
});
} else {
this.logger.debug('Resposta TL1 válida recebida');
resolve({
success: true,
data: dataBuffer // Aceitar resposta válida
});
}
}
};
this.tl1Connection.on('data', dataHandler);
// Enviar comando TL1 formato Fiberhome
this.tl1Connection.write(comando + '\r\n');
// Timeout para resposta
setTimeout(() => {
if (!responseReceived) {
this.tl1Connection.removeListener('data', dataHandler);
reject(new Error('Timeout aguardando resposta TL1'));
}
}, 15000);
});
} catch (error) {
this.logger.error('Erro ao executar comando TL1', { comando, error: error.message });
return {
success: false,
error: error.message
};
}
}
/**
* Obter status de ONU via TL1
*/
async obterStatusONU(serial) {
try {
this.logger.debug('Obtendo status da ONU via TL1', { serial });
// Conectar ao UNM2000
const conectado = await this.conectarUNM2000();
if (!conectado) {
throw new Error('Não foi possível conectar ao UNM2000');
}
const oltId = this.config.unm2000.defaultOLT; // Nome correto da OLT
// BUSCA AUTOMATIZADA: Estrutura correta da OLT
this.logger.debug('=== INICIANDO BUSCA AUTOMATIZADA POR SLOT/PON ===');
this.logger.debug(`OLTID: ${oltId}, Serial: ${serial}`);
// Definir estrutura correta da OLT
const estruturaOLT = [
// Slots 12, 13, 14 com 16 PONs cada
{ slot: 12, maxPons: 16 },
{ slot: 13, maxPons: 16 },
{ slot: 14, maxPons: 16 },
// Slots 15, 16 com 8 PONs cada
{ slot: 15, maxPons: 8 },
{ slot: 16, maxPons: 8 }
];
// Gerar lista de PONs para busca
const listaPons = [];
estruturaOLT.forEach(estrutura => {
for (let pon = 1; pon <= estrutura.maxPons; pon++) {
listaPons.push(`1-1-${estrutura.slot}-${pon}`);
}
});
this.logger.info(`📡 Iniciando busca em ${listaPons.length} PONs: slots 12-16`);
let onuEncontrada = null;
let ponEncontrada = null;
// Buscar em cada PON até encontrar a ONU
for (const ponid of listaPons) {
try {
this.logger.debug(`🔍 Verificando PON ${ponid}...`);
// Listar ONUs desta PON específica
const comandoListarPon = `LST-ONU::OLTID=${oltId},PONID=${ponid}:CTAG::;`;
const resultadoPon = await this.executarComandoTL1(comandoListarPon);
if (resultadoPon.success) {
// Verificar se a ONU está nesta PON (busca case-insensitive)
const serialUpperCase = serial.toUpperCase();
const dataUpperCase = resultadoPon.data ? resultadoPon.data.toUpperCase() : '';
if (resultadoPon.data && dataUpperCase.includes(serialUpperCase)) {
// Extrair informações da ONU na listagem primeiro
const posicaoONU = this.extrairPosicaoONU(resultadoPon.data, serial);
if (posicaoONU) {
// Usar o PONID correto extraído dos dados reais
this.logger.info(`🎯 ONU ${serial} ENCONTRADA NA PON ${posicaoONU.ponid}!`);
// Log dos dados da PON para debug
this.logger.debug('Dados da PON onde ONU foi encontrada:', {
ponidBuscada: ponid,
ponidReal: posicaoONU.ponid,
dataLength: resultadoPon.data.length,
preview: resultadoPon.data.substring(0, 1000)
});
onuEncontrada = {
posicao: posicaoONU,
listagem: resultadoPon.data,
ponid: posicaoONU.ponid // Usar o PONID correto extraído dos dados
};
ponEncontrada = posicaoONU.ponid; // Usar o PONID correto extraído dos dados
// Extrair slot e PON do ponid encontrado
const [, , slot, pon] = posicaoONU.ponid.split('-');
this.logger.info(`📍 Localização: Slot ${slot}, PON ${pon}`);
break; // Encontrou, pode parar a busca
}
}
} else {
this.logger.debug(`❌ Erro na PON ${ponid}: ${resultadoPon.error}`);
}
} catch (error) {
this.logger.debug(`⚠️ Erro ao verificar PON ${ponid}: ${error.message}`);
// Continuar tentando outras PONs
}
}
if (!onuEncontrada) {
throw new Error(`ONU ${serial} não encontrada em nenhuma PON da OLT ${oltId}. Verifique se o serial está correto e se a ONU está cadastrada.`);
}
// Agora buscar informações detalhadas da ONU
this.logger.info(`📊 Coletando informações detalhadas da ONU na PON ${ponEncontrada}...`);
// Extrair número da ONU da posição encontrada
const numeroONU = onuEncontrada.posicao.onuno;
// Usar comandos TL1 que sabemos que funcionam baseados no manual
const comandosDetalhados = [
// Para informações de distância e estado (comando válido do manual)
`LST-ONUSTATE::OLTID=${oltId},PONID=${ponEncontrada},ONUNO=${numeroONU}:CTAG::;`,
// Para informações DDM/potência ótica (comando válido do manual)
`LST-OMDDM::OLTID=${oltId},PONID=${ponEncontrada},ONUNO=${numeroONU}:CTAG::;`,
// Para informações das portas LAN (comando válido do manual)
`LST-ONULANINFO::OLTID=${oltId},PONID=${ponEncontrada},ONUNO=${numeroONU}:CTAG::;`
];
this.logger.debug('Executando comandos TL1 detalhados:', comandosDetalhados);
const [resultadoEstado, resultadoDDM, resultadoLAN] = await Promise.all([
this.executarComandoTL1(comandosDetalhados[0]),
this.executarComandoTL1(comandosDetalhados[1]),
this.executarComandoTL1(comandosDetalhados[2])
]);
// Adicionar dados coletados
onuEncontrada.estadoGeral = resultadoEstado.success ? resultadoEstado.data : null;
onuEncontrada.detalhes = resultadoDDM.success ? resultadoDDM.data : null;
onuEncontrada.lan = resultadoLAN.success ? resultadoLAN.data : null;
// Adicionar respostas detalhadas para processamento
onuEncontrada.detalhados = [
{ comando: comandosDetalhados[0], response: resultadoEstado.data, success: resultadoEstado.success },
{ comando: comandosDetalhados[1], response: resultadoDDM.data, success: resultadoDDM.success },
{ comando: comandosDetalhados[2], response: resultadoLAN.data, success: resultadoLAN.success }
];
// Log dos resultados dos comandos detalhados
this.logger.debug('📊 Resultados dos comandos detalhados:', {
estado: { success: resultadoEstado.success, length: resultadoEstado.data?.length || 0 },
ddm: { success: resultadoDDM.success, length: resultadoDDM.data?.length || 0 },
lan: { success: resultadoLAN.success, length: resultadoLAN.data?.length || 0 }
});
// Tentar extrair mais informações dos dados da listagem original
this.logger.debug('📋 Processando dados da listagem original para extrair informações...');
onuEncontrada.dadosOriginais = onuEncontrada.listagem;
// Processar todos os dados coletados
const statusONU = this.processarStatusONUTL1(onuEncontrada, serial);
this.logger.info('🎉 Status final da ONU processado:', {
serial: statusONU.serial,
slot: statusONU.slot,
pon: statusONU.pon,
online: statusONU.online,
rxPower: statusONU.rxPower,
txPower: statusONU.txPower
});
return {
success: true,
...statusONU
};
} catch (error) {
this.logger.error('Erro ao obter status da ONU via TL1', { serial, error: error.message });
return {
success: false,
error: error.message,
serial
};
}
}
/**
* Obter status da ONU por device name via TL1
*/
async obterStatusONUPorNome(deviceName) {
try {
this.logger.debug('Obtendo status da ONU por nome via TL1', { deviceName });
// Conectar ao UNM2000
const conectado = await this.conectarUNM2000();
if (!conectado) {
throw new Error('Não foi possível conectar ao UNM2000');
}
// Comando TL1 para buscar ONU por nome
const comando = `RTRV-ONU::${deviceName}:1;`;
this.logger.debug('Executando comando TL1', { comando });
const resultado = await this.executarComandoTL1(comando);
if (!resultado.success) {
throw new Error(resultado.error || 'Falha na consulta TL1');
}
// Processar resposta TL1 da ONU
const statusONU = this.processarStatusONUTL1(resultado.data, deviceName);
this.logger.debug('Status ONU processado via TL1', statusONU);
return {
success: true,
...statusONU
};
} catch (error) {
this.logger.error('Erro ao obter status da ONU por nome via TL1', { deviceName, error: error.message });
return {
success: false,
error: error.message,
deviceName
};
}
}
/**
* Extrair posição da ONU da lista de ONUs
*/
extrairPosicaoONU(dadosLista, serial) {
try {
if (!dadosLista || typeof dadosLista !== 'string') {
return null;
}
this.logger.debug('Extraindo posição da ONU da resposta TL1:', {
serial,
serialUpperCase: serial.toUpperCase(),
responseLength: dadosLista.length,
preview: dadosLista.substring(0, 500)
});
// Dividir resposta em linhas para processamento
const linhas = dadosLista.split('\n');
this.logger.debug('Total de linhas para processar:', linhas.length);
for (const linha of linhas) {
// Pular linhas de cabeçalho e vazias
if (linha.includes('OLTID') || linha.includes('----') || linha.trim() === '') {
continue;
}
// Log de cada linha processada (apenas as primeiras 3 para não poluir)
if (linhas.indexOf(linha) < 3) {
this.logger.debug('Processando linha:', linha.substring(0, 200));
}
// Procurar linha que contém o serial na coluna MAC (busca case-insensitive)
const serialUpperCase = serial.toUpperCase();
const linhaUpperCase = linha.toUpperCase();
if (linhaUpperCase.includes(serialUpperCase)) {
this.logger.debug('Serial encontrado na linha:', linha);
// Formato esperado baseado nos logs:
// OLTID PONID ONUNO NAME DESC ONUTYPE IP AUTHTYPE MAC LOID PWD SWVER
// 172.16.10.6 1-1-14-2 68 artenizamendes@clicknetguarai.com.br -- AN5506-02-B -- MAC FHTT92704618 -- -- RP2604
// Dividir por tabs
const campos = linha.split('\t');
this.logger.debug('Campos extraídos por TAB:', campos);
if (campos.length >= 9) {
const oltid = campos[0];
const ponid = campos[1];
const onuno = campos[2];
const name = campos[3];
const mac = campos[8]; // Posição da coluna MAC
// Verificar se o MAC corresponde ao serial procurado (case-insensitive)
if (mac && mac.toUpperCase().includes(serialUpperCase)) {
this.logger.debug('PONID encontrado:', ponid);
return {
ponid: ponid,
encontrado: true,
oltid: oltid,
onuno: onuno,
name: name,
mac: mac,
linhaOriginal: linha
};
}
}
// Fallback: se não conseguiu dividir por TAB, tentar por espaços
const camposEspaco = linha.trim().split(/\s+/);
this.logger.debug('Campos extraídos por espaço:', camposEspaco);
// Procurar o campo PONID (formato x-x-x-x) e verificar se serial está na linha
for (let i = 0; i < camposEspaco.length; i++) {
const campo = camposEspaco[i];
if (campo.match(/^\d+-\d+-\d+-\d+$/) && linhaUpperCase.includes(serialUpperCase)) {
this.logger.debug('PONID encontrado por regex:', campo);
return {
ponid: campo,
encontrado: true,
linhaOriginal: linha
};
}
}
}
}
this.logger.warn('ONU não encontrada na listagem TL1', { serial });
return null;
} catch (error) {
this.logger.error('Erro ao extrair posição da ONU', { error: error.message, serial });
return null;
}
}
/**
* Processar resposta TL1 para status de ONU
*/
processarStatusONUTL1(dadosONU, identificador) {
try {
const resultado = {
serial: identificador,
deviceName: identificador,
slot: 'N/A',
pon: 'N/A',
onuId: 'N/A',
online: false,
rxPower: 'N/A',
txPower: 'N/A',
distance: 'N/A',
portasEthernet: [],
servicosWAN: []
};
if (!dadosONU || typeof dadosONU !== 'object') {
return resultado;
}
this.logger.debug('Processando dados ONU TL1:', dadosONU);
// Se encontramos a posição, a ONU existe
if (dadosONU.posicao && dadosONU.posicao.encontrado) {
resultado.online = true;
// Extrair informações da posição (formato NA-NA-slot-pon ou NA-shelf-slot-pon)
const ponid = dadosONU.posicao.ponid;
const partesPonid = ponid.split('-');
this.logger.debug('Analisando PONID:', { ponid, partes: partesPonid });
if (partesPonid.length >= 4) {
// Formato NA-NA-slot-pon ou NA-shelf-slot-pon
resultado.slot = partesPonid[2];
resultado.pon = partesPonid[3];
// Incluir o número da ONU no ID (slot-pon-numeroONU)
const numeroONU = dadosONU.posicao.onuno || '?';
resultado.onuId = `${partesPonid[2]}-${partesPonid[3]}-${numeroONU}`;
}
// Processar dados específicos dos comandos TL1 detalhados
if (dadosONU.detalhados) {
this.logger.debug('Processando respostas dos comandos TL1 detalhados');
for (const resposta of dadosONU.detalhados) {
if (!resposta || !resposta.response) continue;
const dados = resposta.response;
// Processar LST-ONUSTATE (distância e estado)
if (resposta.comando && resposta.comando.includes('LST-ONUSTATE')) {
// Extrair distância
const distMatch = dados.match(/DISTANCE\s*=\s*(\d+)/i) ||
dados.match(/RANGING\s*=\s*(\d+)/i);
if (distMatch) {
resultado.distance = `${distMatch[1]} m`;
}
// Verificar estado online/offline
if (dados.includes('ONLINE') || dados.includes('ACTIVE')) {
resultado.online = true;
} else if (dados.includes('OFFLINE') || dados.includes('INACTIVE')) {
resultado.online = false;
}
}
// Processar LST-OMDDM (potência ótica)
if (resposta.comando && resposta.comando.includes('LST-OMDDM')) {
// Buscar pela tabela de potência ótica no formato visto
const linhasTabela = dados.split('\n').filter(linha =>
linha.includes('\t') &&
!linha.includes('ONUID\tRxPower') && // header
linha.match(/--\t[+-]?\d+[,.]?\d*/) // linha com dados
);
if (linhasTabela.length > 0) {
// Formato: ONUID RxPower RxPowerR TxPower TxPowerR ...
// Exemplo: -- -19,94 Normal 5,16 High 11,70 Normal ...
const campos = linhasTabela[0].split('\t');
if (campos.length >= 4) {
const rxPower = campos[1]?.replace(',', '.');
const txPower = campos[3]?.replace(',', '.');
if (rxPower && rxPower !== '--' && !isNaN(parseFloat(rxPower))) {
resultado.rxPower = `${rxPower} dBm`;
}
if (txPower && txPower !== '--' && !isNaN(parseFloat(txPower))) {
resultado.txPower = `${txPower} dBm`;
}
}
}
}
// 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' };
}
resultado.portasEthernet[portNum-1].status = status === 'up' ? 'active' :
status === 'down' ? 'inactive' : 'unknown';
}
}
}
}
}
// Tentar extrair distância dos dados da listagem (onde já funcionou)
if (dadosONU.listagem || dadosONU.dadosOriginais) {
const dadosCompletos = dadosONU.listagem || dadosONU.dadosOriginais;
// Análise específica do formato TL1 tabular
const linhasTabela = dadosCompletos.split('\r\n').filter(linha =>
linha.includes('\t') &&
linha.includes(dadosONU.posicao.mac.toLowerCase()) &&
!linha.includes('OLTID\tPONID')
);
if (linhasTabela.length > 0) {
const campos = linhasTabela[0].split('\t');
// Último campo geralmente contém código de ranging (ex: RP2610)
const ultimoCampo = campos[campos.length - 1];
// Extrair número do código RP (Ranging Profile)
const rpMatch = ultimoCampo.match(/RP(\d{2})(\d{2})/);
if (rpMatch) {
// RP2610 = distância baseada no perfil
// Converter baseado em padrões típicos dos equipamentos Fiberhome
const codigoDistancia = parseInt(rpMatch[2]);
if (codigoDistancia > 0) {
// Estimativa baseada no código (cada unidade pode representar ~100m)
const distanciaEstimada = codigoDistancia * 10;
resultado.distance = `${distanciaEstimada} m`;
}
}
}
// Procurar por dados de distância explícitos na listagem
const distanciaMatches = [
dadosCompletos.match(/DISTANCE[=\s:]+(\d+)/gi),
dadosCompletos.match(/RANGING[=\s:]+(\d+)/gi),
dadosCompletos.match(/RANGE[=\s:]+(\d+)/gi),
// Buscar por padrões mais específicos de distância com metros (mínimo 3 dígitos)
dadosCompletos.match(/\b(\d{3,4})\s*m(?:etros?)?\b/gi)
];
for (const matches of distanciaMatches) {
if (matches && matches.length > 0) {
// Pegar o primeiro match válido
const match = matches[0].match(/(\d+)/);
if (match) {
resultado.distance = `${match[1]} m`;
break;
}
}
}
// Extrair informações de potência se disponível na listagem
const rxMatches = [
dadosCompletos.match(/RX[=\s:]+([+-]?\d+\.?\d*)/gi),
dadosCompletos.match(/RXPOWER[=\s:]+([+-]?\d+\.?\d*)/gi)
];
for (const matches of rxMatches) {
if (matches && matches.length > 0) {
const match = matches[0].match(/([+-]?\d+\.?\d*)/);
if (match) {
resultado.rxPower = `${match[1]} dBm`;
break;
}
}
}
const txMatches = [
dadosCompletos.match(/TX[=\s:]+([+-]?\d+\.?\d*)/gi),
dadosCompletos.match(/TXPOWER[=\s:]+([+-]?\d+\.?\d*)/gi)
];
for (const matches of txMatches) {
if (matches && matches.length > 0) {
const match = matches[0].match(/([+-]?\d+\.?\d*)/);
if (match) {
resultado.txPower = `${match[1]} dBm`;
break;
}
}
}
}
// Processar dados detalhados se disponível
if (dadosONU.detalhes) {
this.logger.debug('Processando dados detalhados da ONU:', dadosONU.detalhes);
// Extrair RX Power
const rxMatches = [
dadosONU.detalhes.match(/RXPOWER[=\s:]+([+-]?\d+\.?\d*)/i),
dadosONU.detalhes.match(/RX[=\s:]+([+-]?\d+\.?\d*)/i)
];
for (const match of rxMatches) {
if (match) {
resultado.rxPower = `${match[1]} dBm`;
break;
}
}
// Extrair TX Power
const txMatches = [
dadosONU.detalhes.match(/TXPOWER[=\s:]+([+-]?\d+\.?\d*)/i),
dadosONU.detalhes.match(/TX[=\s:]+([+-]?\d+\.?\d*)/i)
];
for (const match of txMatches) {
if (match) {
resultado.txPower = `${match[1]} dBm`;
break;
}
}
// Extrair distância
const distMatches = [
dadosONU.detalhes.match(/DISTANCE[=\s:]+(\d+)/i),
dadosONU.detalhes.match(/RANGINGTIME[=\s:]+(\d+)/i)
];
for (const match of distMatches) {
if (match) {
resultado.distance = `${match[1]} m`;
break;
}
}
}
// Processar dados de estado geral se disponível
if (dadosONU.estadoGeral) {
this.logger.debug('Processando dados de estado geral:', dadosONU.estadoGeral);
// Verificar se está online/offline
if (dadosONU.estadoGeral.includes('ONLINE') ||
dadosONU.estadoGeral.includes('ACTIVE') ||
dadosONU.estadoGeral.includes('UP')) {
resultado.online = true;
} else if (dadosONU.estadoGeral.includes('OFFLINE') ||
dadosONU.estadoGeral.includes('INACTIVE') ||
dadosONU.estadoGeral.includes('DOWN')) {
resultado.online = false;
}
}
// Se não temos dados específicos das portas, usar padrão
if (resultado.portasEthernet.length === 0) {
resultado.portasEthernet = [
{ porta: 1, status: 'unknown' },
{ porta: 2, status: 'unknown' },
{ porta: 3, status: 'unknown' },
{ porta: 4, status: 'unknown' }
];
}
// Se não temos dados WAN específicos, mas a ONU está online
if (resultado.servicosWAN.length === 0 && resultado.online) {
resultado.servicosWAN.push({
id: 1,
status: 'active',
ip: 'Configurado'
});
}
}
this.logger.debug('Dados TL1 processados:', resultado);
return resultado;
} catch (error) {
this.logger.error('Erro ao processar dados TL1', { error: error.message });
return {
serial: identificador,
deviceName: identificador,
slot: 'N/A',
pon: 'N/A',
onuId: 'N/A',
online: false,
rxPower: 'N/A',
txPower: 'N/A',
distance: 'N/A',
portasEthernet: [],
servicosWAN: []
};
}
}
/**
* Desconectar TL1
*/
async desconectar() {
try {
if (this.tl1Connection && !this.tl1Connection.destroyed) {
this.logger.debug('Desconectando TL1');
this.tl1Connection.end();
this.tl1Connection = null;
}
} catch (error) {
this.logger.error('Erro ao desconectar TL1', error);
}
}
/**
* Verificar se as conexões estão ativas
*/
verificarConexoes() {
return {
olt: false, // Não usamos mais OLT diretamente
unm2000: this.tl1Connection && !this.tl1Connection.destroyed
};
}
/**
* Diagnóstico completo de conectividade
*/
async diagnosticarConectividade() {
const diagnostico = {
olt: {
host: 'N/A',
port: 'N/A',
conectividade: false,
telnet: false,
erro: 'Não utilizado - consultas via TL1'
},
unm2000: {
host: this.config.unm2000.host,
port: this.config.unm2000.port,
conectividade: false,
tl1: false,
erro: null
}
};
// Testar UNM2000
try {
this.logger.debug('Testando conectividade UNM2000...');
diagnostico.unm2000.conectividade = await this.testarConectividade(
this.config.unm2000.host,
this.config.unm2000.port
);
if (diagnostico.unm2000.conectividade) {
this.logger.debug('Testando login TL1 UNM2000...');
diagnostico.unm2000.tl1 = await this.conectarUNM2000();
}
} catch (error) {
diagnostico.unm2000.erro = error.message;
this.logger.error('Erro no diagnóstico UNM2000:', error);
}
return diagnostico;
}
}
module.exports = FiberhomeManager;