Trend Control Description and Options

After defining the Trend Control bindings, or Trend Bindings, the OAS Web HMI library will continually poll the server for realtime data, or Historical Data, depending on the context.

After each polling cycle, a callback function will be executed, allowing you to examine the data, use it in your client side code, or simply apply it to a charting library like Flot. It is your responsibility to implement the callback function and reference it in the Trend Bindings.

The Javascript OAS_config variable contains several options for determining the behavior of the Script Library. This variable is a standard JSON construct. The full definition with defaults desplayed is:

OAS_config =
{
    debug: false,   
    debug_refresh: false,   
    interval: 1000,             
    auto_start: true,       
    token:'',                           
    serverURL:'http://localhost:58725'
};

To add Trend Bindings to this configuration, you will add the following node to your OAS_config construct. The trend_bindings node is an array of Trend Binding objects, each representing data to be displayed in a single chart or to be used together.

trend_bindings: [
    {
        chartid: <string>, 
        samplerate: <integer>,
        timeframe: <integer>,
        tags:[ <array of Tag Definitions - see below> ],
        retain: <optional:integer>,
        callback: <function>
    }
]
  • chartid: string
    This string is available within the callback
  • samplerate: integer
    The server-side sample rate for extracting trend data
  • timeframe: int
    The server-side timeframe
  • tags: array

An array of Tag Definitions. Each tag definition represents a feed of data values corresponding to an OAS Server Tag. You can either provide an array of strings containing Tag names (e.g. ‘Ramp.Value’) or you can provide an array of Tag Definition objects with the tag name and other options.

{
    tag: "Tag.Name",
    label: <string: label that can be used on a chart>,
    color: <string: html color in hex format e.g. '#FFCC00'>,
    historystatprocessing: <string: avg|min|max|lastsample>
    historytag: <string: MyDataLoggingGroup.Field>
    ... other custom nodes ...
}

Historystatprocessing and historytag are optional. Historytag is used to specify the data logging group and field to return history data from. Commonly used when the same tag is defined in multiple logging groups.

  • historystatprocessing: string
    This allows you to explicitly calculate the value of the historical data point. If omitted, “avg” is assumed which will average the value when it spans two entries in the data log.
  • historytag: string
    The history tag allow you to specify where the historical data for that tag can be found. By default, OAS will choose the data logging group based on the sample rate of the trend control. However, you can point to the specific data logging group to use if there is more than one defined on the server logging the tag values. The formats to follow are:

    • <data logging group>. <field name>
      The field name is the actual database column that stores data for the tag in question. For example if you have a data logging group called “DemoLog” and the db field is “Sine_Value” the historytag should be set to “DemoLog.Sine_Value”.
    • \\<network node>\<data logging group>.<field name>
      Additionally if your data logging is being performed by an other OAS server, you can prepend the historytag with “\\<networknode\”. For example, if the above tag data is being logged by another OAS server called “myServer” on the network, the historytag should be set to “\\myServer\DemoLog.Sine_Value”. You can use an IP address or registered domain name for network node as long as it maps to the OAS server performing the data logging.

An array of Tag Definitions. Each tag definition represents a feed of data values corresponding to an OAS Server Tag. You can either provide an array of strings containing Tag names (e.g. ‘Ramp.Value’) or you can provide an array of Tag Definition objects with the tag name and other options.

  • retain: integer
    The number of values to retain between callbacks. For example, if you are displaying real-time data, you will want to set this to the maximum number of points on the x-axis so that any chart using the data will effectively scroll. If you do not set a retain value, all values will be retained, gradually using up more memory over time, and forcing you to manually extract portions for display.
  • callback: function
    A function pointer with that receives a single argument. This function must be globally accessible and will be called on each server refresh of data. The single argument will represent the raw data from the server with metadata about the data set. More information below.
  • returnalldatawithtimes: bool
    An optional flag that determines whether the server will return timestamps for each individual data point. If this setting is not included or is set to false, only the start and end timestamps are included in along with the data points as each is assumed to be averaged between the start and end. Setting this to true will inlude an additional array of timestamps on the server response labeled timesforreturnalldata.

Installation and Configuration – Web Trend

Configuration of OAS Web HMI will not be covered in this document. Once you have a working installation of OAS Web HMI, adding Trend Control configuration is fairly simple. As with OAS Web HMI, the following are required for Trend Control operation:

  • jQuery v1.8.3 or later, found at jquery.com and is also distributed with the OAS Web HMI product
  • The OAS Web HMI Script Library
  • The OAS Web HMI Stylesheet, which is used for styling modal dialogs and can be modified to fit your web design
  • A small block of Javascript containing an authentication token and URL location of the Open Automation Software Server

Additionally, if you would like to integrate with the Flot charting library, you will need to download Flot and various plugins. Each example provided in this document will describe the specific Flot plugins required.

The following is an example of a properly configured, minimal HTML page:

<html>
    <head>
        <script type="text/javascript" src="js/jquery-1.8.3.min.js"></script>
        <script type="text/javascript" src="js/opc-lib-min.js"></script>
        <link rel="stylesheet" stype="text/css" href="css/opc-style.css"/>
        <script type="text/javascript">
            OAS_config = {
                token:'7e61b230-481d-4551-b24b-ba9046e3d8f2',
                serverURL: 'http://localhost:58725'
            };
        </script>
    </head>
    <body>
        Hello World
    </body>
</html>

Of course, this example does not contain any bindings to OAS Server Tags, but contains all elements necessary to connect to a server located at http://localhost:58725 using an authentication token of7e61b230-481d-4551-b24b-ba9046e3d8f2.

Overview – Web Trend Programming

If you are interested in visualizing your data in a desktop or mobile browser with zero programming, you may be interested in OAS Open UIEngine.

Features

The OAS Web HMI provides a flexible, platform-independent way to integrate with Open Automation Software Servers. The addition of the Trend Control allows you to retrieve real time and historical data for any tags exposed as Trend Points within the OPC Server. Included in this release are:

  • A configuration interface for specifying Trend Points to monitor and be displayed
  • A client-side Javascript API for extracting data and transforming it
  • A simple interface for applying Trend Point and Historical Data to the popular open source Flot (www.flotcharts.org)charting library

Requirements

OAS Web HMI Trend Control requires the following:

  • an instance of an Open Automation Software Serveraccessible over an internal or external network
  • working knowledge of HTML
  • working knowledge of Javascript
  • working knowledge of OAS Web HMI configuration

Getting Started – Web Trend

The following content will get you started with Web Trend, building your own web user interfaces with real time and historical data.

NOTE: If you want to visualize your data in a desktop or mobile browser with zero programming, you may be interested in the OAS Open UIEngine .
The UIEngine is a robust no-code web application and HMI builder for developing rich user interfaces in a browser-based development environment.
See the UIEngine Documentation to learn more.

For full reference information visit Programming Reference – Web Trend

Example 1: Simple Trend Data Integration

The following sample illustrates how to add real time animated charting to display a single server tag value as it changes over time. Later examples will show how to track multiple tags on a single chart, as well as how to add some interactivity and switching between real time and historical data.

Step 1:

Important: In order to enable realtime trending of any Tag Value use the Configure OAS application and go to Configure-Tags to enable the Trend Point property on each Tag you want to trend.
You can also use the Tag CSV Export and Import with the column Value – Is Trend Point to enable multiple tags for trending in one step.

