Advanced Configuration

This chapter explains how the various functionalities and features of the Trend can be further customized.

Trend Ruler Window Customization

The trend ruler window is a customizable panel ("trendRulerPanel.pnl") which is located in the /panels directory of your WinCC OA installation. The panel provides a predefined implementation of how to display values and react to specific events. This code needs to be adjusted or extended to match the required behavior of your project.

The font sizes of the popup panel text are hard coded inside of the panel and can only be changed there. By default, the font size 12 is used for text and 16 is used for values.

Using the $DP "$floating" defines if the panel is opened as free floating element (=TRUE; default, including a window title bar) or as a ruler popup. This can also be specified dynamically by using the "floatingRulerWindow" property of the trend. With a floating panel, the last position is saved and used when the panel is opened again.

The public function "rulerChanged" of the panel can be used to react to changes (add, remove, move, etc) to the ruler and to implement the logic of the panel. Within the function, the displayed content of the panel can be updated accordingly.

public rulerChanged(shape theTrend, int area) synchronized(table)
Note: The function rulerChanged is automatically triggered every 500ms, even if there were no changes to the ruler.

Note that following information is required to display the panel:

  • Date/Time-stamp
  • Value of the intersection point (The function "RulerValue" must be available!)
  • Color and/or marker of the curve
  • Event(area) description text (Must be implemented by the user!)
  • Alarm description

Only one trend ruler panel (trendRulerPanel.pnl) can be defined for your project, but for different display options additional custom panels can be loaded using the addSymbol() function from within the trendRulerPanel.pnl.

Trend Ruler Icon

To display an icon for the ruler, the trend uses the "trendRuler_X.png" pictures inside of the /pictures directory, where X represents the corresponding ruler (starting with 1).

Please note that the usage of multiple rulers must be activated using the trend property "maxRulerCount".

Event Curve

The event curve can be used to display specific events or time spans that should be clearly visible inside of the trend curves. The event curve displays the time stamp or time frame in which a specific event was triggered (e.g. changes to values, time or state). For the point in time a horizontal (or vertical for the Vertical Trend) line is displayed within the trend.

The curve type can either be set using the trend configuration panels or by using the trend property "curveType".

When using the event curve, the following notes should be considered:

  • The event line of an event curve is drawn as a percentage of the total plot area, where "min" and "max" define the starting and end percentage of the line. For example, min = 10, max = 40 will result in an event line starting at 10% and end at 40% of the available plot area, starting from the bottom plot border.
  • Multiple events can be stacked and displayed accordingly. This allows an easier distinction between overlapping time ranges.
  • To display a background color for an event range the curve filling must be set, e.g. "fill to bottom" or "fill to refValue".
  • The filling of an event curve is displayed between the "on" and "off" state of a curve. The "off" value was previously defined as "0.0". This was changed to use the curve defined "ref.value" property instead. In the Trend configuration panel in the GEDI this is referred to as "fill ref.value". The default value remains "0.0", but this can be changed in the Trend configuration panel. The value is only used when the selected fill type is not "none".

    CAUTION: In case another ref.value than "0.0" was previously defined, the event curve display will now look different.

    Basically the events should follow the order "on","off","on", etc. but it is possible to follow up on an "on" trigger with another "on" trigger. In this case the event must have a different state to mark, e.g. an invalid visualization.

    An "off" trigger followed by another "off" trigger is displayed as a single line event.

    An "on" event without closing "off" event is continuously drawn until the next "off" trigger occurs.

  • It is recommended to disable the Y-axis of an event curve as it is not used anyway.

Translation of the right click menu of the trend

To translate the right click menu of the trend, translate the files of the UI. For more information see chapter Translation of UI Entries.

Event Curve using string DPEs/JSON

The event curve can also be used to display string DPEs. In this case, the displayed values are determined with following behavior:

  • If the string of the DPE contains a JSON format then the "value" key of the string is displayed (see JSON format below)
  • If the string does not contain JSON, the value is determined as with a CTRL string. A string that contains either "0", "FALSE" or "false" is considered as FALSE, everything else is considered as TRUE.

JSON Structure

The curveValue can now also be a string attribute in JSON format. The following keys are used by the event curve:

  • "value" - any datatype; A value > 0 is considered as TRUE and marks an "on" event (see description above)
  • "text" - string; Text that should be displayed on the event line
  • "alignment" - string; The alignment relative to the event line for text and icon. The following alignment flags are available:
    • AlignLeft - Align to the left of the line
    • AlignHCenter - Align to the horizontal center of the line
    • AlignRight - Align to the right of the line
    • AlignTop - Align to the top of the line
    • AlignVCenter - Align to the vertical center of the line
    • AlignBottom - Align to the bottom of the line

    Horizontal and vertical flags can be combined using the | character, e.g. "AlignTop|AlignLeft".

    When using a vertical trend, the flags remain the same used differently, e.g. "AlignTop" is used to create an alignment to the right side or "AlignVCenter" is used to create an alignment to the horizontal center of the line.

    This behavior is used to keep the compatibility of the DPE in both orientations.

  • "icon" - string; File name of the icon that should be displayed. The path must be relative to the /pictures directory.

Example

Following example code (Trend - Initialize script) fills an empty trend with multiple event curves to give a simple demonstration of a production line, see figure Trend - Event Curve Example.

Note: Please note that for this example, all default curves of the trend must be manually removed to get a similar visual representation.
// [myTrend] [1] - [Initialize] 
  main() 
{ 
  //Variable Definitions and Declarations 
  time t = getCurrentTime(); 
  const bit64 INVALID = "1000001100000000000000000000000000000000000100000000000100100001"; 
  //Trend Visible Area Configuration 
  this.scrollPercent(5); 
  this.visibleTimeRange(0,t-1650,t+200); 
  
  //Dynamically added the Event Curves ProductionLine, PreProduction, ProductionEvents 
  this.addCurve(0,"ProductionLine"); 
  this.addCurve(0,"PreProduction"); 
  this.addCurve(0,"ProductionEvents"); 
  this.curveType("ProductionLine",4); 
  this.curveType("PreProduction",4); 
  this.curveType("ProductionEvents",4); 
  
  this.curveLegendName("ProductionLine", "Production"); 
  this.curveLegendName("PreProduction", "Pre-Production"); 
  this.curveLegendName("ProductionEvents", "Events"); 
  
  //Display Height/Area of the Event Curves 
  this.curveMin("ProductionLine",15.0); 
  this.curveMax("ProductionLine",60.0); 
  this.curveMin("PreProduction",15.0); 
  this.curveMax("PreProduction",60.0); 
  this.curveMin("ProductionEvents",15.0); 
  this.curveMax("ProductionEvents",90.0);
   
  //Design Settings: Colors, Line Types, Fillings, etc. 
  this.backCol("SiemensStone35"); 
  this.curveFillType("ProductionLine", "[solid]"); 
  this.curveFillType("PreProduction", "[hatch,[cross,10,horizontal]]"); 
  this.curveFillType("ProductionEvents", "[solid]"); 
  this.curveLineType("ProductionLine", "[solid,oneColor,JoinMiter,CapButt,3]"); 
  this.curveLineType("PreProduction", "[solid,oneColor,JoinMiter,CapButt,3]"); 
  this.curveLineType("ProductionEvents", "[solid,oneColor,JoinMiter,CapButt,3]"); 
  this.curveColor("ProductionLine","SiemensNaturalBlueDark"); 
  this.curveColor("PreProduction","SiemensSnow"); 
  this.curveColor("ProductionEvents","SiemensNaturalYellowLight"); 
  this.curveFillColor("ProductionLine", "SiemensNaturalBlueLight"); 
  this.curveFillColor("PreProduction", "SiemensSnow"); 
  this.curveFillColor("ProductionEvents", "SiemensNaturalYellowLight");
   
  //mandatory for displaying the Event Curves! 
  this.curveFilled("ProductionLine",1); 
  this.curveFilled("PreProduction",1); 
  this.curveFilled("ProductionEvents",1); 
  
  //Events in displayed order 
  //Pre-Production 
  this.curveValue("PreProduction", "{\"value\":1, \"text\":\"Pre-Production Cycle\",\"icon\":\"scriptWriteOnly\",
                    \"alignment\":\"AlignLeft\"}", t-1400,0); 
  this.curveValue("PreProduction", "{\"value\":0}", t-1200,0); 
  
  //End of Pre-Production and Begin of "Production" 
  this.curveValue("ProductionEvents", "{\"value\":0, \"text\":\"Start Production\",\"icon\":\"vision\",
                    \"alignment\":\"AlignLeft\"}", t-1200, 0); 
  this.curveValue("ProductionLine", "{\"value\":1}", t - 1200, 0); 
  
  //Batch - Events 1-3 
  this.curveValue("ProductionEvents", "{\"value\":0, \"text\":\"Batch 1\", \"icon\":\"trendRuler_1\"}",t-1000, 0); 
  this.curveValue("ProductionEvents", "{\"value\":0, \"text\":\"Batch 2\", \"icon\":\"trendRuler_2\"}",t-750, 0); 
  this.curveValue("ProductionEvents", "{\"value\":0, \"text\":\"Batch 3\", \"icon\":\"trendRuler_3\"}",t-500, 0); 
  
  //Error Event 
  this.curveValue("ProductionEvents", "{\"value\":0, \"text\":\"Error\", \"icon\":\"disconnected\"}",t-400, 0); 
  this.curveValue("ProductionLine", 1.0, t - 400, INVALID); 
  
//Sets the current value invalid. Design can be changed by using the Config Entry "trendStatusPattern" 
  this.curveValue("ProductionEvents", "{\"value\":0, \"text\":\"Error Resolved\",\"icon\":\"apply_16\"}", t-300, 0); 
  
  //Batch - Event 4 
  this.curveValue("ProductionEvents", "{\"value\":0, \"text\":\"Batch 4\", \"icon\":\"trendRuler_4\"}",t-100, 0); 
  this.curveValue("ProductionLine", "{\"value\":1}", t-300, 0); 
  
  //End of Production Cycle 
  this.curveValue("ProductionLine", "{\"value\":0}", t, 0); 
  this.curveValue("ProductionEvents", "{\"value\":0, \"text\":\"End Production\",\"icon\":\"exit\"}", t, 0); 
}
Figure 1. Trend Event Curve Example

