Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Read/write values using Ethernet/IP

I recently have acquired an ACS Linear Actuator (Tolomatic Stepper) that I am attempting to send data to from a Python application. The device itself communicates using Ethernet/IP protocol.

I have installed the library cpppo via pip. When I issue a command in an attempt to read status of the device, I get None back. Examining the communication with Wireshark, I see that it appears like it is proceeding correctly however I notice a response from the device indicating: Service not supported.

Example of the code I am using to test reading an "Input Assembly":

from cpppo.server.enip import client

HOST = "192.168.1.100"
TAGS = ["@4/100/3"]

with client.connector(host=HOST) as conn:
    for index, descr, op, reply, status, value in conn.synchronous(
            operations=client.parse_operations(TAGS)):
        print(": %20s: %s" % (descr, value))

I am expecting to get a "input assembly" read but it does not appear to be working that way. I imagine that I am missing something as this is the first time I have attempted Ethernet/IP communication.

I am not sure how to proceed or what I am missing about Ethernet/IP that may make this work correctly.

like image 983
clutton Avatar asked Jul 16 '15 17:07

clutton


People also ask

What do we use Ethernet IP for within the Allen Bradley PLCs?

EtherNet/IP PLC-5 controllers integrate the Allen-Bradley architecture into an industry- standard TCP/IP Ethernet system, offering a flexible and open solution. With the controller's built-in communication capabilities, your application can use standard Ethernet connectivity to control and monitor production.

What is an EDS file for Ethernet IP?

EDSs are simply ASCII files that describe how a device can be used on an EtherNet/IP network. It describes the objects, attributes and services available in the device. At a minimum, an EDS file conveys the identity information required for a network tool to recognize the device.

What is Ethernet IP communication?

Ethernet/IP (Ethernet Industrial Protocol) is a network communication standard capable of handling large amounts of data at speeds of 10 Mbps or 100 Mbps, and at up to 1500 bytes per packet. The specification uses an open protocol at the application layer. It is especially popular for control applications.


1 Answers

clutton -- I'm the author of the cpppo module.

Sorry for the delayed response. We only recently implemented the ability to communicate with simple (non-routing) CIP devices. The ControlLogix/CompactLogix controllers implement an expanded set of EtherNet/IP CIP capability, something that most simple CIP devices do not. Furthermore, they typically also do not implement the *Logix "Read Tag" request; you have to struggle by with the basic "Get Attribute Single/All" requests -- which just return raw, 8-bit data. It is up to you to turn that back into a CIP REAL, INT, DINT, etc.

In order to communicate with your linear actuator, you will need to disable these enhanced encapsulations, and use "Get Attribute Single" requests. This is done by specifying an empty route_path=[] and send_path='', when you parse your operations, and to use cpppo.server.enip.getattr's attribute_operations (instead of cpppo.server.enip.client's parse_operations):

from cpppo.server.enip import client
from cpppo.server.enip.getattr import attribute_operations

HOST = "192.168.1.100"
TAGS = ["@4/100/3"]

with client.connector(host=HOST) as conn:
    for index, descr, op, reply, status, value in conn.synchronous(
        operations=attribute_operations(
            TAGS, route_path=[], send_path='' )):
        print(": %20s: %s" % (descr, value))

That should do the trick!

We are in the process of rolling out a major update to the cpppo module, so clone the https://github.com/pjkundert/cpppo.git Git repo, and checkout the feature-list-identity branch, to get early access to much better APIs for accessing raw data from these simple devices, for testing. You'll be able to use cpppo to convert the raw data into CIP REALs, instead of having to do it yourself...

...

With Cpppo >= 3.9.0, you can now use much more powerful cpppo.server.enip.get_attribute 'proxy' and 'proxy_simple' interfaces to routing CIP devices (eg. ControlLogix, Compactlogix), and non-routing "simple" CIP devices (eg. MicroLogix, PowerFlex, etc.):

$ python
>>> from cpppo.server.enip.get_attribute import proxy_simple
>>> product_name, = proxy_simple( '10.0.1.2' ).read( [('@1/1/7','SSTRING')] )
>>> product_name
[u'1756-L61/C LOGIX5561']

If you want regular updates, use cpppo.server.enip.poll:

import logging
import sys
import time
import threading

from cpppo.server.enip import poll
from cpppo.server.enip.get_attribute import proxy_simple as device
params                  = [('@1/1/1','INT'),('@1/1/7','SSTRING')]

# If you have an A-B PowerFlex, try:
# from cpppo.server.enip.ab import powerflex_750_series as device
# parms                 = [ "Motor Velocity", "Output Current" ]

hostname                = '10.0.1.2'
values                  = {} # { <parameter>: <value>, ... }
poller                  = threading.Thread(
    target=poll.poll, args=(device,), kwargs={
        'address':      (hostname, 44818),
        'cycle':        1.0,
        'timeout':      0.5,
        'process':      lambda par,val: values.update( { par: val } ),
        'params':       params,
    })
poller.daemon           = True
poller.start()

# Monitor the values dict (updated in another Thread)
while True:
    while values:
        logging.warning( "%16s == %r", *values.popitem() )
    time.sleep( .1 )

And, Voila! You now have regularly updating parameter names and values in your 'values' dict. See the examples in cpppo/server/enip/poll_example*.py for further details, such as how to report failures, control exponential back-off of connection retries, etc.

Version 3.9.5 has recently been released, which has support for writing to CIP Tags and Attributes, using the cpppo.server.enip.get_attribute proxy and proxy_simple APIs. See cpppo/server/enip/poll_example_many_with_write.py

like image 83
pjkundert Avatar answered Sep 30 '22 15:09

pjkundert