Configure Web Services within the OAS Platform. For instructions on how to accomplish this as well as optionally using SSL for secure communications, see the following article:
Configuring OAS Web Services

Step 2:

Be sure to follow instructions for configuring Web HMI as the Trend Data is an extension of that library.

In addition to the 3 previous script libraries (jQuery, json2, and opc-lib-min) copy 2 additional files from the same source location (C:\Program Files\Open Automation Software\OAS\HTML_HMIjs) to the same destination as the others, keeping the files within a flot directory:

  1. js/flot/jquery.flot.min.js
  2. js/flot/jquery.flot.time.min.js

Step 3:

In the head section of the HTML file, add the following script library references:

<script type="text/javascript" src="js/flot/jquery.flot.min.js"></script>
<script type="text/javascript" src="js/flot/jquery.flot.time.min.js"></script>

Once you have an HTML file set up and successfully running HTML HTML, modify the OAS_config script to look like the following:

OAS_config = {
    token:'7e61b230-481d-4551-b24b-ba9046e3d8f2',
    serverURL: 'http://localhost:58725/',
    trend_bindings:[
      {
        chartid:"trend1", 
        samplerate: 1,
        timeframe: 100,
        tags:[
          {
            label: "Random",
            tag: "Random.Value",
            color: "#f00"
          }
        ],
        retain: 100,
        callback:trendCallback
      }
    ]
  };

Note: As with the Web HMI configuration, you must specify the serverURL that includes the Node Name and Port Number that has been registered by the OAS Service Control Manager.

Networking

If the OAS Tags reside on the same OAS Engine as the serverURL all tags can be defined as a local tag.

Local Tag

myGroup.myTag.Value

If the OAS Tags to trend are located on other remote nodes use the following network tag syntax to assign each pen.

Basic Networking

\\192.168.0.1\myGroup.myTag.Value

Live Data Cloud Networking from local OAS Engine

RemoteSCADAHosting.myLiveDataCloudNode.myGroup.myTag.Value

Live Data Cloud Networking though remote OAS Engine

\\192.168.0.1\RemoteSCADAHosting.myLiveDataCloudNode.myGroup.myTag.Value

Step 4:

Within the same script block containing the OAS_config, add the following function. This function will be responsible for rendering the data points returned by the server on each refresh call. As you can see, the name of the function trendCallback matches the value of callback defined in the OAS_config:

function trendCallback(data){
  // set up Flot options for formatting the x-axis
  options = {
    series: {
      lines: {
        show:true,
        fill:true
      }
    },
    xaxis: {
        mode: "time",
        tickSize: [2, "second"],
        tickFormatter: function (v, axis) {
          var dt = new Date(v);
          // display axis label every 30 seconds
            if (dt.getSeconds() % 30 == 0) {
              // format label to include date and time
              return OAS.Util.formatDate(dt,"mm/dd/yyyy hh:MM:ss&nbsp;nbsp;aa")
            }
            return "";
        }
    }
  }
  // locate the binding based on the inbound data
  tb = OAS.Trend.getTrendBinding(data);
  // format the data as a Flot series
  fd = OAS.Flot.buildTrendData(data);
  // call $.plot to draw the chart
  $.plot("#" + tb.chartid, fd, options);
}

In the body of your HTML, add an element where the chart will be drawn, using the following bit of HTML:

<div style="width:600px;height:300px;border:solid 1px #777;padding:20px;margin-bottom:20px;">
  <div id="trend1" style="width:600px;height:300px;"></div>
</div>

Note: The id of the div element is “trend1”, which matches the chartid configured in Step 3.

Save the HTML file and add it to your application in the same way as other Web HMI web pages. The complete file should look like the following:

<html>
  <head>
    <script type="text/javascript" src="js/lib/jquery-1.8.3.min.js"></script>
    <script type="text/javascript" src="js/opc-lib-min.js"></script>
    <script type="text/javascript" src="js/lib/json2.js"></script>
    <script type="text/javascript" src="js/flot/jquery.flot.min.js"></script>
    <script type="text/javascript" src="js/flot/jquery.flot.time.min.js"></script>
    <link rel="stylesheet" stype="text/css" href="css/opc-style.css"/>
    <script type="text/javascript">
      OAS_config = {
        token:'7e61b230-481d-4551-b24b-ba9046e3d8f2',
        serverURL: 'http://localhost:58725/',
        trend_bindings:[
          {
            chartid:"trend1", 
            samplerate: 1,
            timeframe: 100,
            tags:[
              {
                label: "Random",
                tag: "Random.Value",
                color: "#f00"
              }
            ],
            retain: 100,
            callback:trendCallback
          }
        ]
      };
      
      function trendCallback(data){
        // set up Flot options for formatting the x-axis
        options = {
          series: {
            lines: {
              show:true,
              fill:true
            }
          },
          xaxis: {
              mode: "time",
              tickSize: [2, "second"],
              tickFormatter: function (v, axis) {
                var dt = new Date(v);
                // display axis label every 30 seconds
                  if (dt.getSeconds() % 30 == 0) {
                    // format label to include date and time
                    return OAS.Util.formatDate(dt,"mm/dd/yyyy hh:MM:ss&nbsp;aa")
                  }
                  return "";
              }
          }
        }
        // locate the binding based on the inbound data
        tb = OAS.Trend.getTrendBinding(data);
        // format the data as a Flot series
        fd = OAS.Flot.buildTrendData(data);
        // call $.plot to draw the chart
        $.plot("#" + tb.chartid, fd, options);
      }
    </script>
  </head>
 
  <body>
    <div style="width:600px;height:300px;border:solid 1px #777;padding:20px;margin-bottom:20px;">
      <div id="trend1" style="width:600px;height:300px;"></div>
    </div>
  </body>
</html>

Example 2: Multiple Real-Time Charts

The following sample builds upon Example 1, but illustrates how to add multiple real time animated charts to an application as well as adding multiple data sets to a single chart.

Step 1:

Be sure to follow instructions for configuring Web HMI as the Trend Data is an extension of that library.

In addition to the 3 previous script libraries (jQuery, json2, and opc-lib-min) copy 2 additional files from the same source location (C:\Program Files\Open Automation Software\OAS\HTML_HMI\js) to the same destination as the others, keeping the files within a flot directory:

  1. js/flot/jquery.flot.min.js
    js/flot/jquery.flot.time.min.js

Also, please review Example 1 if any of the following steps are unclear.

Step 2:

In the head section of the HTML file, add the following script library references:

<script type="text/javascript" src="js/flot/jquery.flot.min.js"></script>
<script type="text/javascript" src="js/flot/jquery.flot.time.min.js"></script>

Step 3:

Once you have an HTML file set up and successfully running, modify the OAS_config script to look like the following. As you can see from this configuration, there are 2 trend_bindings in the array, with the first containing 2 tags.

The first chart will display both data sets for the Ramp.Value and Random.Value server tags, and the second will display the Sine.Value tag.

OAS_config = {
    token:'7e61b230-481d-4551-b24b-ba9046e3d8f2',
    serverURL: 'http://localhost:58725/',
    trend_bindings:[
      {
        chartid:"trend1", 
        samplerate: 1,
        timeframe: 100,
        tags:[
          {
            label:"Ramp",
            tag:"Ramp.Value",
            color:"#090"
          },
          {
            label: "Random",
            tag: "Random.Value",
            color: "#f00"
          }
        ],
        retain: 100,
        callback:trendCallback
      },
      {
        chartid:"trend2", 
        samplerate: 1,
        timeframe: 100,
        tags:[
          {
            label: "Sine",
            tag: "Sine.Value",
            color: "#00c"
          }
        ],
        retain: 100,
        callback:trendCallback
      }
    ]
  };

