Example #1
0
def scan_message_router(tag_name, position, values, types):
    success_service = set()

    # Read Tag 0x4c
    read_tag = [tag_name + '[' + str(position) + ']']

    with client.connector(host=PLC_HOST) as conn:
        for index, descr, op, reply, status, value in conn.pipeline(
                operations=client.parse_operations(read_tag), depth=2):
            pass

        if status == 0x00:
            success_service.add(0x4c)

    # Write Tag 0x4d
    write_tag = [
        str(tag_name + '[' + str(position) + ']=' + "(" + types + ")" +
            str(values))
    ]

    with client.connector(host=PLC_HOST) as conn:
        for index, descr, op, reply, status, value in conn.pipeline(
                operations=client.parse_operations(write_tag), depth=2):
            pass

        if status == 0x00:
            success_service.add(0x4d)

    print(("Class Message Router 0x02 supports specifics serives " +
           str(success_service)))

    return success_service
Example #2
0
def PLC_Connection(host,tags):
    retVal=[]
    with client.connector(host=host) as conn:
            for index,descr,op,reply,status,value in conn.pipeline(
                operations=client.parse_operations(tags),depth=2):
                    retVal.append(value)
    return retVal
 def attribute_operations( paths ):
     for op in client.parse_operations( paths ):
         if 'attribute' in op['path'][-1]:
             op['method'] = 'get_attribute_single'
         else:
             op['method'] = 'get_attributes_all'
         yield op
Example #4
0
def test_hart_pass_thru_simulated(simulated_hart_gateway):
    """Simulated HART I/O card; always returns Pass-thru Init handle 99 (won't work on a real device)"""
    command, address = simulated_hart_gateway
    #address			= ('127.0.0.1',44818) # If you run: python3 ./hart_test.py

    try:
        assert address, "Unable to detect HART EtherNet/IP CIP Gateway IP address"
        hio = client.connector(host=address[0], port=address[1])

        operations = [
            {
                "method": "service_code",
                "code": HART.PT_INI_REQ,
                "data": [1, 0],  # HART: Read primary variable
                "data_size":
                4 + 2,  # Known response size: command,status,<payload>
                "path": '@0x%X/8' %
                (HART.class_id),  # Instance 1-8 ==> HART Channel 0-7
            },
            {
                "method": "service_code",
                "code": HART.PT_QRY_REQ,
                "data": [99],  # HART: Pass-thru Query handle
                "data_size": 4 +
                5,  # Known response size: 5 (units + 4-byte real in network order)
                "path": '@0x%X/8' %
                (HART.class_id),  # Instance 1-8 ==> HART Channel 0-7
            },
        ]

        # Now, use the underlying client.connector to issue a HART "Read Dynamic Variable" Service Code
        cmdbuf = ''
        with hio:
            results = []
            failures = 0
            for idx, dsc, req, rpy, sts, val in hio.pipeline(
                    operations=client.parse_operations(operations),
                    **hart_kwds):
                log.normal("Client %s: %s --> %r: %s", hio, dsc, val,
                           enip.enip_format(rpy))
                if not val:
                    log.warning(
                        "Client %s harvested %d/%d results; failed request: %s",
                        hio, len(results), len(operations), rpy)
                    failures += 1
                results.append((dsc, val, rpy))
                #cmdbuf		= command_logging( command, cmdbuf )

            # assert failures == 0 # statuses represent HART I/O status, not CIP response status
            assert results[0][-1].init.status in (
                32, 33, 35)  # 32 busy, 33 initiated, 35 device offline
            assert results[1][-1].query.status in (
                0, 34, 35)  # 0 success, 34 running, 35 dead

    except Exception as exc:
        log.warning("Test terminated with exception: %s", exc)
        raise
Example #5
0
def write_xv():
    host = "192.168.0.22"
    #tags = [ "X_Test[0-9]", "X_Test[5]=(DINT)555", "X_Test[0-9]" ]
    tags = ["X_Test[2]=(DINT)65"]
    #data = [123]

    with client.connector( host=host ) as conn:
        for index,descr,op,reply,status,value in conn.pipeline(
            operations=client.parse_operations( tags ), depth=2 ):
            print( "%s: %20s: %s" % ( time.ctime(), descr, value ))
