System Platform и OLE.

Системная платформа - продукт для комплексной автоматизации процессов предприятия от Wonderware.

System Platform и OLE.

Сообщение AirBus » Вт июн 26, 2012 2:57 pm

Добрый день.

В InTouch есть функция создания объекта OLE: OLE_CreateObject(%Объект, "Название_класса");
Как это можно организовать на узле сервера приложений?

Спасибо.
AirBus
 
Сообщения: 84
Зарегистрирован: Чт дек 08, 2011 6:30 pm

Re: System Platform и OLE.

Сообщение Генератор зла » Вт июн 26, 2012 3:46 pm

Скрипты - .Net ф-ции ?
Vita est dolor.
Генератор зла
 
Сообщения: 2860
Зарегистрирован: Вс янв 23, 2011 5:08 pm

Re: System Platform и OLE.

Сообщение AirBus » Вт июн 26, 2012 4:23 pm

Генератор зла писал(а):Скрипты - .Net ф-ции ?

Ссылку на документацию не подскажите ???
AirBus
 
Сообщения: 84
Зарегистрирован: Чт дек 08, 2011 6:30 pm

Re: System Platform и OLE.

Сообщение Генератор зла » Вт июн 26, 2012 5:54 pm

Scripting at the Template Level
Summary: Add additional functionality to a template by creating scripts. Scripts are written using the QuickScript .NET language.
Version: 2.0
Created at 8/13/2008 1:58 PM by TSADMIN
Last modified at 1/9/2009 8:30 AM by Escobar, Raul
This article includes the following topics:
Script Execution Types
Scoping Variables
Scripting for OLE and COM Objects
Determining Object and Script Execution Order
Asynchronous Scripts
Scripting I/O References
Writing to a Database
The following article contains best practice recommendations.
Segregate functionality by creating unique scripts for each segment required.
When functionality within the script will require an extended amount of time to execute, set the script to run asynchronously with a timeout limit. Such functionality is sometimes required by COM objects and .NET
objects (for example, file operations, SQL queries, and so on).
When creating scripts at the template level, you may want to lock them. You can then make changes to the template script, and the changes will propagate to the next level. When a script is locked and there are no declarations or aliases, these sections should also be locked for improved propagation and deployment performance.
When the field devices have a structured containment and addressing convention, create a script that will populate all attributes with an I/O extension at the time of deployment. If instances have been configured using this method, you can use the "Upload Runtime Changes" functionality to synchronize the changes back to the Galaxy Repository.
When adding scripts to templates, use relative names (Me, MyContainer, MyEngine, MyArea, MyPlatform, and MyHost). Using relative names saves you from having to edit absolute references in every instance.
Lock all inherited scripts, otherwise a copy of each assembly/script will be created for each object derived from the template and multiple copies of the same script will be running on the AppEngine object where they are deployed.

Locking the scripts generates one single assembly to be deployed to the AppEngine. The assembly is then shared by all instances derived from that template.
Script Execution Types
The script execution types and when they should be used are as follows:

Startup: Called when the object is loaded into memory. Primarily used to instantiate COM objects and .NET objects.
OnScan: Called the first time an AppEngine calls this object to execute after the object scan state is changed to onscan. Primarily used to initiate attribute values.
Execute: Called every time the AppEngine performs a scan and the object is onscan. Supports conditional trigger types of On True, On False, While True, While False, Periodic, and Data Change. Most run-time functionality is added here.
OffScan: Called when the object is taken offscan. Primarily used to clean up the object and account for any needs that should be addressed as a result of the object no longer executing.
Shutdown: Called when the object is about to be taken out of memory, usually as a result of the AppEngine stopping. Primarily used to destroy COM objects and .NET objects and clean up memory.
Scoping Variables
Declared variables can be of any data type within the development environment plus object, .NET type libraries, and imported types. Declared variables can be up to a three-dimensional array.

