stlehmann / pyads

Python wrapper for TwinCAT ADS
MIT License
254 stars 94 forks source link

Crashing with "symbol not found" when calling get_all_symbols #270

Closed mmachenry closed 2 years ago

mmachenry commented 2 years ago

pyasds-3.3.8, python-3.9.5 I have a pretty simple script that I mostly copied from the documentation.

import sys
import pyads
import socket
from ctypes import sizeof

def get_local_ip_address(remote_server):
    with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as s: 
        s.connect((remote_server, 80))
        return s.getsockname()[0]

def create_route_back(plc_ip):
    local_ip = get_local_ip_address(plc_ip)
    local_net_id = local_ip + '.1.1'

    plc_username = 'Administrator'
    plc_password = '1'
    hostname = socket.gethostname()
    route_name = 'route_to_' + hostname

    print (f""""Creating route:
        local_net_id: {local_net_id}
        local_ip: {local_ip}
        plc_ip: {plc_ip}
        plc_username: {plc_username}
        plc_password: {plc_password}
        route_name: {route_name}
    """)

    pyads.open_port()
    pyads.set_local_address(local_net_id)
    pyads.add_route_to_plc(
        local_net_id,
        local_ip,
        plc_ip,
        plc_username,
        plc_password,
        route_name)
    pyads.close_port()

def plc_connection(plc_ip, plc_net_id):
    create_route_back(plc_ip)
    return pyads.Connection(plc_net_id, pyads.PORT_TC3PLC1, plc_ip)

def print_version(plc):
    (device_name, version) = plc.read_device_info()
    version = f'{version.version}.{version.revision}.{version.build}'
    print(device_name, version)

def get_symbols(plc):
    return [
        (symbol.name, symbol.plc_type)
        for symbol in plc.get_all_symbols()
    ]

def main(plc_ip, plc_net_id):
    with plc_connection(plc_ip, plc_net_id) as plc:
        print_version(plc)
        for (symbol_name, plc_type) in get_symbols(plc):
            print (symbol_name, plc_type)

if __name__ == '__main__':
    main(sys.argv[1], sys.argv[2])

When I run this script with the IP and AMS Net ID of my running PLC, I get a strange error.

2021-10-14T20:23:26+0000 Info: Connected to 10.0.0.10
Plc30 App 3.1.1927
2021-10-14T20:23:26+0000 Info: connection closed by remote
Traceback (most recent call last):
  File "/home/mmachenry/src/telemetry/test/get_plc_symbols.py", line 62, in <module>
    main(sys.argv[1], sys.argv[2])
  File "/home/mmachenry/src/telemetry/test/get_plc_symbols.py", line 58, in main
    for (symbol_name, plc_type) in get_symbols(plc):
  File "/home/mmachenry/src/telemetry/test/get_plc_symbols.py", line 52, in get_symbols
    for symbol in plc.get_all_symbols()
  File "/home/mmachenry/src/telemetry/test/venv/lib/python3.9/site-packages/pyads/ads.py", line 773, in get_all_symbols
    symbol_size_msg = self.read(
  File "/home/mmachenry/src/telemetry/test/venv/lib/python3.9/site-packages/pyads/ads.py", line 699, in read
    return adsSyncReadReqEx2(
  File "/home/mmachenry/src/telemetry/test/venv/lib/python3.9/site-packages/pyads/pyads_ex.py", line 787, in adsSyncReadReqEx2
    raise ADSError(error_code)
pyads.pyads_ex.ADSError: ADSError: symbol not found (1808). 

Notice that the connection works, I'm able to pull the device name and version from the PLC. However, when I try to get_all_symbols, it crashes complaining that some symbol (1808) is not found. Perhaps there's an error in my code. I'd love to know a workaround or where my error is. But I do think at the very least, there's an actionable issue with the confusing error message here.

kryskool commented 2 years ago

Hi @mmachenry

Can you post you PLC code ?

Regards,

stlehmann commented 2 years ago

This could be related to #261. @mmachenry are you using the monitoring attribute in your TwinCAT variable declaration? Basically get_all_symbols should work. Can I ask you to make the follwowing test:

Declare only one variable in your TwinCAT application and try the get_all_symbols function with that. Is there still an error? If yes please post the variable declaration here.

Thanks

mmachenry commented 2 years ago

The problem vanished with test code rewritten to the device.