Example #6
0
 def attribute_operations(self, paths, int_type=None, **kwds):
     for op in client.parse_operations(paths, int_type=int_type or 'SINT', **kwds):
         path_end = op['path'][-1]
         if 'instance' in path_end:
             op['method'] = 'get_attributes_all'
             assert 'data' not in op, "All Attributes cannot be operated on using Set Attribute services"
         elif 'symbolic' in path_end or 'attribute' in path_end or 'element':
             op['method'] = 'set_attribute_single' if 'data' in op else 'get_attribute_single'
         else:
             raise AssertionError("Path invalid for Attribute services: %r", op['path'])
         yield op
Example #7
0
 def attribute_operations(paths, int_type=None, **kwds):
     for op in client.parse_operations(paths,
                                       int_type=int_type or "SINT",
                                       **kwds):
         path_end = op["path"][-1]
         if "instance" in path_end:
             op["method"] = "get_attributes_all"
             assert (
                 "data" not in op
             ), "All Attributes cannot be operated on using Set Attribute services"
         elif "symbolic" in path_end or "attribute" in path_end or "element":
             op["method"] = ("set_attribute_single"
                             if "data" in op else "get_attribute_single")
         else:
             raise AssertionError("Path invalid for Attribute services: %r",
                                  op["path"])
         yield op
Example #8
0
def TagData(mode, tag_name, plc_addr):  #Building a function
    with client.connector(host=plc_addr, port=44818,
                          timeout=timeout) as conn:  #Creates a UDP connection
        operations = client.parse_operations([tag_name])
        if (mode == "wr"):
            failures, transactions = conn.process(operations=operations,
                                                  depth=2,
                                                  multiple=0,
                                                  fragment=False,
                                                  printing=False,
                                                  timeout=timeout)  #Write Tag
        elif (mode == "rd"):
            for index, descr, op, reply, status, value in conn.pipeline(
                    operations=operations, depth=2):  #Read tag
                poz = (value[0])
            if value is None:
                print("None returned while reading %s from PLC %s " %
                      (tag_name, plc_addr))
            return poz
Example #9
0
File: io.py Project: ekw/cpppo
"""
Example of using cpppo.server.enip EtherNet/IP CIP client API.

To see the Tag operations succeed, fire up:
    python -m cpppo.server.enip Tag=DINT[10]
"""
import sys, logging
import cpppo
from cpppo.server.enip import (address, client)

if __name__ == "__main__":
    logging.basicConfig( **cpppo.log_cfg )
    #logging.getLogger().setLevel(logging.INFO)
    host			= 'localhost'	# Controller IP address
    port			= address[1]	# default is port 44818
    depth			= 1		# Allow 1 transaction in-flight
    multiple			= 0		# Don't use Multiple Service Packet
    fragment			= False		# Don't force Read/Write Tag Fragmented
    timeout			= 1.0		# Any PLC I/O fails if it takes > 1s
    printing			= True		# Print a summary of I/O
    tags			= ["Tag[0-9]+16=(DINT)4,5,6,7,8,9", "@0x2/1/1", "Tag[3-5]"]
    
    with client.connector( host=host, port=port, timeout=timeout ) as connection:
        operations		= client.parse_operations( tags )
        failures,transactions	= connection.process(
            operations=operations, depth=depth, multiple=multiple,
            fragment=fragment, printing=printing, timeout=timeout )
    
    sys.exit( 1 if failures else 0 )
    
Example #10
0
from   cpppo.server.enip import client

