Monitoramento MQTT - Khomp IED302

Escrito por Hitfy



Preparação do Proxy e Serviço de coleta MQTT

Foi desenvolvido em python um serviço que executa na maquina pxHitfy-OCI para escuta e criação de threads para receber tópicos MQTT e enviar para o host correto. Lembrando que esse processo só é necessário caso necessite reconstruir o serviço MQTT.


Código do serviço em python (/etc/zabbix/mqtt_zabbix_service.py)

#!/usr/bin/env python3

import threading
import subprocess
from flask import Flask, request, jsonify
from paho.mqtt.client import Client as MQTTClient

app = Flask(__name__)

# Chave: (broker, topic, zabbix_host), Valor: Thread
active_listeners = {}
lock = threading.Lock()

ZABBIX_SERVER = "localhost"  # IP ou hostname fixo do servidor Zabbix

def send_to_zabbix(zabbix_host, key, value):
    try:
        subprocess.run([
            "zabbix_sender", "-z", ZABBIX_SERVER,
            "-s", zabbix_host, "-k", key, "-o", value
        ], check=True)
        print(f"[ZABBIX] {zabbix_host}: {key} = {value}")
    except subprocess.CalledProcessError as e:
        print(f"[ERRO] Falha ao enviar para Zabbix ({zabbix_host}): {e}")

def mqtt_listener(broker, topic, zabbix_host):
    client = MQTTClient()
    client.on_connect = lambda c, u, f, rc: c.subscribe(topic)
    client.on_message = lambda c, u, msg: send_to_zabbix(
        zabbix_host,
        f"mqtt.{topic.replace('/', '_')}",
        msg.payload.decode()
    )

    try:
        client.connect(broker, 1883, 60)
        client.loop_forever()
    except Exception as e:
        print(f"[ERRO] Conexão com {broker} falhou: {e}")

@app.route("/listen", methods=["POST"])
def listen():
    data = request.get_json()
    broker = data.get("broker")
    topic = data.get("topic")
    zabbix_host = data.get("zabbix_host")

    if not broker or not topic or not zabbix_host:
        return jsonify({"error": "Parâmetros 'broker', 'topic' e 'zabbix_host' são obrigatórios."}), 400

    key = (broker, topic, zabbix_host)

    with lock:
        if key in active_listeners:
            return jsonify({"status": "Escutando", "broker": broker, "topic": topic, "zabbix_host": zabbix_host})

        thread = threading.Thread(target=mqtt_listener, args=(broker, topic, zabbix_host), daemon=True)
        active_listeners[key] = thread
        thread.start()
        return jsonify({"status": "Iniciado", "broker": broker, "topic": topic, "zabbix_host": zabbix_host})

@app.route("/status", methods=["GET"])
def status():
    with lock:
        return jsonify({
            "ativos": [f"{b}::{t} -> {h}" for (b, t, h) in active_listeners.keys()]
        })

if __name__ == "__main__":
    app.run(host="0.0.0.0", port=5000)

Preparar libs para ativar o serviço do linux

Instalar as libs Flask, paho-mqtt com o comando abaixo

pip3 install flask paho-mqtt


Criando serviço no linux

Crie o arquivo vim /etc/systemd/system/mqtt_zabbix.service e coloque o código abaixo

[Unit]
Description=Serviço MQTT para envio ao Zabbix
After=network.target

[Service]
Type=simple
ExecStart=/usr/bin/python3 /etc/zabbix/mqtt_zabbix_service.py
WorkingDirectory=/etc/zabbix
Restart=always
RestartSec=5
User=nobody
Environment=PYTHONUNBUFFERED=1

[Install]
WantedBy=multi-user.target

Depois execute os comandos abaixo para criar o serviço, ativar e verificar o status

systemctl daemon-reexec
systemctl daemon-reload
systemctl enable --now mqtt_zabbix.service
systemctl status mqtt_zabbix.service

Verificar logs em tempo real do serviço

journalctl -u mqtt_zabbix.service -f

Comandos para verificar e ativar novos processo de escuta MQTT por tópico

Executar o comando abaixo para verificar o status e listar todos os tópicos que estão sendo ouvidos.

 curl <http://localhost:5000/status>

Executar na maquina que esta instalado o serviço e exibira o resultado abaixo:

{"ativos":["146.235.57.205::remota/211500/measures -> Broker_MQTT_DevIOT","{$BROKER}::{$TOPIC} -> Broker_MQTT_DevIOT"]}


Comando para ativar uma nova escuta de tópico

curl -X POST <http://localhost:5000/listen> -H "Content-Type: application/json"   -d '{"broker": "<IP do Broker MQTT>", "topic": "<Tópico do MQTT>", "zabbix_host": "<Nome do Host>"}'

Executar na maquina que esta instalado o serviço e exibira o resultado abaixo:

{"broker":"146.235.57.205","status":"Escutando","topic":"remota/211500/measures","zabbix_host":"Broker_MQTT_DevIOT"}

OBS.: O serviço MQTT já bloqueia a ativação do mesmo tópico.


Ativação do monitoramento IED302 para coleta de Corrente e Tensão

É necessário criar um host no zabbix, depois adicionar a template (Template_Khomp_IED302_Padrao) e ter as informações do Broker e Tópico:

  • Broker, é o IP que esta instalado o serviço que coleta e envia para o Zabbix. Hoje é o IP 146.235.57.205
  • Tópico, é o caminho que vamos pegar as informações e coletar no zabbix, o tópico é composto por “remota/<Numero de serie>/measures”. Exemplo: remota/211500/measures

Depois de adicionar o host, é necessário ajustar a macro desse host com as informações acima.