A integração Siemens S7 MQTT permite que um S7-1200 ou S7-1500 publique seus dados de processo diretamente em dashboards, historiadores e aplicações na nuvem, sem um servidor SCADA no meio. Neste tutorial você vai comparar as duas abordagens práticas, a biblioteca LMQTT nativa do CLP e um gateway externo, e depois construir um gateway Python funcional que lê um data block e o publica em um broker MQTT via TLS. Você terminará com uma estrutura de topics testada e um checklist para levar tudo à produção.
Duas formas de fazer Siemens S7 MQTT
Os CLPs S7 não falam MQTT de fábrica como falam comunicação S7, PROFINET ou OPC UA. Você tem duas opções realistas.
Opção 1: cliente MQTT dentro do CLP. A Siemens oferece uma biblioteca gratuita para o TIA Portal, geralmente chamada de LMQTT, que implementa um cliente MQTT 3.1.1 sobre os blocos de open user communication (TCON, TSEND, TRCV). O próprio CLP abre uma conexão TCP ou TLS com o broker e publica. Variantes dessa abordagem também existem em processadores de comunicação e dispositivos de borda da Siemens.
Opção 2: gateway externo. Um pequeno PC industrial, dispositivo de borda ou contêiner lê tags do CLP via comunicação S7 (PUT/GET) ou pelo servidor OPC UA do CLP e as publica em MQTT. O programa do CLP não muda, ou muda muito pouco.
| Critério | LMQTT no CLP | Gateway externo |
|---|---|---|
| Hardware extra | Nenhum | PC industrial, dispositivo de borda ou VM |
| Alterações no programa do CLP | Sim: chamadas de FB, buffers, montagem de JSON | Nenhuma ou mínimas |
| Impacto no tempo de ciclo do CLP | Pequeno, mas real; manipulação de strings é custosa | Nenhum |
| TLS | Suportado em firmware recente, com certificados no TIA Portal | Tratado pelo SO e pela biblioteca do gateway |
| Formatação do payload | Montada em SCL, com ferramentas de string limitadas | Qualquer formato, JSON ou Sparkplug com facilidade |
| Store-and-forward | Limitado pela memória do CLP | Buffer em disco no gateway |
| Quem mantém | Programador de CLP | Equipe de TI/TO ou de software |
| Ideal para | Poucos sinais, sem permissão para caixa extra | Muitos sinais, muitos CLPs, lógica mais rica |
Se você só precisa de algumas dezenas de valores de um CLP e adicionar hardware é difícil, o LMQTT é atraente. Se você está conectando uma linha ou uma planta, a abordagem com gateway escala melhor e mantém o CLP focado no controle. As vantagens e desvantagens de arquitetura são tratadas de forma mais ampla em conectividade de CLP para a nuvem.
Opção 1: a biblioteca nativa LMQTT
O fluxo de trabalho no TIA Portal é assim:
- Baixe a biblioteca LMQTT e sua documentação no Siemens Industry Online Support e adicione-a ao projeto como biblioteca global.
- Arraste o bloco de função do cliente para o programa e crie um data block de instância.
- Configure os parâmetros de conexão: hostname do broker, porta, client ID, usuário e senha, keep alive.
- Para TLS, importe o certificado da CA raiz do broker no gerenciador global de certificados do TIA Portal e atribua-o ao CLP. Um broker com certificado Let's Encrypt precisa do certificado ISRG Root X1. Consulte a documentação da biblioteca para ver as versões mínimas de firmware da CPU que suportam open user communication segura.
- Monte o payload em SCL como array de bytes ou string e dispare uma publicação em uma borda de subida, com topic, QoS e flag de retenção.
- Monitore as saídas de status e erro; o bloco informa falhas de conexão, timeouts e rejeições do broker.
Algumas lições de campo:
- Monte o JSON com cuidado. A concatenação de strings em SCL é verbosa e fácil de errar. Mantenha os payloads pequenos e use formatos fixos, ou publique strings numéricas simples em topics separados.
- Dispare na mudança, não a cada ciclo. Publicar em todo ciclo do OB1 vai inundar o broker e os recursos de comunicação do CLP. Use um temporizador ou uma comparação com banda morta.
- Cuidado com o client ID. Dois CLPs com o mesmo client ID vão desconectar um ao outro em loop. Em um broker MQTT gerenciado que vincula client IDs a credenciais, cada CLP precisa do seu próprio conjunto de credenciais.
- Use TLS desde o primeiro dia. Adaptar certificados depois do comissionamento significa outro download e outra janela de parada.
Opção 2: gateway Python com python-snap7
A abordagem com gateway usa a python-snap7 para ler um data block via comunicação S7 e a paho-mqtt para publicar. Ela roda em qualquer máquina Linux ou Windows que alcance o CLP na porta TCP 102.
Prepare o CLP no TIA Portal
As CPUs S7-1200 e S7-1500 bloqueiam leituras S7 externas por padrão. Faça duas alterações e um download:
- Nas propriedades da CPU, em Protection and Security, habilite Permit access with PUT/GET communication from remote partner.
- Nas propriedades do data block que você vai ler, desmarque Optimized block access para que as variáveis tenham offsets de bytes fixos.
Em seguida, crie um data block, por exemplo o DB10, com este layout:
| Offset | Nome | Tipo |
|---|---|---|
| 0.0 | Temperature | Real |
| 4.0 | Pressure | Real |
| 8.0 | MotorSpeed | Int |
| 10.0 | Running | Bool |
O PUT/GET não tem autenticação, então só o habilite em uma rede segmentada em que o gateway seja o único cliente. Se isso não for aceitável na sua planta, leia os mesmos dados pelo servidor OPC UA do S7-1500, como descrito no tutorial de gateway OPC UA para MQTT.
Instale as bibliotecas
python -m venv s7mqtt
source s7mqtt/bin/activate
pip install python-snap7 "paho-mqtt>=2.0"
O script do gateway
Este script lê o DB10 a cada segundo, aplica uma banda morta e publica apenas mudanças relevantes. Ele também mantém um topic de status retido com Last Will, para que os consumidores saibam quando o gateway fica offline.
import json
import time
import uuid
from datetime import datetime, timezone
import snap7
from snap7.util import get_real, get_int, get_bool
import paho.mqtt.client as mqtt
PLC_IP = "192.168.0.10"
RACK, SLOT = 0, 1 # CPUs S7-1200 e S7-1500 usam rack 0, slot 1
DB_NUMBER, DB_SIZE = 10, 12
# Teste primeiro no broker público. Use um prefixo aleatório: a área pública pode ser lida por qualquer pessoa.
BROKER = "broker.connectmq.com"
PORT = 1883
USE_TLS = False
USERNAME = None # produção: "YOUR_USERNAME"
PASSWORD = None # produção: "YOUR_PASSWORD"
CLIENT_ID = f"s7-gw-{uuid.uuid4().hex[:8]}" # produção: "YOUR_CLIENT_ID"
BASE = f"connectmq/demo/{uuid.uuid4().hex[:6]}/plant1/packaging/line2/filler"
DEADBANDS = {"temperature": 0.2, "pressure": 0.05, "motor_speed": 5}
def read_plc(plc):
data = plc.db_read(DB_NUMBER, 0, DB_SIZE)
return {
"temperature": round(get_real(data, 0), 2),
"pressure": round(get_real(data, 4), 3),
"motor_speed": get_int(data, 8),
"running": get_bool(data, 10, 0),
}
def changed(name, new, last):
if name not in last:
return True
if isinstance(new, bool):
return new != last[name]
return abs(new - last[name]) >= DEADBANDS.get(name, 0)
def on_connect(client, userdata, flags, reason_code, properties):
print("MQTT connected:", reason_code)
client.publish(f"{BASE}/status", "online", qos=1, retain=True)
def main():
mq = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2, client_id=CLIENT_ID)
if USERNAME:
mq.username_pw_set(USERNAME, PASSWORD)
if USE_TLS:
mq.tls_set() # o repositório de CAs do sistema valida o certificado Let's Encrypt
mq.will_set(f"{BASE}/status", "offline", qos=1, retain=True)
mq.on_connect = on_connect
mq.connect(BROKER, PORT, keepalive=30)
mq.loop_start()
plc = snap7.client.Client()
last = {}
last_full = 0.0
print("Publishing under", BASE)
while True:
try:
if not plc.get_connected():
plc.connect(PLC_IP, RACK, SLOT)
values = read_plc(plc)
now = time.time()
force = now - last_full > 300 # atualização completa a cada 5 minutos
ts = datetime.now(timezone.utc).isoformat(timespec="seconds")
for name, value in values.items():
if force or changed(name, value, last):
payload = json.dumps({"value": value, "ts": ts, "quality": "good"})
mq.publish(f"{BASE}/{name}", payload, qos=1)
last[name] = value
if force:
last_full = now
except Exception as exc: # CLP inacessível, layout de DB errado etc.
print("PLC read failed:", exc)
mq.publish(f"{BASE}/quality", "bad", qos=1, retain=True)
try:
plc.disconnect()
except Exception:
pass
time.sleep(5)
time.sleep(1)
if __name__ == "__main__":
main()
Veja os dados chegando
Execute o script, anote o prefixo exibido e assine-o em outro terminal:
mosquitto_sub -h broker.connectmq.com -p 1883 -i s7-watch-01 \
-t 'connectmq/demo/+/plant1/packaging/line2/filler/#' -v
Altere um valor na watch table do CLP e o topic correspondente é atualizado em menos de um segundo. Valores que variam menos que a banda morta ficam em silêncio, exatamente o comportamento desejado em uma rede de planta movimentada. O servidor MQTT público (gratuito) serve para este teste, mas nunca envie dados reais de produção para ele.
Migrando para um broker privado com TLS
Para produção, crie um broker privado e altere três configurações: PORT = 8883, USE_TLS = True e o usuário, a senha e o client ID emitidos no portal. Como o ConnectMQ usa um certificado Let's Encrypt, tls_set() com o repositório de CAs do sistema o valida sem precisar distribuir um arquivo de CA próprio. Remova o prefixo connectmq/demo/... e use um caminho ISA-95 limpo, como plant1/packaging/line2/filler/temperature; o portal do ConnectMQ reconhece topics no estilo ISA-95 e mostra os dispositivos organizados por empresa, site, área e linha. Esses mesmos topics ISA-95 também são uma boa base para um gêmeo digital da linha de envase.
Se você está decidindo entre rodar seu próprio broker ao lado dos CLPs e usar um broker MQTT gerenciado, pense em quem vai aplicar patches, renovar certificados e vigiar os limites de conexão às 3 da manhã.
Checklist de produção
- Um conjunto de credenciais e um client ID único por CLP ou gateway.
- TLS na porta 8883; nada de TCP sem criptografia fora da rede da planta.
- PUT/GET habilitado apenas em rede segmentada, ou use OPC UA.
- Bandas mortas dimensionadas por sinal, com atualização completa periódica.
- Topic de status retido com Last Will para os estados online e offline.
- QoS 1 para medições; QoS 0 só para dados de alta taxa que você pode perder.
- O gateway roda como serviço, com reinício automático e logs.
- Os nomes de topics seguem uma hierarquia ISA-95 acordada em todas as linhas.
Solução de problemas em conexões Siemens S7 MQTT
- Erro do snap7 "CLI : function refused by CPU". O PUT/GET não está habilitado ou a CPU não recebeu download desde a alteração.
- "Address out of range". O DB é menor que os bytes solicitados ou ainda está otimizado. Confira a coluna de offsets no TIA Portal.
- Valores parecem lixo. Os offsets estão errados. Lembre que Real tem 4 bytes, Int tem 2 e Bool é empacotado em bits.
- Loop de reconexão MQTT. Client ID duplicado, credenciais erradas ou o gateway conecta com TLS na porta 1883.
- LMQTT preso em "connecting". O DNS não está configurado na CPU ou o certificado da CA falta no repositório de certificados do CLP.
Para o restante do cenário industrial, incluindo Sparkplug B, gateways de borda e design de namespace, leia o guia de IoT industrial com MQTT. Também usa hardware Rockwell? O tutorial de Allen-Bradley MQTT segue o mesmo padrão com EtherNet/IP.
Conecte seus CLPs Siemens ao ConnectMQ
Seu gateway S7 precisa de um broker MQTT na nuvem seguro para publicar. Crie um broker Serverless gratuito em app.connectmq.com, sem cartão de crédito, copie as credenciais geradas para o script e veja as tags do seu CLP aparecerem no explorador de topics ao vivo.
Perguntas frequentes
Um S7-1200 pode publicar MQTT diretamente?
Sim. Com a biblioteca LMQTT da Siemens, um S7-1200 ou S7-1500 pode atuar como cliente MQTT. Consulte a documentação da biblioteca para ver as versões de firmware suportadas, especialmente se você precisa de TLS.
O Siemens S7 MQTT suporta MQTT 5?
A biblioteca nativa do CLP implementa MQTT 3.1.1. Se você precisa de recursos do MQTT 5, como expiração de mensagens, use um gateway externo com uma biblioteca como a paho-mqtt.
É seguro habilitar o acesso PUT/GET?
O PUT/GET não tem autenticação, então só o habilite em uma rede segmentada em que o gateway seja o único cliente. No S7-1500, o servidor OPC UA do CLP com autenticação de usuário é a alternativa mais segura.
Qual QoS os dados do CLP devem usar?
QoS 1 é um bom padrão para medições e status. Use retained messages nos topics de estado para que novos assinantes recebam imediatamente o valor atual.