if __name__ == "__main__":
    ap				= argparse.ArgumentParser()
    ap.add_argument( '-d', '--depth',    default=0, help="Pipelining depth" )
    ap.add_argument( '-m', '--multiple', default=0, help="Multiple Service Packet size limit" )
    ap.add_argument( '-r', '--repeat',   default=1, help="Repeat requests this many times" )
    ap.add_argument( '-a', '--address',  default='localhost', help="Hostname of target Controller" )
    ap.add_argument( '-t', '--timeout',  default=None, help="I/O timeout seconds (default: None)" )
    ap.add_argument( 'tags', nargs='+', help="Tags to read/write" )
    args			= ap.parse_args()

    depth			= int( args.depth )
    multiple			= int( args.multiple )
    repeat			= int( args.repeat )
    operations			= client.parse_operations( args.tags * repeat )
    timeout			= None
    if args.timeout is not None:
        timeout			= float( args.timeout )

    with client.connector( host=args.address, timeout=timeout ) as conn:
        start			= cpppo.timer()
        num,idx			= -1,-1
        for num,(idx,dsc,op,rpy,sts,val) in enumerate( conn.pipeline(
                operations=operations, depth=depth,
                multiple=multiple, timeout=timeout )):
            print( "%s: %3d: %s" % ( timestamp(), idx, val ))
    
        elapsed			= cpppo.timer() - start
        print( "%3d operations using %3d requests in %7.2fs at pipeline depth %2s; %5.1f TPS" % (
            num+1, idx+1, elapsed, args.depth, num / elapsed ))
Example #11
0
"""
Example of using cpppo.server.enip EtherNet/IP CIP client API.

To see the Tag operations succeed, fire up:
    python -m cpppo.server.enip Tag=DINT[10]
"""
import sys, logging
import cpppo
from cpppo.server.enip import address, client

if __name__ == "__main__":
    logging.basicConfig( **cpppo.log_cfg )
    #logging.getLogger().setLevel(logging.INFO)
    host			= 'localhost'	# Controller IP address
    port			= address[1]	# default is port 44818
    depth			= 1		# Allow 1 transaction in-flight
    multiple			= 0		# Don't use Multiple Service Packet
    fragment			= False		# Don't force Read/Write Tag Fragmented
    timeout			= 1.0		# Any PLC I/O fails if it takes > 1s
    printing			= True		# Print a summary of I/O
    tags			= ["Tag[0-9]+16=(DINT)4,5,6,7,8,9", "@0x2/1/1", "Tag[3-5]"]
    
    with client.connector( host=host, port=port, timeout=timeout ) as connection:
        operations		= client.parse_operations( tags )
        failures,transactions	= connection.process(
            operations=operations, depth=depth, multiple=multiple,
            fragment=fragment, printing=printing, timeout=timeout )
    
    sys.exit( 1 if failures else 0 )
    
Example #12
0
                    help="Repeat requests this many times")
    ap.add_argument('-a',
                    '--address',
                    default='localhost',
                    help="Hostname of target Controller")
    ap.add_argument('-t',
                    '--timeout',
                    default=None,
                    help="I/O timeout seconds (default: None)")
    ap.add_argument('tags', nargs='+', help="Tags to read/write")
    args = ap.parse_args()

    depth = int(args.depth)
    multiple = int(args.multiple)
    repeat = int(args.repeat)
    operations = client.parse_operations(args.tags * repeat)
    timeout = None
    if args.timeout is not None:
        timeout = float(args.timeout)

    with client.connector(host=args.address, timeout=timeout) as conn:
        start = cpppo.timer()
        num, idx = -1, -1
        for num, (idx, dsc, op, rpy, sts, val) in enumerate(
                conn.pipeline(operations=operations,
                              depth=depth,
                              multiple=multiple,
                              timeout=timeout)):
            print("%s: %3d: %s" % (timestamp(), idx, val))

        elapsed = cpppo.timer() - start
