Ethernet/IP and Python

M

Thread Starter

Mark Q Norman

I would like to use my python skills to test a Ethernet/IP implementation we are developing. After searching in vain for some python library that will allow me to talk CIP over Ethernet I decided to try an implement my own. I did this by reverse engineering the packets being generated by a EIP package we have been using.
Firstly does anyone know of an existing EIP/CIP python library I could use?

If not does anyone know how I set up a CIP socket?
I initially tried by doing this, the WHOLE_FRAME being constructed from what I saw in wireshark output.
import socket
import string
import select

TCP_IP = '10.0.0.2'
TCP_PORT = 44818
BUFFER_SIZE = 1024
# EtherNet/IP send data
# Encapsulation Header
EIP_COMMAND = '\x6f\x00'
EIP_LENGTH = '\x18\x00'
EIP_SESSION_HANDLE = '\x01\x00\x02\xe8'
EIP_SUCCESS = '\x00\x00\x00\x00'
EIP_SENDER_CONTEXT = '\x38\x00\x02\x00\x00\x00\x85\x01'
EIP_OPTIONS = '\x00\x00\x00\x00'
EIP_ENCAP_HEADER = EIP_COMMAND + EIP_LENGTH + EIP_SESSION_HANDLE + EIP_SUCCESS + EIP_SENDER_CONTEXT + EIP_OPTIONS
# command specific data
EIP_INTHAND = '\x00\x00\x00\x00' # CIP
EIP_TIMEOUT = '\x1e\x00'
EIP_ITEM_COUNT = '\x02\x00'
EIP_TYPE_ITEM1_ID = '\x00\x00'
EIP_TYPE_ITEM1_LEN = '\x00\x00'
EIP_TYPE_ITEM2_ID = '\xb2\x00'
EIP_TYPE_ITEM2_LEN = '\x08\x00'
EIP_COMMAND_SPEC_DATA = EIP_INTHAND + EIP_TIMEOUT + EIP_ITEM_COUNT + EIP_TYPE_ITEM1_ID + EIP_TYPE_ITEM1_LEN + EIP_TYPE_ITEM2_ID + EIP_TYPE_ITEM2_LEN
# CIP
CIP_SERVICE = '\x0e' # get single attribut
CIP_REQ_SIZE = '\x03'
CIP_REQ_PATH = '\x20\x29\x24\x01\x30\x03' # Param 1 Run Forward
CIP = CIP_SERVICE + CIP_REQ_SIZE + CIP_REQ_PATH
# glue all together
WHOLE_FRAME = EIP_ENCAP_HEADER + EIP_COMMAND_SPEC_DATA + CIP

whole_message = ""
for b in WHOLE_FRAME:
whole_message += " " + hex(ord(b))
print whole_message

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
foo = raw_input('socket created...')

s.connect((TCP_IP, TCP_PORT))
foo = raw_input('connected...')

s.send(WHOLE_FRAME)
foo = raw_input('sent...')


s.setblocking(0)
ready = select.select(, [], [], 5)
foo = raw_input('something returned...')
if ready[0]:
data = s.recv(BUFFER_SIZE)
whole_message = ""
for b in data:
whole_message += " " + hex(ord(b))
print whole_message
s.close()

This only partially worked as I got loads of frames generated I do not need.
The original seem to do the connection at the same time as doing the get attribute where as mine seems to do two connections and then does the get attribute.

I think the socket connection needs to carry the CIP framing, but I do not know how to do it. Any pointers would be appreciated,.
Regards Mark
 
You may download "pvbaddon.tar.gz" from
http://tinyurl.com/qckbsq9

After unpacking pvbaddon.tar.gz you will find a copy of the project "TuxEip" under directory "pvbaddon/foreign".

TuxEip is an Ethernet/IP implementation in C.

Unfortunately the original web page of TuxEip has been removed from the internet.
 
M

Mark Q Norman

> You may download "pvbaddon.tar.gz" from
> http://tinyurl.com/qckbsq9

This looks like good stuff. I think it will take me some time to work out how to either use it as is or translate it to python. Any tips and extra guidelines would be welcome. FYI I am working on 64bit Windows 7.
 
L

Lynn August Linse

I have Python which talks to EIP for testing purposes, but it is not public. I work for digi.com, so if you send email to lynnl at Digi (guess at the email address), I can send you a ZIP.

One of the problems/challenges of EIP is UNLIKE Modbus, it is not a simple poll/response. You need to negotiate multiple levels of 'connection', so you need to send several packets BEFORE you can ask for data.
 
Lynn,

I'm working on a simulation software based on python, and I need to be able to read and write tags from/to a rockwell PLC. Do you still have the zip file available?

Thanks

> I have Python which talks to EIP for testing purposes, but it is not public.
> I work for digi.com, so if you send email to lynnl at Digi (guess at the
> email address), I can send you a ZIP.
 
L

Lynn August Linse

Sure, send an email direct to lynnl at digi.com. I've actually been asked quite a bit lately. I am sending only the request creation and response parser, assuming you can handle the socket stuff already.

Reading tags is not too hard. They create a 'symbolic segment' in the object path, so instead of the path selecting an object class/instance/attribute, it selects a named object in the RSLogix5000 data table.

The only thing bad about this is that, unlike Modbus where you can read a hundred values in 1 messages, working with symbols means 1 message == 1 value. There are complex ways to build custom assemblies to for example pack all data on a single HMI page into a single messages, but that is another whole level of complexity.
 
P

Perry Kundert

>Firstly does anyone know of an existing
>EIP/CIP python library I could use?

Mark;

We've implemented a Python based EtherNet/IP CIP parser (see http://hardconsulting.com/products/6-cpppo-enip-api ). It is open source (GPL), so is free to use for internal and/or open-source projects. If you wish to go on an develop a closed-source project, there is a Proprietary licensed version of the library available (so you can keep your product source closed, if you wish).

It is hosted on Github at https://github.com/pjkundert/cpppo. You can "pip install cpppo", and start by creating an EtherNet/IP PLC simulator immediately; this fires one up with a single DINT array with a Tag name "Scada":
<pre>
$ python -m cpppo.server.enip -v Scada=DINT[1000]
</pre>
In another terminal window, you can try writing and reading it (and printing a summary of its actions to standard output; feel free to remove the -v option, unless you want to see what is going on under the covers):
<pre>
$ python -m cpppo.server.enip.client -v --print Scada[1]=99
$ python -m cpppo.server.enip.client -v --print Scada[0-50]
</pre>

If you want to add EtherNet/IP CIP connectivity to your existing Python application, see the example in https://github.com/pjkundert/cpppo/blob/master/server/enip/historize.py

Have fun!
--
Perry Kundert
Owner, Hard Consulting Corporation
 
I have implemented a EIP library in Python. At the moment the library reads and writes multiple tags atomic or user defined. I have successfully tested the library with micrologix, controllogix and compactlogix PLCs. The project is available at

https://github.com/ruscito/pycomm

I included an example script in the repository, but if you need any help let me know.
 
Tengo Python que habla con EIP con fines de prueba, pero no es público. Trabajo para digi.com, por lo que si envía un correo electrónico a lynnl en Digi (suponga la dirección de correo electrónico), puedo enviarle un código postal.

Uno de los problemas/desafíos de EIP es A diferencia de Modbus, no es una simple encuesta/respuesta. Debe negociar varios niveles de 'conexión', por lo que debe enviar varios paquetes ANTES de solicitar datos.
[/CITA]
Hyo estoy intentando comunicarme con una maquina de soldar con ethernet ip podrías ayudarme mi correo es [email protected]
 
Top