fix TopSapp
This commit is contained in:
1 parent
8dc6c594c9
commit
bae6adefcb
42 files changed
+43645
-105
No files matched your search
@@ -0,0 +1,616 @@
|
||||
const { Telnet } = require('telnet-client');
|
||||
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
|
||||
}
|
||||
};
|
||||
|
||||
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 à OLT via Telnet
|
||||
*/
|
||||
async conectarOLT() {
|
||||
try {
|
||||
if (this.telnetConnection && this.telnetConnection.getSocket()) {
|
||||
this.logger.debug('Conexão OLT já existe, reutilizando');
|
||||
return true;
|
||||
}
|
||||
|
||||
// Primeiro, testar conectividade básica
|
||||
this.logger.debug('Testando conectividade com OLT...');
|
||||
const conectividade = await this.testarConectividade(
|
||||
this.config.olt.host,
|
||||
this.config.olt.port,
|
||||
5000
|
||||
);
|
||||
|
||||
if (!conectividade) {
|
||||
throw new Error(`Não foi possível conectar ao host ${this.config.olt.host}:${this.config.olt.port}`);
|
||||
}
|
||||
|
||||
this.logger.debug('Conectando à OLT Fiberhome', this.config.olt);
|
||||
|
||||
this.telnetConnection = new Telnet();
|
||||
|
||||
const params = {
|
||||
host: this.config.olt.host,
|
||||
port: this.config.olt.port,
|
||||
shellPrompt: this.config.olt.shellPrompt,
|
||||
timeout: this.config.olt.timeout,
|
||||
loginPrompt: /Username:|login:/i,
|
||||
passwordPrompt: /Password:|password:/i,
|
||||
username: this.config.olt.username,
|
||||
password: this.config.olt.password,
|
||||
echoLines: 1,
|
||||
debug: true
|
||||
};
|
||||
|
||||
this.logger.debug('Tentando conectar com parâmetros:', {
|
||||
host: params.host,
|
||||
port: params.port,
|
||||
username: params.username,
|
||||
timeout: params.timeout
|
||||
});
|
||||
|
||||
await this.telnetConnection.connect(params);
|
||||
|
||||
// Aguardar o prompt aparecer
|
||||
await new Promise(resolve => setTimeout(resolve, 2000));
|
||||
|
||||
this.logger.info('Conectado à OLT Fiberhome com sucesso');
|
||||
|
||||
return true;
|
||||
|
||||
} catch (error) {
|
||||
this.logger.error('Erro ao conectar à OLT', {
|
||||
error: error.message,
|
||||
host: this.config.olt.host,
|
||||
port: this.config.olt.port,
|
||||
stack: error.stack
|
||||
});
|
||||
|
||||
// Limpar conexão com erro
|
||||
if (this.telnetConnection) {
|
||||
try {
|
||||
this.telnetConnection.end();
|
||||
} catch (e) {
|
||||
// Ignorar erros ao fechar conexão inválida
|
||||
}
|
||||
this.telnetConnection = null;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Conectar ao UNM2000 via TL1
|
||||
*/
|
||||
async conectarUNM2000() {
|
||||
try {
|
||||
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);
|
||||
|
||||
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) => {
|
||||
dataBuffer += data.toString();
|
||||
this.logger.debug('TL1 dados recebidos:', dataBuffer);
|
||||
|
||||
// Verificar se login foi bem-sucedido
|
||||
if (!authenticated && dataBuffer.includes('COMPLD')) {
|
||||
authenticated = true;
|
||||
this.logger.info('Login TL1 bem-sucedido');
|
||||
resolve(true);
|
||||
}
|
||||
});
|
||||
|
||||
this.tl1Connection.connect(this.config.unm2000.port, this.config.unm2000.host, () => {
|
||||
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};`;
|
||||
this.tl1Connection.write(loginCommand + '\r\n');
|
||||
|
||||
// Timeout para autenticação
|
||||
setTimeout(() => {
|
||||
if (!authenticated) {
|
||||
this.logger.error('Timeout na autenticação TL1');
|
||||
reject(new Error('Timeout na autenticação TL1'));
|
||||
}
|
||||
}, 10000);
|
||||
});
|
||||
|
||||
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 ao conectar UNM2000', error);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
this.logger.error('Timeout na conexão UNM2000');
|
||||
reject(new Error('Timeout na conexão'));
|
||||
});
|
||||
});
|
||||
|
||||
} catch (error) {
|
||||
this.logger.error('Erro ao conectar ao UNM2000', error);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Executar comando na OLT
|
||||
*/
|
||||
async executarComandoOLT(comando) {
|
||||
try {
|
||||
if (!this.telnetConnection) {
|
||||
const conectado = await this.conectarOLT();
|
||||
if (!conectado) {
|
||||
throw new Error('Não foi possível conectar à OLT');
|
||||
}
|
||||
}
|
||||
|
||||
this.logger.debug('Executando comando OLT', { comando });
|
||||
|
||||
const resultado = await this.telnetConnection.exec(comando);
|
||||
|
||||
this.logger.debug('Resultado do comando OLT', {
|
||||
comando,
|
||||
resultadoLength: resultado.length
|
||||
});
|
||||
|
||||
return resultado;
|
||||
|
||||
} catch (error) {
|
||||
this.logger.error('Erro ao executar comando na OLT', { comando, error: error.message });
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Executar comando TL1 no UNM2000
|
||||
*/
|
||||
async executarComandoTL1(comando) {
|
||||
try {
|
||||
if (!this.tl1Connection || this.tl1Connection.destroyed) {
|
||||
const conectado = await this.conectarUNM2000();
|
||||
if (!conectado) {
|
||||
throw new Error('Não foi possível conectar ao UNM2000');
|
||||
}
|
||||
}
|
||||
|
||||
this.logger.debug('Executando comando TL1', { comando });
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
let resposta = '';
|
||||
|
||||
const timeout = setTimeout(() => {
|
||||
reject(new Error('Timeout na execução do comando TL1'));
|
||||
}, 10000);
|
||||
|
||||
const onData = (data) => {
|
||||
resposta += data.toString();
|
||||
|
||||
// Verificar se a resposta está completa (termina com ;)
|
||||
if (resposta.includes(';')) {
|
||||
clearTimeout(timeout);
|
||||
this.tl1Connection.off('data', onData);
|
||||
|
||||
this.logger.debug('Resposta TL1 recebida', {
|
||||
comando,
|
||||
respostaLength: resposta.length
|
||||
});
|
||||
|
||||
resolve(resposta);
|
||||
}
|
||||
};
|
||||
|
||||
this.tl1Connection.on('data', onData);
|
||||
this.tl1Connection.write(comando + '\r\n');
|
||||
});
|
||||
|
||||
} catch (error) {
|
||||
this.logger.error('Erro ao executar comando TL1', { comando, error: error.message });
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Obter status da ONU por serial
|
||||
*/
|
||||
async obterStatusONU(serial) {
|
||||
try {
|
||||
this.logger.debug('Obtendo status da ONU', { serial });
|
||||
|
||||
// Primeiro, encontrar a ONU pelo serial
|
||||
const comandoBusca = `show ont info serial ${serial}`;
|
||||
const resultadoBusca = await this.executarComandoOLT(comandoBusca);
|
||||
|
||||
if (!resultadoBusca || resultadoBusca.includes('No such ont')) {
|
||||
return {
|
||||
success: false,
|
||||
error: 'ONU não encontrada',
|
||||
serial
|
||||
};
|
||||
}
|
||||
|
||||
// Extrair informações básicas da ONU
|
||||
const infoONU = this.extrairInfoONU(resultadoBusca);
|
||||
|
||||
if (!infoONU.slot || !infoONU.pon || !infoONU.onuId) {
|
||||
return {
|
||||
success: false,
|
||||
error: 'Não foi possível extrair informações da ONU',
|
||||
serial
|
||||
};
|
||||
}
|
||||
|
||||
// Obter status detalhado
|
||||
const comandoStatus = `show ont info ${infoONU.slot} ${infoONU.pon} ${infoONU.onuId}`;
|
||||
const resultadoStatus = await this.executarComandoOLT(comandoStatus);
|
||||
|
||||
// Obter informações de sinal
|
||||
const comandoSinal = `show ont optical-info ${infoONU.slot} ${infoONU.pon} ${infoONU.onuId}`;
|
||||
const resultadoSinal = await this.executarComandoOLT(comandoSinal);
|
||||
|
||||
// Obter status das portas Ethernet
|
||||
const comandoPortas = `show ont port state ${infoONU.slot} ${infoONU.pon} ${infoONU.onuId} eth all`;
|
||||
const resultadoPortas = await this.executarComandoOLT(comandoPortas);
|
||||
|
||||
// Obter configurações WAN
|
||||
const comandoWAN = `show ont wan-info ${infoONU.slot} ${infoONU.pon} ${infoONU.onuId}`;
|
||||
const resultadoWAN = await this.executarComandoOLT(comandoWAN);
|
||||
|
||||
const status = this.processarStatusONU({
|
||||
info: resultadoStatus,
|
||||
sinal: resultadoSinal,
|
||||
portas: resultadoPortas,
|
||||
wan: resultadoWAN,
|
||||
...infoONU
|
||||
});
|
||||
|
||||
return {
|
||||
success: true,
|
||||
serial,
|
||||
...status
|
||||
};
|
||||
|
||||
} catch (error) {
|
||||
this.logger.error('Erro ao obter status da ONU', { serial, error: error.message });
|
||||
return {
|
||||
success: false,
|
||||
error: error.message,
|
||||
serial
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Obter status da ONU por device name
|
||||
*/
|
||||
async obterStatusONUPorNome(deviceName) {
|
||||
try {
|
||||
this.logger.debug('Obtendo status da ONU por nome', { deviceName });
|
||||
|
||||
// Buscar ONU pelo device name
|
||||
const comandoBusca = `show ont info summary | grep "${deviceName}"`;
|
||||
const resultadoBusca = await this.executarComandoOLT(comandoBusca);
|
||||
|
||||
if (!resultadoBusca || resultadoBusca.trim() === '') {
|
||||
return {
|
||||
success: false,
|
||||
error: 'ONU não encontrada pelo device name',
|
||||
deviceName
|
||||
};
|
||||
}
|
||||
|
||||
// Extrair serial do resultado
|
||||
const serial = this.extrairSerialDoNome(resultadoBusca);
|
||||
|
||||
if (!serial) {
|
||||
return {
|
||||
success: false,
|
||||
error: 'Não foi possível extrair o serial da ONU',
|
||||
deviceName
|
||||
};
|
||||
}
|
||||
|
||||
// Usar o método de busca por serial
|
||||
const resultado = await this.obterStatusONU(serial);
|
||||
resultado.deviceName = deviceName;
|
||||
|
||||
return resultado;
|
||||
|
||||
} catch (error) {
|
||||
this.logger.error('Erro ao obter status da ONU por nome', { deviceName, error: error.message });
|
||||
return {
|
||||
success: false,
|
||||
error: error.message,
|
||||
deviceName
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Extrair informações básicas da ONU do resultado da busca
|
||||
*/
|
||||
extrairInfoONU(resultado) {
|
||||
const linhas = resultado.split('\n');
|
||||
const info = {};
|
||||
|
||||
for (const linha of linhas) {
|
||||
// Buscar padrão: gpon_olt-1/1/1:1
|
||||
const matchSlotPon = linha.match(/gpon_olt-(\d+)\/(\d+)\/(\d+):(\d+)/);
|
||||
if (matchSlotPon) {
|
||||
info.slot = matchSlotPon[1];
|
||||
info.board = matchSlotPon[2];
|
||||
info.pon = matchSlotPon[3];
|
||||
info.onuId = matchSlotPon[4];
|
||||
}
|
||||
|
||||
// Buscar outros dados relevantes
|
||||
if (linha.includes('Serial number:')) {
|
||||
info.serial = linha.split(':')[1]?.trim();
|
||||
}
|
||||
if (linha.includes('Device name:')) {
|
||||
info.deviceName = linha.split(':')[1]?.trim();
|
||||
}
|
||||
}
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extrair serial do device name
|
||||
*/
|
||||
extrairSerialDoNome(resultado) {
|
||||
const linhas = resultado.split('\n');
|
||||
|
||||
for (const linha of linhas) {
|
||||
// Buscar padrão com serial number
|
||||
const match = linha.match(/([A-Z0-9]{12})/);
|
||||
if (match) {
|
||||
return match[1];
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Processar status detalhado da ONU
|
||||
*/
|
||||
processarStatusONU(dados) {
|
||||
const status = {
|
||||
slot: dados.slot,
|
||||
pon: dados.pon,
|
||||
onuId: dados.onuId,
|
||||
deviceName: dados.deviceName || 'N/A',
|
||||
online: false,
|
||||
rxPower: 'N/A',
|
||||
txPower: 'N/A',
|
||||
distance: 'N/A',
|
||||
portasEthernet: [],
|
||||
servicosWAN: []
|
||||
};
|
||||
|
||||
// Processar status online/offline
|
||||
if (dados.info) {
|
||||
status.online = dados.info.includes('online') || dados.info.includes('working');
|
||||
}
|
||||
|
||||
// Processar informações de sinal
|
||||
if (dados.sinal) {
|
||||
const linhas = dados.sinal.split('\n');
|
||||
|
||||
for (const linha of linhas) {
|
||||
if (linha.includes('Rx power')) {
|
||||
const match = linha.match(/([-+]?\d+\.?\d*)/);
|
||||
if (match) status.rxPower = match[1] + ' dBm';
|
||||
}
|
||||
if (linha.includes('Tx power')) {
|
||||
const match = linha.match(/([-+]?\d+\.?\d*)/);
|
||||
if (match) status.txPower = match[1] + ' dBm';
|
||||
}
|
||||
if (linha.includes('Distance')) {
|
||||
const match = linha.match(/(\d+)/);
|
||||
if (match) status.distance = match[1] + ' m';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Processar status das portas Ethernet
|
||||
if (dados.portas) {
|
||||
const linhas = dados.portas.split('\n');
|
||||
|
||||
for (const linha of linhas) {
|
||||
const match = linha.match(/eth\s+(\d+)\s+(\w+)/);
|
||||
if (match) {
|
||||
status.portasEthernet.push({
|
||||
porta: match[1],
|
||||
status: match[2]
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Processar serviços WAN
|
||||
if (dados.wan) {
|
||||
const linhas = dados.wan.split('\n');
|
||||
|
||||
for (const linha of linhas) {
|
||||
if (linha.includes('Service')) {
|
||||
const servicoMatch = linha.match(/Service\s+(\d+).*?(\w+).*?(\d+\.\d+\.\d+\.\d+)?/);
|
||||
if (servicoMatch) {
|
||||
status.servicosWAN.push({
|
||||
id: servicoMatch[1],
|
||||
status: servicoMatch[2],
|
||||
ip: servicoMatch[3] || 'N/A'
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* Desconectar todas as conexões
|
||||
*/
|
||||
async desconectar() {
|
||||
try {
|
||||
if (this.telnetConnection) {
|
||||
await this.telnetConnection.end();
|
||||
this.telnetConnection = null;
|
||||
this.logger.debug('Conexão OLT encerrada');
|
||||
}
|
||||
|
||||
if (this.tl1Connection && !this.tl1Connection.destroyed) {
|
||||
this.tl1Connection.destroy();
|
||||
this.tl1Connection = null;
|
||||
this.logger.debug('Conexão UNM2000 encerrada');
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
this.logger.error('Erro ao desconectar', error);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Verificar se as conexões estão ativas
|
||||
*/
|
||||
verificarConexoes() {
|
||||
return {
|
||||
olt: this.telnetConnection && this.telnetConnection.getSocket(),
|
||||
unm2000: this.tl1Connection && !this.tl1Connection.destroyed
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Diagnóstico completo de conectividade
|
||||
*/
|
||||
async diagnosticarConectividade() {
|
||||
const diagnostico = {
|
||||
olt: {
|
||||
host: this.config.olt.host,
|
||||
port: this.config.olt.port,
|
||||
conectividade: false,
|
||||
telnet: false,
|
||||
erro: null
|
||||
},
|
||||
unm2000: {
|
||||
host: this.config.unm2000.host,
|
||||
port: this.config.unm2000.port,
|
||||
conectividade: false,
|
||||
tl1: false,
|
||||
erro: null
|
||||
}
|
||||
};
|
||||
|
||||
// Testar OLT
|
||||
try {
|
||||
this.logger.debug('Testando conectividade OLT...');
|
||||
diagnostico.olt.conectividade = await this.testarConectividade(
|
||||
this.config.olt.host,
|
||||
this.config.olt.port
|
||||
);
|
||||
|
||||
if (diagnostico.olt.conectividade) {
|
||||
this.logger.debug('Testando login Telnet OLT...');
|
||||
diagnostico.olt.telnet = await this.conectarOLT();
|
||||
}
|
||||
} catch (error) {
|
||||
diagnostico.olt.erro = error.message;
|
||||
this.logger.error('Erro no diagnóstico OLT:', error);
|
||||
}
|
||||
|
||||
// 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;
|
||||
Reference in new issue
Block a user