美文网首页
OPC Server and modbus

OPC Server and modbus

作者: gaoshine | 来源:发表于2021-08-19 10:46 被阅读0次

    OPC Server and modbus

    近期做一个企业内的危险源数据上传的项目,除了需要从传感器采集数据还有从modbus协议的设备采集数据,偶尔也有需要从OPC server取数的需求.

    1.OPC Server

    简单来说,OPC是一套标准,其目的是把PLC特定的协议(如Modbus,Profibus等)抽象成为标准化的接口,作为“中间人”的角色把通用的OPC“读写”请求转换成具体的设备协议来与HMI/SCADA系统直接对接 基于这个标准.

    我们采用python的opcua的库构建自己的 opc server.

    from opcua import ua, Server
    # 设置我们的opc服务器
    server = Server()
    server.set_endpoint("opc.tcp://0.0.0.0:4840/freeopcua/server/")
    
    # 设置我们的命名空间(namespace), 当然也可以不用设置
    uri = "http://ai.kingstars.cn"
    idx = server.register_namespace(uri)
    
    # 获取对象节点(node)
    objects = server.get_objects_node()
    
    # 定义好我们的地址空间
    myobj = objects.add_object(idx, "MyObject")
    myvar = myobj.add_variable(idx, "MyVariable", 6.7)
    myvar.set_writable()    # 设置 MyVariable 可写
    
    # 启动服务!
    server.start()
    
    

    下一步,我们模拟一个不断变化的数值

    try:
        count = 0
        while True:
            time.sleep(1)
            count += 0.1
            myvar.set_value(count)
    finally:
        #close connection, remove subcsriptions, etc
        server.stop()
    
    

    这样一个OPC server就构建完成了.

    2. opc to modbus and modbus tcp server

    下一步构建一个读取OPC服务的 client,并且以 modbus tcp server把 opc的数值发布出去,从而实现OPC2modbus的功能.

    from pymodbus.server.asynchronous import StartTcpServer
    from pymodbus.device import ModbusDeviceIdentification
    from pymodbus.datastore import ModbusSequentialDataBlock
    from pymodbus.datastore import ModbusSlaveContext, ModbusServerContext
    from pymodbus.transaction import ModbusRtuFramer, ModbusAsciiFramer
    from opcua import Client
    
    # 配置 Modbus server
    # Host address of the OPC Server
    opc_host = "opc.tcp://localhost:4840/freeopcua/server/"
    
    # Modbus Server的bind ip及端口
    modbus_host = "0.0.0.0"
    modbus_port = 5020
    
    # Modbus server 信息标识
    identity = ModbusDeviceIdentification()
    identity.VendorName = 'kingstars'
    identity.ProductCode = 'WEIOT'
    identity.VendorUrl = 'http://ai.kingstars.cn'
    identity.ProductName = 'OPC to Modbus'
    identity.ModelName = 'O2M0.1'
    identity.MajorMinorRevision = '0.0.1'
    
    # 更新频率
    update_inteval = 1.5
    
    

    下一步更新 opc_clinet及对应的函数

    opc_client: Client
    
    
    def initiate_client():
        global opc_client
        opc_client = Client(opc_host)
        opc_client.connect()
        return opc_client
    
    
    def shutdown_client():
        global opc_client
        opc_client.disconnect()
    
    
    def updating_writer(context):
    
        root = opc_client.get_root_node()
    
        # 从 OPC Client 获取数据
        myvar = root.get_child(["0:Objects", "2:MyObject", "2:MyVariable"])
        
        # 更新 Modbus 数据
        register = 3
        slave_id = 0x00  # 从站id
        address = 0x00
        value = myvar.get_value()
        context[slave_id].setValues(register, address, [int(value)])
    
    
    def initiate_server(identity, inteval, host, port):
        # 初始化 modbus server及初始数据 
        store = ModbusSlaveContext(
            di=ModbusSequentialDataBlock.create(),
            co=ModbusSequentialDataBlock.create(),
            hr=ModbusSequentialDataBlock.create(),
            ir=ModbusSequentialDataBlock.create(),)
    
        context = ModbusServerContext(slaves=store, single=True)
    
        # 开始循环及回调
        loop = LoopingCall(f=updating_writer, context=context)
        loop.start(inteval, now=False)
    
        # 启动 Modbus server
        print("Modbus Server started. Press Cntl + C to stop...")
        StartTcpServer(context, identity=identity, address=(host, port))
    
    

    以上代码具备OPC client,负责从opc server获取数据,然后启动 modbus server.
    外部设备通过modbus tcp即可获取opc server数据.

    主代码如下:

    if __name__ == "__main__":
        try:
            print("Initializing...")
            print("Starting OPC Client.")
            initiate_client()
            print(f"Client listening at: {opc_host}")
            print("-"*70 + "\n")
            print("Starting Modbus server.")
            print(f"Server hosted at: {modbus_host}:{modbus_port}")
            initiate_server(identity, update_inteval, modbus_host, modbus_port)
        finally:
            print("Sutting down...")
            shutdown_client()
            
    

    3. 测试

    • 启动opc server,模拟实际场景中的OPC服务器,其中设备名称:设备变量 --> MyObject:MyVariable, MyVariable每秒累加.
    • 启动 Modbus server, Modbus server先通过opc clinet采集opc server的设备变量,然后以Modbus TCP服务发布出去,modbus: register = 3,从站id slave_id = 0x00,地址 address = 0x00.
    • 通过外部工具调用 modbus tcp,在0x00,就可以取出不断变化的opc server的变量.

    相关文章

      网友评论

          本文标题:OPC Server and modbus

          本文链接:https://www.haomeiwen.com/subject/nimobltx.html