示例#1
0
文件: logix_test.py 项目: hj91/cpppo
def test_logix_remote_pylogix( count=100 ):
    """Performance of pylogix executing an operation a number of times on a socket connected
    Logix simulator, within the same Python interpreter (ie. all on a single CPU
    thread).  Only connects on the standard port.

    """
    #logging.getLogger().setLevel( logging.NORMAL )
    enip.lookup_reset() # Flush out any existing CIP Objects for a fresh start
    svraddr		        = ('localhost', 44828)
    kwargs			= {
        'argv': [
            #'-v',
            #'--log',		'/tmp/pylogix.log',
            #'--profile',	'/tmp/plogix.prof',
            '--address',	'%s:%d' % svraddr,
            'SCADA=INT[1000]'
        ],
        'server': {
            'control': cpppo.apidict( enip.timeout, { 
                'done': False
            } ),
        },
    }
    logixthread_kwargs		= {
        'count':		count,
        'svraddr':		svraddr,
        'kwargs':		kwargs
    }

    log.normal( "test_logix_remote_pylogix w/ server.control in object %s", id( kwargs['server']['control'] ))
    # This is sort of "inside-out".  This thread will run logix_remote, which will signal the
    # enip_main (via the kwargs.server...) to shut down.  However, to do line-based performance
    # measurement, we need to be running enip.main in the "Main" thread...
    logixthread			= threading.Thread( target=logix_remote_pylogix, kwargs=logixthread_kwargs )
    logixthread.daemon		= True
    logixthread.start()

    try:
        enip_main( **kwargs )
    finally:
        kwargs['server']['control'].done = True # Signal the server to terminate

    logixthread.join()
    log.normal( "Shutdown of server complete" )
示例#2
0
文件: hart_test.py 项目: hj91/cpppo
def main(**kwds):
    """Set up a *Logix w/ a 16-channel HART Interface card, eg. 1756-IF8H"""

    enip.config_files += [__file__.replace('.py', '.cfg')]

    HART(name="HART Channels", instance_id=0)  # Class Object
    for i in range(16):
        HART(name="HART Channel %d" % i, instance_id=i + 1)

    # Establish Identity and TCPIP objects w/ some custom data for the test, from a config file
    return enip_main(argv=sys.argv[1:])
示例#3
0
文件: poll_test.py 项目: hj91/cpppo
def main(**kwds):
    """Set up PowerFlex/20-COMM-E objects (enip.main will set up other Logix-like objects)"""

    enip.config_files += [__file__.replace('.py', '.cfg')]

    DPI_Parameters(name="DPI_Parameters", instance_id=0)  # Class Object
    DPI_Parameters(name="DPI_Parameters",
                   instance_id=DPI_Parameters.OUTPUT_FREQ)
    DPI_Parameters(name="DPI_Parameters",
                   instance_id=DPI_Parameters.MTR_VEL_FDBK)
    DPI_Parameters(name="DPI_Parameters",
                   instance_id=DPI_Parameters.OUTPUT_CURRENT)
    DPI_Parameters(name="DPI_Parameters",
                   instance_id=DPI_Parameters.DC_BUS_VOLTS)
    DPI_Parameters(name="DPI_Parameters",
                   instance_id=DPI_Parameters.ELAPSED_KWH)
    DPI_Parameters(name="DPI_Parameters",
                   instance_id=DPI_Parameters.ACCEL_TIME_1)
    DPI_Parameters(name="DPI_Parameters",
                   instance_id=DPI_Parameters.SPEED_UNITS)

    # Establish Identity and TCPIP objects w/ some custom data for the test, from a config file
    return enip_main(argv=sys.argv[1:], UCMM_class=UCMM_no_route_path)
示例#4
0
    def url(self, **kwds):
        """Produce a url by joining the class' URI and OPTs with any keyword parameters"""
        return self.URI + "?" + urlencode(dict(self.OPT, **kwds))

    def __getitem__(self, key):
        """Obtain the temperature of the city's matching our Attribute's name, convert
        it to an appropriate type; return a value appropriate to the request."""
        try:
            # eg. "http://api.openweathermap.org/...?...&q=City Name"
            data = urlopen(self.url(q=self.name)).read()
            if type(data) is not str:  # Python3 urlopen.read returns bytes
                data = data.decode('utf-8')
            weather = json.loads(data)
            assert weather.get( 'cod' ) == 200 and 'main' in weather, \
                weather.get( 'message', "Unknown error obtaining weather data" )
            cast = float if isinstance(self.parser, REAL) else int
            temperature = cast(weather['main']['temp'])
        except Exception as exc:
            logging.warning("Couldn't get temperature for %s via %r: %s",
                            self.name, self.url(q=self.name), exc)
            raise
        return [temperature
                ] if self._validate_key(key) is slice else temperature

    def __setitem__(self, key, value):
        raise Exception("Changing the weather isn't that easy...")