The issue becomes how to create a .NET data type that is persisted from scan to scan and available to other scripts within the object or available to other objects. Since UDAs only support the base data types, a declared variable or script variable must be used.

Once the variable has been created and values set, it must be added to the .NET global data cache through the following call:

DIM Connection AS System.Data.OLEDB.OLEDBConnection;
{Set required values}
System.AppDomain.CurrentDomain.SetData ("MyConnection", Connection);

When this variable is required in another script, the variable must be dimensioned within the script and then read from the .NET global data cache through the following:

DIM DBConnect AS System.Data.OLEDB.OLEDBConnection;
DBConnect = System.AppDomain.CurrentDomain.GetData("MyConnection");

Script variables have the same options as declared variables. Note that User-defined attributes can only have data types that are available within the development environment and only support one-dimensional arrays.

Variables within a Galaxy can have different scopes:

Global: Global variables can be accessed from anywhere within the Galaxy. Object attributes and user-defined attributes (UDAs) are used to create global variables. The value is held constant when the object is taken offscan.
Script: Variables that have been dimensioned in the declarations section of the script can be accessed from any execution type of the script. These variables will persist from scan to scan, but are cleared when the object goes offscan.
Script Execution Type: Variables that are dimensioned within the execution type of the script are only accessible from within that execution type. These variables will not persist from scan to scan. Do not use a UDA if a DIM (dimensioned variable) will suffice. Most UDAs are checkpointed; DIMs are not. Checkpoints consume scan time. The exception to this rule is a UDA set as "calculated", which by default is not checkpointed. Calculated UDAs have the least "weight".
Scripting for OLE and/or COM Objects
The following script change must be made from InTouch QuickScript to Application Server QuickScript .NET when using OLE and/or COM objects.

Within InTouch, the function call OLE_CreateObject(%Name, "ProgramID") is used to create an instance of an OLE automation object with a starting character for the name of either % or #.

Within Application Server, a standard variable name without the leading % or # is used with a "DIM Name as Object" statement. The variable is then assigned to the OLE/COM object by using the CreateObject("ProgramID") function.

For example, the following code creates a QI _ data component object.

For InTouch
OLE_CreateObject(%QIDC, "QI.DataComponent");

For Application Server
DIM QIDC AS Object;
QIDC = CreateObject("QI.DataComponent");


Using Aliases
Aliases provide a single place for changing the variable, instead of multiple places in the script.

This practice makes script maintenance easier when references contained in that script must be changed.

Create an Alias when

An external attribute must be referenced in the script.
The attribute name is not known or will be unique for each instance of the template. Use three dashes (---) to represent an unknown reference. The dash characters prevent the "could not resolve reference" warning when instances are created.
Alias naming can also make the script easier to read and create. When the same relative reference is used multiple times, create an alias for it.

Determining Object and Script Execution Order
Wonderware Application Server enables control of the object scan order within an Engine, and control of the script execution order within an object. Use this functionality instead of "data handshake bits" to ensure the delivery order of data from script to script and from object to object.

Before considering script execution order, it is necessary to review how objects execute. The following information reviews object execution events at a basic level.

Note For details on object execution, see the object's help files.

AppEngine Execution
The AppEngine is the only engine that hosts more than one object. Object execution is handled by the scheduler primitive, which is single-threaded. It executes objects registered on the host engine repeatedly, and in a sequential order, during the scan interval.

The scan interval is the desired rate of execution of each Automation Object the AppEngine hosts. The following tasks execute engine-to-engine in the following order during the scan interval:

Execution Phase: Individual OnScan objects execute their functionality according to there configuration (defined at Config Time).
Output Processing Phase: All pending output requests (SetAttributes, subscription packets, publish notifications) must be sent. Pending requests intended for the same engine should be sent as one block request so that the receiving engine can process them atomically (and in order).
Checkpoint Snapshot Phase: This task is configured separately and may not occur during every scan interval. If a checkpoint occurs within a given scan interval, it occurs immediately after the Output Processing Phase.

