adicionada função de reiniciar ONU

Signed-off-by: Rodrigo Martins <rodrigo@martinsevieira.adv.br>
This commit is contained in:
Rodrigo Martins committed 2026-04-05 20:08:41 -03:00
1 parent dbd581eb99
commit ec92ef1b88
3 files changed
+431 -1

No files matched your search

+359
View File
@@ -281,6 +281,11 @@ class BotHandler {
await this.handleMudarIPoE(chatId, target);
break;
case 'reiniciar_onu':
console.log(`🔄 Executando handleReiniciarOnu com target: ${target}`);
await this.handleReiniciarOnu(chatId, target);
break;
case 'conectar':
await this.handleConnect(chatId, target);
break;
@@ -2121,6 +2126,15 @@ Digite /help para ver todos os comandos disponíveis!
} else if (data.startsWith('diag_cliente_')) {
console.log(`🔍 Condição diag_cliente_ atendida`);
await this.handleDiagClienteCallback(callbackQuery, data);
} else if (data.startsWith('restart_onu_cli_')) {
console.log(`🔍 Condição restart_onu_cli_ atendida`);
await this.handleRestartOnuClienteCallback(callbackQuery, data);
} else if (data.startsWith('restart_onu_srv_')) {
console.log(`🔍 Condição restart_onu_srv_ atendida`);
await this.handleRestartOnuServicoCallback(callbackQuery, data);
} else if (data.startsWith('confirm_restart_onu_')) {
console.log(`🔍 Condição confirm_restart_onu_ atendida`);
await this.handleConfirmRestartOnuCallback(callbackQuery, data);
} else if (data.startsWith('diag_servico_')) {
console.log(`🔍 Condição diag_servico_ atendida`);
await this.handleDiagServicoCallback(callbackQuery, data);
@@ -8507,6 +8521,351 @@ Digite /help para ver todos os comandos disponíveis!
);
}
}
// ======================================================================
// REINICIAR ONU POR CLIENTE (Nome / CPF)
// ======================================================================
/**
* Reiniciar ONU buscando pelo nome ou CPF do cliente via TopSapp
*/
async handleReiniciarOnu(chatId, query) {
if (!query) {
await this.bot.sendMessage(chatId,
`🔄 *Reiniciar ONU*\n\n` +
`💡 *Como usar:*\n` +
`• "reiniciar onu João da Silva"\n` +
`• "reiniciar onu 123.456.789-10"\n\n` +
`O sistema busca o cliente no TopSapp, detecta a base (Fiberhome ou Datacom) e reinicia a ONU automaticamente.`,
{ parse_mode: 'Markdown' }
);
return;
}
try {
await this.bot.sendMessage(chatId, '🔍 Buscando cliente...');
let location = '';
let searchQuery = query;
if (/guarai|colmeia/i.test(query)) {
location = 'Guarai/Colmeia';
searchQuery = query.replace(/(guarai|colmeia)/gi, '').trim();
} else if (/pedro afonso/i.test(query)) {
location = 'Pedro Afonso';
searchQuery = query.replace(/pedro afonso/gi, '').trim();
}
const resultado = await this.topsapp.buscarCliente(searchQuery, location);
if (!resultado.success) {
await this.bot.sendMessage(chatId, `❌ Erro na busca: ${resultado.error}`);
return;
}
if (!resultado.clientes || resultado.clientes.length === 0) {
await this.bot.sendMessage(chatId, `🔍 Nenhum cliente encontrado para: "${searchQuery}"`);
return;
}
const instancia = resultado.instancia || location;
if (resultado.clientes.length === 1) {
await this._mostrarServicosParaReiniciarOnu(chatId, resultado.clientes[0].id, instancia);
return;
}
// Múltiplos clientes → exibir teclado de seleção
let message = `🔍 *${resultado.clientes.length} clientes encontrados*\n\n`;
const keyboard = [];
resultado.clientes.slice(0, 8).forEach((cliente, index) => {
message += `*${index + 1}.* ${cliente.nome}`;
if (cliente.cpf) message += ` — CPF: \`${cliente.cpf}\``;
message += `\n`;
keyboard.push([{
text: `🔄 Reiniciar ONU: ${cliente.nome.substring(0, 28)}`,
callback_data: `restart_onu_cli_${cliente.id}_${instancia}`
}]);
});
await this.bot.sendMessage(chatId, message, {
parse_mode: 'Markdown',
reply_markup: { inline_keyboard: keyboard }
});
} catch (error) {
console.error('❌ Erro em handleReiniciarOnu:', error);
await this.bot.sendMessage(chatId, `❌ Erro: ${error.message}`);
}
}
/**
* Mostra serviços do cliente para selecionar qual ONU reiniciar
*/
async _mostrarServicosParaReiniciarOnu(chatId, idCliente, location) {
const servicosResult = await this.topsapp.obterServicosCliente(idCliente, location);
if (!servicosResult.success) {
await this.bot.sendMessage(chatId, `❌ Erro ao buscar serviços: ${servicosResult.error}`);
return;
}
const servicos = (servicosResult.servicos || []).filter(s => {
const st = (s.id_status || s.statusNumerico);
return st === 1 || st === '1' || String(s.status).toLowerCase() === 'liberado' || String(s.status).toLowerCase() === 'ativo';
});
if (servicos.length === 0) {
await this.bot.sendMessage(chatId, `⚠️ Cliente sem serviços ativos.`);
return;
}
// Se só tem 1 serviço, ir direto para confirmação
if (servicos.length === 1) {
const s = servicos[0];
await this._confirmarReiniciarOnu(chatId, idCliente, s, location);
return;
}
// Múltiplos serviços → seleção
let message = `🔄 *Selecione o serviço para reiniciar a ONU:*\n\n`;
const keyboard = [];
servicos.forEach((s, i) => {
const nome = s.descricao || s.nome || `Serviço ${i + 1}`;
const serial = s.serial || s.comodato_serial || s.mac || '';
message += `*${i + 1}.* ${nome}${serial ? ` — \`${serial}\`` : ''}\n`;
keyboard.push([{
text: `🔄 ${nome.substring(0, 35)}`,
callback_data: `restart_onu_srv_${idCliente}_${s.id_servico || s.id}_${location}`
}]);
});
await this.bot.sendMessage(chatId, message, {
parse_mode: 'Markdown',
reply_markup: { inline_keyboard: keyboard }
});
}
/**
* Mostra confirmação antes de reiniciar a ONU
*/
async _confirmarReiniciarOnu(chatId, idCliente, servico, location) {
const serial = servico.serial || servico.comodato_serial || servico.mac || '';
const base = servico.base || '';
const nome = servico.descricao || servico.nome || 'Serviço';
if (!serial) {
await this.bot.sendMessage(chatId, `❌ Serviço "${nome}" não possui serial de ONU cadastrado.`);
return;
}
const oltHint = this._resolverOLTporBase(base);
const tipoOLT = oltHint === 'fiberhome' ? '🔶 Fiberhome (TL1)' : '🔷 Datacom (SSH)';
const serialEscaped = serial.replace(/_/g, '\\_');
await this.bot.sendMessage(chatId,
`⚠️ *Confirmar Reinicialização de ONU*\n\n` +
`📦 *Serviço:* ${nome}\n` +
`📡 *Serial:* \`${serialEscaped}\`\n` +
`🏢 *Base:* ${base || 'N/A'}\n` +
`🔌 *Tipo:* ${tipoOLT}\n\n` +
`⚠️ A ONU será reiniciada e o cliente ficará sem conexão temporariamente.`,
{
parse_mode: 'Markdown',
reply_markup: {
inline_keyboard: [
[
{ text: '✅ SIM, Reiniciar', callback_data: `confirm_restart_onu_${serial}_${base}_${location}` },
{ text: '❌ Cancelar', callback_data: 'cancel_action' }
]
]
}
}
);
}
/**
* Callback: seleção de cliente para reiniciar ONU
*/
async handleRestartOnuClienteCallback(callbackQuery, data) {
const chatId = callbackQuery.message.chat.id;
const parts = data.replace('restart_onu_cli_', '').split('_');
const idCliente = parts[0];
const location = parts.slice(1).join('_');
await this.bot.answerCallbackQuery(callbackQuery.id);
await this._mostrarServicosParaReiniciarOnu(chatId, idCliente, location);
}
/**
* Callback: seleção de serviço para reiniciar ONU
*/
async handleRestartOnuServicoCallback(callbackQuery, data) {
const chatId = callbackQuery.message.chat.id;
const parts = data.replace('restart_onu_srv_', '').split('_');
const idCliente = parts[0];
const idServico = parts[1];
const location = parts.slice(2).join('_');
await this.bot.answerCallbackQuery(callbackQuery.id);
// Buscar o serviço completo
const servicosResult = await this.topsapp.obterServicosCliente(idCliente, location);
if (!servicosResult.success) {
await this.bot.sendMessage(chatId, `❌ Erro ao buscar serviço: ${servicosResult.error}`);
return;
}
const servico = (servicosResult.servicos || []).find(s =>
String(s.id_servico || s.id) === String(idServico)
);
if (!servico) {
await this.bot.sendMessage(chatId, `❌ Serviço #${idServico} não encontrado.`);
return;
}
await this._confirmarReiniciarOnu(chatId, idCliente, servico, location);
}
/**
* Callback: confirmação de reiniciar ONU — executa a reinicialização
*/
async handleConfirmRestartOnuCallback(callbackQuery, data) {
const chatId = callbackQuery.message.chat.id;
await this.bot.answerCallbackQuery(callbackQuery.id);
// Formato: confirm_restart_onu_SERIAL_BASE_LOCATION
const rest = data.replace('confirm_restart_onu_', '');
// Serial é o primeiro token (12 chars alfanuméricos)
const serialMatch = rest.match(/^([A-Za-z0-9]+)_(.*)$/);
if (!serialMatch) {
await this.bot.sendMessage(chatId, '❌ Erro ao processar dados de reinicialização.');
return;
}
const serial = serialMatch[1];
const remaining = serialMatch[2]; // BASE_LOCATION
const base = remaining; // usa o restante como base (pode conter location junto)
const oltHint = this._resolverOLTporBase(base);
const serialEscaped = serial.replace(/_/g, '\\_');
await this.bot.editMessageText(
`🔄 *Reiniciando ONU...*\n\n` +
`📡 Serial: \`${serialEscaped}\`\n` +
`⏳ Aguarde...`,
{
chat_id: chatId,
message_id: callbackQuery.message.message_id,
parse_mode: 'Markdown'
}
);
try {
let result;
if (oltHint === 'fiberhome') {
// Reiniciar via TL1 (Fiberhome)
result = await this.fiberhomeTL1.reiniciarOnu(serial);
} else if (oltHint) {
// Reiniciar via SSH (Datacom)
result = await this._reiniciarOnuDatacom(serial, oltHint);
} else {
// Sem base definida — tentar Fiberhome primeiro, depois Datacom
result = await this.fiberhomeTL1.reiniciarOnu(serial);
if (!result.success) {
result = await this._reiniciarOnuDatacomAutoDetect(serial);
}
}
if (result.success) {
await this.bot.sendMessage(chatId,
`✅ *ONU Reiniciada com Sucesso!*\n\n` +
`📡 *Serial:* \`${serialEscaped}\`\n` +
`${result.details ? `🏢 *OLT:* ${(result.details.olt || result.details.oltName || '').replace(/_/g, '\\_')}\n` : ''}` +
`${result.details && result.details.slot ? `📍 *Slot:* ${result.details.slot}\n` : ''}` +
`\n⚡ A ONU estará disponível em alguns instantes.`,
{ parse_mode: 'Markdown' }
);
} else {
await this.bot.sendMessage(chatId,
`❌ *Erro ao reiniciar ONU*\n\n` +
`📡 Serial: \`${serialEscaped}\`\n` +
`⚠️ ${result.error || 'Erro desconhecido'}`,
{ parse_mode: 'Markdown' }
);
}
} catch (error) {
console.error('❌ Erro ao reiniciar ONU:', error);
await this.bot.sendMessage(chatId,
`❌ *Erro ao reiniciar ONU*\n\n⚠️ ${error.message}`,
{ parse_mode: 'Markdown' }
);
}
}
/**
* Reiniciar ONU Datacom via SSH usando serial — busca na OLT indicada
*/
async _reiniciarOnuDatacom(serial, oltId) {
try {
const findResult = await this.ssh.findOnuBySerial(oltId, serial);
if (!findResult || !findResult.success) {
return { success: false, error: `ONU ${serial} não encontrada na OLT ${oltId}` };
}
const { slot, onuId } = findResult.onuInfo;
const oltEquip = this.ssh.equipamentos.get(oltId);
const result = await this.ssh.resetOnuAlternative(oltId, slot, onuId);
return {
...result,
details: {
oltName: oltEquip ? oltEquip.name : oltId,
slot,
onuId,
serial
}
};
} catch (error) {
return { success: false, error: error.message };
}
}
/**
* Reiniciar ONU Datacom — busca em todas as OLTs
*/
async _reiniciarOnuDatacomAutoDetect(serial) {
const olts = this.ssh.listOLTs();
for (const olt of olts) {
try {
const findResult = await this.ssh.findOnuBySerial(olt.id, serial);
if (findResult && findResult.success) {
const { slot, onuId } = findResult.onuInfo;
const result = await this.ssh.resetOnuAlternative(olt.id, slot, onuId);
return {
...result,
details: {
oltName: olt.name,
slot,
onuId,
serial
}
};
}
} catch (e) {
// Tentar próxima OLT
}
}
return { success: false, error: `ONU ${serial} não encontrada em nenhuma OLT Datacom` };
}
}
module.exports = BotHandler;
+57
View File
@@ -1041,6 +1041,63 @@ class FiberhomeManager {
return services;
}
/**
* Reiniciar ONU Fiberhome via TL1
* @param {string} serial - Serial/MAC da ONU
* @returns {Promise<Object>} - Resultado da operação
*/
async reiniciarOnu(serial) {
try {
this.logger.info('Reiniciando ONU Fiberhome via TL1', { serial });
const conectado = await this.conectarUNM2000();
if (!conectado) {
throw new Error('Não foi possível conectar ao UNM2000');
}
serial = serial.toUpperCase();
// Buscar a ONU registrada no sistema
const onuInfo = await this.buscarOnuRegistrada(serial);
if (!onuInfo) {
throw new Error('ONU não encontrada no sistema');
}
const { nameOlt, slot, porta } = onuInfo;
const ponId = `${slot}-${porta}`;
// RESET-ONU
const resetCmd = `RESET-ONU::OLTID=${nameOlt},PONID=NA-NA-${ponId},ONUIDTYPE=MAC,ONUID=${serial}:${this.commandId++}::;`;
this.logger.debug('Enviando RESET-ONU', { comando: resetCmd });
const resultado = await this.executarComandoTL1(resetCmd);
if (!resultado.success) {
throw new Error(resultado.error || 'Falha ao reiniciar ONU');
}
this.logger.info('ONU Fiberhome reiniciada com sucesso', { serial, nameOlt, ponId });
return {
success: true,
message: `ONU ${serial} reiniciada com sucesso`,
details: {
olt: nameOlt,
slot,
porta,
serial
}
};
} catch (error) {
this.logger.error('Erro ao reiniciar ONU Fiberhome', { serial, error: error.message });
return {
success: false,
error: error.message
};
}
}
}
module.exports = FiberhomeManager;
+15 -1
View File
@@ -37,7 +37,8 @@ class NLPProcessor {
'diagnosticar': ['diagnosticar', 'diagnostico', 'diagnose', 'diagnosticar cliente', 'diagnostico cliente', 'checar cliente completo', 'verificar cliente completo', 'relatorio cliente', 'relatorio completo', 'status completo cliente', 'analisar cliente', 'inspecionar cliente', 'situacao do cliente', 'situação do cliente'],
'ver_roteador': ['ver roteador', 'info roteador', 'status roteador', 'roteador', 'cpe', 'ver cpe', 'info cpe', 'dados roteador', 'informações roteador', 'informacoes roteador', 'genieacs', 'ver device', 'info device', 'dispositivo cpe'],
'mudar_ipoe': ['mudar para ipoe', 'mudar ipoe', 'ipoe', 'converter ipoe', 'ativar ipoe', 'habilitar ipoe', 'migrar ipoe', 'migrar para ipoe', 'converter para ipoe', 'passar para ipoe', 'trocar para ipoe', 'mudar pra ipoe'],
'configurar_roteador': ['configurar roteador', 'mudar roteador', 'alterar roteador', 'editar roteador', 'config roteador', 'configurar wifi', 'mudar wifi', 'alterar wifi', 'mudar ssid', 'alterar ssid', 'configurar cpe', 'mudar cpe', 'alterar cpe', 'configurar dns', 'mudar dns', 'configurar dhcp', 'mudar dhcp', 'alterar dhcp', 'mudar configuracoes roteador', 'mudar configurações roteador']
'configurar_roteador': ['configurar roteador', 'mudar roteador', 'alterar roteador', 'editar roteador', 'config roteador', 'configurar wifi', 'mudar wifi', 'alterar wifi', 'mudar ssid', 'alterar ssid', 'configurar cpe', 'mudar cpe', 'alterar cpe', 'configurar dns', 'mudar dns', 'configurar dhcp', 'mudar dhcp', 'alterar dhcp', 'mudar configuracoes roteador', 'mudar configurações roteador'],
'reiniciar_onu': ['reiniciar onu', 'reiniciar onu cliente', 'resetar onu', 'resetar onu cliente', 'reboot onu', 'restart onu', 'reiniciar ont', 'resetar ont', 'reboot ont', 'restart ont', 'reiniciar onu do cliente', 'reset onu cliente']
};
// Padrões de comandos
@@ -64,6 +65,8 @@ class NLPProcessor {
// Padrões específicos para abrir suporte
/^(abrir|criar|adicionar|novo)\s+(suporte|chamado|ticket|atendimento)(?:\s+(.+))?$/i,
/^(suporte|chamado|ticket|atendimento)(?:\s+(.+))?$/i,
// Padrões específicos para reiniciar ONU por cliente
/^(reiniciar|resetar|restart|reboot|reset)\s+(onu|ont)\s+(.+)$/i,
// Padrões específicos para Fiberhome
/^(status|verificar|check)\s+(onu|ont)\s+([A-Z0-9]+)$/i,
/^(onu|ont)\s+(status|verificar|check)\s+([A-Z0-9]+)$/i,
@@ -176,6 +179,17 @@ class NLPProcessor {
const action = match[1];
// Detectar comando de mudar para IPoE (deve vir ANTES de configurar roteador)
// Detectar comando de reiniciar ONU por cliente (nome/CPF)
if (/reiniciar|resetar|restart|reboot|reset/i.test(action) && /onu|ont/i.test(fullMatch)) {
const query = match[3] || match[2] || null;
return {
action: 'reiniciar_onu',
target: query ? query.trim() : null,
confidence: 0.95,
type: 'reiniciar_onu_pattern'
};
}
if (/ipoe/i.test(fullMatch)) {
// "mudar para ipoe João" ou "ipoe João"
const query = match[match.length - 1] || null;