Advanced programming


In this chapter you will learn how to program so-called process applications with iPlus. A process application is a customer end solution created using the iPlus development environment with which business, production or other processes of a company or a technical system are mapped.

The basis for this are application definitions and application projects in which various classes are declared and instantiated that are based on ACComponents.

The following class diagram is an extension of the ACComponent class diagram  and represents an excerpt from the class library with a focus on industrial systems and machines:

 

In this chapter, the focus is on classes, which mostly represent a physical object in reality and are configured in application trees. When the iPlus service is started, these classes are instantiated and represent the overall physical model. In order to be able to fully describe and control an overall technical system, non-physical elements such as functions or other logical objects are also required. These are also configured in the application trees and are instantiated immediately when they are started. We speak of so-called static instances because they are not loaded into the model "just in time" during runtime. The opposite are dynamic instances which will be discussed in more detail in the next chapter "Workflow classes".

Classes the

  • are statically instantiated are derived from the base classes PAClassPhysicalBase and PAProcessFunction and classes that
  • are dynamically instantiated are derived from PWBase .

All process application classes are alarm-capable and are therefore indirect derivatives of "gip.core.autocomponent.PAClassAlarmingBase". 

If a process application class is to represent a physical object, then it is indirectly derived from "gip.core.PAClassPhysicalBase". Otherwise, if it is a logical object (immaterial), then the class is indirectly derived from "gip.core.autocomponent.PABase".


The most primitive variant of a physical object is a module (class " gip.core.autocomponent. PAModule" ). The term is derived from the terms "Control Module" and "Equipment Module" from the "DIN EN 61512" standard. 

So if you want to map electronic components or assemblies, derive from this base class. In the assembly "gip.core.processapplication" some components are already predefined:

 

Sensors

The basic class PASensorBase is used for sensors . Sensors are then differentiated into digital sensors ( PAESensorDigital ) and analog sensors ( PAESensorAnalog ).

Digital sensors

  • PAEContactor : Motor protection switch
  • PAESafetyRelay : protection relay
  • PAEEmergencySwitch : emergency stop switch
  • PAEJamSensor : Silencer
  • PAEMaterialSensor : Materialmelder
  • PAEMisalignment : misalignment monitor
  • PAERotationControl : Wheelbarrow
  • PAEThermistor : thermal motor protection

Analog sensors 

  • PAEThermometer: Thermometer
  • PAEHygrometer : humidity sensor
  • PAEAmmeter : Body measuring device
  • PAEScaleGravimetric: Gravimetrische Waage
  • PAEScaleVolumetric : Volumetric Libra

 

Control modules

Control modules electrical components that can be controlled. A distinction is made between actuators ( PAEActuatorBase ) or drives ( PAEDriveBase ). 

Actuators

  • PAEActuator1way : one-way actuator
    • PAEActValve : one-way valve
    • PAEActSlider : slider
    • PAEActFlap : flap
  • PAEActuator2way : two-way actuator (one input, two outputs)
    • PAEActFlap2 : two-way flap
    • PAEActValve2 : two-way valve
  • PAEActuator1way_3pos : 1-way actuator with 3 positions
    • PAEActDosingSlider : Dossier files
    • PAEActValve_3pos : Dosing valve coarse / fine
  • PAEActuator2way_In : two-way actuator (two inputs, one output)
    • PAEActDiverter : two-way diverter
    • PAEActValve2_In : Two-way valve without basic position
  • PAEActuator3way : three-way actuator
    • PAEActValve3 : three-way valve
    • PAEActValve3_3Flange : three-way valve with three flanges
  • PAEActuator2way_3pos : two-way actuator with basic position
    • PAEActValve2_3pos : two-way valve with basic position
  • PAEActuator2way_1plus2 : Two-way actuator with 2 positions simultaneously
    • PAEActValve2_1plus2 : Two-way valve with 2 positions at the same time
  • PAEActuator2way_Analog : Two-way actuator analog
    • PAEActMixingValve : Mixing valve
    • PAEActValve2_Analog : Mixing valve 

Drives

A distinction is made between motors with a start-up circuit ( PAEEMotorStartCtrl ) or frequency-controlled motors ( PAEEMotorFreqCtrl ).

  • PAEEMotor1D : Motor with one direction of rotation
  • PAEEMotor1D2P : Motors with one direction of rotation and 2 poles 
  • PAEEMotor2D : Motor with two directions of rotation
  • PAEEMotor2D2P : Motors with one direction of rotation and 2 poles
  • PAEEMotorFreq1D : Frequency- controlled motor with one direction of rotation
  • PAEEMotorFreq2D : Frequency- controlled motor with two directions of rotation

According to the composition principle , modules can be recursively combined to form larger assemblies. Larger assemblies such as a machine are not just physical objects, they have a purpose. They provide functions so that production processes or processes in general can be carried out. These are therefore called "process modules " and the base class is " gip.core.autocomponent. PAProcessModule ". Process modules consist of a collection of process functions ( PAProcessFunction ) which are described below. 