Example #13
0
def test_hart_pass_thru_poll(simulated_hart_gateway):
    r"""To test a remote C*Logix w/ a HART card, set up a remote port forward from another host in the
    same LAN.  Here's a windows example, using putty.  This windows machine (at 100.100.102.1)
    forwards a port 44818 on fat2.kundert.ca, to the PLC at 100.100.102.10:44818:

        C:\Users\Engineer\Desktop\putty.exe -R 44818:100.100.102.10:44818 [email protected]


    Now, from another host that can see fat2.kundert.ca:

        $ python -m cpppo.server.enip.list_services --list-identity -a fat2.kundert.ca:44818
        {
            "peer": [
                "fat2.kundert.ca",
                44818
            ],
            ...
            "enip.status": 0,
            "enip.CIP.list_services.CPF.count": 1,
            "enip.CIP.list_services.CPF.item[0].communications_service.capability": 288,
            "enip.CIP.list_services.CPF.item[0].communications_service.service_name": "Communications",
        }
        {
            ...
            "enip.status": 0,
            "enip.CIP.list_identity.CPF.item[0].identity_object.sin_addr": "100.100.102.10",
            "enip.CIP.list_identity.CPF.item[0].identity_object.status_word": 96,
            "enip.CIP.list_identity.CPF.item[0].identity_object.vendor_id": 1,
            "enip.CIP.list_identity.CPF.item[0].identity_object.product_name": "1756-EN2T/D",
            "enip.CIP.list_identity.CPF.item[0].identity_object.sin_port": 44818,
            "enip.CIP.list_identity.CPF.item[0].identity_object.state": 3,
            "enip.CIP.list_identity.CPF.item[0].identity_object.version": 1,
            "enip.CIP.list_identity.CPF.item[0].identity_object.device_type": 12,
            "enip.CIP.list_identity.CPF.item[0].identity_object.sin_family": 2,
            "enip.CIP.list_identity.CPF.item[0].identity_object.serial_number": 11866067,
            "enip.CIP.list_identity.CPF.item[0].identity_object.product_code": 166,
            "enip.CIP.list_identity.CPF.item[0].identity_object.product_revision": 1802,
        }

    """
    command, address = simulated_hart_gateway

    # For testing, we'll hit a specific device
    #address			= ("fat2.kundert.ca", 44818)
    #address			= ("100.100.102.10", 44818)
    #address			= ("localhost", 44818)
    route_path = None
    route_path = [{'link': 2, 'port': 1}]
    try:
        assert address, "Unable to detect HART EtherNet/IP CIP Gateway IP address"
        #hio				= client.implicit( host=address[0], port=address[1] )
        hio = client.connector(host=address[0], port=address[1])

        # Just get the primary variable, to see if the HART device is there.
        operations = [
            {
                "method": "service_code",
                "code": HART.RD_VAR_REQ,
                "data": [],  # No payload
                "data_size":
                4 + 36,  # Known response size: command,status,<payload>
                "path": '@0x%X/8' %
                (HART.class_id),  # Instance 1-8 ==> HART Channel 0-7
                "route_path": route_path,
            },
        ]

        with hio:
            for idx, dsc, req, rpy, sts, val in hio.pipeline(
                    operations=client.parse_operations(operations),
                    **hart_kwds):
                log.normal("Client %s: %s --> %r: %s", hio, dsc, val,
                           enip.enip_format(rpy))

        path = '@0x%X/8' % (HART.class_id)
        data = hart_pass_thru(hio,
                              path=path,
                              hart_data=[1, 0],
                              route_path=route_path,
                              data_size=4)  # with no size

        # The small response carries the 4-byte value, the long CIP MSG response additionally
        # carries the data type We receive the long response.
        value = None
        if data and len(data) >= 4:
            units = data[0] if len(data) > 4 else None
            packer = struct.Struct(enip.REAL_network.struct_format)
            value, = packer.unpack_from(buffer=bytearray(data[-4:]))
        log.normal("Read primary variable Value: %s (units: %s), from: %r",
                   value, units, data)

        # HART Command 3 gets all 4 variables
        data = hart_pass_thru(hio,
                              path=path,
                              hart_data=[3, 0],
                              route_path=route_path,
                              data_size=4 * 4)  # with no size

        # small response carries PV, SV, TV, FV values, no data types
        value = []
        if data and len(data) == 4 * 4:
            # Short
            packer = struct.Struct(enip.REAL_network.struct_format)
            for i in range(0, len(data), 4):
                value += packer.unpack_from(buffer=bytearray(data[i:i + 4]))
        elif data and len(data) >= 24:
            # Long
            packer = struct.Struct(enip.REAL_network.struct_format)
            value = cpppo.dotdict()
            value.current, = packer.unpack_from(buffer=bytearray(data[0:]))
            value.PV_units = data[4]
            value.PV, = packer.unpack_from(buffer=bytearray(data[5:]))
            value.SV_units = data[10]
            value.SV, = packer.unpack_from(buffer=bytearray(data[11:]))
            value.TV_units = data[14]
            value.TV, = packer.unpack_from(buffer=bytearray(data[15:]))
            value.FV_units = data[19]
            value.FV, = packer.unpack_from(buffer=bytearray(data[20:]))
        log.normal("Read all variables Values: %s, from: %r",
                   enip.enip_format(value), data)

        # HART Command 12 gets the 24-character Message
        data = hart_pass_thru(hio,
                              path=path,
                              hart_data=[12, 0],
                              route_path=route_path,
                              data_size=4 * 4)  # with no size
        value = None
        if data and len(data):
            try:
                value = bytes(data).decode('ascii')
            except:
                value = hexdump(data)
            log.normal("Read Message: \n%s\nfrom: %r", value, data)

        # HART Command 0 gets the identity
        data = hart_pass_thru(hio,
                              path=path,
                              hart_data=[0, 0],
                              route_path=route_path,
                              data_size=4 * 4)  # with no size
        value = None
        if data and len(data):
            value = hexdump(data)
            log.normal("Read Identity: \n%s\nfrom: %r", value, data)

        # HART Command 13 gets the Tag
        data = hart_pass_thru(hio,
                              path=path,
                              hart_data=[13, 0],
                              route_path=route_path,
                              data_size=4 * 4)  # with no size
        value = None
        if data and len(data):
            value = hexdump(data)
            log.normal("Read Tag: \n%s\nfrom: %r", value, data)

    except Exception as exc:
        log.warning("Test terminated with exception: %s", exc)
        raise