sys.exit(enip_main(attribute_class=Attribute_weather))
示例#5
0
    def __setitem__( self, key, value ):
        try:
            # vvvv -- Process an EtherNet/IP CIP Write [Tag [Fragmented]].
            # 
            # We'll just store the value, and output the write request (and the value written) to
            # our time-series history file.
            # 
            super( Attribute_historize, self ).__setitem__( key, value )
            self.__logger.write( { 'write': value }, serial=(self.name, (
                key.indices( len( self ))[0]   if isinstance( key, slice ) else key,
                key.indices( len( self ))[1]-1 if isinstance( key, slice ) else key,
            )))
            # ^^^^
        except Exception as exc:
            # vvvv -- Process an EtherNet/IP CIP Write [Tag [Fragmented]] Exception.
            # 
            # Something went wrong with the Write request processing.  Log something intelligent and
            # re-raise the exception, to return a failure to the EtherNet/IP client.
            # 
            self.__logger.comment(
                "%s: PLC I/O Write Tag %20s[%5s-%-5s] Exception: %s" % (
                    history.timestamp(), self.name,
                    key.indices( len( self ))[0]   if isinstance( key, slice ) else key,
                    key.indices( len( self ))[1]-1 if isinstance( key, slice ) else key,
                    exc ))
            # ^^^^
            raise

sys.exit( enip_main( attribute_class=Attribute_historize ))
示例#6
0
def main(argv=None, idle_service=None, **kwds):
    """Run a cpppo.server.enip.main simulating a bunch of Tags, with the initial data specified in the
    config file matching the name of the simulator (eg. simulator_example.cfg).  Append your own
    configuration file name to the enip.config_files list, or put a [Simulator] block in one of the
    other Cpppo configuration files.

    We'll traverse any keys specified in the configuration, create each of them as Attributes (at
    any specified @<class>/<instance>/<attribute> CIP address), and populate the enip.tags dictionary with
    them.  Any number of tags can be specified with their type, optional CIP address and/or array
    length, and optionaly initial value(s) data.  We'll add any [Simulator] tags to the supplies sys.argv data,
    and let the enip.main parse all the tag names and type/address/size.  Then, we'll initialize the
    attributes afterward everything starts up, by looking up the tag names in enip.tags, and
    assigning the initial values.

    [Simulator]
    Something Floating              = REAL          = 1.0
    Many Reals                      = REAL[100]     = 0.1, 0.2, 0.3
    INTS                            = INT[10]  # ten INTs starting off at zero value
    Specific CIP Address@123/4/5    = DINT          = 999

    """
    if argv is None:
        argv = sys.argv[1:]

    # Remember any tags we find w/ optional values CSV.  We won't know the type 'til after the
    # Attribute is created by enip.main, so just store the raw CSV for now.  Use the Object class'
    # config_loader, and only look for [Simulator] entries (don't use DEFAULT).  Iterate thru all
    # the entries, adding an entry to kwds for each.
    values = {}  # All collected Tags w/ a CSV of initial values

    # Load config_files early (with case sensitivity); enip.main will re-do it, case-insensitively
    optionxform = Object.config_loader.optionxform
    Object.config_loader.optionxform = str  # Case-sensitive
    Object.config_loader.read(config_files)

    if 'Simulator' in Object.config_loader:
        for nam, typ in Object.config_loader['Simulator'].items():
            val = None
            if '=' in typ:
                # Optional value(s)
                typ, val = typ.split('=', 1)
                typ, val = typ.strip(), val.strip()
            argv += ['='.join((nam, typ))]  # eg. Tag@123/4/5=REAL[100]
            if val:
                # A non-empty initial value was provided; strip off any optional CIP address and
                # save the initial values provided.
                if '@' in nam:
                    nam = nam[:nam.index('@')]
                values[nam] = val

    Object.config_loader.optionxform = optionxform
    Object.config_loader.clear()

    def idle_init():
        """First time thru, set up any initia values; subsequently, perform original idle_service."""
        if idle_init.complete:
            if idle_service:
                idle_service()
            return
        idle_init.complete = True
        for nam in values:
            # Got initial value(s) for this one.
            val_list = []
            try:
                val_list, = csv.reader([values[nam]],
                                       quotechar='"',
                                       delimiter=',',
                                       quoting=csv.QUOTE_ALL,
                                       skipinitialspace=True)
                ent = dict.__getitem__(
                    tags,
                    nam)  # may be 'Tag.SubTag'; avoid dotdict '.' resolution
                typ = ent.attribute.parser.__class__.__name__  # eg. 'REAL'
                _, _, cast = client.CIP_TYPES[typ]
                ent.attribute[0:len( val_list )] \
                                    = [ cast( v ) for v in val_list ]
            except Exception as exc:
                print("Failed to set %s[0:%d] = %r" %
                      (nam, len(val_list), val_list))
                raise

    idle_init.complete = False

    # Establish Identity, TCPIP, etc. objects, and any custom [Simulator] tags from the config file(s).
    return enip_main(argv=argv, idle_service=idle_init, **kwds)