Note: As with the Web HMI configuration, you must specify the serverURL that includes the Node Name and Port Number that has been registered by the OAS Service Control Manager.

Step 4:

Within the same script block containing the OAS_config, add the following function. This function will be responsible for rendering the data points reterned by the server on each refresh call.

As you can see, the name of the function trendCallback matches the value of callback defined in the OAS_config. Also, this is identical to the callback used in the first example. The single callback can be used to render any number of trend charts placed on the page.

function trendCallback(data){
  // set up Flot options for formatting the x-axis
  options = {
    series: {
      lines: {
        show:true,
        fill:true
      }
    },
    xaxis: {
      mode: "time",
      tickSize: [2, "second"],
      tickFormatter: function (v, axis) {
        var dt = new Date(v);
        // display axis label every 30 seconds
        if (dt.getSeconds() % 30 == 0) {
          // format label to include date and time
          return OAS.Util.formatDate(dt,"mm/dd/yyyy hh:MM:ss&nbsp;aa")
        }
        return "";
      }
    }
  }
  // locate the binding based on the inbound data
  tb = OAS.Trend.getTrendBinding(data);
  // format the data as a Flot series
  fd = OAS.Flot.buildTrendData(data);
  // call $.plot to draw the chart
  $.plot("#" + tb.chartid, fd, options);
}

Step 5:

In the body of your HTML, add an element for each trend chart to be drawn:

<div style="width:600px;height:300px;border:solid 1px #777;padding:20px;margin-bottom:20px;">
  <div id="trend1" style="width:600px;height:300px;"></div>
</div>
<div style="width:600px;height:300px;border:solid 1px #777;padding:20px;margin-bottom:20px;">
  <div id="trend2" style="width:600px;height:300px;"></div>
</div>

Note: The id of the div elements are “trend1” and “trend2“, respectively, which matches the chartid configured in Step 3 for each binding.

Step 6:

Save the HTML file and add it to your application in the same way as other Web HMI web pages. The complete file should look like the following:

<html>
  <head>
    <script type="text/javascript" src="js/lib/jquery-1.8.3.min.js"></script>
    <script type="text/javascript" src="js/opc-lib-min.js"></script>
    <script type="text/javascript" src="js/lib/json2.js"></script>
    <script type="text/javascript" src="js/flot/jquery.flot.min.js"></script>
    <script type="text/javascript" src="js/flot/jquery.flot.time.min.js"></script>
    <link rel="stylesheet" stype="text/css" href="css/opc-style.css"/>
    <script type="text/javascript">
      OAS_config = {
        token:'7e61b230-481d-4551-b24b-ba9046e3d8f2',
        serverURL: 'http://localhost:58725/',
        trend_bindings:[
          {
            chartid:"trend1", 
            samplerate: 1,
            timeframe: 100,
            tags:[
              {
                label:"Ramp",
                tag:"Ramp.Value",
                color:"#090"
              },
              {
                label: "Random",
                tag: "Random.Value",
                color: "#f00"
              }
            ],
            retain: 100,
            callback:trendCallback
          },
          {
            chartid:"trend2", 
            samplerate: 1,
            timeframe: 100,
            tags:[
              {
                label: "Sine",
                tag: "Sine.Value",
                color: "#00c"
              }
            ],
            retain: 100,
            callback:trendCallback
          }
        ]
      };
      
      function trendCallback(data){
        // set up Flot options for formatting the x-axis
        options = {
          series: {
            lines: {
              show:true,
              fill:true
            }
          },
          xaxis: {
              mode: "time",
              tickSize: [2, "second"],
              tickFormatter: function (v, axis) {
                var dt = new Date(v);
                // display axis label every 30 seconds
                  if (dt.getSeconds() % 30 == 0) {
                    // format label to include date and time
                    return OAS.Util.formatDate(dt,"mm/dd/yyyy hh:MM:ss&nbsp;aa")
                  }
                  return "";
              }
          }
        }
        // locate the binding based on the inbound data
        tb = OAS.Trend.getTrendBinding(data);
        // format the data as a Flot series
        fd = OAS.Flot.buildTrendData(data);
        // call $.plot to draw the chart
        $.plot("#" + tb.chartid, fd, options);
      }
    </script>
  </head>
 
  <body>
    <div style="width:600px;height:300px;border:solid 1px #777;padding:20px;margin-bottom:20px;">
      <div id="trend1" style="width:600px;height:300px;"></div>
    </div>
    <div style="width:600px;height:300px;border:solid 1px #777;padding:20px;margin-bottom:20px;">
      <div id="trend2" style="width:600px;height:300px;"></div>
    </div>
  </body>
</html>

Example 3: Interactive Charts

The following sample illustrates how you can add interactivity to your charts, by rendering a cursor that follows the mouse position, a popup that displays the chart value at the location where the mouse hovers, and even temporarily pauses the real time rendering when a value is displayed.

Step 1:

Be sure to follow instructions for configuring Web HMI as the Trend Data is an extension of that library.

In addition to the 3 previous script libraries (jQuery, json2, and opc-lib-min) copy 3 additional files from the same source location (C:\Program Files\Open Automation Software\OAS\HTML_HMIjs) to the same destination as the others, keeping the files within a flot directory:

  1. js/flot/jquery.flot.min.js
  2. js/flot/jquery.flot.time.min.js
  3. js/flot/jquery.flot.crosshair.min.js

Also, please review Examples 1 and 2 if any of the following steps are unclear.

Step 2:

In the head section of the HTML file, add the following script library references:

<script type="text/javascript" src="js/flot/jquery.flot.min.js"></script>
<script type="text/javascript" src="js/flot/jquery.flot.time.min.js"></script>
<script type="text/javascript" src="js/flot/jquery.flot.crosshair.min.js"></script>

Step 3:

In the head section of the HTML file, add the following CSS style definitions that will be used to format the chart and popup elements:

<style type="text/css">
    .container {
      width:600px;height:300px;
    }
    .outer-container {
      width:600px;height:300px;
      border:solid 1px #666;
      padding:20px;
    }
    body {
      padding:40px;
      background-color:#fff;
    }
    #tooltip {
      position:absolute;
      z-index:9999;
      border:2px solid #fff;
      padding:2px;
      background-color:#666;
      color:#fff;
      box-shadow:2px 2px 2px 0px rgba(0,0,0,0.2);
    }
  </style>

Step 4:

Once you have an HTML file set up and successfully running, modify the OAS_config script to look like the following.

OAS_config = {
    token:'7e61b230-481d-4551-b24b-ba9046e3d8f2',
    serverURL: 'http://localhost:58725/',
    trend_bindings:[
      {
        chartid:"trend1", 
        samplerate: 1,
        timeframe: 100,
        tags:[
          {
            label: "Sine",
            tag: "Sine.Value",
            color: "#66c"
          }
        ],
        retain: 100,
        callback:trendCallback
      }
    ]
  };

Note: As with the Web HMI configuration, you must specify the serverURL that includes the Node Name and Port Number that has been registered by the OAS Service Control Manager.