Process functions appear as asynchronous methods on a process module, which are usually started by workflow classes. PAProcessModule implements the IACComponentTaskExec interface so that these method calls take place in a standardized way .

However, asynchronous calls may only be made if the process module has first been assigned by a workflow group (read the section " Runtime behavior and physical model "). The "allocation" of a process module is carried out by the use of the service point Semaphore:

[ACPropertyPoint(true,1)]
public ACPointServiceACObject Semaphore { get; }

The standard capacity of the semaphore = 1. This means that a maximum of one workflow group can occupy the process module or resource at the same time. You can set a different capacity by overwriting the method  in your derivation.public virtual uint OnGetSemaphoreCapacity()

There are various derivations from PAProcessModule for the MES extensions in the assembly " gip.mes.processapplication ":

  • PAProcessModuleVB : A process module that can handle application data (production order, picking order, ...). End users interact with process modules via the user interface in order to access the application data and manage the data using business objects.
  • PAMSilo & PAMTank : An extension of  PAProcessModuleVB to manage containers and their stock.
  • PAMIntermediatebin : intermediate container
  • PAMHopperscale : container scale
  • PAMParkingspace : parking space
  • PAM loading station : filling station or receiving point
  • PAMBeltscale: Bandwaage
  • Many other process engineering objects ...

 


The " gip.core.autocomponent. PABase " class has the ACState property to describe the current process state in which the instance is currently. A change in status results in the corresponding status-dependent method being called. The data type of the ACState property is " gip.core.autocomponent. ACStateEnum " and it is based on the  ISA-S88 standards:

public enum ACStateEnum : short
{
SMIdle = 0,
SMStarting = 100,
SMRunning = 200,
SMCompleted = 300,
SMResetting = 400,

SMPausing = 210,
SMPaused = 211,
SMResuming = 212,

SMHolding = 220,
SMHeld = 221,
SMRestarting = 222,

SMStopping = 310,
SMStopped = 311,

SMAborting = 320,
SMAborted = 321,

SMBreakPoint = 90,
SMBreakPointStart = 91,
}

You can read about the possible state transitions in the "Process control" chapter . The classes derived from PABase do not necessarily have to support all states and state transitions . Workflow classes that are derived from PWBase usually only use some of the ACState states. Functions that are derived from PAProcessFunction mostly use all states. Let's take a look at how to implement process functions below:


Before reading this section, familiarize yourself with the following concepts:

  1. Status-dependent methods
  2. Asynchronous methods
  3. Interface IACComponentTaskExec
  4. Physical model from the user's point of view .

PAProcessFunction is an abstract class. You need to derive them in order to use them. PAProcessFunction is programmed in such a way that it mainly consists of virtual methods and properties that can be overwritten if necessary in order to change the standard behavior. However, some of them have to be overwritten. Which these are is explained below using the example code.

 

Statusmethoden

For every ACStateEnum value that the ACState property can take, there is a corresponding status method :

public virtual void SMStarting()
public virtual void SMRunning()
public virtual void SMCompleted()
public virtual void SMResetting()
public virtual void SMPausing()
public virtual void SMPaused()
public virtual void SMResuming()
public virtual void SMHolding()
public virtual void SMHeld()
public virtual void SMRestarting()
public virtual void SMAborting()
public virtual void SMAborted()
public virtual void SMStopping()
public virtual void SMStopped()

These virtual methods are called either when the status changes or cyclically at one-second intervals. The cyclic call is activated by calling the "PABase . SubscribeToProjectWorkCycle ()" method and deactivated by the" PABase . UnSubscribeToProjectWorkCycle () method". PAProcessFunction uses these methods if an error has occurred so that a cyclical check is made to see whether the error status has been corrected in the meantime. UnSubscribeToProjectWorkCycle () is then called so that the processor is not unnecessarily loaded when there is nothing to do . If you want to monitor such error states in your derivation at cyclical intervals, then use these two methods as well. The cyclic calls are made by the PABase class in the DoWork () method  . It reads the ACState variable and looks in the method list, whether there is a method with the same name. If the method is found, then this is called. In the method list only the methods are listed that start withACMethodState attribute  class and the IsPeriodic property is set to true . This is the case with the methods listed above. Example:

[ACMethodState("en{'Starting'}de{'Startend'}", 20, true)]
public virtual void SMStarting()

 

Transitions-Methoden 

Changes of state occur through so-called "transitions" , which are either executed automatically in the background or through UI interaction in which the user calls one of the transition methods:

public virtual void Pause()
public virtual void Resume()
public virtual void Hold()
public virtual void Restart()
public virtual void Abort()
public virtual void Stopp()
public virtual void Reset()

[ACMethodAsync("Process", "en{'Start'}de{'Start'}", (short)MISort.Start, false)]

public virtual ACMethodEventArgs Start(ACMethod acMethod)

The start method differs from the other transition methods in that it is an asynchronous method for starting the process function at all.

The call of transition methods is secured by the corresponding IsEnabled method so that invalid state transitions do not take place. Which state transitions are permitted is defined using state transition tables. The state transition table for ACState is in the abstract base class  gip.core.autocomponent. PAFuncStateConvBase implemented.

 

State transition table PAFuncStateConvBase

Two static methods are defined in PAFuncStateConvBase with which the standard state transition table can be queried:

public static ACStateEnum GetDefaultNextACState(ACStateEnum acState, string transitionMethod = "")
public static bool IsEnabledTransitionDefault(ACStateEnum acState, string transitionMethod, PAProcessFunction paProcessFunction)

GetDefaultNextACState () returns the next subsequent state, depending on the current state transferred in the "acState" parameter. The second optional parameter specifies which transition or transition method is called. The names of the transition methods are declared in the constants of the static class ACStateConst:

ACStateConst.TMStart, ACStateConst.TMRun, ACStateConst.TMPause, ACStateConst.TMResume, ACStateConst.TMHold, ACStateConst.TMRestart, ACStateConst.TMAbort, ACStateConst.TMStopp, ACStateConst.TMReset

If the parameter "transitionMethod" is left blank, returns the standard successor state. Otherwise the next state that will occur when the corresponding transition method is called. 

The "IsEnabledTransistionDefault ()" method returns which transition method may be called in a certain state.

 

Individual state transition table

If you want to program a different state machine or you have connected an external system (e.g. via a PLC or OPC connection) that uses other variables with which another state machine is implemented and this must be transferred to the iPlus state machine, then route Deselect the PAFuncStateConvBase class and add your class as a child component of the PAProcessFunction. The following methods must be implemented in your " converter class" :

public abstract ACStateEnum GetNextACState(PAProcessFunction sender, string transitionMethod = "");
public abstract bool IsEnabledTransition(PAProcessFunction sender, string transitionMethod);
public abstract MsgWithDetails SendACMethod(PAProcessFunction sender, ACMethod acMethod);
public abstract PAProcessFunction.CompleteResult ReceiveACMethodResult(PAProcessFunction sender, ACMethod acMethod, out MsgWithDetails msg);

A process function calls the instance method "GetNextACState ()" implemented by you instead of the static method "GetDefaultNextACState" and the instance method" IsEnabledTransition ()" instead of the static method " IsEnabledTransistionDefault ()".

In the SMStarting state, the basic implementation calls the " SendACMethod ()" method so that the parameters are sent to the external system. In the SMCompleted state, however, "ReceiveACMethodResult ()" is called to query the result from the external system. You must also program these two methods in your converter class .

Converter classes usually have further network-compatible destination properties declared, which in turn are linked to source properties of communication driver classes by property binding. These properties basically reflect the "state machine of their own standard". Program your converter class event- oriented so that you react to change events of these properties and transfer them to the ACState state machine and set the CurrentACState property of the parent process function (ParentACComponent) directly.

 

Example

The following program code was taken from the sample project, which you can download from the start page, in order to be able to understand the steps how to implement your own process function:

 

  1. Derive from PAProcessFunction. The ACClassInfo attribute class must be constructed as follows:
    1. Use Global.ACKinds .TPAProcessFunction to tell iPlus that it is a process function.
    2. "Global.ACStorableTypes .Required" must be used because, for example, the ACState property can be persisted and the state must be restored when the service is restarted.
    3. Reference the associated workflow class that is compatible with this process function. In this example it is "PWOrder .PWClassName" which you will get to know as an example in the following chapter (PWNodeProcessMethod) .
  2. Declare the parameter and return list of the virtual method (ACMethod) that is transferred when the start method is called asynchronously. Finally, generate an instance of ACMethodWrapper to announce the virtual method to the iPlus runtime by calling "RegisterVirtualMethod ()".
  3. Declare an Execute helper for the static calls by passing the static Execute handler as a delegate to the RegisterExecuteHandler () method.
  4. Override the start method and publish it using the  ACMethodAsync attribute class .
  5. From this moment on, a process function is fully programmed and can be used in the iPlus development environment. However, the actual program code for what the function should actually do is still missing. This is why the SMRunning method has been overwritten in this code example and, for demonstration purposes, it waits for three cyclic calls because it was first activated with "SubscribeToProjectWorkCycle" and then the cyclic processing is deactivated with "UnSubscribeToProjectWorkCycle".
  6. In this step the actual functionality is programmed. In this example, the actual purpose is to write "order data" to a file that has been transferred by the asynchronous caller (workflow class) in the "Content" parameter. Because writing a file could take a long time, this writing process is transferred to the DelegateQueue of the root ACComponent ( application manager ). This means that the calling thread (cyclic processing) is not blocked and other functions are then used immediately.
  7. In the last step, you bring the state machine into the "SMCompleted" state. When the auxiliary property  ACStateConverter not "zero" is , then you have added a separate converter class in the application tree as a child instance. In this case, your converter class decides what the next state will be - this could possibly also be a state other than "SMCompleted". When the auxiliary property  ACStateConverter "zero" is the default implementation is used and SMCompleted returned.

Finally, an important note : Always override the "SMIdle ()" method to reset your private field values. In the SMIdle state, a function must always be brought to the basic state - as it was originally created in the heap when it was generated !