Advanced programming


Network-capable properties automatically distribute their values across the network in the event of a change.

All clients that have established network connections to the server and logged on to the server using a proxy component receive an automatic update of their values in the background(asynchronous communication).

"Local" properties on the other hand, work synchronously and are therefore only suitable for occasional network access.


Network-capable properties offer the possibility of so-called "property binding". The concept of property binding enables you to "connect" a property of component A with another property of component B in order to achieve automatic forwarding of value changes.

 

First, a few examples of a better understanding:

Thermometers

Suppose you have a "Thermometer" class that has the "Temperature" property and has been defined as an instance in an application tree (Component A). Since the thermometer actually exists as a physically real object and its temperature has to be transferred to iPlus, another class/instance is required which is able to read the value via bus technology, I/O cards or other interfaces (Component B). Using a configuration mechanism, this communication component (driver) can be configured so that it can read the temperature value and make it available as a network property. In the iPlus development environment in the "Bindings" tab, you can now connect the two properties using drag and drop. In more detail, this property of component B is the actual data source, because the original value comes from here and must be passed on to component A and its temperature property. So because component A cannot generate the temperature value itself and depends on this value coming from another component, the temperature property of the thermometer class is called the data target or alternate property.

Alarm distributor e-Mail

Suppose you have programmed your own classes that have an alarm count property (Component A). Whenever the counter of one of the many instances (Component A) is incremented an e-mail should be sent. Since your classes do not have mail capability and your function is completely different, you need a further Component B, in which the mail functionality is implemented and you can configure it to recipient addresses, for example. This mail component also has an alarm counting property. Whenever your value increases, an e-mail is sent. Now you have to use the iPlus development environment to connect the alarm counting properties of the many component A instances with the alarm counting property of the mail class again. Based on the previous example, you will now think that the alarm counting property of the mail class is a data target and the others are the data source. This is not the case. You must not use the flow direction of the data as a basis for the decision, but must decide which component has to keep the "original" value and which has only "copies". After all, in this example one would like all alarm counting properties of component A to always have the same value. Thus the alarm counting property of the mail class (component B) is the data source (source) and all other components B are the data target (target).

 

Source and Target Properties

The examples show that a decision must be made during the design or programming phase as to which property is a source and which property is a target or deputy. Therefore you have to use two other attribute classes instead of the "ACPropertyInfo" attribute class you already know:

Or if you define the properties "virtual" via the development environment, you have to select the checkbox "Network capable" and optionally "Data proxy" if you want the property to be a data target.

You can read more about the concept of data binding at Wikipedia or msdn. In contrast to WPF data binding, data distribution only takes place within the data model and not to the user interface. In addition, the data is not only distributed within the same application domain, but is also network transparent.


The following figure explains how data distribution is technically solved:

 

The two rounded rectangles on the right are real components that have been instantiated on the server side. The rectangles with the dashed lines on the left represent proxy objects on the client side. 

At the bottom right is component A which has a  source property (S) and is connected to the target property (T) of component B at the top right. The green "binding" line symbolizes the property binding stored in the ACClassPropertyRelation table that has been defined using the iPlus development environment.

On the client side, the properties at the proxy instances are displayed with S'  and  T' on the left.

 

Change in value in source S

If the value in source S changes, the following data flows occur:

  • (A) The value is transferred to the data deputy T.
  • (B) The value change at T results in a network transmission being asynchronous to the proxy property T'. If several clients in the network have "subscribed" to this component, of course all others are also updated.
  • (E) Network transmission to the S' proxy property is also asynchronous.

 

Change in value in target T

If the value in target T changes, the following data flows occur:

  • (B) Network transmission to the proxy property T' (also to other clients).
  • (D) The value is transferred to source S.
  • (E) Network transmission to proxy property S' (also to other clients).

 

Value change in proxy source S'

If the value on the client side changes to source S', the following data flows occur:

  • (F) The value is transferred to the real source property S via the network.
  • (E) Source property S triggers a network transfer to proxy property S' from other clients who have subscribed to this component.
  • (A) The value is transferred to the data substitute T.
  • (B) Network transmission to the T' proxy property (also to other clients).

 

Change in value in proxy target T'

If the value on the client side changes to data deputy T', the following data flows occur:

  • (C) The value is transferred to the real target property T via network.
  • (B) Target property T triggers a network transfer to proxy property T' from other clients who have subscribed to this component.
  • (D) The value is transferred to source S.
  • (E) Network transmission to proxy property S'.