Step 5:

Within the same script block containing the OAS_config, add the following functions. These will control showing and hiding the popup that will display the chart value where the cursor is hovering.

// hide the tooltip element
function hideToolTip(){
  $("#tooltip").hide();
}
 
// show tooltip on demand
function showToolTip(item){
  hideToolTip(); 
  tt = $("#tooltip")
  if (tt.length == 0) {
    // create tooltip element if it doesn't exist
    tt = $("<div id='tooltip'></div>")
    $("body").append(tt)
    tt.hide();
  }
  $("#tooltip").css("background-color",item.series.color);
  var x = item.datapoint[0].toFixed(2);
  var dt = new Date(parseInt(x));
  var dtf = OAS.Util.formatDate(dt,"hh:MM:ss&nbsp;aa");
  var y = item.datapoint[1].toFixed(2);
 
  $("#tooltip").html(dtf + " = " + y).css({
    top: item.pageY + 5, 
    left: item.pageX + 5
  }).fadeIn(200);
}

Step 6:

Also within the script block, add the following call that will bind the mouse hover events to the chart elements.

// set up event handler for displaying tooltip on hover
$(document).ready(function(){
  // 'plothover' event is fired by Flot when mouse hovers over
  //  any plot points on the chart
  $("#trend1").bind("plothover", function (event, pos, item) {
    // item represents the plot point
    if (item) {
      if (previousPoint != item.dataIndex) {
        previousPoint = item.dataIndex;
        showToolTip(item)
        // stop the OAS Trend data calls to the server
        if (OAS.is_refreshing()) OAS.toggle_refresh(false);
      }
    } else {
      // restart refreshes
      if (!OAS.is_refreshing()) OAS.toggle_refresh(true);
      hideToolTip();
      previousPoint = null;            
    }
  });
});

Step 7:

The final function added to the scripts should be the trendCallback. As with other examples, this is the function executed ever time new data points are received from the OAS Server.

This also demonstrates how the grid is configured to listen to hover and click events, and how the crosshair is added to make it easier to see when the mouse hovers over it.

function trendCallback(data) {
  // locate the binding based on the inbound data
  tb = OAS.Trend.getTrendBinding(data);
  
  // set up Flot options for formatting the x-axis
  options = {
    series: {
      lines: {
        show:true,
        fill:true
      }
    },
    grid: { hoverable: true, clickable: true },
    crosshair: { mode: "x"},
    xaxis: {
        mode: "time",
        tickSize: [2, "second"],
        tickFormatter: function (v, axis) {
          var dt = new Date(v);
          if (tb.mode == "trend" && dt.getSeconds() % 30 == 0) {
              return OAS.Util.formatDate(dt,"mm/dd/yyyy hh:MM:ss&nbsp;aa")
          }
            return "";
        }
    }
  }
  
  // format the data as a Flot series
  fd = OAS.Flot.buildTrendData(data);
  // call $.plot to draw the chart
  $.plot("#" + tb.chartid, fd, options);
}

Step 8:

In the body of your HTML, add an element where the chart will be drawn:

<div id="trendContainer" class="outer-container">
  <div id="trend1" class="container"></div>
</div>

Step 9:

Save the HTML file and add it to your application in the same way as other Web HMI web pages. The complete file should look like the following:

<html>
  <head>
    <script type="text/javascript" src="js/lib/jquery-1.8.3.min.js"></script>
    <script type="text/javascript" src="js/opc-lib-min.js"></script>
    <script type="text/javascript" src="js/lib/json2.js"></script>
    <script type="text/javascript" src="js/flot/jquery.flot.min.js"></script>
    <script type="text/javascript" src="js/flot/jquery.flot.time.min.js"></script>
    <script type="text/javascript" src="js/flot/jquery.flot.crosshair.min.js"></script>
    <link rel="stylesheet" stype="text/css" href="css/opc-style.css"/>
    <style type="text/css">
      .container {
        width:600px;height:300px;
      }
      .outer-container {
        width:600px;height:300px;
        border:solid 1px #666;
        padding:20px;
      }
      body {
        padding:40px;
        background-color:#fff;
      }
      #tooltip {
        position:absolute;
        z-index:9999;
        border:2px solid #fff;
        padding:2px;
        background-color:#666;
        color:#fff;
        box-shadow:2px 2px 2px 0px rgba(0,0,0,0.2);
      }
    </style>
    <script type="text/javascript">
      OAS_config = {
        token:'7e61b230-481d-4551-b24b-ba9046e3d8f2',
        serverURL: 'http://localhost:58725/',
        trend_bindings:[
          {
            chartid:"trend1", 
            samplerate: 1,
            timeframe: 100,
            tags:[
              {
                label: "Sine",
                tag: "Sine.Value",
                color: "#66c"
              }
            ],
            retain: 100,
            callback:trendCallback
          }
        ]
      };
 
      // hide the tooltip element
      function hideToolTip(){
        $("#tooltip").hide();
      }
 
      // show tooltip on demand
      function showToolTip(item){
        hideToolTip(); 
        tt = $("#tooltip")
        if (tt.length == 0) {
          // create tooltip element if it doesn't exist
          tt = $("<div id='tooltip'></div>")
          $("body").append(tt)
          tt.hide();
        }
        $("#tooltip").css("background-color",item.series.color);
        var x = item.datapoint[0].toFixed(2);
        var dt = new Date(parseInt(x));
        var dtf = OAS.Util.formatDate(dt,"hh:MM:ss&nbsp;aa");
        var y = item.datapoint[1].toFixed(2);
 
        $("#tooltip").html(dtf + " = " + y).css({
          top: item.pageY + 5, 
          left: item.pageX + 5
        }).fadeIn(200);
      }
 
      // set up event handler for displaying tooltip on hover
      $(document).ready(function(){
        // 'plothover' event is fired by Flot when mouse hovers over
        //  any plot points on the chart
        $("#trend1").bind("plothover", function (event, pos, item) {
          // item represents the plot point
          if (item) {
            if (previousPoint != item.dataIndex) {
              previousPoint = item.dataIndex;
              showToolTip(item)
              // stop the OAS Trend data calls to the server
              if (OAS.is_refreshing()) OAS.toggle_refresh(false);
            }
          } else {
            // restart refreshes
            if (!OAS.is_refreshing()) OAS.toggle_refresh(true);
            hideToolTip();
            previousPoint = null;            
          }
        });
      });
      
      function trendCallback(data) {
        // locate the binding based on the inbound data
        tb = OAS.Trend.getTrendBinding(data);
        
        // set up Flot options for formatting the x-axis
        options = {
          series: {
            lines: {
              show:true,
              fill:true
            }
          },
          grid: { hoverable: true, clickable: true },
          crosshair: { mode: "x"},
          xaxis: {
              mode: "time",
              tickSize: [2, "second"],
              tickFormatter: function (v, axis) {
                var dt = new Date(v);
                if (tb.mode == "trend1" && dt.getSeconds() % 30 == 0) {
                    return OAS.Util.formatDate(dt,"mm/dd/yyyy hh:MM:ss&nbsp;aa")
                }
                  return "";
              }
          }
        }
        
        // format the data as a Flot series
        fd = OAS.Flot.buildTrendData(data);
        // call $.plot to draw the chart
        $.plot("#" + tb.chartid, fd, options);
      }
    </script>
  </head>
 
  <body>
    <div id="trendContainer" class="outer-container">
      <div id="trend1" class="container"></div>
    </div>
  </body>
</html>

Example 4: Historical Data

The following sample illustrates how you can switch a chart between real time and historical data modes, with the historical data being a snapshot of all data points between a start and end date/time.

Step 1:

Be sure to follow instructions for configuring Web HMI as the Trend Data is an extension of that library.

In addition to the 3 previous script libraries (jquery, json2, and opc-lib-min) copy 3 additional files from the same source location (C:\Program Files\Open Automation Software\OAS\HTML_HMIjs) to the same destination as the others, keeping the files within a flot directory:

  1. js/flot/jquery.flot.min.js
  2. js/flot/jquery.flot.time.min.js
  3. js/flot/jquery.flot.crosshair.min.js

Also, please review Examples 1 and 2 if any of the following steps are unclear.

Step 2:

In the head section of the HTML file, add the following script library references:

<script type="text/javascript" src="js/flot/jquery.flot.min.js"></script>
<script type="text/javascript" src="js/flot/jquery.flot.time.min.js"></script>
<script type="text/javascript" src="js/flot/jquery.flot.crosshair.min.js"></script>

Step 3:

In the head section of the HTML file, add the following CSS style definitions that will be used to format the chart and popup elements:

<style type="text/css">
    .container {
      width:600px;height:300px;
    }
    .outer-container {
      width:600px;height:300px;
      border:solid 1px #666;
      padding:20px;
    }
    body {
      padding:40px;
      background-color:#fff;
    }
    #tooltip {
      position:absolute;
      z-index:9999;
      border:2px solid #fff;
      padding:2px;
      background-color:#666;
      color:#fff;
      box-shadow:2px 2px 2px 0px rgba(0,0,0,0.2);
    }
  </style>

Step 4:

Once you have an HTML file set up and successfully running, modify the OAS_config script to look like the following.

OAS_config = {
    token:'7e61b230-481d-4551-b24b-ba9046e3d8f2',
    serverURL: 'http://localhost:58725/',
    trend_bindings:[
      {
        chartid:"trend1", 
        samplerate: 1,
        timeframe: 100,
        tags:[
          {
            label: "Sine",
            tag: "Sine.Value",
            color: "#66c"
          }
        ],
        retain: 100,
        callback:trendCallback
      }
    ]
  };

Note: As with the Web HMI configuration, you must specify the serverURL that includes the Node Name and Port Number that has been registered by the OAS Service Control Manager.

Step 5:

Within the same script block containing the OAS_config, add the following functions. These will control showing and hiding the popup that will display the chart value where the cursor is hovering, as well as functions for showing ins hiding axes when historical data is being displayed.

There is also a simple utility function used to validate the values entered into the text boxes on the page, ensuring that they are valid dates.

// hide the tooltip element
function hideToolTip(){
  $("#tooltip").hide();
}
 
// show tooltip on demand
function showToolTip(item){
  hideToolTip(); 
  tt = $("#tooltip")
  if (tt.length == 0) {
    // create tooltip element if it doesn't exist
    tt = $("<div id='tooltip'></div>")
    $("body").append(tt)
    tt.hide();
  }
  $("#tooltip").css("background-color",item.series.color);
  var x = item.datapoint[0].toFixed(2);
  var dt = new Date(parseInt(x));
  var dtf = OAS.Util.formatDate(dt,"hh:MM:ss&nbsp;aa");
  var y = item.datapoint[1].toFixed(2);
 
  $("#tooltip").html(dtf + " = " + y).css({
    top: item.pageY + 5, 
    left: item.pageX + 5
  }).fadeIn(200);
}
 
// display history axes for just start and end time since
//  data points may be spread over a long period of time
function setHistoryAxes(data){
  $("#trendContainer").append($("<div id='historyAxes'></div>"));
  sd = $("<div style='float:left;'>" + OAS.Util.formatDate(data.firsttime, "mm/dd/yyyy<br/>hh:MM:ss&nbsp;aa") + "</div>");
  ed = $("<div style='float:right;'>" + OAS.Util.formatDate(data.lasttime, "mm/dd/yyyy<br/>hh:MM:ss&nbsp;aa") + "</div>");
  $("#historyAxes").append(sd);
  $("#historyAxes").append(ed);
  $("#historyAxes").append($("<div stye='clear:both;'></div>"));
}
function clearHistoryAxes(){
  $("#historyAxes").remove();
}
function validDate(d) {
  if ( Object.prototype.toString.call(d) === "[object Date]" ) {
    if ( !isNaN( d.getTime() ) ) {
      return true;
    }
  }
  return false;
}

Step 6:

Also within the script block, add the following call that will bind the mouse hover events to the chart elements and the click events for the buttons on the page.

// set up event handler for displaying tooltip on hover
$(document).ready(function(){
  // 'plothover' event is fired by Flot when mouse hovers over
  //  any plot points on the chart
  $("#trend1").bind("plothover", function (event, pos, item) {
    // item represents the plot point
    if (item) {
      if (previousPoint != item.dataIndex) {
        previousPoint = item.dataIndex;
        showToolTip(item)
        // stop the OAS Trend data calls to the server
        if (OAS.is_refreshing()) OAS.toggle_refresh(false);
      }
    } else {
      // restart refreshes
      if (!OAS.is_refreshing()) OAS.toggle_refresh(true);
      hideToolTip();
      previousPoint = null;            
    }
  });
  $("#showHistory").click(function(){
    try {
      dts = new Date($("#startDate").val())
      dte = new Date($("#endDate").val())
      if (validDate(dts) && validDate(dte)){
        OAS.Trend.getHistoryData("trend1",dts,dte);
        $(this).attr("disabled",true);
        $("#resumeTrend").attr("disabled",false);
      }
    }
    catch(err) {
      alert(err.message);
    }
  });
  $("#resumeTrend").click(function(){
    OAS.Trend.resumeTrendData("trend1");
    $(this).attr("disabled",true);  
    $("#showHistory").attr("disabled",false);
  });
});

Step 7:

The final function added to the scripts should be the trendCallback. As with other examples, this is the function executed ever time new data points are received from the OAS Server.

This also demonstrates how the grid is configured to listen to hover and click events, and how the crosshair is added to make it easier to see when the mouse hovers over it.

function trendCallback(data) {
  // locate the binding based on the inbound data
  tb = OAS.Trend.getTrendBinding(data);
  
  // set up Flot options for formatting the x-axis
  options = {
    series: {
      lines: {
        show:true,
        fill:true
      }
    },
    grid: { hoverable: true, clickable: true },
    crosshair: { mode: "x"},
    xaxis: {
        mode: "time",
        tickSize: [2, "second"],
        tickFormatter: function (v, axis) {
          var dt = new Date(v);
          if (tb.mode == "trend" && dt.getSeconds() % 30 == 0) {
              return OAS.Util.formatDate(dt,"mm/dd/yyyy hh:MM:ss&nbsp;aa")
          }
            return "";
        }
    }
  }
  
  // format the data as a Flot series
  fd = OAS.Flot.buildTrendData(data);
  // call $.plot to draw the chart
  $.plot("#" + tb.chartid, fd, options);
}

Step 8:

In the body of your HTML, add an element where the chart will be drawn:

<div id="trendContainer" class="outer-container">
  <div id="trend1" class="container"></div>
</div>
<div style="margin-top:30px;">
  <input type="button" id="showHistory" value="SHOW HISTORY"></input>
  start date: <input type="text" id="startDate"></input>
  end date: <input type="text" id="endDate"></input>
  <br/>
  <input type="button" id="resumeTrend" value="RESUME TREND" disabled="disabled"></input>
</div>

Step 9:

Save the HTML file and add it to your application in the same way as other Web HMI web pages. The complete file should look like the following:

<html>
  <head>
    <script type="text/javascript" src="js/lib/jquery-1.8.3.min.js"></script>
    <script type="text/javascript" src="js/opc-lib-min.js"></script>
    <script type="text/javascript" src="js/lib/json2.js"></script>
    <script type="text/javascript" src="js/flot/jquery.flot.min.js"></script>
    <script type="text/javascript" src="js/flot/jquery.flot.time.min.js"></script>
    <script type="text/javascript" src="js/flot/jquery.flot.crosshair.min.js"></script>
    <link rel="stylesheet" stype="text/css" href="css/opc-style.css"/>
    <style type="text/css">
      .container {
        width:600px;height:300px;
      }
      .outer-container {
        width:600px;height:330px;
        border:solid 1px #666;
        padding:20px;
      }
      body {
        padding:40px;
        background-color:#fff;
      }
      #tooltip {
        position:absolute;
        z-index:9999;
        border:2px solid #fff;
        padding:2px;
        background-color:#666;
        color:#fff;
        box-shadow:2px 2px 2px 0px rgba(0,0,0,0.2);
      }
      #historyAxes {
        font-size:12px;
        padding-left:25px;
      }
      input[type=button] {
        border:solid 1px #ccc;
        font-weight:bold;
        padding:5px 20px;
      }
    </style>
    <script type="text/javascript">
      OAS_config = {
        token:'7e61b230-481d-4551-b24b-ba9046e3d8f2',
        serverURL: 'http://localhost:58725/',
        trend_bindings:[
          {
            chartid:"trend1", 
            samplerate: 1,
            timeframe: 100,
            tags:[
              {
                label: "Sine",
                tag: "Sine.Value",
                color: "#66c"
              }
            ],
            retain: 100,
            callback:trendCallback
          }
        ]
      };
 
      // hide the tooltip element
      function hideToolTip(){
        $("#tooltip").hide();
      }
 
      // show tooltip on demand
      function showToolTip(item){
        hideToolTip(); 
        tt = $("#tooltip")
        if (tt.length == 0) {
          // create tooltip element if it doesn't exist
          tt = $("<div id='tooltip'></div>")
          $("body").append(tt)
          tt.hide();
        }
        $("#tooltip").css("background-color",item.series.color);
        var x = item.datapoint[0].toFixed(2);
        var dt = new Date(parseInt(x));
        var dtf = OAS.Util.formatDate(dt,"hh:MM:ss&nbsp;aa");
        var y = item.datapoint[1].toFixed(2);
 
        $("#tooltip").html(dtf + " = " + y).css({
          top: item.pageY + 5, 
          left: item.pageX + 5
        }).fadeIn(200);
      }
 
      // display history axes for just start and end time since
      //  data points may be spread over a long period of time
      function setHistoryAxes(data){
        $("#trendContainer").append($("<div id='historyAxes'></div>"));
        sd = $("<div style='float:left;'>" + OAS.Util.formatDate(data.firsttime, "mm/dd/yyyy<br/>hh:MM:ss&nbsp;aa") + "</div>");
        ed = $("<div style='float:right;'>" + OAS.Util.formatDate(data.lasttime, "mm/dd/yyyy<br/>hh:MM:ss&nbsp;aa") + "</div>");
        $("#historyAxes").append(sd);
        $("#historyAxes").append(ed);
        $("#historyAxes").append($("<div stye='clear:both;'></div>"));
      }
      function clearHistoryAxes(){
        $("#historyAxes").remove();
      }
      function validDate(d) {
        if ( Object.prototype.toString.call(d) === "[object Date]" ) {
          if ( !isNaN( d.getTime() ) ) {
            return true;
          }
        }
        return false;
      }
 
      // set up event handler for displaying tooltip on hover
      $(document).ready(function(){
        // 'plothover' event is fired by Flot when mouse hovers over
        //  any plot points on the chart
        $("#trend1").bind("plothover", function (event, pos, item) {
          // item represents the plot point
          if (item) {
            if (previousPoint != item.dataIndex) {
              previousPoint = item.dataIndex;
              showToolTip(item)
              // stop the OAS Trend data calls to the server
              if (OAS.is_refreshing()) OAS.toggle_refresh(false);
            }
          } else {
            // restart refreshes
            if (!OAS.is_refreshing()) OAS.toggle_refresh(true);
            hideToolTip();
            previousPoint = null;            
          }
        });
        $("#showHistory").click(function(){
          try {
            dts = new Date($("#startDate").val())
            dte = new Date($("#endDate").val())
            if (validDate(dts) && validDate(dte)){
              OAS.Trend.getHistoryData("trend1",dts,dte);
              $(this).attr("disabled",true);
              $("#resumeTrend").attr("disabled",false);
            }
          }
          catch(err) {
            alert(err.message);
          }
        });
        $("#resumeTrend").click(function(){
          OAS.Trend.resumeTrendData("trend1");
          $(this).attr("disabled",true);  
          $("#showHistory").attr("disabled",false);
        });
      });
      
      function trendCallback(data) {
      // locate the binding based on the inbound data
      tb = OAS.Trend.getTrendBinding(data);
      
      // set up Flot options for formatting the x-axis
      options = {
        series: {
          lines: {
            show:true,
            fill:true
          }
        },
        grid: { hoverable: true, clickable: true },
        crosshair: { mode: "x"},
        xaxis: {
            mode: "time",
            tickSize: [2, "second"],
            tickFormatter: function (v, axis) {
              var dt = new Date(v);
              if (tb.mode == "trend" && dt.getSeconds() % 30 == 0) {
                  return OAS.Util.formatDate(dt,"mm/dd/yyyy hh:MM:ss&nbsp;aa")
              }
                return "";
            }
        }
      }
      
      // format the data as a Flot series
      fd = OAS.Flot.buildTrendData(data);
      // call $.plot to draw the chart
      $.plot("#" + tb.chartid, fd, options);
    }
    </script>
  </head>
 
  <body>
    <div id="trendContainer" class="outer-container">
      <div id="trend1" class="container"></div>
    </div>
    <div style="margin-top:30px;">
      <input type="button" id="showHistory" value="SHOW HISTORY"></input>
      start date: <input type="text" id="startDate"></input>
      end date: <input type="text" id="endDate"></input>
      <br/>
      <input type="button" id="resumeTrend" value="RESUME TREND" disabled="disabled"></input>
    </div>
  </body>
</html>

Overview – Web Trend

NOTE: If you want to visualize your data in a desktop or mobile browser with zero programming, you may be interested in the OAS Open UIEngine .
The UIEngine is a robust no-code web application and HMI builder for developing rich user interfaces in a browser-based development environment.
See the UIEngine Documentation to learn more.

For full reference information visit Programming Reference – Web Trend

The OAS Web Trend provides a flexible, platform-independent way to integrate with Open Automation Software Servers. The addition of the Web Trend allows you to retrieve and interact with real time and historical trend data from the OAS Server.

FAQs – .NET Data Connector

Bad Data Quality in .NET Application.
Below are some possible reasons your .NET application is not able to read OAS tag values.

Data Source Quality

Use Configure-Tags to verify that the data quality of the source tags is "Good Quality". Menu Configure Tags
Quality Good

Security

The Default security group on either the local or remote OAS Engine may have Disable All Tags from Reading checked under the Read Tags Tab.  See Restrict Tag Access of Security setup to see how read, write, and browse access can be restricted. View how to Implement User Credentials in Client Applications to provide log in method for each user in the .NET application.

Network

.NET applications can be defined to communicate to remote OAS Engines.  See Network Communications Troubleshooting to verify that port 58727 is allowing both incoming and outgoing traffic through your firewall.

Tag Path

The full tag path would include the full tag name including its parent groups and the variable of the Tag.
MyGroup.MyTag.Value
Tag names are case sensitive and the current value of a tag would be .Value as the most common variable.
If the tag is from a remote OAS Engine see Basic Networking for standard remote tag syntax or Live Data Cloud Networking if the OAS Engine system has a dynamic IP address.
\\192.168.0.1\TagName.Value

License

Use Configure-License to verify that a product feature .NET Data Connector, WinForm HMI, or WPF HMI is enabled on the data source system where the tags are located. Menu Configure License
Enabled Products

Target Framework for WPF and WinForm Applications

The project type for WinForm and WPF applications should be set to include (.NET Framework) and target .NET Framework 4.6.1 or greater. WinForm Target Framework See the correct project type for WinForm above that is listed as Windows Forms App (.NET Framework) while Windows Forms App would not be the correct project type.

Assembly References

Visual Studio on some operating systems will assign a legacy assembly to the project causing an incompatibility due to an older version of the reference assembly.  A common assembly that can be incorrect is Newtonsoft.Json that has been registered in the GAC by another software product. Select Newtonsoft.Json under the Project References to verify the correct path and version as 13.0.0.0.
Newtonsoft.Json Assembly Reference If the Path does not reference the OAS installation directory remove the reference and select to Add Reference and browse for dll from the respective directory for the specific product feature. For .NET Framework applications include the .dlls located in C:\Program Files\Open Automation Software\OAS\Controls\NetFramework\. The Target Framework set for the VS project must be .NET Framework 4.6.1 or greater. For .NET Standard supporting the following targets include the. dlls located in C:\Program Files\Open Automation Software\OAS\Controls\NetStandard\. See a list of locations for the correct type in the troubleshooting type After updating to OAS Version 17 the project no longer compiles for a list of correct project reference paths for each type of Visual Studio Project.

.NET Assembly is Blocked

If you have copied an application or project to another computer you may need to Unblock one or more the .dll files. Right click on the .dll file that you have downloaded. Check the Unblock checkbox for security as shown in the example below, then click Apply or OK. Excel Add-In

Legacy .NET Application with OAS Version 17

 If the OAS .NET assemblies are from OAS version 16 or less contact support@oasiot.com for compatibility instructions.
After updating to OAS Version 17 the project no longer compiles

OAS version 17 implements an improved network interface which requires some additional assemblies.

All dependent .dlls are located in the relative subdirectory of the Controls directory of the OAS installation directory, typically C:\Program Files\Open Automation Software\OAS\Controls\.

To add a reference to a Visual Studio project right click on References in the Solution Explorer.

Add Reference

Select Browse to browse the directory for each application feature.

Browse Assemblies

Include all .dlls files in the respective directory for the specific product feature.

For .NET Framework applications include the .dlls located in C:\Program Files\Open Automation Software\OAS\Controls\NetFramework\.

The Target Framework set for the VS project must be .NET Framework 4.6.1 or greater.

For .NET Standard supporting the following targets include the. dlls located in C:\Program Files\Open Automation Software\OAS\Controls\NetStandard\.

  • .NET 5 or greater
  • .NET Core 2.0 or greater
  • .NET Framework 4.61 or greater
  • Xamarin.iOS 10.14 or greater
  • Xamarin.Android 8.0 or greater
  • UWP 1.0.0.16299 or greater

WPF HMI Assemblies

  • C:\Program Files\Open Automation Software\OAS\Controls\NetFramework\OPCWPFDashboard\

WinForm HMI Assemblies

  • C:\Program Files\Open Automation Software\OAS\Controls\NetFramework\OPCControls\

Alarm .NET Assemblies

  • C:\Program Files\Open Automation Software\OAS\Controls\NetFramework\OPCAlarmControl\
  • C:\Program Files\Open Automation Software\OAS\Controls\NetFramework\OPCAlarmDataOnly\
  • C:\Program Files\Open Automation Software\OAS\Controls\NetStandard\OASAlarms\

Trend .NET Assemblies

  • C:\Program Files\Open Automation Software\OAS\Controls\NetFramework\OPCTrendControl\
  • C:\Program Files\Open Automation Software\OAS\Controls\NetFramework\OPCTrendDataOnly\
  • C:\Program Files\Open Automation Software\OAS\Controls\NetStandard\OASTrends\

.NET Data Connector Assemblies

  • C:\Program Files\Open Automation Software\OAS\Controls\NetFramework\OPCSystemsDataConnector\
  • C:\Program Files\Open Automation Software\OAS\Controls\NetStandard\OASData\

Server Configuration Assemblies

  • C:\Program Files\Open Automation Software\OAS\Controls\NetFramework\OPCSystems\
  • C:\Program Files\Open Automation Software\OAS\Controls\NetStandard\OASConfig\
 
Is there example code of the .NET Data Connector?

Yes, refer to the OAS Example Service Code for working code examples if both C# and Visual Basic.

What assemblies do I need to deploy with my application?
Include OASData.dll as Local Copy reference to target the following.
  • .NET 5
  • .NET Core 2.o or greater
  • .NET Framework 4.61 or greater
  • Xamarin.iOS 10.14 or greater
  • Xamarin.Android 8.0 or greater
  • UWP 1.0.0.16299 or greater
For .NET Framework 4.6 or less include OPCSystemsDataConnector.dll.

Videos – .NET Data Connector

Refer to the following video on how to programmatically access data from the Open Automation Software real-time data service and directly from OPC Servers using DirectOPC.

.NET Data Connector

Connect Visual Studio applications to interface with Industry 4.0 data and share data to IIoT applications on-premise or over the Internet.

Real-time Data Access .NET Applications

How to make any .NET application a live data source to all products.  Also how to share data from any data source to .NET applications.

View the following networking videos for syntax on how to enable remote communications.

Easy Networking

How to network all products to central service using a fixed IP Address or registered domain name for the Internet.

Live Data Cloud

How to host data from any Windows PC with a standard Internet connection.  No fixed IP Address or registered domain name required.

.NET Data Connector

To access data from the Open Automation Software real-time data service you can use the OPCSystemsDataConnector component in the OPCSystemsDataConnector.dll.

Refer to the .NET Realtime Data Access section for full syntax examples.

Refer to the Forms FormReadValues and FormWriteValues in the WinForm Example Source Code installed with Open Automation Software for a documented working example of the data component.

With the release of the OAS Platform v12, the .NET Data Connector is based on .NET Standard 2.0. This allows you to read and write OAS data from an application that can be deployed to any supported OS, including Linux, Mac, Android, and iOS.

Frequently Asked Questions – .NET Alarm

WPF Properties Edit Ellipses Missing in VS 2022
Visual Studio 2022 design time properties no longer support custom property editors for WPF applications.  Use Visual Studio 2019 to develop WPF applications. The free Community Edition of Visual Studio 2019 can be download from https://visualstudio.microsoft.com/vs/older-downloads/. WinForm applications are still well supported in Visual Studio 2022.
Bad Data Quality in .NET Application.
Below are some possible reasons your .NET application is not able to read OAS tag values.

Data Source Quality

Use Configure-Tags to verify that the data quality of the source tags is "Good Quality". Menu Configure Tags
Quality Good

Security

The Default security group on either the local or remote OAS Engine may have Disable All Tags from Reading checked under the Read Tags Tab.  See Restrict Tag Access of Security setup to see how read, write, and browse access can be restricted. View how to Implement User Credentials in Client Applications to provide log in method for each user in the .NET application.

Network

.NET applications can be defined to communicate to remote OAS Engines.  See Network Communications Troubleshooting to verify that port 58727 is allowing both incoming and outgoing traffic through your firewall.

Tag Path

The full tag path would include the full tag name including its parent groups and the variable of the Tag.
MyGroup.MyTag.Value
Tag names are case sensitive and the current value of a tag would be .Value as the most common variable.
If the tag is from a remote OAS Engine see Basic Networking for standard remote tag syntax or Live Data Cloud Networking if the OAS Engine system has a dynamic IP address.
\\192.168.0.1\TagName.Value

License

Use Configure-License to verify that a product feature .NET Data Connector, WinForm HMI, or WPF HMI is enabled on the data source system where the tags are located. Menu Configure License
Enabled Products

Target Framework for WPF and WinForm Applications

The project type for WinForm and WPF applications should be set to include (.NET Framework) and target .NET Framework 4.6.1 or greater. WinForm Target Framework See the correct project type for WinForm above that is listed as Windows Forms App (.NET Framework) while Windows Forms App would not be the correct project type.

Assembly References

Visual Studio on some operating systems will assign a legacy assembly to the project causing an incompatibility due to an older version of the reference assembly.  A common assembly that can be incorrect is Newtonsoft.Json that has been registered in the GAC by another software product. Select Newtonsoft.Json under the Project References to verify the correct path and version as 13.0.0.0.
Newtonsoft.Json Assembly Reference If the Path does not reference the OAS installation directory remove the reference and select to Add Reference and browse for dll from the respective directory for the specific product feature. For .NET Framework applications include the .dlls located in C:\Program Files\Open Automation Software\OAS\Controls\NetFramework\. The Target Framework set for the VS project must be .NET Framework 4.6.1 or greater. For .NET Standard supporting the following targets include the. dlls located in C:\Program Files\Open Automation Software\OAS\Controls\NetStandard\. See a list of locations for the correct type in the troubleshooting type After updating to OAS Version 17 the project no longer compiles for a list of correct project reference paths for each type of Visual Studio Project.

.NET Assembly is Blocked

If you have copied an application or project to another computer you may need to Unblock one or more the .dll files. Right click on the .dll file that you have downloaded. Check the Unblock checkbox for security as shown in the example below, then click Apply or OK. Excel Add-In

Legacy .NET Application with OAS Version 17

 If the OAS .NET assemblies are from OAS version 16 or less contact support@oasiot.com for compatibility instructions.
After updating to OAS Version 17 the project no longer compiles

OAS version 17 implements an improved network interface which requires some additional assemblies.

All dependent .dlls are located in the relative subdirectory of the Controls directory of the OAS installation directory, typically C:\Program Files\Open Automation Software\OAS\Controls\.

To add a reference to a Visual Studio project right click on References in the Solution Explorer.

Add Reference

Select Browse to browse the directory for each application feature.

Browse Assemblies

Include all .dlls files in the respective directory for the specific product feature.

For .NET Framework applications include the .dlls located in C:\Program Files\Open Automation Software\OAS\Controls\NetFramework\.

The Target Framework set for the VS project must be .NET Framework 4.6.1 or greater.

For .NET Standard supporting the following targets include the. dlls located in C:\Program Files\Open Automation Software\OAS\Controls\NetStandard\.

  • .NET 5 or greater
  • .NET Core 2.0 or greater
  • .NET Framework 4.61 or greater
  • Xamarin.iOS 10.14 or greater
  • Xamarin.Android 8.0 or greater
  • UWP 1.0.0.16299 or greater

WPF HMI Assemblies

  • C:\Program Files\Open Automation Software\OAS\Controls\NetFramework\OPCWPFDashboard\

WinForm HMI Assemblies

  • C:\Program Files\Open Automation Software\OAS\Controls\NetFramework\OPCControls\

Alarm .NET Assemblies

  • C:\Program Files\Open Automation Software\OAS\Controls\NetFramework\OPCAlarmControl\
  • C:\Program Files\Open Automation Software\OAS\Controls\NetFramework\OPCAlarmDataOnly\
  • C:\Program Files\Open Automation Software\OAS\Controls\NetStandard\OASAlarms\

Trend .NET Assemblies

  • C:\Program Files\Open Automation Software\OAS\Controls\NetFramework\OPCTrendControl\
  • C:\Program Files\Open Automation Software\OAS\Controls\NetFramework\OPCTrendDataOnly\
  • C:\Program Files\Open Automation Software\OAS\Controls\NetStandard\OASTrends\

.NET Data Connector Assemblies

  • C:\Program Files\Open Automation Software\OAS\Controls\NetFramework\OPCSystemsDataConnector\
  • C:\Program Files\Open Automation Software\OAS\Controls\NetStandard\OASData\

Server Configuration Assemblies

  • C:\Program Files\Open Automation Software\OAS\Controls\NetFramework\OPCSystems\
  • C:\Program Files\Open Automation Software\OAS\Controls\NetStandard\OASConfig\
 
The database engine language is different than the Regional Language settings of the Data Logging and / Alarm Logging Service. Data Logging updates, Alarm Logging updates, trend history, and / alarm history is not working due to invalid date format.
Go to Configure-Options-History and Enable History Date Format. Examples: yyyy-MM-dd HH:mm:ss MM/dd/yyyy HH:mm:ss
After updating Open Automation Software with the incremental update the project no longer compiles or the application no longer works.
Make sure to Unblock the dlls before copying to C:\Program Files\Open Automation Software\OAS\Controls\NetFramework\.
To Unblock the files copy to a trusted location for your system, Desktop works well, then right click on the file and select Properties to select Unblock. Then copy from your Desktop to the correct directory in C:\Program Files\Open Automation Software\OAS\Controls\.
Does OPCAlarm.NET support OPC Alarm & Events specification?
Yes, go to Configure-OPC Alarm and Event Servers using the Configure OAS application to define each A&E OPC Server to subscribe to.
How do I programmatically get realtime and historical alarms?
Use the GetAlarmDataTable method to return a DataTable object with all alarms and the values for each property of an alarm.
DataTable myDataTable;
            myDataTable = opcAlarmControl1.GetAlarmDataTable();

What assemblies do I need to deploy with my application?
Include the following in References as Local Copy:
  • C1.Win.C1FlexGrid2.dll
  • OPCAlarmControl.dll
  • OPCSystemsInterface.dll