Example #14
0
def operate(host='localhost',
            port=44818,
            tags=[],
            udp=False,
            broadcast=False,
            timeout=5,
            repeat=1,
            depth=1,
            fragment=False,
            route_path=None,
            send_path='',
            simple=False,
            multiple=False,
            priority_time_tick=5,
            timeout_ticks=157):
    """
    Read/write specified EthernetIP tags

    Function arguments are similar to cpppo.server.enip.client command line
    arguments.

    Args:
        host: host to connect (default: localhost)
        port: port to connect (44818)
        tags: list of tag operations, e.g. TAG1, TAG2[0-2], TAG3[5]=5,
            TAG4=77.99 (refer to client CLI for more help)
        udp: use UDP/IP (default: False)
        broadcast: allow multiple peers, and use of broadcast address (default:
            False)
        timeout: EIP timeout (default: 5s)
        repeat: times to repeat request (default: 1)
        depth: pipeline requests to this depth (default: 1)
        fragment: always use read/write tag fragmented requests (default: False)
        route_path: <port>/<link> or JSON (default: '[{"port": 1, "link":
            0}]'); 0/false to specify no/empty route_path
        send_path: send Path to UCMM (default: @6/1); specify an empty string
            '' for no send path
        simple: access a simple (non-routing) EIP CIP device (eg. MicroLogix,
            default: False)
        multiple: use multiple service packet request targeting ~500 bytes
            (default: False)
        priority_time_tick: timeout tick length N range (0,15) (default: 5 ==
            32), where each tick is 2**N ms. Eg. 0 ==> 1ms., 5 ==> 32ms., 15 ==>
            32768ms
        timeout_ticks: timeout duration ticks in range (1,255) (default: 157 ==
            5024ms)
    Returns:
        tuple (result, failures) where result is a list of operation results
        (lists for get, True for set) and failures is a number of failed
        operations
    Raises:
        socket exceptions if connection has been failed
    """
    addr = (host, port)
    multiple = 500 if multiple else 0
    # route_path may be None/0/False/'[]', send_path may be None/''/'@2/1'.
    # simple designates '[]', '' respectively, appropriate for non-routing CIP
    # devices, eg. MicroLogix, PowerFlex, ...
    route_path   = device.parse_route_path( route_path ) if route_path \
                                      else [] if simple else None
    send_path   = send_path                if send_path \
                                      else '' if simple else None
    failures = 0
    transactions = []
    with connector(host=addr[0],
                   port=addr[1],
                   timeout=timeout,
                   udp=udp,
                   broadcast=broadcast) as connection:
        if tags:
            operations = parse_operations(
                recycle(tags, times=repeat),
                route_path=route_path,
                send_path=send_path,
                timeout_ticks=timeout_ticks,
                priority_time_tick=priority_time_tick)
            failed, transactions = connection.process(operations=operations,
                                                      depth=depth,
                                                      multiple=multiple,
                                                      fragment=fragment,
                                                      printing=False,
                                                      timeout=timeout)
            failures += failed
    return transactions, failures
