Documente Academic
Documente Profesional
Documente Cultură
Table of Contents
Copyrights
© 2017 Schneider Electric Software, LLC. All rights reserved.
No part of this documentation shall be reproduced, stored in a retrieval system, or transmitted by any means,
electronic, mechanical, photocopying, recording, or otherwise, without the prior written permission of Schneider
Electric Software, LLC. No liability is assumed with respect to the use of the information contained herein.
Although precaution has been taken in the preparation of this documentation, Schneider Electric Software, LLC
assumes no responsibility for errors or omissions. The information in this documentation is subject to change without
notice and does not represent a commitment on the part of Schneider Electric Software, LLC. The software described
in this documentation is furnished under a license agreement. This software may be used or copied only in
accordance with the terms of such license agreement.
ArchestrA, Avantis, DYNSIM, eDNA, EYESIM, Foxboro, Foxboro Evo, I/A Series, InBatch, InduSoft, InStep, IntelaTrac,
InTouch, PIPEPHASE, PRiSM, PRO/II, PROVISION, ROMeo, Schneider Electric, SIM4ME, SimCentral, SimSci, Skelta,
SmartGlance, Spiral Software, VISUAL FLARE, WindowMaker, WindowViewer, and Wonderware are trademarks of
Schneider Electric SE, its subsidiaries, and affiliated companies. An extensive listing of Schneider Electric Software,
LLC trademarks can be found at: http://software.schneider-electric.com/legal/trademarks/. All other brands may
be trademarks of their respective owners.
Contact Information
Wonderware Technical Support
Phone
Contact Software Learning Services for assistance regarding classes, schedule, offerings, frequently asked questions,
tuition, policies, and more.
Email: software.training@schneider-electric.com
Toll-Free U.S. and Canada: 1-866-998-7246
Direct: 1-949-639-8508
Fax: 1-949-639-1847
Introduction
This section provides background information about the InTouch OMI Software Developer Kit.
About the InTouch OMI SDK
InTouch OMI App Development Guidelines
Acronyms and Definitions
All classes, methods, properties, etc. that are exposed in the various SDKs are supported by the following .NET
programming languages:
C#
VB.Net
Visual C++ .Net
Managed Extensions for C++
Naming Conventions
SDK assembly and DLL names conform to the following pattern:
ArchestrA.Client.<SDK_Extension>.DLL, where SDK_Extension is the name of the SDK. For example, the name of the
DLL for the RunTimeData SDK is "ArchestrA.Client.RunTimeData.DLL."
Namespace names: Public namespace names conform to the same naming pattern as for SDK assembly and DLL
names, minus the "DLL" file extension. For example, the name of the namespace for the RunTimeData SDK is
"ArchestrA.Client.RunTimeData."
Non-public implementations of the the SDK namespace use the same name as the public namespace, but are
appended with "Internal." For example, "Archestra.Client.RunTimeData.Internal."
Key Concepts
This section defines some of the terms and technologies that you should be familiar with before using this SDK.
Screen Profiles
Layouts and Panes
Configurable Properties
Screen Profiles
Screen profiles define physical screen characteristics for ViewApps. Physical screen characteristics include resolution,
whether the screen is touch-enabled, and orientation (portrait or landscape). For additional information,
see WebHelp/index.htm#257577.
Configurable Properties
An InTouch OMI app can contain two types of configurable properties:
CLR (.NET Framework) properties
Dependency properties
CLR properties can only be set at configuration (design) time, while dependency properties can be bound to any
attribute and can be set at run time. If a dependency property is changed at run time, the new value is propagated
to the attribute. Dependency properties are data-bindable at design time, and you can set the binding direction to in
(read), out (write), or both. To change the binding direction, click on the arrow to toggle the binding direction.
Getting Started
Installation
Requirements
Getting Around the SDK
App Development Best Practices
InTouch OMI App Limitations and Restrictions
Installation
The InTouch OMI SDK and all component assemblies are installed automatically on the node when you select the IDE
component of Application Server for installation, using either the product-based or role-based option. Setup installs
the SDK binaries under the ArchestrA\Framework folder, in the following location:
64-bit systems: C:\Program Files (x86)\ArchestrA\Framework\AcfSdk\Libs
32-bit systems: C:\Program Files\ArchestrA\Framework\AcfSdk\Libs
Requirements
To use the InTouch OMI SDK, you must have the following software, operating system, and framework components
installed on your development system:
Visual Studio 2013 or higher
.NET Framework 4.5.2 or higher
Wonderware Application Server IDE (WSP 2017 Update 1)
Controls
Standard Microsoft Designer Mode: Controls should support the Standard Microsoft Designer Mode for controls.
Control instances should be constructed in designer mode within ACF configuration tools when they are imported into
the Visualization Repository, and placed into the standard MSFT Designer Mode when edited. This mode should be
taken into account by the control developer to prevent unintended connections to data sources from occurring while
the control is being configured. The control developer must determine any required changes in behavior that are
needed if the host indicates that the control is running in the configuration environment.
IDisposable pattern: If necessary, implement the IDisposable pattern. When the IDisposable pattern is implemented,
the ACF host calls the Dispose() method on a control’s framework element whenever the control is closed.
Blocking operations: Do not block the UI thread for long operations. ACF supports one thread per top level window.
Other controls within the same window may be controlling live information and should not be frozen and made
unresponsive because of a blocking operation.
Cross-control communication: Each Screen Layout (top level window) in an ACF application has its own thread.
Since controls can only be accessed by callers running on their thread, all cross-control communication must be done
using the other control’s dispatcher object. This includes a control accessing its own properties when handling events
potentially fired from a different thread.
Use proper encapsulation (public vs private): Ensure that all types defined in App code are appropriately marked as
public or private. Only mark as public the controls and control properties that need to be used by consumers.
Filter public controls: Use the AppManifest.xml file to filter out any public controls that should not be visible in the
Galaxy Graphics Toolbox. This is useful when third-party DLLs that have public controls are included in the Apps
folder, but you do not want those controls to be visible in the Galaxy Graphics Toolbox. You can also usethe
AppManifest.xml file to filter out public properties on controls.
Specify default Values and categories: Controls should specify default values and categories for their public
browsable properties. This is standard for well-behaved controls edited via a property grid. It enables values to be
reset to their defaults and show in bold style if edited.
Follow standard exception handling patterns: Refer to the Microsoft guidelines at the following URL:
https://docs.microsoft.com/en-us/dotnet/standard/design-guidelines/exceptions.
Run-Time Data
Bulk subscribe to references: To read run-time data, subscribe the references in bulk and wait for the data change
event, instead of performing an async read for each of the reference.
Component SDKs
The component SDK assemblies reside under the folder: C:\Program Files (x86)\ArchestrA\Framework\AcfSdk\Libs.
ArchestrA.Client.CommonUtil.dll
ArchestrA.Client.Navigation.dll
ArchestrA.Client.ProcessControls.dll
ArchestrA.Client.RuntimeData.dll
ArchestrA.Client.ViewApp.dll
ArchestrA.Client.WebControls.dll
AppConfig SDK
The AppConfig SDK lets you build an application editor that runs in the System Platform IDE. Application developers
can use this application editor for setting global configuration options for all instances of your custom app. It is not a
requirement to include an app editor with your custom app, but if More basic apps do not need their own editors and
can be configured within the Layout Editor or the ViewApp Editor. The AppConfig SDK is exposed by the AppConfig
assembly (ArchestrA.Client.AppConfig), and includes several public interfaces and classes, including:
EditorActivityViewModelBase: This class allows the application developer to implement new activity derived from
the EditorActivityViewModelBase and add new activity in the app editor.
IEditorConfig: This interface allows the application developer to initialize, save, load and implement the app.
IEditorBase: This interface permits hosting of IEditorConfig and provides support for command, preference, save,
and load. It is implemented by Schneider Electric internal framework and is used in the App Editor.
IEnumerable<IEditorActivity> GetActivities();
}
4. Create an App Activity class, derived from the EditorActivityViewModelBase. Use this class to implement all
front end logic. You will also use this class to create an activity tab in the editor. For more information,
see EditorActivityViewModelBase Class.
5. Link the App Activity class with a class derived from the base View class (WPF user control).
6. Compile your code and build the app editor DLL assembly.
7. Create a folder and move the app DLL, app editor DLL, any dependent DLLs, and the appmanifest.xml file into
it.
8. From the System Platform IDE (ArchestrA IDE), use the ArchestrA App option from the Galaxy > Import menu
to select the folder that contains your app and import the app into the IDE.
9. After importing the app, open it from the Graphic Toolbox and configure the app with the editor you created.
EditorActivityViewModelBase Class
To create a tab or activity in your app editor, create a class derived from EditorActivityViewModelBase. This class
lets you override the following methods and properties:
1. Label: This sets the name of the tab that will appear at the top of the app editor.
2. RegisterCommands: This registers a command for the tab.
3. OnDeactivated: This is set when the tab is deactivated.
4. OnActivated: This is set when the tab activated.
5. OnInitialized: This is set when the tab is initialized.
EditorActivityViewModelBase has the following public methods that you can use to implement new app editor
activity:
1. SetDirty: Enables a user to save changes to the configuration in the editor.
2. IsActive: In an editor with multiple tabs, this method indicates whether a tab is active or inactive.
3. IsReadOnly: This method indicates if the editor is open in readonly mode.
EditorActivityViewModelBase contains the following protected methods/properties that can used when
IEditor Interface
The IEditor interface is used in the AppConfig Editor but is implemented within the internal framework.
IEditor
public interface IEditorBase
{
/// <summary>
/// Gets the name of the editor instance.
/// </summary>
string EditorName { get; }
/// <summary>
/// Sets the editor's dirty flag to true, i.e., IsDirty returns true after
calling this method.
/// </summary>
void SetDirty();
/// <summary>
/// Gets the editor's preferences.
/// </summary>
IPreference Preferences { get; }
/// <summary>
/// Gets the editor's CommandManager.
/// </summary>
IAppCommandManagerBase AppCommandManager { get; }
/// <summary>
/// Gets a value indicating whether the editor instance is read-only
/// </summary>
bool IsReadOnly { get; }
}
/// <summary>
/// IEditorBase calls InitializeEditor from interal framework.
/// </summary>
/// <param name="editor">The editor holds the logic for save, load, command
manager, and preference</param>
public void InitializeEditor(IEditorBase editor)
}
/// <summary>
/// Name of the page/tab/activity
/// </summary>
public override string Label
{
get
{
return "sample activity";
}
}
}
CommonUtil SDK
The CommonUtil SDK exposes the CommonUtil assembly (ArchestrA.Client.CommonUtil.dll) and namespace, and lets
you access common utilities, methods, and attributes. These include dispose and finalize methods, setting localized
(translated language) descriptions, and a method for setting a ResourceDictionary.
RunTimeData SDK
The main functional element of the RuntimeData SDK is a .NET assembly that lets you subscribe to, read from, and
write to either a single value reference or multiple references simultaneously. The assembly name that contains the
RuntimeData APIs is ArchestrA.Client.RuntimeData.dll, and the namespace of the assembly is
ArchestrA.Client.RuntimeData. A single value reference is a value on a single attribute for an object. The RunTime
SDK cannot be called from an external service. It can only be used inside the control of an InTouch OMI app. With the
RuntimeData SDK, you can:
Subscribe to a reference and get its current Value, Time and QualityStatus.
Write a value to a reference.
Read a value from a reference.
Perform secured/verified write operations.
The RunTimeData assembly contains two namespaces:
ArchestrA.Client.MyViewApp
ArchestrA.Client.RuntimeData
The ArchestrA.Client.MyViewApp namespace contains the following additional namespaces and classes:
Alarms
Navigation
Security
Language
Playback
Settings
System
The callback in the above sample is sent from a background thread. If the handler code in the App has any UI-
specific logic, the handler must execute in its Dispatcher. The above value is received in an action that has
been passed in. Alternatively, you can get the data by using references[0].VTQ.Value.
3. Optional: Asynchronous read:
Asynchronous Read
var vtqArray = await this.DataSubscription.ReadAsync
{
new [] {new DataReferenceSource("GRNode.CPULoad")} }
4. Write from subscription (see step 2 for subscription details). The following code sample shows how to write
data to the subscription.
Write to Subscription
references[0].Write(10, (r, s)=>{});
/// Or to write to an element in array:
references[0].Write(10, 0, (r, s)=>{});
IRuntimeDataClient
Controls in an ArchestrA App must implement the IRuntimeDataClient interface to be able to read/write run-time
data.
IRuntimeDataClient
public interface IRuntimeDataClient
{
/// <summary>
/// Gets or sets the DataSubscription instance. Framework will the
DataSubscription instance to be used by client to read/write runtime data.
/// </summary>
DataSubscription DataSubscription {get; set;}
}
DataSubscription
public abstract class DataSubscription
{
/// <summary>
/// Read the runtime data asynchronously.
/// </summary>
/// <param name="dataReferenceSources">The data reference source
/// array</param>
/// <returns>The VTQ array of the references</returns>
public abstract Task<VTQ[]> ReadAsync(DataReferenceSource[]
dataReferenceSources);
/// <summary>
/// Write the runtime data asynchronously.
/// When writing to an ArchestrA attribute in which security is
/// SecuredWrite or VerifiedWrite, the corresponding pop-up dialog box
/// will automatically popup and the method will return when the dialog
/// box is dismissed and the data is either written to the source or fails.
/// </summary>
/// <param name="dataReferenceSource">The data reference source</param>
/// <param name="value">The value to be written</param>
/// <returns>The status of the write operation</returns>
public abstract Task<WriteOperationStatus> WriteAsync(DataReferenceSource
dataReferenceSource , object value);
/// <summary>
/// Subscribe the runtime data references.
/// </summary>
/// <param name="dataReferenceSources">The data reference source array</param>
/// <returns>The subscribed data reference array</returns>
WriteOperationStatus
Use the WriteOperationStatus class to receive write status when writing data to a reference.
WriteOperationStatus
public enum WriteOperationStatus
{
/// <summary>
/// Indicates success
/// </summary>
WriteSuccess = 0,
/// <summary>
/// Indicates failure
/// </summary>
WriteFailed = 1,
/// <summary>
/// Indicates failure because of application authentication issues
/// </summary>
ApplicationAuthenticationError = 2,
/// <summary>
/// Indicates failure because of user authentication issues
/// </summary>
UserAuthenticationError = 3,
/// <summary>
/// Indicates failure because of user authorization issues
/// </summary>
UserAuthorizationError = 4,
/// <summary>
/// Indicates failure because of unsupported operation
/// </summary>
NotSupportedOperation = 5,
/// <summary>
/// Indicates failure because the item is already deleted
/// </summary>
ItemAlreadyDeletedOrDoesNotExist = 9,
/// <summary>
/// Indicates failure because the item is invalid
/// </summary>
InvalidMonitoredItems = 10,
/// <summary>
/// Indicates failure because the operation failed
/// </summary>
OperationFailed = 11,
/// <summary>
/// Indicates failure because of no connection
Subscribe to References
DataReferenceSource
The DataReferenceSource class is used to define and subscribe to the reference source, and to receive data from it.
DataReferenceSource
public class DataReferenceSource
{
/// <summary>
/// Initializes a new instance of the DataReferenceSource class.
/// </summary>
/// <param name="referenceString">The reference string</param>
/// <param name="owningObject">The owning object name</param>
/// <param name="dataChangedAction">The action to receive the data/quality
change</param>
public DataReferenceSource(string referenceString, string owningObject,
Action<DataReference> dataChangedAction);
/// <summary>
/// Initializes a new instance of the DataReferenceSource class.
/// </summary>
/// <param name="referenceString">The reference string</param>
/// <param name="dataChangedAction">The action to receive the data/quality
change</param>
public DataReferenceSource(string referenceString, Action<IDataReference>
dataChangedAction);
/// <summary>
/// Gets the owning object.
/// </summary>
public string OwningObject { get; }
/// <summary>
/// Gets the reference string.
/// </summary>
public string ReferenceString { get; }
/// <summary>
/// Gets the action to receive the data/quality update.
/// The Action passes the DataReference that triggers the data change.
/// </summary>
public Action<IDataReference> DataChangedAction { get; }
}
DataReference
Once you have subscribed to the DataReferenceSource, you can receive the DataReference from it. The
DataReference can then be used to read/write the run-time data.
DataReference
public abstract class DataReference
{
/// <summary>
/// Gets the VTQ of the data item
/// </summary>
VTQ
public abstract class VTQ
{
/// <summary>
/// Gets the value of the data item.
/// </summary>
public abstract DataValue Value { get; }
/// <summary>
/// Gets the quality and status of the data item.
/// </summary>
Value
Value represents the value of the data item value and related data conversion utility methods.
Value
public class Value
{
/// <summary>
/// Gets or sets the raw data value contained in this class.
/// </summary>
public abstract object RawValue { get; }
/// <summary>
/// Gets the value as type Integer.
/// </summary>
public abstract int ValueAsInt32 { get; }
/// <summary>
/// Gets the value as type Float.
/// </summary>
public abstract float ValueAsFloat { get; }
/// <summary>
/// Gets the value as type Double.
/// </summary>
public abstract double ValueAsDouble { get; }
/// <summary>
/// Gets the value as type String.
/// </summary>
public abstract string ValueAsString { get; }
/// <summary>
/// Gets the value as type DateTime.
/// </summary>
public abstract DateTime ValueAsDateTime { get; }
/// <summary>
/// Gets the value as type Duration.
/// </summary>
public abstract TimeSpan ValueAsDuration { get; }
/// <summary>
/// Gets the value as type bool.
/// </summary>
/// <value><c>true</c> if [value as bool]; otherwise, <c>false</c>.</value>
public abstract bool ValueAsBool { get; }
/// <summary>
/// Gets a value indicating whether this instance is empty
/// </summary>
/// <value><c>true</c> if this instance is empty; otherwise,
<c>false</c>.</value>
public abstract bool IsEmpty { get; }
/// <summary>
/// Gets a value indicating whether the value is an array.
/// </summary>
/// <value><c>true</c> if this instance is array; otherwise,
QualityStatus
The QualityStatus class represents the data quality and status, and related helper methods.
QualityStatus
public abstract class QualityStatus
{
/// <summary>
/// This defines the bits when the quality does not exist.
/// </summary>
public const int QualityNotExist = -1;
/// <summary>
/// Gets the status setting enum.
/// </summary>
public abstract StatusSettingType StatusSetting { get; }
/// <summary>
/// The data quality follows OPC UA standard, or QualityNotExist if it does not
exist.
/// </summary>
public abstract int OpcUaQuality { get; }
/// <summary>
/// The data quality used by ArchestrA, or QualityNotExist if it does not
exist.
/// </summary>
public abstract int MxQuality { get; }
/// <summary>
/// Returns true if the quality is good.
/// </summary>
/// <returns>True if good</returns>
public abstract bool IsGood();
/// <summary>
/// Returns true if the quality is bad.
/// </summary>
/// <returns>True if bad</returns>
StatusSettingType
The StatusSettingType enum represents the data status settings used in the Galaxy style library configuration.
StatusSettingType
public enum StatusSettingType : byte
{
/// <summary>
/// Represents a Communication Error type.
/// </summary>
Communication = 0,
/// <summary>
/// Represents a Configuration Error type.
/// </summary>
Configuration = 1,
/// <summary>
/// Represents a Pending Error type.
/// </summary>
Pending = 2,
/// <summary>
/// Represents an Operational Error type.
/// </summary>
Operational = 3,
/// <summary>
/// Represents a Software Error type.
/// </summary>
Software = 4,
/// <summary>
/// Represents a Security Error type
/// </summary>
Security = 5,
/// <summary>
/// Represents a Warning Error type.
/// </summary>
Warning = 6,
/// <summary>
/// Represents Out Of Service.
/// </summary>
OutOfService = 7,
/// <summary>
/// Represents a Device Failure.
/// </summary>
DeviceFailure = 8,
/// <summary>
/// Represents a Bad Error type.
Language Namespace
If multiple languages have been configured in a Galaxy, you can manage the languages and locales in an application.
This allows users to implement multiple languages/locales in your application during configuration, and to change the
language during run time. Three attributes in the language namespace are provided for setting language and locale:
CurrentLanguage: This attribute contains the current language, for example, "English," and can be set
during run time to change the application language.
CurrentCultureInfo: This attribute contains locale-type information, for example, "en-US," and can be set
during run time to change the locale.
CurrentLCID: This attribute contains a numeric identifier that corresponds to the locale, for example, "01,"
and can be set during run time to change the locale.
In addition, the language namespace includes three properties. All use an array that holds ;language and locale IDs
that currently configured.
Languages
Lcids:
CultureInfos
Attributes
Language attributes are exposed in the Titlebar sample app when the Language property is enabled. A dropdown list
of configured languages is displayed in the ViewApp, and users can then change the ViewApp language during run
time. You can use the same language namespace attributes and properties in your own custom apps.
CurrentLanguage Attribute
The CurrentLanguage attribute holds the currently-configured language for the ViewApp. The CurrentLanguage
method returns the currently-configured language for the ViewApp.
CurrentLanguage
/// <summary>
/// Gets or sets the current language.
/// </summary>
/// <value>
CurrentLCID Attribute
The CurrentLCID attribute holds the currently-configured locale ID for the ViewApp. The CurrentLCID is an integer
value that corresponds to the currently-selected language for the ViewApp.
CurrentLCID
/// <summary>
/// Gets or sets the current LCID.
/// </summary>
/// <value>
/// The current LCID.
/// </value>
public static int CurrentLCD
CurrentCultureInfo Attribute
The CurrentCultureInfo attribute holds the currently-configured locale information, for example, EN-us (English-
United States), for the ViewApp. The CurrentCultureInfo method returns the currently-configured locale for the
ViewApp.
CurrentCultureInfo
Type your example code here. It will be automatically colorized when you switch to
Preview or build the help system.
Properties
Languages Property
The Languages property uses an array that lists the languages that are configured in language settings. The languages
are set in the System Platform IDE, under Galaxy > Configure > Languages. The Language property includes the
Languages index. The Languages index number is exactly the same as the LCID index number in the LCIDs array and
the CultureInfo index number in the CulturesInfo array.
Languages
/// <summary>
/// Gets the list of configured languages. The Languages array will have the same size
as the LCIDs array.
/// The Language index within the Languages array, the LCID index within the LCIDs
array, and the CultureInfos index within the CultureInfos array will all have the same
index number.
/// </summary>
/// <value>
/// The configured languages.
/// </value>
public static string[] Languages
Lcids Property
The Lcids property uses an array that lists the LCIDs (language and locale IDs) that are configured in language
settings. The Lcids property is set in the System Platform IDE, under Galaxy > Configure > Languages. The Lcids
Lcids
/// <summary>
/// Gets the LCIDs. The LCID array will have the same size as the Languages array.
/// The LCID index within the Lcids array, the Languages index within the Languages
array, and the CultureInfos index within the CultureInfos array will all have the same
index number.
/// </summary>
/// <value>
/// The configured Lcids.
/// </value>
public static string[] Lcids
CultureInfos Property
The CultureInfos property uses an array that lists the CultureInfos numbers (language and locale IDs) that are
configured in language settings. The CultureInfos property is set in the System Platform IDE, under Galaxy >
Configure > Languages. The CultureInfos property includes the CultureInfo index. The CultureInfo index number is
the exactly the same number as the Language index number in the Languages property and the LCID index number in
the LCIDs property.
CultureInfos
/// <summary>
/// Gets the Culture Information. The CultureInfos array will have the same size as the
Languages array.
/// The CultureInfos index within the CultureInfos array, the Languages index within
the Languages array, and the LCID index within the Lcids array will all have the same
index number.
/// </summary>
/// <value>
/// The configured culture information.
/// </value>
public static string[] CultureInfos
Interface Methods
Get Current Language Method
LocaleItem GetCurrentLanguage()
Returns the currently-configured Locale ID (LCID) and the language name in the LocaleItem structure.
LocaleEverntArgs Class
GraphicControl SDK
The ArchestrA.Client.ProcessControls assembly contains the Graphic Control SDK, which exposes reusable graphic
and alarm adorner controls. The graphic control exposes the following dependency properties:
GraphicName
OwningObject
EnableInteractiveContent
EnableTriggeringNavigation
GraphicControl Reference
// Create a reference
xmlns:controls="clr-
namespace:ArchestrA.Client.ProcessControls;assembly=ArchestrA.Client.ProcessControls"
// Use the control
<controls:GraphicControl GraphicName="{Binding SymbolName}"}/>
2. Retrieve the content from a navigation path, based on filter options as shown below. Refer to the navigation
model assembly (ArchestrA.Client.Navigation.NavigationModel):
Retrieve Content
public static ArchestrA.Client.Navigation.ContentData[]
GetContentInHierarchy(string navigationHierarchyPath,
3. Show the GraphicControl in the ACF app. The GraphicControl is defined under the namespace
ArchestrA.Client.ProcessControls, and the assembly that defines the APIs is ArcestrAClient.ProcessControls.DLL.
4. Retrieve the content from the navigation path, baseed on the filter options you have set. The search content API
s defined under the namespace ArchestrA.Client.Navigation. The assembly defined these APIs is
ArchestrA.Client.Navigation.dll.
GraphicControl Properties
GraphicControl is a user control, wrapped around the InTouch OMI visualization module. This provides an easy to
instantiate and display the InTouch OMI visualization module in any ACF app. GraphicControl abstracts all of the logic
for instantiating and rendering graphics in a XAML template, and exposes the following properties. You can bind these
properties within the apps that you write to use their functionality.
GraphicName: [Required] The name of the graphic to be displayed in an app. You must provide a value for
the GraphicName. The syntax for setting the GraphicName is ObjectName.SymbolName.
OwningObject: [Optional] This sets the owning object of the graphic. If a value for OwningObject is not
provided, the tagname of the object associated with the graphic is used.
EnableInteractiveContent: If true, this enables the content to be interactive. In a graphic, this property
controls whether or not user-interaction animations are enabled. The default setting this property is true.
EnableTriggeringNavigation: If true, clicking on content that does not include an interaction animation
triggers a move to the naviation item linked to the content. The default setting for this property is false.
FilterOptions Class
/// <summary>
This class holds the filter options applied to a specific navigation item.
/// </summary>
public class FilterOptions
{
/// <summary>
/// Gets or sets option Levels of Search.
/// Provides the levels of search performed on the hierarchy of a navigation
path.
/// </summary>
public LevelsOfSearch LevelsOfSearch { get; set; }
/// <summary>
/// <summary>
/// <summary>
/// Gets or sets option ContentType
/// 1) This field should be one of the content types in the system
/// 2) This field is ignored if the value is empty.
/// </summary>
public string ContentType { get; set; }
}
SortOrder
/// <summary>
/// This option controls how are sorted from the API
/// </summary>
public enum SortOrder
{
/// <summary>
/// This is the default option, which fills the control based on the order in which
it finds the content.
/// This is similar to depth-first search
/// </summary>
None = 0,
/// <summary>
/// Sorts content based on name in alphabetic order.
/// </summary>
Alphabetical
}
Navigation Search Mode: This option specifies the navigation search mode that determines which navigation
path hierarchy is considered at the API level.
/// In FixedLocation mode, a search starts from a specific navigation path node provided
by the user.
/// </summary>
FixedLocation = 0,
/// <summary>
/// In CurrentPath mode, a search starts from the current navigation path node
selected by the user.
/// This is same path as MyViewApp.Navigation.CurrentPath
/// </summary>
CurrentNav CurrentPath,
/// <summary>
/// In ChildrenAlone mode, a search starts from the child navigation nodes of a parent
/// node specified by the user.
/// </summary>
ChildrenAlone
}
LevelsOfSearch: This option provides the levels of search to be performed on a specified navigation path
pathhierarchy.
LevelsOfSearch
/// <summary>
/// This option provides the different levels of search that system allows
/// </summary>
public enum LevelsOfSearch
{
/// <summary>
/// Searches all levels of a navigation hierarchy.
/// </summary>
All = 0,
/// <summary>
/// Searches only one level of a navigation hierarchy.
/// </summary>
SearchesOneLevel,
/// <summary>
/// <summary>
Return Type: The return type of the API is an array of the ContentData. The ContentData array contains
information such as the name of the content and its owning object.
Return Type
/// <summary>
/// This class holds content information, such as name and owning object.
/// </summary>
public class ContentData
{
/// <summary>
/// <summary>
/// Gets the owning object of the content.
/// </summary>
public string OwningObject { get; }
}
Navigation SDK
Navigation in an InTouch OMI Project (Galaxy) allows the user to leverage the existing asset model and existing
Graphic Toolbox folder structure (GTB), or build a custom hierarchy of run-time behaviors. These behaviors allow the
runtime user to perform various actions to show content, browse information, etc. The Navigation SDK is designed to
allow you to build a visible control, such as the NavTreeControl, that shows either your custom build hierarchy or
existing hierarchies in the Galaxy. The Navigation SDK is delivered as ArchestrA.Client.Navigation.dll, which is
installed with the remainder of the InTouch OMI assemblies as part of the ArchestrA IDE installation.
The main functional element of the Navigation SDK is a .NET assembly that lets you retrieve the underlying
navigation model and NavigationItems to provide an easy way to access the navigation hierarchies in your ACF apps.
The Navigation SDK exposes the following classes:
NavigationModel
NavigationItem
NavigationException
The namespace for these classes is:
ArchestrA.Client.Navigation
The assembly name is:
ArchestrA.Client.Navigation.DLL
NavigationModel
public abstract class NavigationModel
{
/// <summary>
/// Gets the default NavigationModel of the ViewApp
/// </summary>
public static NavigationModel ViewAppNavigationModel { get; }
/// <summary>
/// Gets the root item of the model
/// </summary>
public abstract NavigationItem RootItem { get; }
/// <summary>
/// Gets the collection of navigation items.
/// <summary>
/// Gets the item for the given navigation item path
/// </summary>
/// <param name="navigationItemFullPath"> Full path or URI of a particular hierarchy item
/// </param>
/// <returns> Navigation item
/// </returns>
public abstract NavigationItem GetItemBypath(string navigationItemFullPath);
/// <summary>
/// Retrieves the content available under the navigation hierarchy path, based on the the
given filter options
/// </summary>
/// <param name="NavigationHierarchyPath"> The navigation hierarchy path. This should be
something like
/// \\Home\NavigationItem1
/// </param>
/// <param name="FilterOption"> This is the filter criteria to retrieve content
/// </param>
/// <returns> Array of ContentData </returns>
public abstract ContentData[] GetContentInHierarchy(string navigationHierarchyPath,
FilterOptions filterOptions);
}
NavigationItem
This class is exposed to define how individual navigation items in the underlying ViewApp Navigation Model should appear. It
contains all required information to show a visual representation of a navigation item in various forms.
NavigationItem
public abstract class NavigationItem
{
/// <summary>
/// Gets or sets the actual name of the Navigation Item.
/// </summary>
public virtual string Name { get;}
/// <summary>
/// Gets or sets the friendly name of the Navigation Item to be shown on
/// navigation-aware control items.
/// </summary>
public virtual string Title { get;}
/// <summary>
/// Gets or sets a value indicating whether or not the Navigation Item has errors.
/// </summary>
/// <value>
/// <c>true</c> if [HasErrors]; otherwise, <c>false</c>.
/// </value>
public virtual bool HasErrors { get;}
/// <summary>
/// Gets or sets the errors for this Navigation Item.
/// </summary>
public virtual IEnumerable Errors { get;}
/// <summary>
/// <summary>
/// Gets the child item collection.
/// </summary>
/// <returns> An observable collection of navigation item that are immediate child items
of this instance.
/// </returns>
public abstract ReadOnlyNavigationItemCollection Items { get; }
/// <summary>
/// Gets the previous sibling.
/// </summary>
/// <returns>NavigationItem
/// </returns>
navigationItem public NavigationItem PreviousSibling
/// <summary>
/// Gets the next sibling.
/// </summary>
/// <returns>NavigationItem
/// </returns>
public NavigationItem NextSibling
/// <summary>
/// Gets a value indicating the path of the item in its hierarchy.
/// </summary>
public string Path
/// <summary>
/// Gets or sets a value that indicates the Access Level of the configured Nav Item.
/// </summary>
public virtual int AccessLevel { get; }
/// <summary>
/// Gets the item located at a given hierarchy path.
/// </summary>
/// <param name="fullPath"> The full or relative path of the item to be retrieved.
/// </param>
/// <returns> Requested Navigation Item
public abstract NavigationItem GetItem(string fullPath);
}
NavigationException
NavigationException
/// <summary>
/// A custom exception class that wraps the exception/error information related to the
Navigation Extension.
/// </summary>
[Serializable]
public class NavigationException : Exception
{
/// <summary>
/// Initializes a new instance of the <see cref="NavigationException"/> class.
/// </summary>
/// <param name="message">The error message that explains the reason for the
exception.
/// </param>
/// <param name="innerException">The exception that is the cause of the current
exception, or a null reference
/// (nothing in Visual Basic) if no inner exception is specified.
/// </param>
public NavigationException(string message, Exception innerException)
: base(message, innerException)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="NavigationException"/> class.
/// </summary>
/// <param name="info">The <see
cref="T:System.Runtime.Serialization.SerializationInfo" /> that holds the
/// serialized object data about the exception being thrown.
/// </param>
/// <param name="context">The <see
cref="T:System.Runtime.Serialization.StreamingContext" /> that contains
/// contextual information about the source or destination.
/// </param>
protected NavigationException(SerializationInfo info, StreamingContext context)
: base(info, context)
{
}
}
ViewApp SDK
The ViewApp SDK is the core SDK assembly. It exposes the ViewApp assembly (ArchestrA.Client.ViewApp.dll) and lets
you access InTouch OMI ViewApp features, such as displaying content and activating slide-in panes. It also contains
the language namespace, and provides access to language attributes that can allow users to localize a running
ViewApp. Localizing a ViewApp can include changing the language as well as how other settings, such as numerical
formats and time/date are rendered.
The ViewApp SDK provides access to the following content-rendering features:
ShowContent
ShowLayout
ActivateSlideInPane
ActivateSlideInPane
The ActivateSlideInPane() method is used to activate the slide-in-pane. This method has two parameters:
Control: This is the framework element that triggers the ActivateSlideInPane action. In the Navigation
hierarchy, it searches for the parent window that contains the element, and activates the slide-in pane at
that level of the hierarchy.
PanePosition: This is an enumeration with four possible values (Left, Right, Top, Bottom). This determines
which slide-in pane is activated.
ActivateSlideInPane
/// <summary>
/// Activates Slide-In Pane (Left,Right,Top,Bottom)
/// </summary>
/// <param name="control">Reference to control that was added to the pane</param>
/// <param name="slideInPanePosition">Slide-In Pane position</param>
public abstract void ActivateSlideInPane(object control, SlideInPanePosition
panePosition);
SetLayoutState
The SetLayoutState() method is used to maximize, minimize, and restore layouts when the user selects the
corresponding button. This method has two parameters:
Control: This is the framework element that triggers the SetLayoutState action. In the Navigation hierarchy, it
searches for the parent window that contains the element, and maximizes, minimizes, or restores the window at that
level of the hierarchy.
WindowState: This is an enumeration from System.Windows.WindowState. It has three values:
Normal
Minimize
Restore
CloseLayout
The CloseLayout() method is used to close the Layout window. This method has one parameter:
Control: This is the framework element that triggers the CloseLayout action. In the Navigation hierarchy, it
searches for the parent window that contains the element, and closes the layout at that level of the
hierarchy.
CloseLayout
SlideInPanePosition
The SlideInPanePosition enumeration is passed to the ActivateSlideInPane API. It has four values to set the position of
the slide-in pane:
Top
Bottom
Left
Right
SlideInPanePosition
public enum SlideInPanePosition
{
/// <summary>
/// Indicates left slide in pane
/// </summary>
Left = 0,
/// <summary>
/// Indicates right slide in pane
/// </summary>
Right = 1,
/// <summary>
/// Indicates top slide in pane
/// </summary>
Top = 2,
/// <summary>
/// Indicates bottom slide in pane
/// </summary>
Bottom = 3,
}
ViewApp Attributes
You can access references and enable or disable features through the use of ViewApp attributes. There are seven
attribute categories: Alarms, Language, Navigation, Playback (historical playback), Security, Settings, and System.
Sample Apps
The code for several sample apps is included with the SDK assemblies, and reside under the folder: C:\Program Files
(x86)\ArchestrA\Framework\AcfSdk\Samples. The sample apps are:
ContentPresenterApp: Shows graphic items from one or more selected nodes of a ViewApp navigation
model.
DocViewerApp: Provides a PDF and text file viewer. This app uses the AppConfig SDK and illustrates how to
build an app editor.
HamburgerApp: Controls the movement of a selected layout slide-in pane. During run time, the
HamburgerApp appears as a button consisting of three parallel horizontal lines.
NavBreadcrumb: Shows a user-selected sequential path through ViewApp navigation model.
NavCommon: Provides the common set of references used by the NavTree and NavBreadcrumb apps.
NavTree: Shows a hierarchical arrangement of parent and child navigation items that together represent a
ViewApp navigation model.
WebBrowserApp: Shows a full-featured, Chromium-based web browser that supports WPF apps.
Before you begin writing your own apps, we recommend that you examine these apps. To view the sample code, use
Visual Studio to open the SDKSamples.sln solution file, located in the Samples folder. Each app uses InTouch OMI
component SDKs and are commented. Use the apps as models as you build your own applications.
Initial Setup
1. In Visual Studio, create a new project.
2. Select a supported language: Visual Basic, C#, or C++.
3. Select Windows Desktop.
4. Select either WPF User Control Library or WPF Custom Control Library and press OK.
5. Select .NET Framework 4.5.1.
6. Enter a name for your new application.
Note: We recommend that you start with WPF User Control Library to create your user controls, as this may be
a simpler starting point. However, if you are comfortable creating custom controls, feel free to use the WPF
Custom Control Library.
UserControl1.xaml
<UserControl x:Class="MyOMIApp.UserControl1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300" x:Name="MyUserControl">
<StackPanel Background="{Binding Background, ElementName=MyUserControl}">
<TextBox Text="Welcome to My OMI Navigation Display App" Foreground="{Binding
Foreground, ElementName=MyUserControl}" FontSize="{Binding Fontsize,
ElementName=MyUserControl}"></TextBox>
</StackPanel>
</UserControl>
The design view of the control shows the static text in a textbox enclosed within the StackPanel.
AppManifest.xml File
Public classes are automatically exposed in your app as controls. Properties of these controls are similarly exposed.
When your app is imported into the System Platform IDE and selected by a user in the Layout and ViewApp Editors,
For each control you wish to expose for use, list any configurable properties that should be visible. A control does not
have to have configurable properties.
If no AppManifest.xml file is included, all controls and properties for each control, including those in
dependent files, will be exposed.
If an AppManifest.xml file is included that does not explicitly include controls, no controls or properties will
be exposed.
If your app includes an app editor, the AppManifest.xml file is required. If not, the AppManifest.xml file is
optional.
The AppManifest.xml file must specify the assembly name, control name(s), and configurable properties (if any) for
each control. The control name (ControlFullName) is the public class name, and is prefaced by the assembly name
(separated by a period (dot)). The structure of the AppManifest.xml file is as follows:
AppManifest Structure
<Filters>
<Control AssemblyName="ArchestrA.Apps.MyOMIApp"
ControlFullName="ArchestrA.Apps.MyOMIApp.MyControl">
<PropertyName="Configurable Property 1" />
<PropertyName="Configurable Property 2" />
<PropertyName="Configurable Property 3" />
</Control>
</Filters>
<Editor EditorFullName="ArchestrA.Apps.MyOMIApp.Editor.OMIEditor"
AssemblyName="ArchestrA.Apps.MyOMIApp.Editor">
</Editor>
Note that the EditorFile name is the AssemblyName with a "dll" suffix. The EditorFullName is the fully qualified name
of the class that implements the editor.
Example AppManifest.xml
<?xml version="1.0"?>
<AppManifest AppVersion="1.0.0">
<Filters>
<!--List all the Controls that need to be exposed to the ArchestrA IDE user to
utilize them in a View Application.
Only the controls listed here will be available for the IDE users to place them on
panes within a Layout or a ViewApp.-->
<Control AssemblyName="ArchestrA.Apps.SampleApp"
ControlFullName="ArchestrA.Apps.SampleApp.MyControl1A">
<!--List the public properties on this control that need to be exposed when user
is configuring this control in a Layout or
a ViewApp. The Property Editor within the Layout Editor and ViewApp Editor
includes these properties when this control is
selected and allows the user configure new default values.-->
<Property Name="InContext" />
<Property Name="Configuration" />
<Control AssemblyName="ArchestrA.Apps.SampleApp"
ControlFullName="ArchestrA.Apps.SampleApp.MyControl2B>
<Property Name="InContext" />
<Property Name="FontSize" />
<Property Name="Background" />
<Property Name="Foreground" />
</Control>
</Filters>
<!--If this app has an editor to edit its settings, provide the editor class and
assembly.
If there is no App Editor, leave the editor xml element empty.-->
<Editor EditorFullName="ArchestrA.Apps.SampleApp.Editor.SettingsEditor"
AssemblyName="ArchestrA.Apps.SampleApp.Editor">
<!--List any files that are only needed by the App Editor in the IDE node. These
files are available only on the IDE node,
and are not deployed to the run-time node.-->
<EditorFile Name="ArchestrA.Apps.SampleApp.Editor.dll />
</Editor>
</AppManifest>
Activities
The AppConfig framework provides the core capabilities for your editor (activity), and provides the ability to save
and close an app, to launch a window, etc. Each activity needs to know what information has to be saved in the app
and what information gets loaded into the app at run time. Configuration information is saved into the app object
itself (within the IDE), and then at run time, the configuration information is extracted from the app object and
uploaded to the run time app. When a configuration change is detected (object is dirty), the save, save and close,
and close options will be enabled within the title bar. You will have to define the file name, file format (for
example, json, xml, text file, etc.), and file location for saving the configuration information.
Keep in mind that an app editor can encompass multiple editors (activities). You can choose have each activity
create its own configuration file, or use a single configuration for all activities. The following sample illustrates how
to implement load and save in the main activity:
EditorActivityViewModelBase
You will also have to implement the EditorActivityViewModelBase class. Your main activity is derived from this class.
If you are implementing multiple activities, use the Label property to add tabs on the title bar for each activity.
Label Property
public virtual string Label
{
get { return Properties._string.Label;
}
You can customize Views and View Models as needed within your editor. You will need to add one View Model and
View for each activity, on a one to one to one basis. Only one instance of an editor that defines the App Editor UI is
required to contain all activities, Views, and View Models. You can associate the View and View Model within the
WPF framework; there are many options for doing this association. For example, to define a View Model:
Generic.xaml
<DataTemplate DataType="{x:Type omiAppEditor:EditorMainActivityViewModel}">
<view:AppEditorView />
</DataTemplate>
Read-Only Mode
The framework also exposes the read-only mode, but you must add this to your editor. You will have to add code get
the status of the app object from the UI and disable the UI in your editor if the app object is opened as read-only.
Use the isReadOnly property, which gets a value that indicates whether or not object is in IsReadOnly state.
IsReadOnly
public virtual bool IsReadOnly { get; private set; }
AppManifest.xml File
The AppManifest.xml file is a requirement if you are adding an editor for your app. See AppManifest.xml File for
additional information about this file. You must define two items in the AppManifest file:
AssemblyName: This is the same as the namespace (name of the dll, minus the dll extension).
EditorFullName: This is the fully qualified class name of the type that implements the IEditorConfig
interface. It is the namespace plus the name of the control.
AppManifest.xml
<AppManifest>
<Filters>
</Filters>
<Editor AssemblyName="ArchestrA.Visualization.MyOMIAppEditor"
EditorFullName="ArchestrA.Visualization.MyOMIAppEditor.MyOMIConfigEditor">
</Editor>
</AppManifest>
IEditorActivity Methods
public virtual void RegisterCommands()
{
ResourceDictionary icons = new ResourceDictionary() { Source =
GetResourceUri((typeof(SampleActivity).Assembly), "Resources/Icons.xaml") );
DrawingBrush comIcon1 = icons[
public virtual bool CanCloseEditor()
{
return true;
}
Using Security
You can add security to your app by adding a secure login capability. The following code sample outlines how to do
this.
SecureLoginSampleApp
namespace SecureLoginSampleApp
{
using MyViewApp = ArchestrA.Client.MyViewApp;
/// <summary>
/// Interaction logic for SecureLoginViewSample.xaml
/// </summary>
public partial class SecureLoginViewSample : UserControl
{
public SecureLoginViewSample()
{
InitializeComponent();
this.Loaded += SecuritySampleApp_Loaded;
}
private void SecuritySampleApp_Loaded(object sender, RoutedEventArgs e)
{
this.DataContext = new SecureLoginSampleVM();
SecureLoginSampleVM vm = this.DataContext as SecureLoginSampleVM;
if (vm != null)
{
vm.Initialize();
}
}
private void Button_Click(object sender, RoutedEventArgs e)
{
MyViewApp.Security.ShowLoginDialog();
}
private void Logout_Click(object sender, RoutedEventArgs e)
{
MyViewApp.Security.Logout();
}
}
}
Troubleshooting
Add a Link to the Logger
Debug a Running App
Debug an Initializing App
To Import an App
1. Assemble the App, together with all required dependencies and related files, into a folder.
2. Select Import from the Galaxy menu.
3. Select ArchestrA App.
4. Select the folder that contains the App to be imported. The contained App, along with all dependent files,
including dependent files contained in subfolders, are imported when you select OK.
5. The app appears as a new object in the GraphicToolbox when the import successfully completes named
"DisplayModule_00n," where n is 1 or the next available integer. Rename the app as needed.
The new app object can be moved to another folder in the Graphic Toolbox, deleted, or exported as an
.aaPKG file for use in another Galaxy.
To Test an App
1. Test your app by adding it to a layout and using the layout in a ViewApp.
2. When you add the app to a layout, its public properties should be visible for configuration. If you have added
an AppManifest.xml file, you should see only the public properties that are listed in the AppManifest.xml.
3. Deploy the ViewApp and open it with the Wonderware Application Manger to verify the operation of the
app in run time.
API References
The InTouch OMI SDK provides programmatic access to its component SDK assemblies and namespaces. Use the
methods and parameters that these provide to build your own InTouch OMI custom applications that can users can
configure for their ViewApps.