genieacs: try fix search

Signed-off-by: Rodrigo Bertoldo de Sousa Martins <rodrigo.sousa.577@gmail.com>
This commit is contained in:
rodrigo committed 2026-04-01 09:24:00 -03:00
1 parent c003631efc
commit a701b85754
2 files changed
+39 -7

No files matched your search

+36 -4
View File
@@ -8,6 +8,7 @@ const logger = require('../utils/logger');
*/ */
const DEVICE_PROJECTION = [ const DEVICE_PROJECTION = [
'_tags', '_tags',
'Tags',
'DeviceID.SerialNumber', 'DeviceID.SerialNumber',
'DeviceID.ProductClass', 'DeviceID.ProductClass',
'DeviceID.Manufacturer', 'DeviceID.Manufacturer',
@@ -110,23 +111,45 @@ class GenieACSApi {
/** /**
* Busca um dispositivo por serial number. * Busca um dispositivo por serial number.
* Tenta exato primeiro; se não encontrar, tenta uppercase (usuário pode ter digitado minúsculo).
* @param {string} serial - Serial number * @param {string} serial - Serial number
* @param {Object} instance - Instância de GenieACSConfig * @param {Object} instance - Instância de GenieACSConfig
*/ */
async buscarDispositivo(serial, instance) { async buscarDispositivo(serial, instance) {
logger.info(`[GenieACS] Buscando serial "${serial}" em ${instance.name}`); logger.info(`[GenieACS] Buscando serial "${serial}" em ${instance.name}`);
return this._buscar({ 'DeviceID.SerialNumber': serial }, instance, 'serial'); // Tentativa 1: exato como foi informado
const r1 = await this._buscar({ 'DeviceID.SerialNumber': serial }, instance, 'serial');
if (r1.success) return r1;
// Tentativa 2: uppercase (seriais costumam ser armazenados em maiúsculas)
const upper = serial.toUpperCase();
if (upper !== serial) {
logger.info(`[GenieACS] Tentando serial em uppercase: "${upper}"`);
return this._buscar({ 'DeviceID.SerialNumber': upper }, instance, 'serial');
}
return r1;
} }
/** /**
* Busca um dispositivo pela TAG (nome de usuário TopSapp). * Busca um dispositivo pela TAG (nome de usuário TopSapp).
* No GenieACS, as tags são armazenadas no campo _tags (array de strings). * Usa regex case-insensitive para não depender de maiúsculas/minúsculas.
* @param {string} tag - Valor da tag (ex.: login PPPoE do cliente) * @param {string} tag - Valor da tag (ex.: login PPPoE do cliente)
* @param {Object} instance - Instância de GenieACSConfig * @param {Object} instance - Instância de GenieACSConfig
*/ */
async buscarPorTag(tag, instance) { async buscarPorTag(tag, instance) {
logger.info(`[GenieACS] Buscando por TAG "${tag}" em ${instance.name}`); logger.info(`[GenieACS] Buscando por TAG "${tag}" em ${instance.name}`);
return this._buscar({ '_tags': tag }, instance, 'tag'); // Escapa caracteres especiais de regex no valor da tag
const tagEscaped = tag.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
// Tentativa 1: campo _tags com regex case-insensitive (formato array)
const r1 = await this._buscar(
{ '_tags': { '$regex': `^${tagEscaped}$`, '$options': 'i' } },
instance, 'tag'
);
if (r1.success) return r1;
// Tentativa 2: campo Tags.<nome> = true (formato objeto, como exibido na UI)
logger.info(`[GenieACS] Tentando campo Tags.${tag} em ${instance.name}`);
return this._buscar({ [`Tags.${tag.toLowerCase()}`]: true }, instance, 'tag');
} }
/** /**
@@ -141,7 +164,16 @@ class GenieACSApi {
const autoChannel5 = get('InternetGatewayDevice.LANDevice.1.WLANConfiguration.2.AutoChannelEnable'); const autoChannel5 = get('InternetGatewayDevice.LANDevice.1.WLANConfiguration.2.AutoChannelEnable');
// _tags é um array direto na raiz do objeto (não segue o padrão _value) // _tags é um array direto na raiz do objeto (não segue o padrão _value)
const tags = Array.isArray(raw._tags) ? raw._tags : []; // Tags também pode vir como objeto { clickcolmeia2025: { _value: true } } (formato UI do GenieACS)
let tags = [];
if (Array.isArray(raw._tags)) {
tags = raw._tags;
} else if (raw.Tags && typeof raw.Tags === 'object') {
// Extrai as chaves do objeto Tags onde o valor é true
tags = Object.entries(raw.Tags)
.filter(([k, v]) => k !== '_timestamp' && (v === true || (v && v._value === true)))
.map(([k]) => k);
}
return { return {
deviceId : raw._id || null, deviceId : raw._id || null,
+3 -3
View File
@@ -171,7 +171,7 @@ class NLPProcessor {
const serial = match[match.length - 1] || match[2]; const serial = match[match.length - 1] || match[2];
return { return {
action: 'ver_roteador', action: 'ver_roteador',
target: serial ? serial.trim().toUpperCase() : null, target: serial ? serial.trim() : null,
confidence: 0.95, confidence: 0.95,
type: 'genieacs_pattern' type: 'genieacs_pattern'
}; };
@@ -754,11 +754,11 @@ class NLPProcessor {
// Detectar "ver roteador SERIAL" / "roteador SERIAL" via GenieACS // Detectar "ver roteador SERIAL" / "roteador SERIAL" via GenieACS
if (/roteador|cpe/i.test(text) && !/onu|ont|sinal|signal/i.test(text)) { if (/roteador|cpe/i.test(text) && !/onu|ont|sinal|signal/i.test(text)) {
const rrMatch = text.match(/(?:ver|info|status|dados)?\s*(?:roteador|cpe)\s+([A-Z0-9_-]+)/i); const rrMatch = text.match(/(?:ver|info|status|dados)?\s*(?:roteador|cpe)\s+([A-Z0-9_@.-]+)/i);
if (rrMatch && rrMatch[1]) { if (rrMatch && rrMatch[1]) {
return { return {
action: 'ver_roteador', action: 'ver_roteador',
target: rrMatch[1].trim().toUpperCase(), target: rrMatch[1].trim(),
confidence: 0.9, confidence: 0.9,
type: 'keyword_roteador' type: 'keyword_roteador'
}; };