Viewport/Preselection Trend

For selecting and zooming into a specific time range of the trend curve, a new viewport feature is available. To open the viewport, the function "areaViewportTimeRange" can be used.

When using the viewport widget, the following notes and restrictions must be considered:

  • The order of linked areas cannot be changed for the viewport widget.
  • For displaying the ruler pop-up panel inside of the main area instead of inside of the viewport area, the pop-up panel must be customized. The function call "setPosition(area);" must be changed to "setPosition(<main display area>);".
  • The viewport area as well as the main trend area must be linked using the function "linkAreas". Consider that first the main trend area ID and afterwards the viewport area ID must be used: "linkAreas(<Main Area ID>, <Viewport Area ID>);"
  • The design of the viewport widget can be changed using CSS. The available classes and examples can be found here, respectively here.
  • Consider that extensive zooming into the trend may cause the viewport sliders to disappear, as they selected time range cannot be displayed within the available amount of pixels.
  • The Scrolling Mode of the Viewport Widget can be defined with the property "areaViewportPageScrollMode".
  • By using the property "areaMargins" the margin of the viewport can be changed to use a e.g. a different width compared to the trend area.
Figure 2. Trend including a Viewport Widget below

Overlay Text

The property "areaPlotOverlayText" allows to place a custom text and content over an area of the trend. HTML can be used to place fully designed icons and captions for the area.

Interaction Possibilities Configuration

To configure the allowed interactions with the trend elements, the properties "areaInteractionFlag","areaInteractionFlags","areaPlotInteractionFlag" and "areaPlotInteractionFlags" are available. They can be used to define whether panning, zooming or the context menu are available.

Displayed Area Range Restriction

To restrict the maximum displayed time span of an area, the property "areaMaximumTimeSpan" can be used.

Trend display with gaps

