# IOT Discovery [En construcción] # Introducción La integración **Pandora IOT** tiene como finalidad supervisar mensajes que se reciben de **un servidor broker de mqtt.** Para ello**, la integración hace uso de un servidor broket MQTT,** que abre la posibilidad de suscribirse a un topic para recibir mensajes **y un plugin de Discovery,** que permite configurar un filtrado de estos mensajes y visualizar el postprocesado de estos en la consola de PandoraFMS mediante agentes y módulos que se envían vía XML al servidor de pandora. # Elementos de la integración IOT La integración IOT se compone principalmente de dos elementos clave, un servidor broker MQTT que se encargara de recibir los mensajes y almacenarlos en base de datos y un plugin de discovery que se encargara de filtrar estos mensajes previamente almacenados en base de datos y procesar estos para una visualización según sea requerida de estos que facilitara la automatización de alarmas o lo que sea necesario realizar con estos datos. - ##### **Servidor MQTT** Este servicio se encarga de conectarse a un servidor MQTT, recibir mensajes de un tema específico y almacenarlos en una base de datos. También registra logs en archivos y en la consola, limpia periódicamente los datos antiguos y maneja correctamente el cierre del programa para evitar pérdidas de información. - ##### **Plugin discovery** Este script se encarga de conectarse a la base de datos en los que se han almacenado los mensajes previamente con el receptor, realizar un filtrado de mensajes en base a una configuración previamente realizada por el usuario y crea agentes y módulos en base a los mensajes que pasan los filtros. # Instalación manual Puedes realizar una instalación manual del servidor MQTT de la siguiente manera: ##### **el8** Debes instalar el fichero .rpm llamado pandora\_iot\_server-1.0-1.el8.x86\_64.rpm ``` sudo dnf install ./pandora_iot_server-1.0-1.el8.x86_64.rpm ``` ##### **el9** Debes instalar el fichero .rpm llamado pandora\_iot\_server-1.0-1.el9.x86\_64.rpm ``` sudo dnf install ./pandora_iot_server-1.0-1.el9.x86_64.rpm ``` ##### **ubuntu** Debes instalar el fichero .deb llamado pandora\_iot\_server\_1.0-1.deb ``` sudo dpkg -i pandora_iot_server_1.0-1.deb ``` Una vez ejecutado el comando, nos pedirá confirmación, para instalar el server. [![image.png](https://pandorafms.com/guides/public/uploads/images/gallery/2025-02/scaled-1680-/XUdimage.png)](https://pandorafms.com/guides/public/uploads/images/gallery/2025-02/XUdimage.png) Después de aceptar, se instalará el servidor y podremos empezar a configurar la escucha de mensajes. [![image.png](https://pandorafms.com/guides/public/uploads/images/gallery/2025-02/scaled-1680-/85Nimage.png)](https://pandorafms.com/guides/public/uploads/images/gallery/2025-02/85Nimage.png) # Prerrequisitos - El servidor MQTT debe estar instalado en el entorno en el que se pretende realizar la escucha de mensajes. - El plugin de discovery, debe estar previamente cargado en PandoraFMS para poder configurar las tareas. - Se requiere conectividad al servidor MQTT - Se requiere conectividad hacia la base de datos que almacenara los mensajes. # Parámetros servidor MQTT ##### **Parámetros**
-c,--conf\_fileRuta al archivo de configuración
-v,--verbosityActivar modo debug
##### **Archivo de configuración (--conf)** ``` [DEFAULT] ;;topic topic = < Topic al que se suscribirse para recibir mensajes. > ;; connection host = < Host del servidor en el que se escucharan los mensajes > port = < Puerto del servidor en el que se escucharan los mensajes > ;; protocol supports: tcp, websockets, unix ; protocol = < Tipo de protocolo. Aceptados : tcp, websockets, unix ; user = < Usuario > ; password = < Contraseña > ; ssl = 0 < Activar cifrado ssl > ; trust_ssl = < Verificacion de certificado > ;; Database ; dbuser = < Usuario de la base de datos (opcional) > ; dbpass = < Contraseña de la base de datos (opcional) > ; dblocation = < Localización del fichero de base de datos > ; dbname = < Nombre del fichero de base de datos > ; data_cleaning_period = < Periodo de reestablecimiento de los datos > ;; Logs ;; log_name = < Nombre del fichero de logs > ; log_location = < Ruta del fichero de logs > ; log_level = < Nivel del log > ; max_log_bytes = < Tamaño máximo de log > ; log_rotation_count = < > ``` ##### **Ejemplo** ``` [DEFAULT] ;;topic topic = testtopic/# ;; connection host = test.mosquitto.org port = 1883 ;; protocol supports: tcp, websockets, unix ; protocol = websockets ; user = ro ; password = readonly ; ssl = 0 ; trust_ssl = 1 ;; Database ; dbuser = ; dbpass = ; dblocation = /opt/pandora/iot/db ; dbname = pandora_iot.db ; data_cleaning_period = 86400 ;; Logs ;; log_name = pandora_iot44.log ; log_location = /var/log/pandora/ ; log_level = debug ; max_log_bytes = 50_000_000 ; log_rotation_count = 3 ``` # Configurando el servidor MQTT Este script permite suscribirse a un tópico MQTT, recibir mensajes y almacenarlos en una base de datos SQLite. A continuación se describen los pasos para configurarlo y ejecutarlo correctamente. ##### **1.Configuración del archivo de configuración** Antes de ejecutar el script, se debe crear un archivo de configuración en formato .ini. Este archivo contiene los parámetros necesarios para la conexión al broker MQTT, la base de datos y la configuración de logs. Un ejemplo de archivo de configuración es el siguiente: ``` [DEFAULT] ;; MQTT Topic topic = testtopic/# ;; Conexión MQTT host = test.mosquitto.org port = 1883 protocol = tcp ssl = 0 trust_ssl = 1 ;; Base de Datos dbuser = usuario dbpass = contraseña dblocation = /ruta/del/directorio/db dbname = pandora_iot.db data_cleaning_period = 86400 ;; Logs log_name = pandora_iot.log log_location = /ruta/del/directorio/logs log_level = debug max_log_bytes = 50_000_000 log_rotation_count = 3 ``` #### Parámetros clave: - **`topic`**: Define el tópico MQTT al que se suscribirá el script (por ejemplo, `testtopic/#`). - **`host` y `port`**: Especifican la dirección y puerto del broker MQTT. - **`protocol`**: El protocolo a usar para la conexión MQTT (por ejemplo, `tcp` o `websockets`). - **`ssl`**: Habilita o deshabilita la conexión SSL. (0 para deshabilitar, 1 para habilitar). - **`trust_ssl`**: Controla si se debe confiar en los certificados SSL del broker. - **`dbuser` y `dbpass`**: Credenciales para acceder a la base de datos. - **`dblocation`**: Directorio donde se almacenará la base de datos SQLite. - **`dbname`**: Nombre de la base de datos SQLite. - **`data_cleaning_period`**: Tiempo (en segundos) para realizar limpieza de datos antiguos en la base de datos. - **`log_location`**: Directorio donde se almacenarán los archivos de log. - **`log_level`**: Nivel de detalle de los logs (por ejemplo, `debug`). - **`max_log_bytes` y `log_rotation_count`**: Configuración para la rotación de logs. - ##### **2. Arrancar el servicio.** Se podrá lanzar el servicio con el siguiente comando : ``` systemctl start pandora_iot_server ``` Para dejar de recibir y almacenar mensajes se puede pausar el servicio con : ``` systemctl stop pandora_iot_server ``` # Parámetros del plugin de Discovery ##### **Parámetros**
--confRuta al archivo de configuración
--filter\_confRuta al achivo de filtros para los mensajes
--verbositySirve para activar el modo debug
##### **Archivo de configuración (--conf)** ``` db_path = Ruta a la base de datos sql lite threads = < Número máximo de threads utilizados > timestamp_filter = < Timestamp en segundos desde el que se filtraran los mensajes > agents_group_name = < Nombre de grupo para los agentes creados > interval = < Intervalo en segundos para los agentes > tentacle_ip = < IP de la máquina destino para los agentes creados > tentacle_port = < Puerto de tentacle, por defecto : 41121 > ``` ##### **Ejemplo** ``` db_path = /var/spool/pandora/data_in/discovery/pandorafms.iot/mqtt_messages.db threads = 4 timestamp_filter = 1738000000 agents_group_name = Unknown interval = 300 tentacle_ip = 127.0.0.1 tentacle_port = 41121 ``` ##### **Archivo para filtrar los mensajes (--filter\_conf)** ``` #======================================================================= #Configuración de filtros #======================================================================= filter_begin: < Marca el inicio de una configuración de filtro. Todo lo que esté hasta filter_end pertenece al mismo filtro. Obligatorio. > filter_module_name: < Nombre asignado al módulo que genera el filtro. Obligatorio. > filter_module_type: < Tipo de módulo que genera el filtro. Obligatorio. > filter_topic: < Expresión regular o texto exacto que debe coincidir con el tema del mensaje para que se aplique el filtro. Opcional. Por defecto, coincide con cualquier tema. > filter_topic_exact_match: < Define si filter_topic se trata como una expresión regular (0) o como texto exacto (1). Opcional. Por defecto es 0. > filter_message: < Expresión regular o texto exacto que debe coincidir con el contenido del mensaje para que se aplique el filtro. Opcional. Por defecto, coincide con cualquier mensaje. > filter_message_exact_match: < Define si filter_message se trata como una expresión regular (0) o como texto exacto (1). Opcional. Por defecto es 0. > filter_message_capture_regex: < Expresión regular con grupos de captura para extraer valores del mensaje. > < Los valores capturados se almacenarán en macros '__regexN__', donde N es el índice del grupo de captura. > filter_message_capture_json: < Lista de rutas JSON (separadas por '|') para extraer valores, utilizando el mismo formato que jq. > < Los valores capturados se almacenarán en macros '__jsonN__', donde N es el índice de la ruta. > filter_module_value: < Valor asignado al módulo que genera el filtro. Obligatorio. > filter_end: < Marca el final de una configuración de filtro. Todo lo que esté desde filter_begin pertenece al mismo filtro. Obligatorio. > #Macros disponibles para su uso en filter_module_name y filter_module_value: __topic__: < Se reemplaza con el tema exacto del mensaje procesado. > __regexN__: < Se reemplaza con el valor correspondiente capturado por filter_message_capture_regex. > __jsonN__: < Se reemplaza con el valor correspondiente capturado por filter_message_capture_json. > ``` ##### **Ejemplo** ``` filter_begin​ filter_module_name pressure filter_module_type generic_data_string filter_topic sensor/humidity filter_topic_exact_match 1 filter_message Value: filter_message_exact_match 1 filter_message_capture_regex (\b\w{6}\b).*?(\b\w{7}\b).*?(\d{3})\s(\w)- filter_message_capture_json  filter_module_value 1__regex1__ __regex2__ __topic__ filter_end filter_begin​ filter_module_name humidity filter_module_type generic_data_string filter_topic sensor/pressure filter_topic_exact_match 1 filter_message  filter_message_exact_match 1 filter_message_capture_regex  filter_message_capture_json $.extra_info[0].value|$.extra_info[1].value filter_module_value 2 __json1__ __json2__ filter_end ``` # Configurando el plugin de Discovery Este plugin puede integrarse con el *Discovery* de Pandora FMS. Para ello se debe cargar el paquete ".disco" que puede descargar desde la librería de Pandora FMS: [https://pandorafms.com/library/](https://pandorafms.com/library/) [![image.png](https://pandorafms.com/guides/public/uploads/images/gallery/2025-02/scaled-1680-/image.png)](https://pandorafms.com/guides/public/uploads/images/gallery/2025-02/image.png) Una vez cargado, se podrá recibir y supervisar mensajes de un broker, creando tareas de *Discovery* desde la sección *Management > Discovery > App* Para cada tarea se solicitarán los siguientes datos mínimos: - **DB path:** Ruta del fichero de base de datos. - **Timestamp**: Timestamp en segundos desde el que se filtrará. - **Tentacle IP**: IP del servidor de Tentacle al que enviar los datos de los agentes. Normalmente este parámetro no se modificará. - **Tentacle port**: Puerto del servidor de Tentacle al que enviar los datos. Normalmente este parámetro no se modificará. - **Tentacle extra options:** Opciones extra de Tentacle. [![image.png](https://pandorafms.com/guides/public/uploads/images/gallery/2025-02/scaled-1680-/tjkimage.png)](https://pandorafms.com/guides/public/uploads/images/gallery/2025-02/tjkimage.png) También se podrá ajustar la configuración de los filtros para personalizar la monitorización deseada: [![image.png](https://pandorafms.com/guides/public/uploads/images/gallery/2025-02/scaled-1680-/nWDimage.png)](https://pandorafms.com/guides/public/uploads/images/gallery/2025-02/nWDimage.png) - **Max threads:** Número de hilos a utilizar. - **FIlter message modules**: Opciones de configuración de filtros para los módulos. Mas detalle sobre las opciones y etiquetas posibles a utilizar en este apartado en la seccion " [parámetros"](https://pandorafms.com/guides/public/books/iot-discovery-en-construccion/page/parametros-del-plugin-de-discovery) de este manual. Las tareas completadas con éxito tendrán un resumen de ejecución con la siguiente información: [![image.png](https://pandorafms.com/guides/public/uploads/images/gallery/2025-02/scaled-1680-/iOkimage.png)](https://pandorafms.com/guides/public/uploads/images/gallery/2025-02/iOkimage.png) - **Total agents** : Número total de agentes generados por la tarea. - **Total messages:** Numero total de mensajes que han pasado los filtros. # Configurando el filtrado de mensajes El plugin hace uso de distintos filtros en los que apoyarse para la filtración de mensajes. ### **Filtrado de topic** Para el filtrado de topic, se hace uso de las etiquetas Filter\_topic y Filter\_topic\_exact\_match - ##### **Filter\_topic** Expresión regular o texto exacto que deba coincidir con el topic del mensaje para cumplirse el filtro. Es opcional. Por defecto haría match con cualquier topic. - ##### **Filter\_topic\_exact\_match** Indica si lo indicado en filter\_topic se tratará como una expresión regular (0) o como un texto exacto (1). Es opcional. Por defecto su valor es 0. ##### **Ejemplos** Haciendo uso de los filtros **Filter\_topic** y **Filter\_topic\_exact\_match** podremos elegir el topic al que suscribirse. Podemos indicar directamente el nombre del topic o buscar un patron de regex en este. Supongamos que tienes un topic MQTT llamado: ``` sensors/temperature/livingroom ``` ***EJEMPLO 1 filter\_topic\_exact\_match 1 (Texto exacto)*** Podríamos configurar filter\_topic especifando el nombre del topic. ``` filter_topic sensors/temperature/livingroom ``` y configurar filter\_topic\_exact\_match a 1, para que busque solo ese topic. ``` filter_topic_exact_match 1 ``` Si en vez de especificar el nombre del topic completo, especificamos solo una parte de este : ``` filter_topic sensors/temperature/ ``` También coincidiría. [![image.png](https://pandorafms.com/guides/public/uploads/images/gallery/2025-02/scaled-1680-/Fb9image.png)](https://pandorafms.com/guides/public/uploads/images/gallery/2025-02/Fb9image.png) ***EJEMPLO 2 filter\_topic\_exact\_match 0 (Expresión regular)*** Podríamos configurar filter\_topic especifando una expresión regular que haga match con el nombre del topic al que se pretende suscribir. Por ejemplo, la siguiente, que miraría que empiecen por "sensors" y terminen en "livingroom" ``` filter_topic ^sensors/.*?/livingroom$ ``` y configurar filter\_topic\_exact\_match a 0, para que filtre por expresión regular, en vez de texto exacto. ``` filter_topic_exact_match 0 ``` [![image.png](https://pandorafms.com/guides/public/uploads/images/gallery/2025-02/scaled-1680-/Ge5image.png)](https://pandorafms.com/guides/public/uploads/images/gallery/2025-02/Ge5image.png) ### **Filtrado de mensajes** Para el filtrado de topic, se hace uso de las etiquetas Filter\_topic y Filter\_topic\_exact\_match - ##### **Filter\_message** Expresión regular o texto exacto que deba coincidir con el mensaje para cumplirse el filtro. Es opcional. Por defecto haría match con cualquier mensaje. - ##### **FIlter\_message\_exact\_match** Indica si lo indicado en filter\_message se tratará como una expresión regular (0) o como un texto exacto (1). Es opcional. Por defecto su valor es 0. ##### **Ejemplos** Haciendo uso de los filtros **Filter\_message**y **Filter\_message\_exact\_match** podremos filtrar los mensajes que se van a recibir. Podemos indicar directamente contenido del mensaje o buscar un patron de regex en este. Supongamos que tienes un mensaje como este: ``` {"message":"Move up right", "status":"active", "datetime":"2025-02-11T14:30:54.260Z", "data":{"yaw_rate":0.11466979980468749, "pitch_rate":0.6159210205078126, "yaw_direction":"right", "pitch_direction":"up"}} ``` ***EJEMPLO 1 filter\_message\_exact\_match 1 (Texto exacto)*** Podríamos configurar filter\_message especifando el texto del mensaje. ``` filter_message Move up right ``` y configurar filter\_topic\_exact\_match a 1, para que busque solo ese topic. ``` filter_message_exact_match 1 ``` Si en vez de especificar el nombre del topic completo, especificamos solo una parte de este : ``` filter_message Move up ``` También coincidiría. [![image.png](https://pandorafms.com/guides/public/uploads/images/gallery/2025-02/scaled-1680-/Zo5image.png)](https://pandorafms.com/guides/public/uploads/images/gallery/2025-02/Zo5image.png) ***EJEMPLO 2 filter\_message\_exact\_match 0 (Expresión Regular)*** Podríamos configurar filter\_message especifando una expresión regular que haga match con los mensajes que se pretenden filtrar. Por ejemplo, la siguiente, buscaría un mensaje que contenga las palabras "move" y "right" ``` filter_message Move.*right|right.*Move ``` y configurar filter\_message\_exact\_match a 0, para que filtre por expresión regular, en vez de texto exacto. ``` filter_message_exact_match 0 ``` [![image.png](https://pandorafms.com/guides/public/uploads/images/gallery/2025-02/scaled-1680-/tGrimage.png)](https://pandorafms.com/guides/public/uploads/images/gallery/2025-02/tGrimage.png) ### **Generación y uso de macros** ##### **Ejemplos** Imagina que tenemos el siguiente mensaje: ``` { "message": "Move up right", "status": "active", "datetime": "2025-02-11T14:30:54.260Z", "data": { "yaw_rate": 0.11466979980468749, "pitch_rate": 0.6159210205078126, "yaw_direction": "right", "pitch_direction": "up" } } ``` Y queremos capturar algunas partes del mensaje, por ejemplo : - **`yaw_direction`** (dirección del giro), que es `"right"`. - **`pitch_direction`** (dirección de inclinación), que es `"up"`. - **`message`**, que contiene `"Move up right"`. Además, también queremos capturar el **`topic`** al que pertenece el mensaje en una macro para incluirlo en el valor. Para ello deberíamos seguir los siguientes pasos, pudiendo hacerlo con Filter\_message\_capture\_regex y FIlter\_message\_capture\_json: - ##### **FIlter\_message\_capture\_regex** Con Filter\_message\_capture\_regex se espera una expresión regular con grupos de captura para obtener valores del mensaje. Aquello que haga match con los grupos de captura se almacenará en macros “\_\_regexN\_\_”, siendo N la posición del grupo de captura de la regex. Los pasos para configurar las macros a capturar serían los siguientes: **1. Configurar filter\_message\_capture\_regex para capturar las partes necesarias:** Usamos una expresión regular para capturar "yaw\_direction", "pitch\_direction" y el contenido de "message". ``` filter_message_capture_regex \"yaw_direction\":\\s?\"(\\w+)\".*\"pitch_direction\":\\s?\"(\\w+)\".*\"message\":\\s?\"([^\"]+)\" ``` **2. Configurar filter\_module\_value para incluir las macros que contienen los valores capturados y el topic.** ``` filter_module_value __topic__ | Yaw Direction: __regex1__ | Pitch Direction: __regex2__ | Message: __regex3__ ``` **Ejemplo de configuración completa** [![image.png](https://pandorafms.com/guides/public/uploads/images/gallery/2025-02/scaled-1680-/V6simage.png)](https://pandorafms.com/guides/public/uploads/images/gallery/2025-02/V6simage.png) ``` filter_begin​ filter_module_name temperature humidity filter_module_type generic_data_string filter_topic testtopic/rgb/test/action/ filter_topic_exact_match 1 filter_message Move up right filter_message_exact_match 1 filter_message_capture_regex \"yaw_direction\":\\s?\"(\\w+)\".*\"pitch_direction\":\\s?\"(\\w+)\".*\"message\":\\s?\"([^\"]+)\" filter_message_capture_json filter_module_value __topic__ | Yaw Direction: __regex1__ | Pitch Direction: __regex2__ | Message: __regex3__ filter_end ``` Entonces, con el mensaje y la configuración mostradas de ejemplos previamente, se crearía el siguiente agente: [![image.png](https://pandorafms.com/guides/public/uploads/images/gallery/2025-02/scaled-1680-/w0timage.png)](https://pandorafms.com/guides/public/uploads/images/gallery/2025-02/w0timage.png) Y el siguiente módulo de mensaje: [![image.png](https://pandorafms.com/guides/public/uploads/images/gallery/2025-02/scaled-1680-/l2gimage.png)](https://pandorafms.com/guides/public/uploads/images/gallery/2025-02/l2gimage.png) [![image.png](https://pandorafms.com/guides/public/uploads/images/gallery/2025-02/scaled-1680-/MPjimage.png)](https://pandorafms.com/guides/public/uploads/images/gallery/2025-02/MPjimage.png) - ##### **Filter\_message\_capture\_json** Con Filter\_message\_capture\_json se espera una lista de rutas dentro de un JSON (separadas por”|”) de las cuales capturar sus valores. Usando el mismo formato que el comando jq. Aquello que se capture por cada path se almacenará en macros “\_\_jsonN\_\_”, siendo N la posición del path dentro de la lista. . Los pasos para configurar las macros a capturar serían los siguientes: **1. Configurar filter\_message\_capture\_json para capturar las partes necesarias del JSON.** ``` filter_message_capture_json $.data.yaw_direction|$.data.pitch_direction|$.message ```

Las rutas JSONPath deben comenzar con $ porque representa la raíz del documento JSON.

**2. Configurar filter\_module\_value para incluir las macros que contienen los valores capturados y el topic.** ``` filter_module_value __topic__ | Yaw Direction: __json1__ | Pitch Direction: __json2__ | Message: __json3__ ``` **Ejemplo de configuración completa** [![image.png](https://pandorafms.com/guides/public/uploads/images/gallery/2025-02/scaled-1680-/yIUimage.png)](https://pandorafms.com/guides/public/uploads/images/gallery/2025-02/yIUimage.png) ``` filter_begin​ filter_module_name __topic__ get right filter_module_type generic_data_string filter_topic testtopic/rgb/test/action/ filter_topic_exact_match 1 filter_message Move up right filter_message_exact_match 1 filter_message_capture_regex filter_message_capture_json $.data.yaw_direction|$.data.pitch_direction|$.message filter_module_value __topic__ | Yaw Direction: __json1__ | Pitch Direction: __json2__ | Message: __json3__ filter_end ``` Entonces, con el mensaje y la configuración mostradas de ejemplos previamente, se crearía el siguiente agente: [![image.png](https://pandorafms.com/guides/public/uploads/images/gallery/2025-02/scaled-1680-/w0timage.png)](https://pandorafms.com/guides/public/uploads/images/gallery/2025-02/w0timage.png) Y el siguiente módulo de mensaje: [![image.png](https://pandorafms.com/guides/public/uploads/images/gallery/2025-02/scaled-1680-/l2gimage.png)](https://pandorafms.com/guides/public/uploads/images/gallery/2025-02/l2gimage.png) [![image.png](https://pandorafms.com/guides/public/uploads/images/gallery/2025-02/scaled-1680-/MPjimage.png)](https://pandorafms.com/guides/public/uploads/images/gallery/2025-02/MPjimage.png) # Ejecución manual El formato de la ejecución del plugin es el siguiente: ``` ./proccess_messages --conf < ruta al fichero de configuración > --filter_conf < ruta al fichero con los filtros para los mensajes > ``` Por ejemplo: ``` ./proccess_messages --conf /var/spool/pandora/data_in/discovery/pandorafms.iot/file.conf --filter_conf /var/spool/pandora/data_in/discovery/pandorafms.iot/file_filters.conf ``` La ejecución devolverá una salida en formato JSON con información sobre la ejecución, y generará un fichero XML para cada agente (topic) y cada mensaje que haya pasado los filtros, que enviará al servidor de Pandora FMS por el método de transferencia indicado en la configuración. Por ejemplo: {"summary": {"Total agents": 2, "Total messages": 141}} ``` {"summary": {"Total agents": 2, "Total messages": 2}} ``` # Agentes y módulos generados por el plugin - Se creara un agente por cada topic que contenga mensajes que hayan pasado los filtros - Se creará un módulo por cada mensaje que haya pasado los filtros.

Recuerda que no puede haber mas de un modulo con el mismo nombre en el mismo agente.