admin管理员组

文章数量:1180541

I am trying to read data from a Siemens S7-1500 PLC in an asynchronous way using Python and the snap7 library. My goal is to read multiple tags concurrently. However, I am encountering the error b'CLI : Job pending' while running the following code.

Here is the Python script I have tried:

import snap7
from snap7.util import get_int
import asyncio
from concurrent.futures import ThreadPoolExecutor

PLC_IP = "192.168.0.162"
RACK = 0
SLOT = 0

# Define a global ThreadPoolExecutor
executor = ThreadPoolExecutor()

# Function to create and connect a new client
def create_client():
    client = snap7.client.Client()
    client.connect(PLC_IP, RACK, SLOT)
    if client.get_connected():
        print("Connected to the PLC successfully!")
        return client
    else:
        raise ConnectionError("Failed to connect to the PLC.")
client = create_client()

# Synchronous function to read from the PLC
def sync_read_plc(db_number, offset, length):
    try:
        data = client.db_read(db_number, offset, length)
        value = get_int(data, 0)
        return value
    finally:
        client.disconnect()

# Asynchronous wrapper for reading
async def async_read_plc(db_number, offset, length):
    loop = asyncio.get_running_loop()
    return await loop.run_in_executor(executor, sync_read_plc, db_number, offset, length)

# Asynchronous function to handle multiple PLC reads
async def read_multiple_tags():
    # List of tags to read (offsets and lengths)
    tags = [
        (19, 278, 2),  # (DB number, offset, length)
        (19, 280, 2),
        (19, 282, 2),
    ]

    # Create tasks for reading all tags asynchronously
    tasks = [async_read_plc(db_number, offset, length) for db_number, offset, length in tags]

    # Gather results (execute all tasks concurrently)
    results = await asyncio.gather(*tasks)

    # Display results
    for i, value in enumerate(results):
        print(f"Tag {i}: {value}")

# Main function to run the asyncio event loop
def main():
    asyncio.run(read_multiple_tags())

if __name__ == "__main__":
    main()

When I run this script, I get the following error:

Connected to the PLC successfully!
b'CLI : Job pending'
b'CLI : Job pending'
Traceback (most recent call last):
  File "async_copy.py", line 63, in <module>
    main()
  File "async_copy.py", line 60, in main
    asyncio.run(read_multiple_tags())
  File "/path/to/python/asyncio/runners.py", line 194, in run
    return runner.run(main)
  ...
RuntimeError: b'CLI : Job pending'

My Understanding:

  • I am using asyncio with ThreadPoolExecutor to run synchronous reads (sync_read_plc) in separate threads.
  • However, since all tasks use the same snap7 client instance (client), it seems that the PLC or the snap7 library does not handle multiple concurrent requests correctly.

Is there any other way to use async calls without using multiple threads, then that way is also appreciated. My ultimate goal is to read from multiple tags (~1000) with low latency (~20ms). P.S: I am able to read data if I am reading from only one tag.

本文标签: How to read data from Siemens S71500 PLC asynchronously using Python and snap7Stack Overflow