When using RDB archiving, a display gap in a trend can occur between the historical data and the current data. This gap can occur when data (a few seconds ago) is being stored only in the RDB manager's local buffer at the moment and is not being flushed to the Oracle database.

The trend shows values until the last data flush from the WinCC OA buffer to Oracle. Current new data is received directly from the Event Manager and must not be read from the database.

The flush interval for RDB archiving can be configured. Consider that a shorter flush interval provides the advantage of a shorter gap, but increases the load of the RDB manager and the network traffic. The configuration for the flush interval is the maximum time the data will remain in the buffer before it is flushed.

A buffer is flushed when the defined block size or the timeout for the flush interval is reached. The block size is configured in the RDB configuration panel by using the parameter " Entries/Block". In the RDB configuration the flush interval is defined by using the parameter "Flush interval". We recommend to use a flush interval >= 1000 msec. However, this is a general recommendation and the values should be specified considering the project size, network traffic etc.

Infinite Values

Infinite values are not drawn (viz.: not in curves, fills, markers, ect.). Instead, a thin dotted line perpendicular to the value axis marks the start and end of each infinite value, except for event trend type. A label next to this line displays the actual value (e.g.: inf, -inf or nan)
Note: For event curves, the special cases (-inf, inf, nan) are displayed if the textual display (JSON) of the value is activated.

Event curve with infinite values and two further curves

main()
{
  time t = getCurrentTime();
  int count = 10;
  int timeStep = 30;
  bit64 status = 15;

  TREND1.curveType("#1_1", 4); // 4 = Event
  TREND1.curveLegendName("#1_1", "EventCurve");

  TREND1.addCurve(0, "#1_2");
  TREND1.curveColor("#1_2", "blue");
  TREND1.curveType("#1_2", 1); // 1 = Steps
  TREND1.curveLegendName("#1_2", "StepsCurve");
  TREND1.linkCurves("#1_2", "#1_1"); // all curves should have the same scale

  TREND1.addCurve(0, "#1_3");
  TREND1.curveColor("#1_3", "green");
  TREND1.curveType("#1_3", 2); // 2 = Linear
  TREND1.curveLegendName("#1_3", "LinearCurve");
  TREND1.linkCurves("#1_3", "#1_1"); // all curves should have the same scale

  t -= (long)(count * timeStep);

  TREND1.curveValue("#1_1", "{\"icon\": \"trendRuler_1.png\", \"text\": \"-Infinite\", \"value\": \"-inf\"}", t, status);
  TREND1.curveValue("#1_2", 5, t, status);
  TREND1.curveValue("#1_3", 10, t, status);
  t += timeStep;

  TREND1.curveValue("#1_1", "{\"icon\": \"trendRuler_2.png\", \"text\": \"+Infinite\", \"value\": \"inf\"}", t, status);
  TREND1.curveValue("#1_2", 40, t, status);
  TREND1.curveValue("#1_3", 80, t, status);
  t += timeStep;

  TREND1.curveValue("#1_1", "{\"icon\": \"trendRuler_3.png\", \"text\": \"noValue\", \"value\": \"NaN\"}", t, status);
  TREND1.curveValue("#1_2", 25, t, status);
  TREND1.curveValue("#1_3", 50, t, status);
  t += timeStep;

  TREND1.curveValue("#1_1", "{\"icon\": \"trendRuler_4.png\", \"value\": 12}", t, status);
  TREND1.curveValue("#1_2", 35, t, status);
  TREND1.curveValue("#1_3", 70, t, status);
  t += timeStep;

  TREND1.curveValue("#1_1", "{\"text\": \"'OA'\", \"value\": \"OA\"}", t, status);
  TREND1.curveValue("#1_2", 20, t, status);
  TREND1.curveValue("#1_3", 40, t, status);
  t += timeStep;

  TREND1.curveValue("#1_1", "{\"icon\": \"trendRuler_6.png\", \"text\": \"Number34\", \"value\": 34}", t, status);
  TREND1.curveValue("#1_2", 30, t, status);
  TREND1.curveValue("#1_3", 60, t, status);
  t += timeStep;
}
Figure 3. Infinite values

Trend Grid

The grid of the trend area can be customized to match your design requirements by using following functions: