153 lines
6.4 KiB
JavaScript
153 lines
6.4 KiB
JavaScript
const GenieACSApi = require('./api');
|
|
const GenieACSConfig = require('./config');
|
|
const logger = require('../utils/logger');
|
|
|
|
class GenieACSManager {
|
|
constructor() {
|
|
this.api = new GenieACSApi();
|
|
this.config = new GenieACSConfig();
|
|
logger.info('GenieACSManager inicializado');
|
|
console.log('📡 GenieACSManager inicializado');
|
|
}
|
|
|
|
/**
|
|
* Verifica se ao menos uma instância está configurada.
|
|
*/
|
|
isReady() {
|
|
return this.config.isReady();
|
|
}
|
|
|
|
/**
|
|
* Busca informações de um roteador/CPE pelo serial number ou pela TAG (username TopSapp).
|
|
* Tenta por serial primeiro; se não encontrar, tenta por TAG.
|
|
* Se o termo contém "@", também tenta a parte antes do @ como TAG.
|
|
*
|
|
* @param {string} termo - Serial ou TAG do dispositivo
|
|
* @param {string} location - Texto de localização (opcional)
|
|
* @returns {Promise<Object>} - { success, device, instance, searchedBy, error }
|
|
*/
|
|
async buscarRoteador(termo, location = '') {
|
|
if (!this.isReady()) {
|
|
return {
|
|
success: false,
|
|
error: 'GenieACS não está configurado. Verifique as variáveis GENIEACS_* no arquivo .env'
|
|
};
|
|
}
|
|
|
|
const instance = this.config.getInstanceByLocation(location);
|
|
const termoLimpo = termo.trim();
|
|
|
|
// 1ª tentativa: busca por serial (exato e uppercase)
|
|
logger.info(`[GenieACS] Tentando como serial: "${termoLimpo}"`);
|
|
const porSerial = await this.api.buscarDispositivo(termoLimpo, instance);
|
|
if (porSerial.success) {
|
|
return { ...porSerial, instance: instance.name };
|
|
}
|
|
|
|
// 2ª tentativa: busca por TAG (termo completo)
|
|
logger.info(`[GenieACS] Não encontrado como serial. Tentando como TAG: "${termoLimpo}"`);
|
|
const porTag = await this.api.buscarPorTag(termoLimpo, instance);
|
|
if (porTag.success) {
|
|
return { ...porTag, instance: instance.name };
|
|
}
|
|
|
|
// 3ª tentativa: se o termo tem "@", tentar só a parte antes do @ como TAG
|
|
// (ex.: "clickcolmeia2025@isp" -> tenta "clickcolmeia2025")
|
|
if (termoLimpo.includes('@')) {
|
|
const tagBase = termoLimpo.split('@')[0].toLowerCase();
|
|
logger.info(`[GenieACS] Tentando TAG sem domínio: "${tagBase}"`);
|
|
const porTagBase = await this.api.buscarPorTag(tagBase, instance);
|
|
if (porTagBase.success) {
|
|
return { ...porTagBase, instance: instance.name };
|
|
}
|
|
}
|
|
|
|
// Nenhum resultado
|
|
const errConexao = porSerial.error || porTag.error;
|
|
return {
|
|
success: false,
|
|
error: errConexao || `Nenhum dispositivo encontrado com serial ou TAG "${termoLimpo}"`
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Sincroniza o login PPPoE do TopSapp como TAG no GenieACS.
|
|
*
|
|
* Fluxo:
|
|
* 1. Busca o dispositivo pelo serial (vindo do TopSapp)
|
|
* 2. Deriva a TAG do login PPPoE (parte antes do "@", em minúsculo)
|
|
* 3. Se a TAG ainda não existir no dispositivo, adiciona via NBI
|
|
*
|
|
* @param {string} serial - Serial do dispositivo (do cadastro TopSapp)
|
|
* @param {string} pppoeLogin - Login PPPoE do cliente (ex.: "clickcolmeia2025" ou "user@isp")
|
|
* @param {string} location - Texto de localização (opcional)
|
|
* @returns {Promise<Object>} - { success, tag, deviceId, already, error }
|
|
*/
|
|
async sincronizarTagPPPoE(serial, pppoeLogin, location = '') {
|
|
if (!this.isReady() || !serial || !pppoeLogin) {
|
|
return { success: false, skipped: true };
|
|
}
|
|
|
|
const instance = this.config.getInstanceByLocation(location);
|
|
|
|
// A TAG usa apenas a parte antes do "@", em minúsculo,
|
|
// igualando ao padrão que o GenieACS já exibe na UI (ex.: "clickcolmeia2025")
|
|
const tag = pppoeLogin.split('@')[0].toLowerCase();
|
|
|
|
// Localizar dispositivo pelo serial
|
|
const result = await this.api.buscarDispositivo(serial.trim(), instance);
|
|
if (!result.success || !result.device?.deviceId) {
|
|
logger.warn(`[GenieACS] Sync TAG: dispositivo serial "${serial}" não encontrado`);
|
|
return { success: false, error: 'Dispositivo não encontrado pelo serial' };
|
|
}
|
|
|
|
const deviceId = result.device.deviceId;
|
|
const tagsAtuais = result.device.tags || [];
|
|
|
|
// Verificar se a tag já está presente (case-insensitive)
|
|
if (tagsAtuais.some(t => t.toLowerCase() === tag)) {
|
|
logger.info(`[GenieACS] Sync TAG: "${tag}" já existe em ${deviceId}`);
|
|
return { success: true, already: true, tag, deviceId };
|
|
}
|
|
|
|
// Adicionar a TAG
|
|
logger.info(`[GenieACS] Sync TAG: adicionando "${tag}" em ${deviceId}`);
|
|
const addResult = await this.api.adicionarTag(deviceId, tag, instance);
|
|
return { ...addResult, tag, deviceId };
|
|
}
|
|
/**
|
|
* Aplica um conjunto de setParameterValues a um dispositivo já conhecido pelo deviceId.
|
|
*
|
|
* @param {string} deviceId - _id do dispositivo no GenieACS
|
|
* @param {Array} paramValues - Array de [paramName, value, xsdType]
|
|
* @param {string} location - Texto de localização (opcional)
|
|
* @returns {Promise<Object>} - { success, error }
|
|
*/
|
|
async configurarRoteador(deviceId, paramValues, location = '') {
|
|
if (!this.isReady() || !deviceId) {
|
|
return { success: false, error: 'GenieACS não configurado ou deviceId ausente' };
|
|
}
|
|
const instance = this.config.getInstanceByLocation(location);
|
|
return this.api.setParameterValues(deviceId, paramValues, instance);
|
|
}
|
|
|
|
/**
|
|
* Relê um dispositivo pelo seu _id para obter dados atualizados.
|
|
*
|
|
* @param {string} deviceId - _id do dispositivo
|
|
* @param {string} location - Texto de localização (opcional)
|
|
* @returns {Promise<Object>} - { success, device, instance, searchedBy }
|
|
*/
|
|
async buscarRoteadorPorId(deviceId, location = '') {
|
|
if (!this.isReady() || !deviceId) {
|
|
return { success: false, error: 'GenieACS não configurado ou deviceId ausente' };
|
|
}
|
|
const instance = this.config.getInstanceByLocation(location);
|
|
const result = await this.api._buscar({ '_id': deviceId }, instance, 'id');
|
|
if (result.success) return { ...result, instance: instance.name };
|
|
return result;
|
|
}
|
|
}
|
|
|
|
module.exports = GenieACSManager;
|