The following figure shows a more complex scenario where there are two servers:

 

The first example was changed so that component B is located in a different application tree (project) (see server B on the screen). A second user was created in the user management and this second application tree (project) was assigned as server. The first project in which component A is located was assigned to the second user as a client. The first user still starts component A as server (see Server A on the screen). You can read more about the project assignment to a user in the tutorial

As a result of this configuration, Server B instantiates component A as proxy.

  

Change in value in source S

If the value in source S changes, the following data flows occur:

  • (A) The value is transferred to the data deputy S' on server B.
  • (B) Since the target property T is now bound to data deputy S', T is updated.
  • (C) The value change in T results in a network transfer to the proxy property T' on the client (also to other clients).

 

Change in value in target T

If the value in target T changes, the following data flows occur:

  • (C) Network transmission to the proxy property T' (also to other clients).
  • (E) The value is transferred to the proxy source S'.
  • (F) Network transmission back to server A to the real property S.

 

Change in value in proxy target T'

If the value on the client side changes to data deputy T', the following data flows occur:

  • (D) The value is transferred to the real target property T via the network.
  • (E) The value is transferred to the proxy source S'.
  • (F) Network transmission back to server A to the real property S.

Declaration via IACContainerTNet<T>

Unlike the declaration of local properties, network-enabled properties cannot be declared like normal C# properties. Instead, you must declare a property with the generic type IACContainerTNet<T>.

 

ACPropertyBindingTarget- and ACPropertyBindingSource attribute class

Instead of using the ACPropertyInfo attribute class, as is the case with local properties, you must now use ACPropertyBindingTarget and ACPropertyBindingSource attribute classes. 

 

 


The following example shows how to work with network properties..

  • Lines 1-6 of the program assume that you are in the class where the "TareWeight" property is defined (this).
  • Lines 8 of the program assume that you are in a different instance, but in the same application domain.
  • Lines 9 of the program assume that you are in a different application domain or on a different computer and that the "TareWeight" property is accessed via the network.

 

Persistance behavior

In the example above, a StoredTareWeight property has been defined. The last parameter of the ACPropertyBindingSource constructor specifies that the value of the property is to be persisted in the database. This means that within the ValueT setter method call, the value is automatically stored (row 7). If this instance is created again the next time ValueT is booted, ValueT receives the value that was last saved in the database during initialization.

Read more in the chapter "Persistance".


In the previous sections, two scenarios were used to explain how property changes are transported between client and server and target and source properties. As a developer, you now want to know

  • who triggered this property change,
  • where it took place,
  • Perform validations and manipulate the value change before it is finally saved in the source property,
  • and cancel the forwarding somewhere along the entire transport route (Target-Proxy->Target->Source-Proxy->Source) at a specific point.

The interface IACPropertyNetServer provides the event ValueUpdatedOnReceival for this purpose. It is comparable with the combination of

but it contains much more information due to the network capability of the system.

See the following example:

 

The event handler ACPropertyChangedEventHandler has the following signature:

public delegate void ACPropertyChangedEventHandler(object sender, ACPropertyChangedEventArgs e, ACPropertyChangedPhase phase)

 

ParameterDescription
object senderReference to the property that called this event handler.

ACPropertyChangedEventArgs e

Ableitung von PropertyChangedEventArgs.
Has the property public IACPropertyNetValueEvent ValueEvent which has the following properties:

  • Guid RequestID: Unique ID generated by the caller/author (first property to execute the value change). The ValueEvent is then passed along the entire transport route to the end point with the same RequestID. If the value change at the end point is successful, a new event is generated and distributed in the network (broadcast). Through the distribution, the caller can then wait in his ACPropertyChangedEventHandler for his RequestID to evaluate what happened to the change request.
  • bool Handled: If Handled is set to true, this event is no longer forwarded to the next property (on the route to the endpoint). In this case a new IACPropertyNetValueEvent is generated, the EventType property is set to RefusedRequest and distributed in the network or sent back to the caller.
  • string Message: Message that can be generated from the rejecting property to inform the sender of the reason.
  • string ACUrl: Address of the ACComponent
  • string ACIdentifier: Name/ID of the property generated by the event.
  • bool IsRequestedValueStillValid: Is "true" if the requested value change is still valid. Is false if another proxy has simultaneously created another request or an internal change to the source property has occurred. In this case, the value is obsolete.
  • EventTypes EventType: The reason why this event was generated.
    • Request,
    • RefusedRequest,
    • Response,
    • ValueChangedInSource,
    • FetchValue
  • EventRaiser Sender: Describes who the caller/author was who generated this event.
    • Source, 
    • Target,
    • Proxy
  • object InvokerInfo: Contains additional information about driver-specific objects (e.g. ValueQT from OPC or S7TCPItem...) that have changed the value.
  • object ChangedValue: New value to which the property is to be or was set.
  • bool ForceBroadcast: Is "true" if the property value has not been changed, but the event is to be transported to the end point.

