【开发者实战】用Python和Docker在边缘计算网关上统一读写西门子与三菱PLC

Python+Docker统一读写PLC

摘要 :对于IIoT应用开发者而言,如何优雅地处理底层异构的PLC协议,是一个常见的挑战。本文将提供一个具体的、可复现的实战项目:在一个开放的工业边缘计算网关(以鲁邦通EG系列为例)上,利用Python和Docker,创建一个统一的数据服务,实现对西门子S7和三菱MC协议PLC的并发、异步读写,并将结果通过统一的MQTT主题发布。

导语 :作为开发者,我们理想中的数据采集应该是:调用一个简单的API,如read_tag("Motor_Speed"),而无需关心这个标签是来自西门子的DB块,还是三菱的D寄存器。本文将向你展示,如何利用工业边缘计算网关的开放性和计算能力,结合强大的开源社区,构建出这样一个与底层协议细节解耦的、优雅的南向数据服务。

项目架构设计

我们将构建一个运行在Docker容器内的Python应用。该应用包含三个核心模块:

  1. S7 Client Module: 使用python-snap7库,负责与西门子PLC通信。

  2. MC Client Module: 使用pymcprotocol库,负责与三菱PLC通信。

  3. Main Service Module: 负责调度上述两个客户端,并发地、周期性地轮询点位,并将读取到的数据,以统一的JSON格式,发布到MQTT Broker。

1. 准备Dockerfile

我们需要一个包含Python环境和所需库的ARM64 Docker镜像。

Dockerfile:

Dockerfile

# Use an ARM64 compatible Python base image from a trusted source
FROM arm64v8/python:3.9-slim-bullseye

# Install snap7 library dependencies
RUN apt-get update && apt-get install -y libsnap7-1 libsnap7-dev && rm -rf /var/lib/apt/lists/*

WORKDIR /app

COPY requirements.txt .
# Install Python libraries
RUN pip install --no-cache-dir -r requirements.txt

COPY . .

CMD ["python", "main.py"]

requirements.txt:

python-snap7
pymcprotocol
paho-mqtt

2. 核心代码实现 (main.py)

为了实现并发轮询,我们为每台PLC创建一个独立的线程。

Python

import snap7
import pymcprotocol
import paho.mqtt.client as mqtt
import threading
import time
import json

# --- Config ---
SIEMENS_IP = '192.168.1.10'
MITSUBISHI_IP = '192.168.1.11'
MQTT_BROKER = 'localhost' # Use the gateway's own MQTT broker
MQTT_TOPIC_PREFIX = 'factory/plc'

# --- Siemens Polling Thread ---
def siemens_poller():
    client = snap7.client.Client()
    try:
        client.connect(SIEMENS_IP, 0, 1) # Rack 0, Slot 1
    except Exception as e:
        print(f"Siemens connection error: {e}")
        return

    while True:
        try:
            # Read DB1, starting at byte 0, for 4 bytes (a REAL value)
            data = client.db_read(1, 0, 4)
            speed = snap7.util.get_real(data, 0)
            payload = {"tag": "Motor_Speed", "value": speed, "ts": time.time()}
            mqtt_client.publish(f"{MQTT_TOPIC_PREFIX}/siemens", json.dumps(payload))
            print(f"Published Siemens data: {payload}")
        except Exception as e:
            print(f"Siemens read error: {e}")
        time.sleep(1)
    client.disconnect()

# --- Mitsubishi Polling Thread ---
def mitsubishi_poller():
    client = pymcprotocol.Type3E()
    try:
        client.connect(MITSUBISHI_IP, 5002) # Port for MC Protocol
    except Exception as e:
        print(f"Mitsubishi connection error: {e}")
        return
        
    while True:
        try:
            # Read D100 and D101 (a 32-bit integer)
            value = client.batchread_wordunits(headdevice="D100", readsize=2)
            # Assuming D100 is low word, D101 is high word for a DINT
            dint_value = (value[1] << 16) + value[0]
            payload = {"tag": "Total_Count", "value": dint_value, "ts": time.time()}
            mqtt_client.publish(f"{MQTT_TOPIC_PREFIX}/mitsubishi", json.dumps(payload))
            print(f"Published Mitsubishi data: {payload}")
        except Exception as e:
            print(f"Mitsubishi read error: {e}")
        time.sleep(2)
    client.close()

# --- Main ---
if __name__ == '__main__':
    # Setup MQTT Client
    mqtt_client = mqtt.Client()
    mqtt_client.connect(MQTT_BROKER, 1883, 60)
    mqtt_client.loop_start()

    # Create and start threads
    s7_thread = threading.Thread(target=siemens_poller)
    mc_thread = threading.Thread(target=mitsubishi_poller)
    
    s7_thread.start()
    mc_thread.start()

    s7_thread.join()
    mc_thread.join()

3. 部署到边缘计算网关

  1. 构建镜像: 在开发机上,使用docker buildx build --platform linux/arm64 -t my-plc-collector . --load命令构建好多架构镜像。

  2. 推送镜像: 将镜像推送到Docker Hub或私有仓库。

  3. 在网关上运行: 通过SSH登录到鲁邦通边缘计算网关,执行:

    Bash

    docker run -d --name plc_collector --restart always --network host your-repo/my-plc-collector:latest
    

    我们使用--network host是为了让容器能直接访问到局域网内的PLC和网关上可能运行的本地MQTT Broker。

4. 验证

你可以使用一个MQTT客户端(如MQTTX),订阅factory/plc/#主题,就能看到来自西门子和三菱PLC的数据,被统一格式化后,源源不断地发布出来。

常见问题解答 (FAQ)

  • 问题1:为什么不使用厂商自带的中间件(如E2C Pro)而是自己开发?

    • 答:厂商中间件能解决80%的通用需求,非常高效。但当遇到非标协议、需要进行复杂的数据预处理或需要与特定系统进行深度集成时,自定义开发就提供了无限的灵活性。一个好的工业边缘计算网关应该同时提供这两种选择。

  • 问题2:这种并发轮询方式,在PLC数量很多时,性能如何保证?

    • 答:当PLC数量增加时,基于线程的模型会遇到性能瓶颈。更优的架构是采用基于asyncio的异步I/O模型,使用一个单线程的事件循环来处理所有PLC的通信,可以轻松支持数十上百台PLC的并发连接。

  • 问题3:开源的PLC通信库可靠吗?

    • 答:像python-snap7pymcprotocol都是在社区经过了大量验证的、相对成熟的库。但在生产环境中大规模使用前,仍需进行详尽的压力和异常测试。对于追求极致稳定性的项目,使用厂商(如鲁邦通)经过商业验证和加固的协议驱动,是更稳妥的选择。

总结鲁邦通工业边缘计算网关的开放性,为开发者提供了巨大的舞台。通过结合强大的开源社区和现代化的Docker部署技术,我们能够以一种高效、统一且可扩展的方式,攻克工业现场最棘手的异构协议集成难题。本文的实战项目,仅仅是一个开始。基于这个架构,你可以轻松地扩展支持更多品牌的PLC,或在数据发布前,增加更复杂的本地分析和处理逻辑,从而构建出真正强大的边缘智能应用。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值