Example #15
0
def test_hart_simple(simulated_hart_gateway):
    # No Multiple Service Packet supported by HART I/O Card simulator
    command, address = simulated_hart_gateway
    #address			= ("127.0.0.1", 44818)
    #address			= ("100.100.102.10", 44818)
    route_path = None
    route_path = [{'link': 2, 'port': 1}]
    try:
        assert address, "Unable to detect HART EtherNet/IP CIP Gateway IP address"
        hio = client.connector(host=address[0], port=address[1])
        # Establish an Implicit EtherNet/IP CIP connection using Forward Open
        #hio			= client.implicit( host=address[0], port=address[1], connection_path=None )
        PV = 1.23
        operations = [
            {
                "method": "service_code",
                "code": HART.RD_VAR_REQ,
                "data": [],  # No payload
                "data_size":
                4 + 36,  # Known response size: command,status,<payload>
                "path": '@0x%X/8' %
                (HART.class_id),  # Instance 1-8 ==> HART Channel 0-7
            },
            'HART_7_Data.PV = (REAL)0',  # would fail 'til first HART Read Dynamic Variable is done
            {
                "method": "service_code",
                "code": HART.RD_VAR_REQ,
                "data": [],  # No payload
                "data_size":
                4 + 36,  # Known response size: command,status,<payload>
                "path": '@0x%X/8' %
                (HART.class_id),  # Instance 1-8 ==> HART Channel 0-7
            },
            'HART_7_Data.PV = (REAL)%s' % PV,
            {
                "method": "service_code",
                "code": HART.RD_VAR_REQ,
                "data": [],  # No payload
                "data_size":
                4 + 36,  # Known response size: command,status,<payload>
                "path": '@0x%X/8' %
                (HART.class_id),  # Instance 1-8 ==> HART Channel 0-7
            },
        ]

        # Now, use the underlying client.connector to issue a HART "Read Dynamic Variable" Service Code
        simout = ''
        with hio:
            results = []
            failures = 0
            for idx, dsc, req, rpy, sts, val in hio.pipeline(
                    operations=client.parse_operations(operations,
                                                       route_path=route_path),
                    **hart_kwds):
                log.normal("Client %s: %s --> %r: %s", hio, dsc, val,
                           enip.enip_format(rpy))
                if not val:
                    log.warning(
                        "Client %s harvested %d/%d results; failed request: %s",
                        hio, len(results), len(operations), rpy)
                    failures += 1
                results.append((dsc, val, rpy))

            rpylast = results[-1][-1]
            assert failures in (0, 1)
            assert near(rpylast.read_var.PV, PV)

    except Exception as exc:
        log.warning("Test terminated with exception: %s", exc)
        raise
Example #16
0
#!/usr/bin/env  python2

from cpppo.server.enip import client
import time

host = "192.168.179.131"
tags = ["SCADA[1]", "SCADA[2]"]

with client.connector(host=host) as conn:
    for index, descr, op, reply, status, value in conn.pipeline(
            operations=client.parse_operations(tags), depth=2):
        print("%s: %20s: %s" % (time.ctime(), descr, value))
Example #17
0
#host = "192.168.0.22"
#tags = "X_Test[5-7]"
print("Start Reading PLC")
# Read Items from Access Config file into List and strip /n
with open('config.txt') as f:
        w = [word.strip() for word in f]
        l1 = str(w[1])
        #print(l1)               #PLC Ip Address:
        l3 = str(w[3])
        #print(l3)               #PLC Tags:

host = (l1)
tags = [l3]
        
with client.connector( host=host ) as conn_w:
    req1 = conn_w.write('X_Text[0-9]', data=[1,1,1,1,1,1,1,1,1,1])
    req2 = conn_w.read('X_Text[0-9]')
    assert conn_w.readable( timeout=1.0 ), "Failed to receive reply 1"
    rpy1 = next( conn_w )
    assert conn_w.readable( timeout=1.0 ), "Failed to receive reply 2"
    rpy2 = next( conn_w )
    

with client.connector (host=host) as conn_r:
        for index, descr, op, reply, status, value in conn_r.pipeline( 
         operations=client.parse_operations(tags), depth=2):   
            print("%20s: %s" % (descr, value))
raw=("%s" % (value[2]))
plcValue1=(raw)
print(raw)
print("Read Done")
Example #18
0
        # path			= [
        #     # {'symbolic': 'A63FGRDT'},
        #     {'class':1}, {'instance':1},# {'attribute':7},
        # ]
    )
else:
    route_path, send_path		= None, None	# Routed (eg. C*Logix)
    #route_path, send_path		= defaults.route_path_default, defaults.send_path_default
    connection			= client.connector(
        host			= hostname,
        timeout			= timeout,
        sender_context		= sender_context,
    )

    
with connection as conn:
    data			= True
    while True:
        # Perform some I/O on the Connected channel
        begun			= cpppo.timer()
        operations		= client.parse_operations( params, route_path=route_path, send_path=send_path )
        failed,txs		= conn.process(
            operations=operations, depth=depth, multiple=multiple,
            fragment=fragment, printing=printing, timeout=timeout )
        elapsed			= cpppo.timer() - begun

        # Now, wait for spontaneous data
        data,elapsed		= client.await_response( conn, timeout=1 )
        if data: log.normal( "Received: {data!r}".format( data=data ))

Example #19
0
def hart_pass_thru(io, path, hart_data, data_size, route_path=None):
    """For eg. hart_data=[1, 0], data_size=4 for HART command 1.  Returns None on failure, or the HART
    command response data payload.
    
    Harvests a Pass-thru Init handle, and issues Query on it 'til successs.

    """
    # Try to start the Pass-thru command, with the Pass-thru Init, and get handle
    operations = [
        {
            "method": "service_code",
            "code": HART.PT_INI_REQ,
            "data": hart_data,
            "data_size":
            4 + 2,  # Known response size: command,status,<payload>
            "path": path,  # Instance 1-8 ==> HART Channel 0-7
            "route_path": route_path,
        },
    ]

    # Look for a reply init.status of 33 initiated. Actually, it appears that status 0 indicates success.
    handle = None
    while handle is None:
        time.sleep(.1)
        with io:
            for idx, dsc, req, rpy, sts, val in io.pipeline(
                    operations=client.parse_operations(operations),
                    **hart_kwds):
                log.detail("Client %s: %s --> %r: request: %s\nreply:%s", io,
                           dsc, val, enip.enip_format(req),
                           enip.enip_format(rpy))
                if rpy.status == 0 and rpy.init.status in (
                        33, ):  # 32 busy, 33 initiated, 35 device offline
                    handle = rpy.init.handle
    log.normal("HART Pass-thru command Handle: %s", handle)

    # Query for success/failure (loop on running)
    operations = [
        {
            "method": "service_code",
            "code": HART.PT_QRY_REQ,
            "data": [handle],  # HART: Pass-thru Query handle
            "data_size": 4 +
            data_size,  # Known response size: 5 (units + 4-byte real in network order)
            "path": path,  # Instance 1-8 ==> HART Channel 0-7
            "route_path": route_path,
        },
    ]

    reply = {}
    while not reply or (reply.status == 0 and reply.query.status
                        == 34):  # 0 success, 34 running, 35 dead
        time.sleep(.1)
        with io:
            for idx, dsc, req, rpy, sts, val in io.pipeline(
                    operations=client.parse_operations(operations),
                    **hart_kwds):
                log.detail("Client %s: %s --> %r: %s", io, dsc, val,
                           enip.enip_format(rpy))
                reply = rpy
        log.normal("HART pass-thru command Status: %s",
                   reply.get('query.status'))

    return reply.get('query.reply_data.data', None)