ACPropertyChangedPhase phase

If "BeforeBroadcast", then the new value "ChangedValue" has not yet been accepted. Setting the Handled property to true does not change the value.

If "AfterBroadcast", then the new value "ChangedValue" was accepted (ValueT) and transferred to the communication service so that the clients in the network are updated.

Important: The EventHandler is always called twice in a row!

  • The first itme before the new value is transferred to the property (phase = BeforeBroadcast).
  • The second time after the new value has been accepted (phase = AfterBroadcast). 

Property bindings defined by the iPlus development environment are stored in the ACClassPropertyRelation table with the ConnectionTypeIndex = 11 (Global.ConnectionTypes.ConnectionPhysical). During the initialization phases (ACInit und ACPostInit), these table entries are read and the properties are bound together.

Binding properties via the iPlus development environment can be very time-consuming if you have to bind many properties. There are two possible solutions:

  1. You program your own business object or a plug-in for the iPlus development environment that automatically makes entries in the ACClassPropertyRelation table via database access.
  2. or you dynamically bind the source and target properties during the initialization phase of your ACComponent class. This is explained in more detail in the following code example:

 

Always after ACPostInit()!

In line 2. BindMyProperties() is made after calling base.ACPostInit(). Only then it is guaranteed that all instances are available and a dynamic binding is possible.

 

Interface IACPropertyNetTarget

In the UML diagram of the properties section it can be seen that for properties provided by the [ACPropertyBindingTarget] another property class is used by the framework that implements the interface IACPropertyTarget. Usually an instance of the class ACPropertyNetTarget<T> is generated here. The IACPropertyTarget provides a property "Source" which can be used to query whether a source property is already bound (see line 3).

 

Interface IACPropertyNetSource

Properties that are provided with the [ACPropertyBindingSource] are instantiated using the ACPropertyNetSource<T> class, which implements the IACPropertySource interface. The IACPropertySource provides a property "Targets" to query whether specific target properties are bound (see line 5).

 

Dynamic Binding

To bind a target property to a source property, use the BindPropertyToSource() method, which is available with two overloads:

public PropBindingBindingResult BindPropertyToSource(IACPropertyNetSource acPropertySource, PropBindingMode bindingMode = PropBindingMode.BindAndBroadcast)

This method only binds properties that are of the same data type (type of ValueT). If the data types are different, PropBindingBindingResult.NotCompatibleTypes is returned.

 

public PropBindingBindingResult BindPropertyToSource(IACPropertyNetSource acPropertySource, 
out IACPropertyNetTarget newTarget, out string message,
bool bindInDBIfConverterNeeded = true, PropBindingMode bindingMode = PropBindingMode.BindAndBroadcast)

This method first calls method (a). If the data types are incompatible, the method generates either

  • a new target property of the class ACPropertyNetTargetConverter<T,S> and replaces the current reference (the method returns PropBindingBindingResult.TargetPropReplaced)
  • or it modifies/repairs the data type of the source property. In this case, the iPlus service must be restarted for this change to become active. You can recognize this by the return value PropBindingBindingResult.TypeOfSourceWasChanged.

Changing the ValueT property triggers the ValueUpdatedOnReceival event. The ACPropertyChangedEventArgs class contains some information about the originator, but sometimes this information is not sufficient. For this purpose the property object InvokerInfo is provided in which further individual information is transmitted. This makes sense especially if you are developing drivers (OPC, OPC-UA, Modbus...) and want to transfer driver specific information.

In this case, you should not just set the ValueT property like this, but instead use the overloaded methods for a change in value: