Chart

The chart is feature rich plot widget. The ability to display multiple axes (both x and y) means Web Chart is a great way to present a lot of information within a limited space. It allows trends and patterns in the data to be visualized thus providing insight into details that might otherwise be missed.

Multiple x-axis support enables different time period comparisons. Diverse production data can be added to a single graph, making the comparison of critical outliers much easier by removing the need to switch between graphs. Multiple y-axis support enables different scale comparison. Variables with different scales can have a strong relation, e.g. temperature and humidity. Thanks to multi y-axis support these relations can now be easily illustrated. Combination of both multi x and y-axis makes Web Chart a powerful tool for chart plotting, analysis and trend exploration.

Web Chart also offers a wider range of chart types, such as Candlestick, Spline, Waterfall and others for robust data visualization.

Model

{
    "type": "chart",
    "name": "My Chart",
    "modelRoot": {},
    "tagSearchTable": {},
    "ranges": {},
    "chart": {}
}

Model Root

The modelRoot property defines from which KPI Model object, defined in the back end, to start the model tree view, shown in the left chart panel. If this property is not set the tree will display the whole KPI Model hierarchy taking into account object permissions of the currently logged in user. By setting the includeRoot property to true, the model view will display the specified object including its children. By setting it to false, the model view will display the children of specified object.

{
    "modelRoot": {
        "path": "/Company/Plant A", // Object path of an object in the KPI Model.
        "includeRoot": false // Default is false.
    }
}

Can also configure multiple root objects.

{
    "modelRoot": [
        {
            "path": "/Company/Plant A",
            "includeRoot": true
        },
        {
            "path": "/Company/Plant C",
            "includeRoot": true
        }
    ]
}

There is also a depth (positive integer) field to limit the number of objects hierarchy level.

Data source

The dataSource property can be used to initialize the content and appearance of the chart widget. Typically this would be done by using a function action to invoke a Lua script in the back end. The data returned by invoking the dataSource pipeline should be an JSON object with a chart property, its fields initialized to contain the required pen and axis settings.

{
    "chart" : {
        // Chart fields as described below
    }
}
When using a dataSource to initialize the widget, the chart property in the initial model should be omitted. If it is present it will override the settings returned by the data source pipeline.

Ranges

The ranges property is used to define one or more groups of time ranges, drawn as translucent rectangles in the plot area of the chart. These are useful to highlight intervals of interest, such as batch runs, production stops etc.

In this context, a group is a collection of one or more interval-records each of which defines a start and end time as well as a text label. The data are provided in the group by a dataSource that should return an array of range records.

The schema definition of the group is used to map fields in each record to the starttime, endtime and label of the interval to be drawn. It also has properties used to control the appearance and positioning of ranges in the chart.

{
    "ranges": {
        "groups": [
            {
                "dataSource": {},
                "schema": {
                    "borders": {},
                    "draw": true,
                    "fields": {},
                    "label": {},
                    "position": {},
                    "rules": [],
                    "style": {},
                    "styleByTheme": {},
                    "x_axis": [],
                    "y_axis": []
                }
            }
        ]
    }
}

The table below provides more information about the range model properties.

name description

groups

Array of group definitions. Each group defines a dataSource to retrieve the ranges and a schema to control how these are displayed.

dataSource

Defines the logic to retrieve the ranges. The dataSource is invoked once for each x_axis listed in the schema at which time it receives the axis start and end times as ISO UTC time strings in the incoming message payload, an example of which is shown below:

{
    "payload": {
        "starttime": "2023-02-07T10:10:20.150Z",
        "endtime": "2023-02-07T10:12:20.150Z"
    }
}

They are automatically included in the farg parameter when using a function action in the dataSource.

The data source should return ranges related to this time range as an array of records. Each array element is expected to contain at least two fields to indicate the interval start and end times. They can be expressed as epoch integers or ISO UTC strings.

Although not mandatory, it is recommended to also include a label field in each record. Any number of additional metadata properties can be provided for use in match rules.

When multiple schema.x_axis entries are provided the range records from all dataSource invocation are merged.

schema

Defines field mappings, display properties and rule definitions.

borders

Default appearance of the range interval vertical borders

style and styleByTheme

The following styling options are supported for the vertical borders of range intervals:

  • borderWidth: Numeric width of the border in pixels,

  • color: CSS color name or RGB value. For example "midnightblue" or "#191970".

  • opacity: fraction ranging from 0 for fully transparent to 1 for totally opaque. The default border opacity is 1

draw

Boolean value used to show or hide the intervals in this group. Note that all range intervals, regardless of the settings in the rules will be hidden when draw is set to false at this level.

fields

Mappings used to identify which fields in the data records returned by the dataSource are used for the interval edges and label.

starttime and endtime

Names of the data fields which contain the interval start and end time, expressed as either an Epoch integer or ISO time string.

label