The checkpointer status is checked to see if it is still busy from a previous checkpoint. If not, a new asynchrounous checkpoint is initiated with a checkpoint snapshot.
Input Processing Phase: The goal of this phase is to process all input requests (SetAttributes, subscription packets, publish notifications). Input requests are retrieved one at a time. If any input requests are left in the
queue, they are processed during the idle period before the next scan interval. At least one queued input request is processed following the Output Processing Phase, and before the Execution Phase.

Scan Overruns are a boolean condition that becomes true when the Execution Phase crosses from one scan interval to the next. When a Scan Overrun occurs, a new Execution Phase is delayed until the next scan interval begins. Any of the phases in the above list can cause a Scan Overrun when they extend beyond the scan interval.
All objects deployed on the AppEngine are processed in the following order:

DIObjects (multiple DIObjects are processed alphabetically by tagname), hosted ApplicationObjects, then their Areas (numerically).

Common Object Execution Order
The execution order of object instances running on an engine is configured within the Object Information tab of the object editor. As an engine executes its scan, it will process the objects in the order specified.

Each named script within an object can be specified to run as either just after inputs or just before outputs. The order in which the scripts are listed in either category is the order in which the scripts will be executed.

Each object executes its functionality in the following order:

Read inputs.
Execute "just after inputs" scripts.
Execute object native functionality (the UserDefined object has none).
Execute "just before outputs" scripts.
Write outputs.
Test alarms.
Each script is executed in its entirety before the next script is executed. This behavior is different from InTouch, where a script can trigger another script, such as a data change script. Within InTouch, the calling script halts while the data change script is run.

Within Application Server, each script completes before the next script is run. If a user-defined attribute of a second object instance is set during the execution of the script, and that UDA triggers a script on the second object, the script of the second object may or may not run during the same scan of the engine. If the second object is configured to run after the first object, the script on the second object will run during the same scan.

If the second object has already been serviced during the scan, the script on the second object will run during the following scan. Since the Engine manages each object, a script runs only as fast as the engine's scan period or some multiple of that period. If the engine's scan period is one second, and an object script is set to periodic for every 1.5 seconds, the script will run every other scan (that is, every two seconds).

Data requested or sent to objects residing on another engine/platform are updated on the next scan. This is also true for Application Objects on the same AppEngine if an Application Object needs data from another object but it executes before it on the scan.

For example, when Object A executes, it needs the output values from Object B.

The values received are from the previous scan, because Object B has not executed yet in the current scan. You must wait one scan if you want to verify a write of this type. Alternatively, you can change the execution order in the Object Editor so that Object B executes first.

Asynchronous Scripts An asynchronous script runs in a separate thread and is not directly tied into the engine's scan process. Therefore, reading and writing to any object attributes (including the calling object) is a slow process. An asynchronous script should not Read or Write within a long FOR-NEXT loop to a UDA or other external source. Since the asynchronous script runs in a separate thread, it must wait until the next scan of the engine for all the Read or Write transactions to occur. If the scripts have not all been completed at the next scan, the system must wait for another scan. A single-system test with an engine scan period of one second achieved approximately 70 UDA writes per second and 35 UDA reads per second.

Asynchronous Timeout Limit Settings
The asynchronous timeout limit must also be set appropriately. If the script times out, the script is halted in an indeterminate state. There is no mechanismfor determining what line the script was executing when it was halted. Therefore, another script should be checking for asynchronous script time outs and cleaning up any remaining inconsistencies.

Scripting I/O References
An Onscan script can automatically assign all the input source and output destination attributes of the template to their target reference string. Several different strategies to accomplish this are possible. In general, the suggestions included in this document will only work if a strict naming convention is used throughout the system.

Scripting I/O References Example 1
Create an Initialization script that runs when the object first goes Onscan. This script directs all the I/O sources or destinations used by the object to the appropriate device integration (DIObject) object, topic, and address.

If at all possible, do not hard-code any of the address components (DIObject name, topic, and I/O address). The one exception might be the I/O address if it is identical in all PLCs addressed by the object.

The DIObject should be named in a manner that can be determined from some other component in the system, such as the engine or platform name plus "PLC." The topic should also be determined from some other component in the system, such as Area. If there is only one topic, use a fixed name.

For PLCs that allow textual address names such as Control Logix, using the same object or hierarchical name for the instance within AutomationObject Server is the best approach.

The following example assumes that one DIObject with one topic called "Topic" is available on the same engine as the object referencing it. The object is based on the $DiscreteDevice template and has two inputs called OLS and CLS representing the open and close limit switches of a valve. The object name partially defines the address name within the PLC. The onscan script is similar to the following example:

Me.OLS.InputSource = MyEngine.Tagname + "PLC.Topic." + Me.Tagname + "OLS"; Me.CLS.InputSource = MyEngine.Tagname + "PLC.Topic." + Me.Tagname + "CLS";

Scripting I/O References Example 2
If the PLC does not have textual names, or different brands of PLCs are in use within the facility, the previous strategy can be abstracted one more level by using the attribute list within the DIObject.

The Topic tab contains a list of attributes for each tag with a textual name and an item reference. The same code as shown above could be used for a PLC with an address convention of B3:12.

In the Topic tab of the device integration object, add a couple of entries for the object. Suppose the object instance name was Valve220; the following entries would have to be in the attribute list: The Onscan script would still be the same.

The added advantage of using the attribute list is that all the I/O definitions are located in one central spot. A second DIObject with essentially the same set of I/O points can easily be created and, if necessary, modified by dumping and loading the existing DIObject. Other slight modifications are to store the DIObject name and topic name within UDAs on the area object hosting the automation object. Then it could be referenced by MyArea.DIName, where DIName is the name of the string UDA on the area object.

Writing to a Database
To write to a database

Create an AppDomain object that handles a message queue.
At the object level, fill the message queue with the values to be written.
At the engine level, create an object that moves the entries from MSMQ to the database, using Stored Procedures. The scripting may run asynchronously as no collecting is required.
Note The Message Queue service may use a large amount of memory, depending on the amount of data written.

Best Practice
The following are best practices to keep in mind regarding scripting:

Use stored procedures (SPs) when reading/writing to the database to decrease database access time (use a set-up object to create the SPs and then undeploy this object). As an extension to this concept; try to create "services" at a higher level (area, engine or platform) to support common data tasks.
Do not use OnScan scripts to access external data from multiple instances simultaneously. Managing object references by accessing external files from all instances at the same time (onscan) is not recommended. Either some type of handshake mechanism between the Platform and object is required to make this a viable approach, or you might use other methods to achieve this functionality.
Avoid extensive use of scripting within objects when possible. The extensive use of scripting influences the overall performance of the application. Look for opportunities to reduce the amount of scripting, if possible. Bear in mind that each condition needs to be evaluated, even though the script might not be executed. If you have thousands of these scripts implemented, the scripts will use more CPU time than just the execution of the logic. Instead, use a common database access object on a separate engine to perform a connection/read and then expose the returned data in a UDA array or queue for the other objects to read. This practice allows the database object to stop the scan of its engine without affecting the engine used by the requesting objects. If very robust scripts are needed, asynchronous scripts perform more efficiently because they do not stop executing; however, be aware of the time needed to transfer the data back into the database.
Avoid reading a database from within an object script because the engine stops scanning until the connection is made or the query is returned. Using asynchronous scripts does not help in this instance, because the asynchronous script must collect the data and transfer it back into the object for use. If it cannot finish all the 'writes,' it will start over on the next scan. This retrieval can take many scans.
Handle database connections using the .NET AppDomain object at the AppEngine level. This connection can be used by the Application Objects running on that AppEngine to execute the actual database transactions through stored procedures. An effective implementation is to create a template for DB-connector AppEngines. If every AppEngine () uses the same name for the .NET AppDomain object, Application Objects can be configured regardless of the AppEngine on which they run.

Do NOT create a database connection for every object.
Use asynchronous scripting, when appropriate. For example, use asynchronous scripts to execute functions that tend to "hang" or slow down the processing of other scripts (scripts that verify SQL connections, etc.).
Optimize dynamic referencing within scripts. In certain cases it may be necessary to dynamically configure Input source and Output destination references by writing scripts that execute at run-time.

It is important to write these scripts so that they execute only one time: When the object is initially deployed. One method of optimizing reference setting is to check within the script to see if the default " --- " is present. If so, the script sets the dynamic reference string. Once the string is set one time, it is checkpointed to disk, so that subsequent Engine or failover restarts will already be configured.

This practice is especially important in large systems (large I/O) where reconfiguring thousands of I/O references on Startup (and using excessive CPU resources) is avoided.
Use caution when including Data Change scripts. Recall that Data Change scripts are executed in three instances: Value Change, Quality Change, and a Set OnScan event (when the value is set from "nothing" to its default, and the quality changes).

When large numbers of Data Change scripts are included, a failover event could cause all the Data Change scripts to execute at the same time, causing unwanted consequences.

А так, дока по работе с OLE через .Net - на сайте Майкрософта в разделе доки по .Net
Vita est dolor.
Генератор зла
 
Сообщения: 2860
Зарегистрирован: Вс янв 23, 2011 5:08 pm

Re: System Platform и OLE.

Сообщение AirBus » Пн июл 09, 2012 3:23 pm

Здравствуйте, хотелось бы вернуться к вопросу темы.
К сожалению, у меня так и не получилось запустить мой объект.
Я написал в скрипте on scan для AppEngine:

DIM St as object;
St = CreateObject( "STLib.ISTCtrl" );
St.Subscribe( );
St.Start( );

Затем делаю deploy движка, объект не работает. В SMC следующие записи об ошибках:

AppEngine_Server_IAS.STStart: Script performed an illegal operation.

и вторая ошибка

AppEngine_Server_IAS.STStart: mscorlib: Значение не может быть неопределенным.
Имя параметра: type

Когда я использовал методы Subscribe и start в InTouch, то никаких проблем не возникало, все работает.


На wdnresource.wonderware.com нашел две TechNote по использованию Com объектов это technote 369 и 824.
В Technote 824 описывается использование System.Speech.dll
там приведен вот такой скрипт:

Dim speaker as System.Speech.Synthesis.SpeechSynthesizer;
speaker = new System.Speech.Synthesis.SpeechSynthesizer;
Logmessage("Demo using a Microsoft Framework dll: UDTextToSpeech");

speaker.Rate = me.speakerRate; 'default value = 1;
speaker.Volume =me.speakerVolume; 'default value = 100;
speaker.SpeakAsync( me.saySomethingText);

me.bTalkNow = false;


Когда я делаю такой скрипт для своего объекта при проверке появляется ошибка: Script STStart (OnScan): Constructor overload not found (Line2, col6)

Вот мой скрипт:


Dim St as STLib.ISTCtrl;
St = new STLib.ISTCtrl;

St.Subscribe( );
St.Start( );
AirBus
 
Сообщения: 84
Зарегистрирован: Чт дек 08, 2011 6:30 pm

Re: System Platform и OLE.

Сообщение Генератор зла » Пн июл 09, 2012 7:23 pm

AirBus писал(а):Script performed an illegal operation

1.
This message indicates the following: 1. imported assembly filename has been manually changed (assembly filename should not be changed). 2. AppEngine should be restarted before reimporting modified assembly files.
2.
App server looks for the dependant dlls in the ....\Program Files\ArchestrA\Framework\bin folder. Once all the dependant dlls are copied in this folder, the error message does not come up any more.
Vita est dolor.
Генератор зла
 
Сообщения: 2860
Зарегистрирован: Вс янв 23, 2011 5:08 pm


Вернуться в Wonderware System Platform

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 11