Code Monkey home page Code Monkey logo

Comments (6)

pjkundert avatar pjkundert commented on July 20, 2024

Ya, I've been working on generalizing the cpppo methods to more cleanly handle writes. It works fine (you can try it out using cpppo.server.enip.client via the Command-Line Interface (see docs). Remember to specify the data type as DINT, eg ... 'some_tag[0-3]=(DINT)0,1,2,3'

I have an experimental branch called 'feature-proxy-write' that is a work-in-progress, to get the cpppo.server.enip.get_attribute 'proxy' interface to cleanly handle both reading and writing. You could take a look at that.

I have been much too busy to work on this; some Cpppo "Support" contracts could help that... ;)

from cpppo.

karyuv avatar karyuv commented on July 20, 2024

Hello Sir,
Thanks a lot for your swift reply. Here is the python code; which tries to write an array of dints.

while True:
        try:
            with client.connector( host= plc_ip_address) as conn:
                while True:
                    time_prev=time.time()
                    data = []
                    for c in range(5):
                        data.append(int(0))

                    req = conn.write("CDS_PLC_RawData_TLC", data,"DINT")
                    try:

                        rpy = next(conn)
                        print rpy

                    except AssertionError:  
                        print "Response timed out!! Tearing Connection and Reconnecting!!!!!"
                        break
                    except AttributeError:
                        print "Tag J1_pos not written:::Will try again::"
                        break


Here is my error:

Traceback (most recent call last):
File "./tag_write.py", line 27, in
req = conn.write("CDS_PLC_RawData_TLC", data,"INT")
File "/usr/local/lib/python2.7/dist-packages/cpppo-3.9.4-py2.7.egg/cpppo/server/enip/client.py", line 701, in write
sender_context=sender_context )
File "/usr/local/lib/python2.7/dist-packages/cpppo-3.9.4-py2.7.egg/cpppo/server/enip/client.py", line 766, in unconnected_send
us.request.input = bytearray( device.dialect.produce( us.request )) # eg. logix.Logix
File "/usr/local/lib/python2.7/dist-packages/cpppo-3.9.4-py2.7.egg/cpppo/server/enip/logix.py", line 423, in produce
result += UINT.produce( data.write_frag.elements )
File "/usr/local/lib/python2.7/dist-packages/cpppo-3.9.4-py2.7.egg/cpppo/server/enip/parser.py", line 172, in produce
return struct.pack( cls.struct_format, value )
struct.error: cannot convert argument to integer

Any thoughts?. Thank you.

from cpppo.

pjkundert avatar pjkundert commented on July 20, 2024

The conn.write API is pretty low level, and needs alot of detail information. This is usually provided by client.parse_operations:

>>> from cpppo.server.enip import client
>>> list(client.parse_operations([ "some_tag=(DINT)0,1,2,3"] ))
[{'path': [{'symbolic': 'some_tag'}], 'elements': 4, 'data': [0, 1, 2, 3], 'method': 'write', 'tag_type': 196}]

So, if you want to call it directly, supply:

from cpppo.server.enip import client
client.write( [{'path': [{'symbolic': 'some_tag'}], elements=len( data ), data=data, tag_type=client.enip.DINT.tag_type )

from cpppo.

pjkundert avatar pjkundert commented on July 20, 2024

Also; don't forget that there is a turn-around time, awaiting the response from the client device.

I've rewritten your example to be a bit more correct:

import socket
import time
from cpppo.server.enip import client
plc_ip_address          = "127.0.0.1"
timeout                 = 5.0

while True:
    try:
        with client.connector( host= plc_ip_address, timeout=timeout ) as conn:
            while True:
                data = [int(0) for c in range( 5 )]
                req = conn.write( "CDS_PLC_RawData_TLC", elements=len( data ), data=data,
                              tag_type=client.enip.DINT.tag_type )
                rpy,ela = client.await( conn, timeout=timeout )
                print rpy

    except AssertionError:
        print "Response timed out!! Tearing Connection and Reconnecting!!!!!"
    except AttributeError:
        print "Tag J1_pos not written:::Will try again::"
    except socket.error as exc:
        print "Couldn't send command: %s" % ( exc )

    time.sleep( .1 )

All this is sort of taken care of, if you use the client.connector API's simple 'process' method. This performs all tag I/O (allows pipeline depth, multiple request packets, etc., if desired), and synchronously returns the list of response after all I/O is complete:

#
# Run simulator in another window:
#     python -m cpppo.server.enip -va localhost --print CDS_PLC_RawData_TLC=DINT[4]
#

import socket
import time
import cpppo
from cpppo.server.enip import client
plc_ip_address                  = "127.0.0.1"
timeout                         = 5.0

import logging
#cpppo.log_cfg['level'] = logging.DETAIL
logging.basicConfig( **cpppo.log_cfg )

tags                            = ["CDS_PLC_RawData_TLC[0-3]=(DINT)0,1,2,3"]
while True:
    try:

        with client.connector( host=plc_ip_address, timeout=timeout ) as conn:
            operations          = client.parse_operations( tags )
            failures,replies    = conn.process(
                operations=operations, timeout=timeout )
        for rpy in replies:
            print rpy

    except Exception as exc:
        print "EtherNet/IP I/O Failed: %s" % ( exc )
    time.sleep( .1 )

from cpppo.

karyuv avatar karyuv commented on July 20, 2024

Hello Sir,
Thanks a lot for the code!!. It is working well :).

I have one more question; I have been using the client.main(["-a", plc_ip_address, Tag]) to write tags to PLC. I was looking for other write features; as it was not that quick as connector.write.
Connector.write is fast because it an unconnected send?.

from cpppo.

pjkundert avatar pjkundert commented on July 20, 2024

All EtherNet/IP CIP I/O in the Cpppo library use "Unconnected" sends. The key to faster I/O is to set up the connection, and then to use it without closing it. The client.main API always sets up, uses, and then closes a connection. By maintaining your own connection and then using it repeatedly, you get much higher transaction rates.

To improve this much, much further -- use the client.pipeline API. This allows you to issue multiple transaction requests, before receiving the transaction replies. You can keep the PLC "saturated" with requests, instead of letting it sit idle while you await the response to a previous request.

from cpppo.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.