Name of the data field to use as the interval/range label.

label

Set the display style for the range text label

style and styleByTheme

Style settings to apply to the text label. The following options are available:

  • color: Text color name or RGB value string.

  • font: CSS font declaration, for example "20px Arial, sans-serif"

  • opacity: Fraction between 0 and 1. The default value is 1.

text

Fallback text to use when a label is not available.

position

Used to set the height of the range bar relative to the vertical size of each y_axis the group is mapped to.

start and end

Value between 0 and 100 indicating where along the height of the y_axis the range bar should start and end. Using these properties the height of the range bar can be adjusted to be some percentage of the y-axis height.

rules

Array of one or more rule definitions. They provide a great deal of flexibility to conditionally shape the appearance of selected range entries. This is useful to change the formatting/style of certain ranges that should stand out in the chart, for example those where some or other problem occurred.

They can also be used to visually group subsets of the ranges by assigning them to different y-axes or start and end positions.

match

All rule elements should define a match condition to select the range entries the rule applies to. Match expressions are evaluated on every data record in turn and have access to all the fields of the range. Note that each range entry can only be matched to one rule. If multiple rules match the same range entry, only the settings of the first match will be applied!

Match expressions are constructed in the same way as those of the tree widget rules.

borders

Border styling to apply when the match expression returns true. These override any setting defined at schema level.

draw

Set to false to hide all ranges that match the rule. Note that when draw is set to false at schema level this property is ignored.

fields

Field mappings to use for matching ranges. This is particularly useful if the dataSource returns a heterogeneous set of range records where the time and label fields don’t all have the same name.

label

Override label formatting.

position

Override position settings

style and styleByTheme

Override range bar styling.

x_axis

Overrides the x-axes that the range is applied to. This setting should be used with some caution since it can result in unexpected behavior. More specifically, if the new x-axis has a wider time range than the one or more assigned at schema level, or it does not overlap with with them at all, the range records for the non-overlapping sections will not have been retrieved. This is because x-axis assignments due to a rule match does not trigger the dataSource to re-fetch range values bounded by the new axis time range.

y_axis

Override the y-axes the range is mapped to.

style and styleByTheme

Set the appearance of the range bar

color

Range bar fill color, expressed as a color name or RGB string.

opacity

Range bar opacity value between 0 and 1. The default is 0.7

x_axis

Ranges can be assigned to one or more x-axes, by providing the relevant axis IDs. The property can also be omitted in which case the ranges in the group will be applied to the first axis in the chart.x_axis array.

It is important to note, that the group’s data source is evaluated once for each axis in the list. The returned data is merged into a combined set. This implies that the same range data will potentially be retrieved multiple times where the x-axis time ranges overlap.

y_axis

Range bars can be assigned to one or more y-axes by adding their IDs to this array property.

Example

To see the ranges in action add the following Lua script library to your system, calling it rangesDemo. The getRanges function returns one or more sets of ranges that span the width from arg.starttime to arg.endtime. The ranges JSON below illustrated how the function is used to generate some test data.

local lib = {}

-- Supported input arguments:
-- starttime and endtime: indicate the time range to generate the ranges for
-- rangeSets: one or more range intervals is generated for each element in the array.
--   { name: base name for the set,
--     intervals: number of ranges to generate with the same base name,
--     omitLabel: optional index for one range to not be assigned a label,
--     errorRange: optional index for one range to have error flag set to true }
function lib:getRanges( arg, _, _ )
    local TEN_MINUTES = 10 * 60 * 1000
    local DEFAULT_INTERVAL_COUNT = 2

    -- Apply some defaults for the start and end time if none were provided
    local starttime = syslib.gettime( arg.starttime or syslib.gettime(syslib.now() - TEN_MINUTES))
    local endtime = syslib.gettime( arg.endtime or syslib.gettime(syslib.now()))

    -- Make sure we generate some data even if no rangeSets were provided
    local rangeSets = arg.rangeSets or { {name = "one", intervals = DEFAULT_INTERVAL_COUNT } }

    -- construct the ranges.
    local ranges = {}
    -- Add a bit of randomness to the start and end time of the intervals to make things a bit more interesting
    math.randomseed( syslib.now() )

    for nr, set in ipairs( rangeSets ) do
        local numIntervals = set.intervals or DEFAULT_INTERVAL_COUNT
        local name = set.name or ("set " .. nr)
        local jitter = (endtime - starttime )  / ( numIntervals * 6 )
        local increment = (endtime - starttime )  / (numIntervals * 2 )
        local timeOffset = starttime - increment/2
        local i = 1

        while i <= (numIntervals * 2 ) do
            local intervalNr = math.floor( (i-1)/2 + 1 )
            local lbl =  name .. "\nInterval " .. intervalNr
            if ( intervalNr == set.omitLabel ) then lbl = nil end -- Omit the label to test the fallback text highlighting
            table.insert( ranges, {
                st = math.floor( timeOffset + i * increment - math.random() * jitter ),
                et = math.floor( timeOffset + (i+1) * increment + math.random() * jitter ),
                lbl = lbl,
                n = name,
                err = intervalNr == set.errorRange } )
            i = i + 2
        end
    end
    return ranges
end

return lib

Once the lib is in place, the following ranges element can be added to a chart widget to display some test data. Two sets of range are shown. The rules illustrate how range styling and positions can be adjusted based on field values in the range data returned by the dataSource

{
    "ranges": {
        "groups": [
            {
                "dataSource": [
                    {
                        "type": "function",
                        "ctx": "/System",
                        "lib": "rangesDemo",
                        "func": "getRanges",
                        "farg": {
                            "rangeSets": [
                                {
                                    "name": "Test Set 1",
                                    "intervals": 3,
                                    "omitLabel": 2
                                },
                                {
                                    "name": "Test Set 2",
                                    "intervals": 4,
                                    "errorRange": 2
                                }
                            ]
                        }
                    }
                ],
                "schema": {
                    "draw": true,
                    "fields": {
                        "endtime": "et",
                        "starttime": "st",
                        "label": "lbl"
                    },
                    "borders": {
                        "style": {
                            "borderWidth": 2,
                            "color": "orange"
                        },
                        "styleByTheme": {
                            "light": {
                                "color": "darkorange"
                            }
                        }
                    },
                    "label": {
                        "style": {
                            "color": "white",
                            "font": "15px Arial, sans-serif"
                        },
                        "text": "Fallback\nText"
                    },
                    "rules": [
                        {
                            "match": {
                                "n": "Test Set 1"
                            },
                            "position": {
                                "start": 5.5,
                                "end": 65.5
                            },
                            "style": {
                                "color": "#191970",
                                "opacity": 1
                            },
                            "label": {
                                "text": "Override\nFallback\nText"
                            },
                            "draw": true,
                            "styleByTheme": {
                                "light": {
                                    "color": "midnightblue"
                                }
                            }
                        },
                        {
                            "match": {
                                "$expr": {
                                    "$and": [
                                        {
                                            "$eq": [
                                                "$n",
                                                "Test Set 2"
                                            ]
                                        },
                                        {
                                            "$eq": [
                                                "$err",
                                                true
                                            ]
                                        }
                                    ]
                                }
                            },
                            "position": {
                                "start": 55,
                                "end": 95
                            },
                            "style": {
                                "color": "red",
                                "opacity": 0.5
                            }
                        },
                        {
                            "match": {
                                "$expr": {
                                    "$and": [
                                        {
                                            "$eq": [
                                                "$n",
                                                "Test Set 2"
                                            ]
                                        },
                                        {
                                            "$ne": [
                                                "$err",
                                                true
                                            ]
                                        }
                                    ]
                                }
                            },
                            "position": {
                                "start": 55,
                                "end": 95
                            },
                            "style": {
                                "color": "hotpink",
                                "opacity": 0.5
                            }
                        }
                    ]
                }
            }
        ]
    }
}

Tag Search Table

The tagSearchTable definition is used to provide a pre-configured list of tags from which entries can be selected as chart pens. The selectable items are shown using a Table widget when a user clicks on the table icon to the right of the "Pens" label. Selectable items are declared in the data property within tagSearchTable or the old tagtable field.

The config below matches the data which is configured on the tagtable field or is fetched from the KPI Model items from the custom table with name tagtable.

Each entry in the table data list must contain at least a (name or Name) and (path or Path) field.

{
    "tagSearchTable": {
        "captionBar": { // Customize the table caption bar.
            "hidden": true
        },
        "schema": [
            {
                "name": "Name",
                "sort": "asc"
            },
            {
                "name": "Description",
                "title": "Description"
            },
            {
                "name": "Path"
            }
        ]
    }
}

If the tagtable property is not used, a data field can be defined in the tagSearchTable directly.

{
    "tagSearchTable": {
        "data": [
            {
                "name": "My Tag 1",
                "qualified": false,
                "description": "This is non qualified tag 1",
                "path": "/System/Core/MyTag1"
            },
            {
                "name": "My Tag 2",
                "qualified": false,
                "description": "This is non qualified tag 2",
                "path": "/System/Core/MyTag2"
            },
            {
                "name": "My Important Tag 10",
                "qualified": true,
                "description": "This is Important qualified tag 10",
                "path": "/System/Core/MyImportantTag10"
            },
            {
                "name": "My Important Tag 11",
                "qualified": true,
                "description": "This is non qualified tag 11",
                "path": "/System/Core/MyImportantTag11"
            }
        ],
        "schema": [
            {
                "name": "name",
                "title": "Name",
                "sort": "asc"
            },
            {
                "name": "qualified",
                "title": "Q",
                "enum": {
                    "X": true,
                    "-": false
                }
            },
            {
                "name": "description",
                "title": "Description"
            },
            {
                "name": "path",
                "title": "Path"
            }
        ]
    }
}

Any valid top level pen field can be provided in the tagSearchTable. This allows settings like aggregate, OpcEngUnit,trend_type etc. to be configured in the tag-table in addition to the name and path. Complex properties such as style and themes can be defined in the data elements but will be shown in the table as [object Object].

{
    "tagSearchTable": {
        "options": {
            "pageSize": 20,
            "editable": true
        },
        "data": [
            {
                "name": "My Tag 1",
                "qualified": false,
                "description": "This is non qualified tag 1",
                "path": "/System/Core/MyTag1",
                "DecimalPlaces": 2,
                "aggregate": "AGG_TYPE_RAW",
                "trend_type": "HT_LINE",
                "style": { // Will be applied, but details are not visible in the tag search table
                    "line": "DASH2",
                    "marker": "MARKER_STYLE_TRIANGLE",
                    "thickness": "MEDIUM"
                }
            },
            {
                // etc.
            }
        ]
    }
}

Note: Since the tag search table is essentially a "regular" table widget. it also has a state property.

Tag Table

When a tagtable is provided a table icon is shown on the right inspector panel in the pens section. From the + button, additional pens can be added to the chart.

A tagtable can be provided either by configuring an array of objects containing at least name and path or by assigning a single object path of a system Table Holder object to the property.

{
    "tagtable": [
        {
            "name": "",         // Will become the pen name.
            "path": "",         // Path to the object
        }
    ]
}

Or with camel casing fields.

{
    "tagtable": [
        {
            "Name": "",         // Pen name
            "Path": "",         // Path to the object
            "Description": ""   // (Optional)
        }
    ]
}

Pointing to a Table Holder.

{
    "tagtable": "/System/Core/Folder/MyTags"    // Object Path
}

Chart Model

The chart model is used to define the appearance of X anf Y axes and the time series trace data (pens) to plot against them.

{
    "class": "Trend",
    "name": "My Trend",
    "x_axis": [],           // Array of X Axis objects
    "y_axis": [],           // Array of Y Axis objects
    "pens": []              // Array of Pen objects
}

Note: The work-model can be changed interactively by clicking on the brush icon brush in the right-hand widget panel. From here, pens and axis parameters can be viewed and modified. These changes can also be exported using the save tool SaveCompilationBtn in the chart toolbar and loaded with the load tool LoadCompilationBtn.

X Axis Model

The X Axis property is defined in the chart element.

{
    "chart": {
        "x_axis": [
            {
               // first x-axis
            }
        ]
    }
}

Since the chart supports multiple X Axes, it is a list of objects which have the following fields:

{
    "id": 1,
    "name": "X-1",
    "description": "Simulated Flow 1",
    "start_time": "*-1d",
    "end_time": "*",
    "intervals_no": 100,
    "position": {
        "alignment": "bottom",
        "end": 100,
        "orientation": "bottom",
        "start": 0,
        "value": 1
    },
    "themes": {
        "dark": {
            "color": "white"
        },
        "light": {
            "color": "black"
        }
    },
    "locked": true,
    "grid": false,
    "ticks": {
        "count": 2
    },
    "cursors": []
}
name description

cursors

(optional) Array of cursor objects. Each element in the array must contain a timestamp. An optional "context" string can also be configured which is shown when the mouse cursor hovers over the cursor bubble.

Note: Cursors settings can be inspected and cursors deleted interactively by clicking on the tear-drop icon tear-drop in the right-hand widget panel.

Also see addCursors for details on how to programmatically manipulate cursors.

timestamp

X-Axis timestamp where the cursor will be drawn. The value can be on of the following:

  • Epoch time in milliseconds.

  • Relative time string.

context

A string to show when hovering over the cursor bubble on the X-Axis.

end_time

End time of the axis.

grid

Enable/disable grid lines (boolean). If ticks are defined the grid lines are aligned with the ticks.

id

Axis id.

intervals_no

Number of intervals.

locked

Lock/unlock axis (boolean).

name

Name of the axis.

position

Object holding configuration properties related to axis positioning.

alignment

Set the axis to be drawn either at the "bottom" (default) or "top" of the plot area

orientation

Set to either "bottom" or "top" resulting in the tick labels to be shown below or above the axis.

start and end

Value between 0 and 100 indicating where along the width of the available plot area the x-axis starts and ends. Using these properties, two or more axes can be drawn next to each other on the same row.

value

Position value. This is a number between 1 and 8, indicating then row where the axis is downs. Position 1 is closest to the plot area.

start_time

Start time of the axis.

themes

Object holding styling options (see below).

ticks

(optional) Object with tick configuration options.

count

Number of ticks between start and end tick. Omit this to have it on auto.

format

Display format for the axis thick labels. see https://day.js.org/docs/en/display/format for details of the supported options.

For example, to show only the hour and minutes for the x-axis tick label, the format can be set to "HH:mm"

Y Axis Model

The Y Axis property is defined in the chart element.

{
    "chart": {
        "y_axis": [
            {
               // first y-axis
            }
        ]
    }
}

Since the chart supports multiple Y Axes, it is a list of objects which have the following fields:

{
    "id": 1,
    "name": "Y",
    "position": {
        "alignment": "left",
        "end": 100,
        "orientation": "left",
        "start": 0,
        "value": 1
    },
    "range": {
        "max": {
            "mode": "auto",
            "value": 0
        },
        "min": {
            "mode": "auto",
            "value": 0
        }
    },
    "themes": {
        "dark": {
            "color": "white"
        },
        "light": {
            "color": "black"
        }
    },
    "locked": false,
    "grid": false,
     "ticks": {
        "count": 2
    }
}

Pens

The Pens property is defined in the chart element.

{
    "chart": {
        "pens": [
            {
               // single pen
            }
        ]
    }
}

It is a list of pen objects, each of which refers to a system object for which time series values are plotted. Pens have the following fields:

{
    "id": 1,
    "name": "Simulated Density",
    "path": "/System/Core/Examples/Demo Data/Process Data/DC4711",
    "DecimalPlaces": 2,             // Overrules the object DecimalPlaces property
    "OpcEngUnit": "$",              // Overrules the object OpcEngUnit property
    "trend_type": "HT_LINE",
    "aggregate": "AGG_TYPE_INTERPOLATIVE",
    "style": {
        "line": "SOLID",
        "marker": "MARKER_STYLE_NONE",
        "thickness": "SEMISMALL"
    },
    "themes": {
        "dark": {
            "color": "aqua"
        },
        "light": {
            "color": "aqua"
        }
    },
    "x_axis": [
        1
    ],
    "y_axis": [
        1
    ],
    "draw": true
}
name description

aggregate

Aggregation method to use for the data.

DecimalPlaces

Number of decimal places used for data-point values. If the property is omitted, the value defined in the system object pointed to by the path will be used.

draw

Boolean value indicating whether or not to draw the trace.

id

Numeric id used to identify the pen.

name

Display name for the pen. If the property is omitted, the name of the object referred to in the path will be used.

OpcEngUnit

If provided, overrides the engineering units configured in the system object.

path

Path to the object to be plotted on the chart.

style

Defines style properties for the pen. Note that this style property does not refer to CSS settings as is the case for other widgets, but instead only support the options shown below:

line

Sets the trace line to be solid or one of three dashed styles.

marker

Select the marker style. Note that points with changes, that are recorded in the historian, will show a vertical line marker superimposed on top of the selected one. (To see the data changes, select the "modified Data Points" tab in the right-hand widget panel modifiedDataPoints and click on a vertical line marker).

The representation of changed data points in the graph and panel are in preview and aspects of the UI may change in coming releases.

thickness

Sets the line thickness and marker size. The property is ignored when the trend_type is set to "Candelstick", "Column", "ValueBand" or "Waterfall".

themes

Used to select pen colors to match the selected theme (light of dark)

trend_type

Select one of the following renderings for the dataset:

  • "Area"

  • "Candlestick"

  • "Column"

  • "Line"

  • "Points": Shows only markers

  • "Spline"

  • "SplineArea"

  • "StepArea"

  • "StepLine"

  • "ValueBand"

  • "Waterfall"

x_axis

Array of X-Axis ids on which to draw the trace

y_axis

Array of Y-Axis ids on which to draw the trace

Options

{
    "options": {
        "showToolbar": true,
        "leftPanel": false,
        "rightPanel": false,
        "bottomPanel": false,
        "play": "live",
        "relativeXAxis": false,
        "groupXAxis": true
    }
}
name description

showToolbar

hide or show the whole toolbar.

leftPanel

hide or show panel

rightPanel

hide or show panel

bottomPanel

hide or show panel

showToolbar

hide or show the toolbar.

play

live or refresh

relativeXAxis

Shows X-Axis labels in relative time, starting at 0, ending at end_time - start_time. Relative time is toggled interactively by clicking on the relative time icon relativeAxisIcon.

groupXAxis

Grouping X-Axes causes them all to use the time span of the one with the longest duration. In other words, the end times of all axes are set such that they all have the same [end_time - start_time] and that duration is equal to that of the axis with the longest time span.

This is useful to show traces on the same time scale. Note that adjusting the end-time of the X-Axis is purely for display purposes, and does not cause more data to be loaded for any of the pens. The setting is toggled in the UI by clicking on the grouping icon groupAxisIcon in the right panel.

Receive messages (Send Topics)

This widget receive messages from others. Besides the generic topics, this widget also support:

addCursors

Send topic addCursors adds one or more cursors. If the cursor already exists the one in the payload will be ignored. Send a timestamp in the payload to add the cursor to that time on the x-axis. The timestamp can be sent in ISO, Epoch, or relative time format. An optional context field can also be defined in the object. It will be shown when hovering over the cursor. The context can be defined as a string, an object, or an array.

{
    "type": "send",
    "to": "chartWidgetID",
    "message": {
        "topic": "addCursors",
        "payload": [
            {
                "timestamp": 1613481658185
            },
            {
                "timestamp": "*-1h",
                "context": "Show this on cursor hover"
            }
        ]
    }
}

To clear cursors send empty payload.

{
    "type": "send",
    "to": "chartWidgetID",
    "message": {
        "topic": "setCursors",
        "payload": []
    }
}

addPens

Add pen(s) with the provided list of pen objects or object paths. The addPens topic type provides a way to add pen(s) to a chart. (This can be particularly useful when firing an onSelect action - such as on table row select)

Add pen(s) by providing the object paths:

{
    "type": "send",
    "to": "ChartWidget",
    "message": {
        "topic": "addPens",
        "payload": {
            "pens": [
                "/System/Core/Examples/Demo Data/Process Data/DC4711",
                "/System/Core/Examples/Demo Data/Process Data/DC666",
                "/System/Core/Examples/Demo Data/Process Data/FC4711"
            ]
        }
    }
}

Add pen(s) by providing pen objects:

{
    "type": "send",
    "to": "ChartWidget",
    "message": {
        "topic": "addPens",
        "payload": {
            "pens": [
                {
                    "name": "FC4711",
                    "path": "/System/Core/Examples/Demo Data/Process Data/FC4711",
                    "style": {
                        "line": "SOLID",
                        "marker": "MARKER_STYLE_NONE",
                        "thickness": "SEMISMALL"
                    },
                    "trend_type": "HT_LINE"
                },
                {
                    "name": "DC666",
                    "path": "/System/Core/Examples/Demo Data/Process Data/DC666",
                    "style": {
                        "line": "SOLID",
                        "marker": "MARKER_STYLE_NONE",
                        "thickness": "SEMISMALL"
                    },
                    "trend_type": "HT_LINE"
                }
            ]
        }
    }
}

setCursors

Send topic setCursors will update the current set of cursors in the chart. Send timestamp in the payload to set the cursor on that timestamp. The timestamp can be send in ISO, Epoch, or relative time format. An optional context field can be defined as a string, an object, or an array. It will be shown when hovering over the cursor.

{
    "type": "send",
    "to": "chartWidgetID",
    "message": {
        "topic": "setCursors",
        "payload": [
            {
                "timestamp": 1613480658185
            },
            {
                "timestamp": "*-1h",
                "context": "Show this on cursor hover"
            }
        ]
    }
}

setTagTable

Setting the tag table by object path and prompt the Tags dialog.

{
    "type": "send",
    "to": "ChartWidget",
    "message": {
        "topic": "setTagTable",
        "payload": {
            "tagTable": "/System/Core/Examples/WebStudio/Tables/Process Data Tags",
            "prompt": true
        }
    }
}

setTimeSpan

If a time period in the form of starttime and/or endtime is received, the widget will change the X-Axis accordingly when those X-Axis is not locked.

Changing the time period.

{
    "type": "send",
    "to": "ChartWidget",
    "message": {
        "topic": "setTimeSpan",
        "payload": {
            "starttime": "2020-10-01T14:00:00.000Z",
            "endtime": "2020-10-01T16:00:00.000Z"
        }
    }
}

Actions

Supported action hooks:

  • onDataPointClick: is invoked when a data marker is clicked. The payload received by the action pipeline is an array of items each of which contains the v (value), q (quality), t (timestamp) and p (path) of data points under the mouse pointer.

    • Modified data points: A vertical-line marker is drawn on data points for which changes are recorded in the system historian. If a pen marker is configured, the modified data and pen markers are combined.

    • Markers: onDataPointClick only returns data when a marker is clicked. This can be either a marker configured in the pens section, or a modified-data marker.

    • Quality value: The quality value reported for each modified point in the payload will have bits 10 and 3 set to one (see getrawhistory for more details).

    The example below shows how to check for the presence of the change bits in the quality field.

    {
        "onDataPointClick": {
            "type": "switch",
            "case": [
                {
                    "match": {
                        "q": {
                            "$bitsAllSet": [
                                10,
                                3
                            ]
                        }
                    },
                    "action": {
                        "type": "notify",
                        "text": "Point was modified"
                    }
                },
                {
                    "match": {},
                    "action": {
                        "type": "notify",
                        "text": "Point was not modified"
                    }
                }
            ]
        }
    }
  • onNewChart: is invoked when the "new chart" toolbar button is pressed, providing a convenient way to initialize chart properties. Actions in the pipeline can be used to set selected chart fields in a message payload. At the end of the pipeline, the resulting message is passed to the back end, where default values are added for omitted parameters thus providing a fully qualified chart model.

    In the example below a pen is added to the new chart, the number of intervals is set to 50 points and the x-axis time range to one day.

    Even though only a small subset of properties were provided, all required model parameters are initialized as is revealed by inspecting the work-model.

    {
        "actions": {
            "onNewChart": [
                {
                    "type": "passthrough",
                    "message": {
                        "payload": {
                            "chart": {
                                "class": "Trend",
                                "pens": [
                                    {
                                        "path": "/System/Core/Examples/Demo Data/Process Data/DC666"
                                    }
                                ],
                                "x_axis": [
                                    {
                                        "intervals_no": 20,
                                        "end_time": "*",
                                        "start_time": "*-1d"
                                    }
                                ]
                            }
                        }
                    }
                }
            ]
        }
    }

Examples

Complete chart model:

{
    "type": "chart",
    "name": "My Chart",
    "chart": {
        "class": "Trend",
        "description": "Demo Data/Process Data",
        "name": "Demo Process Data - FC4711",
        "pens": [
            {
                "draw": true,
                "id": 1,
                "name": "Simulated Flow on X-1",
                "path": "/System/Core/Examples/Demo Data/Process Data/FC4711",
                "aggregate": "AGG_TYPE_INTERPOLATIVE",
                "style": {
                    "line": "SOLID",
                    "marker": "MARKER_STYLE_NONE",
                    "thickness": "SEMISMALL"
                },
                "themes": {
                    "dark": {
                        "color": "aqua"
                    },
                    "light": {
                        "color": "aqua"
                    }
                },
                "trend_type": "HT_LINE",
                "x_axis": [
                    1
                ],
                "y_axis": [
                    1
                ]
            },
            {
                "draw": true,
                "id": 1,
                "name": "Simulated Flow on X-2",
                "path": "/System/Core/Examples/Demo Data/Process Data/FC4711",
                "style": {
                    "line": "SOLID",
                    "marker": "MARKER_STYLE_NONE",
                    "thickness": "SEMISMALL"
                },
                "themes": {
                    "dark": {
                        "color": "green"
                    },
                    "light": {
                        "color": "green"
                    }
                },
                "trend_type": "HT_LINE",
                "x_axis": [
                    2
                ],
                "y_axis": [
                    1
                ]
            }
        ],
        "x_axis": [
            {
                "description": "Simulated Flow 1",
                "end_time": "*",
                "grid": false,
                "id": 1,
                "intervals_no": 100,
                "locked": true,
                "name": "X-1",
                "position": {
                    "alignment": "bottom",
                    "end": 100,
                    "orientation": "bottom",
                    "start": 0,
                    "value": 1
                },
                "start_time": "*-1d",
                "themes": {
                    "dark": {
                        "color": "white"
                    },
                    "light": {
                        "color": "black"
                    }
                }
            },
            {
                "description": "Simulated Flow 2",
                "end_time": "*",
                "grid": false,
                "id": 2,
                "intervals_no": 100,
                "locked": false,
                "name": "X-2",
                "position": {
                    "alignment": "bottom",
                    "end": 100,
                    "orientation": "bottom",
                    "start": 0,
                    "value": 2
                },
                "start_time": "*-1d",
                "themes": {
                    "dark": {
                        "color": "white"
                    },
                    "light": {
                        "color": "black"
                    }
                }
            }
        ],
        "y_axis": [
            {
                "description": "m³/h",
                "grid": false,
                "id": 1,
                "locked": false,
                "name": "Y",
                "position": {
                    "alignment": "left",
                    "end": 100,
                    "orientation": "left",
                    "start": 0,
                    "value": 1
                },
                "range": {
                    "max": {
                        "mode": "fixed",
                        "value": 100
                    },
                    "min": {
                        "mode": "fixed",
                        "value": 0
                    }
                },
                "themes": {
                    "dark": {
                        "color": "white"
                    },
                    "light": {
                        "color": "black"
                    }
                }
            }
        ]
    }
}

Example to add a pen to the trend by selecting a row in a table:

{
    "version": "1",
    "widgets": [
        {
            "type": "table",
            "id": "table2",
            "options": {
                "multi": false
            },
            "data": [
                {
                    "name": "DC4711",
                    "path": "/System/Core/Examples/Demo Data/Process Data/DC4711"
                },
                {
                    "name": "DC666",
                    "path": "/System/Core/Examples/Demo Data/Process Data/DC666"
                },
                {
                    "name": "FC4711",
                    "path": "/System/Core/Examples/Demo Data/Process Data/FC4711"
                },
                {
                    "name": "FC666",
                    "path": "/System/Core/Examples/Demo Data/Process Data/FC666"
                },
                {
                    "name": "TC4711",
                    "path": "/System/Core/Examples/Demo Data/Process Data/TC4711"
                },
                {
                    "name": "TC666",
                    "path": "/System/Core/Examples/Demo Data/Process Data/TC666"
                },
                {
                    "name": "PC4711",
                    "path": "/System/Core/Examples/Demo Data/Process Data/PC4711"
                },
                {
                    "name": "PC666",
                    "path": "/System/Core/Examples/Demo Data/Process Data/PC666"
                },
                {
                    "name": "QC4711",
                    "path": "/System/Core/Examples/Demo Data/Process Data/QC4711"
                },
                {
                    "name": "QC666",
                    "path": "/System/Core/Examples/Demo Data/Process Data/QC666"
                }
            ],
            "layout": {
                "w": 7,
                "h": 12,
                "x": 0,
                "y": 0,
                "static": false
            },
            "actions": {
                "onSelect": [
                    {
                        "type": "transform",
                        "aggregateOne": [
                            {
                                "$group": {
                                    "pens": {
                                        "$push": "$path"
                                    }
                                }
                            }
                        ]
                    },
                    {
                        "type": "send",
                        "to": "editor"
                    },
                    {
                        "type": "send",
                        "to": "chart1",
                        "message": {
                            "topic": "addPens"
                        }
                    }
                ]
            }
        },
        {
            "type": "chart",
            "id": "chart1",
            "layout": {
                "w": 17,
                "h": 9,
                "x": 7,
                "y": 0,
                "static": false
            }
        },
        {
            "type": "editor",
            "id": "editor",
            "name": "Debug message",
            "layout": {
                "w": 17,
                "h": 3,
                "x": 7,
                "y": 9,
                "static": false
            }
        }
    ]
}

Lua

An example to define a chart widget in Lua:

local chart01 = {
    layout = {
        w = 12,
        h = 6,
        x = 0,
        y = 6,
        locked = false
    },
    id = "chart01",
    type = "chart",
    name = "Chart 01",
    chart = {
        class = "Trend",
        description = "Demo Data/Process Data",
        name = "Demo Process Data - FC4711",
        x_axis = {
            {
                end_time = "*",
                grid = false,
                id = 1,
                intervals_no = 100,
                locked = true,
                name = "X-1",
                position = {
                    alignment = "bottom",
                    ["end"] = 100,
                    orientation = "bottom",
                    start = 0,
                    value = 1
                },
                start_time = "*-1d",
                themes = {
                    dark = {
                        color = "white"
                    },
                    light = {
                        color = "black"
                    }
                }
            },
            {
                end_time = "*",
                grid = false,
                id = 2,
                intervals_no = 100,
                locked = false,
                name = "X-2",
                position = {
                    alignment = "bottom",
                    ["end"] = 100,
                    orientation = "bottom",
                    start = 0,
                    value = 2
                },
                start_time = "*-1d",
                themes = {
                    dark = {
                        color = "white"
                    },
                    light = {
                        color = "black"
                    }
                }
            }
        },
        y_axis = {
            {
                id = 1,
                grid = false,
                locked = false,
                name = "Y",
                position = {
                    alignment = "left",
                    ["end"] = 100,
                    orientation = "left",
                    start = 0,
                    value = 1
                },
                range = {
                    max = {
                        mode = "fixed",
                        value = 100
                    },
                    min = {
                        mode = "fixed",
                        value = 0
                    }
                },
                themes = {
                    dark = {
                        color = "white"
                    },
                    light = {
                        color = "black"
                    }
                }
            }
        },
        pens = {
            {
                id = 1,
                name = "Simulated Flow on X-1",
                path = "/System/Core/Examples/Demo Data/Process Data/FC4711",
                aggregate = "AGG_TYPE_INTERPOLATIVE",
                draw = true,
                style = {
                    line = "SOLID",
                    marker = "MARKER_STYLE_NONE",
                    thickness = "SEMISMALL"
                },
                themes = {
                    dark = {
                        color = "aqua"
                    },
                    light = {
                        color = "aqua"
                    }
                },
                trend_type = "HT_LINE",
                x_axis = {
                    1
                },
                y_axis = {
                    1
                }
            },
            {
                id = 1,
                name = "Simulated Flow on X-2",
                path = "/System/Core/Examples/Demo Data/Process Data/FC4711",
                aggregate = "AGG_TYPE_INTERPOLATIVE",
                draw = true,
                style = {
                    line = "SOLID",
                    marker = "MARKER_STYLE_NONE",
                    thickness = "SEMISMALL"
                },
                themes = {
                    dark = {
                        color = "green"
                    },
                    light = {
                        color = "green"
                    }
                },
                trend_type = "HT_LINE",
                x_axis = {
                    2
                },
                y_axis = {
                    1
                }
            }
        }
    }
}