def test_powerflex_poll_success(simulated_powerflex_gateway): #logging.getLogger().setLevel( logging.INFO ) command, address = simulated_powerflex_gateway try: assert address, "Unable to detect PowerFlex EtherNet/IP CIP Gateway IP address" values = {} def process(p, v): print("%s: %16s == %s" % (time.ctime(), p, v)) values[p] = v process.done = False poller = threading.Thread(target=poll.poll, args=(powerflex_750_series, ), kwargs={ 'address': address, 'cycle': 1.0, 'timeout': 0.5, 'process': process, }) poller.deamon = True poller.start() try: # Polling starts immediately time.sleep(.5) assert len(values) == 2 # Make sure it repeats values.clear() assert len(values) == 0 time.sleep(1.0) assert len(values) == 2 # Allow time to refresh values on next poll values['Output Current'] = 1.0 time.sleep(1.0) finally: process.done = True poller.join(1.0) assert not poller.is_alive(), "Poller Thread failed to terminate" assert 'Output Current' in values and near(values['Output Current'][0], 123.45) assert 'Motor Velocity' in values and near(values['Motor Velocity'][0], 789.01) except Exception as exc: logging.warning("Test terminated with exception: %s", exc) raise
def test_powerflex_poll_success( simulated_powerflex_gateway ): #logging.getLogger().setLevel( logging.INFO ) command,address = simulated_powerflex_gateway try: assert address, "Unable to detect PowerFlex EtherNet/IP CIP Gateway IP address" values = {} def process( p, v ): print( "%s: %16s == %s" % ( time.ctime(), p, v )) values[p] = v process.done = False poller = threading.Thread( target=poll.poll, args=(powerflex_750_series,), kwargs={ 'address': address, 'cycle': 1.0, 'timeout': 0.5, 'process': process, }) poller.deamon = True poller.start() try: # Polling starts immediately time.sleep(.5) assert len( values ) == 2 # Make sure it repeats values.clear() assert len( values ) == 0 time.sleep(1.0) assert len( values ) == 2 # Allow time to refresh values on next poll values['Output Current'] = 1.0 time.sleep(1.0) finally: process.done = True poller.join( 1.0 ) assert not poller.is_alive(), "Poller Thread failed to terminate" assert 'Output Current' in values and near( values['Output Current'][0], 123.45 ) assert 'Motor Velocity' in values and near( values['Motor Velocity'][0], 789.01 ) except Exception as exc: logging.warning( "Test terminated with exception: %s", exc ) raise
def test_powerflex_simple( simulated_powerflex_gateway ): #logging.getLogger().setLevel( logging.INFO ) command,address = simulated_powerflex_gateway try: assert address, "Unable to detect PowerFlex EtherNet/IP CIP Gateway IP address" pf = powerflex( host=address[0], port=address[1], timeout=1 ) # Reading a list of nothing should work... assert list( pf.read( [] )) == [] # At the least, it ensures we have a non-None .identity print( "PowerFlex Identity: %s" % pf ) assert "None" not in str( pf ), "No EtherNet/IP CIP connection, or no Identity" # Simple read of Tag, using Read Tag; returns list of bare list of data elements tag = "SCADA[0-9]" value, = pf.read( [ tag ] ) print( "Tag: %15s: %r" % ( tag, value )) assert type( value ) is list and all( v == 0 for v in value ) # Read of CIP Object/Instance/Attribute using Get Attribute Single, interpreted as an # arbitrary CIP data type. Returns list of result values, each a dict of decoded data. # Providing a type to use to decode the data produces whatever dictionary the type parses # into, unchanged: get = ( "@1/1/1", enip.INT ) value, = pf.read( [ get ] ) print( "Vendor Number: %15s: %r" % ( get[0], value )) assert len( value ) == 1 and 'INT' in value[0] and value[0]['INT'] == 0x0001 get = ( "@1/1/7", enip.SSTRING ) value, = pf.read( [ get] ) print( "Product Name: %15s: %r" % ( get[0], value )) assert len( value ) == 1 and 'SSTRING' in value[0] and value[0].SSTRING.string == 'PowerFlex/20-COMM-E' # Get the DPI Parameter 0x93, Instance 3, Attribute 9 Output_Current attribute, interpreted # as REAL. 1 element. get = ( "@0x93/7/10", enip.REAL ) value, = pf.read( [ get] ) print( "Output_Current: %15s: %r" % ( get[0], value )) assert len( value ) == 1 and 'REAL' in value[0] and near( value[0].REAL, 123.45 ) # Get the DPI parameter 0x93, Instance 3, Attribute 9 Output_Current attribute, interpreted # as INT. 1 element. Providing named CIP types shucks the dictionary container, and # produces just the target typed data: get = ( "@0x93/140/10", "INT" ) value, = pf.read( [ get] ) print( "Accel_Time_1: %15s: %r" % ( get[0], value )) assert len( value ) == 1 and value[0] == 567 get = ( "@1/1", [ "INT", "INT", "INT", "INT", "INT", "DINT", "SSTRING", "USINT" ]) value, = pf.read( [ get] ) print( "Identity (all): %15s: %r" % ( get[0], value )) assert value == [1, 14, 54, 2836, 12640, 7079450, u'PowerFlex/20-COMM-E', 255] # TCPIP Object get = ( "@0xF5/1", [ "DWORD", "DWORD", "DWORD", "EPATH", "IPADDR", "IPADDR", "IPADDR", "IPADDR", "IPADDR", "STRING", "STRING" ]) value, = pf.read( [ get] ) print( "TCPIP (all): %15s: %r" % ( get[0], value )) assert value == [2, 48, 16, [{'class': 246}, {'instance': 1}], '10.0.0.4', '255.255.252.0', '10.0.0.1', '10.0.0.1', '8.8.8.8', u'example.com', u'powerflex'] # List Identity ident = pf.list_identity() assert ident.sin_addr == "10.0.0.4" except Exception as exc: logging.warning( "Test terminated with exception: %s", exc ) raise
def test_powerflex_simple( simulated_powerflex_gateway ): # logging.getLogger().setLevel( logging.INFO ) command,address = simulated_powerflex_gateway try: assert address, "Unable to detect PowerFlex EtherNet/IP CIP Gateway IP address" pf = powerflex( host=address[0], port=address[1], timeout=1 ) # Reading a list of nothing should work... assert list( pf.read( [] )) == [] # At the least, it ensures we have a non-None .identity print( "PowerFlex Identity: %s" % pf ) assert "None" not in str( pf ), "No EtherNet/IP CIP connection, or no Identity" # Simple read of Tag, using Read Tag; returns list of bare list of data elements tag = "SCADA[0-9]" value, = pf.read( [ tag ] ) print( "Tag: %15s: %r" % ( tag, value )) assert type( value ) is list and all( v == 0 for v in value ) # Read of CIP Object/Instance/Attribute using Get Attribute Single, interpreted as an # arbitrary CIP data type. Returns list of result values, each a dict of decoded data. # Providing a type to use to decode the data produces whatever dictionary the type parses # into, unchanged: get = ( "@1/1/1", enip.INT ) value, = pf.read( [ get ] ) print( "Vendor Number: %15s: %r" % ( get[0], value )) assert len( value ) == 1 and 'INT' in value[0] and value[0]['INT'] == 0x0001 get = ( "@1/1/7", enip.SSTRING ) value, = pf.read( [ get] ) print( "Product Name: %15s: %r" % ( get[0], value )) assert len( value ) == 1 and 'SSTRING' in value[0] and value[0].SSTRING.string == 'PowerFlex/20-COMM-E' # Get the DPI Parameter 0x93, Instance 3, Attribute 9 Output_Current attribute, interpreted # as REAL. 1 element. get = ( "@0x93/7/10", enip.REAL ) value, = pf.read( [ get] ) print( "Output_Current: %15s: %r" % ( get[0], value )) assert len( value ) == 1 and 'REAL' in value[0] and near( value[0].REAL, 123.45 ) # Get the DPI parameter 0x93, Instance 3, Attribute 9 Output_Current attribute, interpreted # as INT. 1 element. Providing named CIP types shucks the dictionary container, and # produces just the target typed data: get = ( "@0x93/140/10", "INT" ) value, = pf.read( [ get] ) print( "Accel_Time_1: %15s: %r" % ( get[0], value )) assert len( value ) == 1 and value[0] == 567 get = ( "@1/1", [ "INT", "INT", "INT", "INT", "INT", "DINT", "SSTRING", "USINT" ]) value, = pf.read( [ get] ) print( "Identity (all): %15s: %r" % ( get[0], value )) assert value == [1, 14, 54, 2836, 12640, 7079450, u'PowerFlex/20-COMM-E', 255] # TCPIP Object get = ( "@0xF5/1", [ "DWORD", "DWORD", "DWORD", "EPATH", "IPADDR", "IPADDR", "IPADDR", "IPADDR", "IPADDR", "STRING", "STRING" ]) value, = pf.read( [ get] ) print( "TCPIP (all): %15s: %r" % ( get[0], value )) assert value == [2, 48, 16, [{'class': 246}, {'instance': 1}], '10.0.0.4', '255.255.252.0', '10.0.0.1', '10.0.0.1', '8.8.8.8', u'example.com', u'powerflex'] # List Identity ident = pf.list_identity() assert ident.sin_addr == "10.0.0.4" except Exception as exc: logging.warning( "Test terminated with exception: %s", exc ) raise
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