Getting Started – Web Alarm

The following content will get you started with Web Alarm, building your own web user interfaces with real time and historical alarm 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 Alarm

Example: Simple Web Alarm

The following sample illustrates how to display real time web alarms as well as enabling a feature to switch between real time and historical alarms.

Step 1

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 Alarm Control is an extension of that library.

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

jquery.dataTables.min.js

Step 3

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

<script type="text/javascript" src="js/datatables/jquery.dataTables.min.js”></script>

Step 4

Next, copy 3 additional css files into the css directory:

  1. font-awesome.min.css
  2. jquery.dataTables.css
  3. opc-alarm-style.css

Step 5

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

<link rel="stylesheet" stype="text/css" href="css/font-awesome.min.css"/>
<link rel="stylesheet" stype="text/css" href="css/jquery.dataTables.css"/>
<link rel="stylesheet" stype="text/css" href="css/opc-alarm-style.css"/>

Step 6

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

OAS_config = {
    token:'7e61b230-481d-4551-b24b-ba9046e3d8f2',
    serverURL: 'http://localhost:58725/',
    alarm_bindings:[
      {
        alarmid:"alarm1", 
        showDelete: true,
        showHistory: true
      }
    ]
  };

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 7

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

<div id="alarm1"></div>

Note: The id of the div element is “alarm1“, which matches the alarmid configured in the previous step.

Step 8

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/jquery-1.8.3.min.js"></script>
      <script type="text/javascript" src="js/opc-lib-min.js"></script>
      <script type="text/javascript" src="js/datatables/jquery.dataTables.min.js"></script>
      <link rel="stylesheet" stype="text/css" href="css/opc-style.css"/>
      <link rel="stylesheet" stype="text/css" href="css/font-awesome.min.css"/>
      <link rel="stylesheet" stype="text/css" href="css/jquery.dataTables.css"/>
      <link rel="stylesheet" stype="text/css" href="css/opc-alarm-style.css"/>
      <script type="text/javascript">
        OAS_config = {
          token:'7e61b230-481d-4551-b24b-ba9046e3d8f2',
          serverURL: 'http://localhost:58725/',
          alarm_bindings:[
            {
              alarmid:"alarm1",
              showDelete:true,
              showHistory:true
            }
          ]       
        };
      </script>
    </head>
    <body>
      <div id="alarm1"></div>   
    </body>
</html>

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>

Getting Started – .NET Alarm

The following resources will provide you information to integrate the .NET Alarm control into a Visual Studio project targeting .NET Framework.

The .NET Alarm windows can also be accessed in the prebuilt Trends and Alarms Dashboard that can be used directly for local and remote deployment.

If you do not have a copy of Visual Studio you can download a free version of Visual Studio Community (formerly Visual Basic Express or C# Express) from visualstudio.microsoft.com/vs/community.  You can choose whether to use Visual Basic or C#, but if you have no experience with either language, Visual Basic is easier for new developers.  No programming is required to use .NET Alarm.

The following steps can be used to add an alarm window to a C#, C++, or Visual Basic.NET application. All properties are programmatically accessible.

The following example demonstrates the alarm window with no code required. You can use Visual Studio 2019 with WPF applications and Visual Studio 2022 with WinForm applications.

Alarm Properties

The descriptions of each property of the alarm control can be viewed when selecting the property.

Step 1: Create New Project

Start Visual Studio and select File->New->Project to create a new C# or VB project for Windows Forms App (.NET Framework).

Visual Studio New Project

When prompted choose C# or Visual Basic as language to target Windows Desktop applications.

Visual Studio Project Selection

Choose Windows Forms App (.NET Framework) as the new project type for C# or Visual Basic.

Visual Studio Windows Forms App

Set the Project name, Location, and the Framework of 4.6.2 or greater.

Visual Studio WinForm New Project

Select Create in the lower right corner.

VS Project Create

Step 2: Add OPCAlarmControl to Form

Select View-Toolbox to select controls from the Open Automation Software group.

VS View Toolbox

From the Toolbox if OPCAlarmControl components are not available right click in the Toolbox and select Choose Items.

.NET WinForm HMI 294

NOTE: If you have installed Visual Studio after Open Automation Software you can either right click on the Toolbox and select Choose Items to include the OPCControls.dll assembly from C:\Program Files\Open Automation Software\OAS\Controls\NetFramework\OPCControls\ or uninstall Open Automation Software and reinstall to register the OPCControls.dll assembly with Visual Studio.

From the .NET Framework Components select the OPCAlarmControl component and then select OK.

.NET Alarm 402

Step 3: Add OPCAlarmControl to Form

Add the OPCAlarmControl or OPCWPFAlarm component onto the Form or Window.

.NET Alarm 403

Resize both the form and alarm window to the desired size.

.NET Alarm 404

Right click on the alarm window and select Properties.

.NET WinForm HMI 297

Set the Anchor property to Top, Bottom, Left, Right.

.Net Trend 363

Step 4: Define Alarm Properties

Expand the AlarmFilter property and set the desired filter settings for the alarm window.

.NET Alarm 405

Step 5: Networking Alarms

To define remote OAS Engines to interface with select the AlarmNetworkNodes property and click on the small grey square with the 3 dots at the right.

.NET Alarm 406

Select all network nodes you wish to receive alarms from to this alarm window.

.NET Alarm 407

NOTE: If you want the application to be deployed across a network to remote PCs select the Network Node or enter an IP Address in the NetworkNode field and use the Select button to include the network node or IP Address of the OAS Engine source.

Step 6: Retain Runtime Changes to File

If you desire for the operator’s changes to the alarm window during runtime to remain set the ConfgiurationFile property to a valid file path. Make sure each system the application will run on that the directory path is valid.

.Net Trend 371

Note: If you set this property to a file make sure you deploy the file with the application in the directory you specify.

Leave this property blank if you wish to have the default properties set during configuration remain on the application restarting.

Step 7: Build Project

Set the compile mode on the Visual Studio toolbar to Release.

VS Release Mode

Select Build from the VS menu and select to build the application.

VS Build App

Step 8: Run Project

Use Windows Explorer to browse for the application located in the bin\Release directory and run the application.

.NET Alarm 408

Step 8: Deploy Application

To deploy the application to remote nodes first make sure the AlarmNetworkNodes selection as described in Step 9 is set to a Network Node or IP Address. Then simply copy the files in the bin\Release directory to the target systems or follow the Smart Client deployment section in this help file to deploy your application using Click Once Deployment.

To deploy the application simply copy the files in the bin\Release directory to the target systems, or follow the Smart Client Deployment guide using Click Once Deployment. The remote system that will run the application should have the .NET Framework version installed that the application targets.

Getting Started – .Net Trend

If you do not have a copy of Visual Studio you can download a free version of Visual Studio Community (formerly Visual Basic Express or C# Express) from visualstudio.microsoft.com/vs/community.  You can choose whether to use Visual Basic or C#, but if you have no experience with either language, Visual Basic is easier for new developers.  No programming is required to use .NET Trend for WPF and WinForm applications.

Step 1

Start Visual Studio and select File->New->Project to create a new C#, C++, or VB.

.NET WinForm HMI 292

WPF: If you are using WPF choose the OPCWPFDashboard assembly then use the OPCWPFTrend control.

WinForm: If you are using WinForm choose OPCTrendControl assembly.

Step 2

Select Windows Application or WPF Application as the project type.

.Net Trend 359

** Note: When using Visual Studio 2010 set the Target Framework to the full Framework. The Client Profile does not have the components needed for trending in your application.

View the following video on how to set the Target Framework for you Visual Basic or C# application:

Step 3

For WinForm applications from the Toolbox if OPCTrendControl is not available right click in the Toolbox and select Choose Items.

From the .NET Framework Components select OPCTrendControl and then select OK.

For WPF applications from the Toolbox right click to select all OPCWPFDashboard assembly controls including the OPCWPFTrend control.

Note: If you have installed Visual Studio after Open Automation Software you can either Browse and include the OPCWPFDashboard.dll assembly from C:\Program Files\Open Automation Software\OAS\ or uninstall Open Automation Software and reinstall to register the OPCWPFDashboard.dll assembly with Visual Studio.

.Net Trend 360

Use Add Reference and browse C:\Program Files\Open Automation Software\OAS\ to add the 5 following Nevron assemblies.

Step 4

Add the OPCTrendControl or OPCWPFTrend component onto the Form or Window.

.Net Trend 361

Resize both the form and trend window to the desired size.

.Net Trend 362

Step 5

Right click on the trend window and select Properties.

.NET WinForm HMI 297

Step 6

Set the Anchor property to Top, Bottom, Left, Right.

.Net Trend 363

Step 7

Expand the ChartRates property and set the TimeFrame to 60 seconds.

.Net Trend 364

Step 8

Select the Pens property and click on the small grey square with the 3 dots at the right.

.Net Trend 365

Step 9

Select the Local OAS Service to display a list of available Tags to

.Net Trend 366

Important: If you do not see the desired Tag in this list go back to Configure-Tags and enable the Trend Point property for the Tags you wish 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.

Note: If you wish to run this application on remote PCs make sure to include the Network Node or IP Address of the OAS Engine.  Select your Network Node or IP Address in the Browse Tags window.

Local Tag

myGroup.myTag.Value

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 10

Expand the Ramp Tag and select Value.

.Net Trend 368

Select the Add Pen button or right click on Value and select Add Pen.

.Net Trend 369

Step 11

The pen Ramp.Value will appear in the lower left list of pens. You can select the pen to change of the pen properties that appear to the right. The YAxisRangeHigh and YAxisRangeLow properties are important when the trend windows YAxis.ScaleMode property is set to PercentOfPenRanges.

Step 12

Select OK from the Pens dialog.

Step 13

Expand the Views property and set the trend window Lighting and PerspectiveView to the desired settings.

.Net Trend 370

Step 14

If you desire for the operator’s changes to the trend window during runtime to remain set the ConfigurationFile property to a valid file path. Make sure each system the application will run on that the directory path is valid.

.Net Trend 371

Note: If you set this property to a file make sure you deploy the file with the application in the directory you specify.

Leave this property blank if you wish to have the default properties set during configuration remain on the application restarting.

Step 15

Set the compile mode on the Visual Studio toolbar to Release.

.NET WinForm HMI 305

Step 16

Select Build from the VS menu and select to Build the application.

.NET WinForm HMI 306

Step 17

Use Windows Explorer to browse for the application located in the binRelease directory and run the application.

.Net Trend 372

Step 18

To deploy the application to remote nodes first make sure the Pen selection as described in Step 9 is set to a Network Node or IP Address. Then simply copy the files in the binRelease directory to the target systems or follow the Smart Client deployment section in this help file to deploy your application using Click Once Deployment.

View the following video on Smart Client Deployment:

Getting Started – .NET WinForm HMI

  • 00:00 – Introduction
  • 00:10 – How to Create an HMI Presentation using OPC Controls.NET
  • 00:30 – How to Use the Controls without Writing any Code
  • 00:36 – Create a Winform Application
  • 01:11 – Select OPC Controls Components
  • 01:33 – Label Control
  • 01:47 – Network Node
  • 02:21 – Set the Formatting
  • 02:32 – OPC Controls Button
  • 02:40 – Set the Color of the Button
  • 02:47 – Set the Pump Value
  • 03:20 – Test the Application
  • 03:47 – More Questions

If you do not have a copy of Visual Studio you can download a free version of Visual Studio Community (formerly Visual Basic Express or C# Express) from https://visualstudio.microsoft.com/vs/express/.  You can choose whether to use Visual Basic or C#, but if you have no experience with either language, Visual Basic is easier for new developers.  No programming is required to use WinForm HMI.

The following steps can be used to add visualization to a C#, C++, or Visual Basic.NET application. Refer to the VB.NET example for programmatic interface of using the OPCControls components. All properties are programmatically accessible.

The following example demonstrates the use of WinForm HMI with no code required.

Step 1: Create New Project

Load the default DemoTags Tag configuration file if you have replaced your tag configuration with your own tags.

Start Visual Studio and select File->New->Project to create a new C# or VB project for Windows Forms App (.NET Framework).

Visual Studio New Project

When prompted choose C# or Visual Basic as language to target Windows Desktop applications.

Visual Studio Project Selection

Choose Windows Forms App (.NET Framework) as the new project type for C# or Visual Basic.

Visual Studio Windows Forms App

Set the Project name, Location, and the Framework of 4.6.2 or greater.

Visual Studio WinForm New Project

Select Create in the lower right corner.

VS Project Create

Step 2: Add Controls to Form

Select View-Toolbox to select controls from the Open Automation Software group.

VS View Toolbox

From the Toolbox if OPCControls components are not available right click in the Toolbox and select Choose Items.

.NET WinForm HMI 294

NOTE: If you have installed Visual Studio after Open Automation Software you can either right click on the Toolbox and select Choose Items to include the OPCControls.dll assembly from C:\Program Files\Open Automation Software\OAS\Controls\NetFramework\OPCControls\ or uninstall Open Automation Software and reinstall to register the OPCControls.dll assembly with Visual Studio.

From the .NET Framework Components select all of the OPC Controls components and then select OK.

.NET WinForm HMI 295

Label

Add an OPCControlsLabel component onto the Form.

.NET WinForm HMI 296

Right click on the OPCControlsLabel window and select Properties.

.NET WinForm HMI 297

Select the TextOPCSystems_Tag property and use the browse button at the right to set the Open Automation Software Tag to Ramp.Value.

.NET WinForm HMI 298

NOTE: If you wish to run this application on remote PCs make sure to include the Network Node or IP Address of the OAS Engine.  Select your Network Node or IP Address in the Browse Tags window.

Value is the most commonly used Variable.  See Tag Variables for a complete list of all variables possible.

Local Tag

myGroup.myTag.Value

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

The following is an example of accessing an element of an array as a read only variable.

myGroup.myTag.Value[0]

Note: All Tag names are case sensitive. Ramp.Value is valid, ramp.value is not.

Button

Add an OPCControlsButton to the Form.

.NET WinForm HMI 299

Set the TextOPCSystems_Tag to Pump.Value. If the Pump Tag does not exist create a Boolean Tag using Configure-Tags with the name Pump.

Set the Format fields as defined below.

.NET WinForm HMI 300

Set the BackColorOPCSystems_Tag to Pump.Value.

.NET WinForm HMI 301

Set the SetValueOPCSystems_Tag to Pump.Value and the SetValueOPCSystems property to True.

.NET WinForm HMI 302

TextBox

Add an OPCControlsTextBox to the Form.

.NET WinForm HMI 303

Set the TextOPCSystems_Tag property to Pump.Value.  The Format properties for Boolean to Off and On.

.NET WinForm HMI 304

Step 4: Build Project

Set the compile mode on the Visual Studio toolbar to Release.

VS Release Mode

Select Build from the VS menu and select to build the application.

VS Build App

Step 5: Run Project

Use Windows File Explorer to browse for the application located in the bin\Release directory and run the application.

.NET WinForm HMI 307

Step 6: Deploy Application

NOTE: For remote deployment first make sure the Tags as described in steps 4, 5, and 6 are set to a Network Node or IP Address. You can optionally use the OPCControlsNetworkNodes component and assign a network node alias to change all “localhost” tags to the desired remote node.  This is done with the AddNetworkNodeAlias method. Refer to the VB.NET Example on the exact syntax of how to use this method. Notice how all OPC Controls data sources for a particular node can be reassigned to a remote node with one simple call.

To deploy the application simply copy the files in the bin\Release directory to the target systems, or follow the Smart Client Deployment guide using Click Once Deployment. The remote system that will run the application should have the .NET Framework version installed that the application targets.

Step 7: Other Controls and Properties

There are other OPCControls Components to add to the project with different properties to each control.  ImageIndex is available in many of the controls to display different images based on analog or discrete data.

The OPCControlsData component can be used to access data via code with very simple methods. Refer to the .NET Real Time Data Access Programmatic Interface.

Getting Started – WPF Expression Blend

Step 1

Load the default DemoTags Tag configuration if you have replaced your tag configuration with your own tags.

Start Expression Blend 4.0 and select New Project to create a new C#, or VB.

WPF Expression Blend 268

Step 2

Select WPF Application as the project type and Version 3.5 or 4.0

WPF Expression Blend 269

Step 3

From the Assets tab if OPCWPF components are not available, In the Projects Tab right click on References and select Add Reference to the following DLL.

For Version 3.5…

C:\Program Files\Open Automation Software\OAS\Blend3.5OPCWPF.dll

Or if you are using Version 4…

C:\Program Files\Open Automation Software\OAS\Blend4.0OPCWPFDashboard.dll

If it is available go to Step 4.

WPF Expression Blend 270

Step 4

From the Assets Tab add an OPCWPFLabel component onto the Window.

WPF Expression Blend 271

Choose the Selection Tool and then click on the label.

Select the Content_Tag property and use the browse button at the right to set the Open Automation Software Tag to Ramp.Value.

WPF Expression Blend 272

Note: If you wish to run this application on remote PCs make sure to include the Network Node or IP Address of the OAS Service source.

Note: All Tag names are case sensitive. Ramp.Value is valid, ramp.value is not.

Note: You can use the DirectOPC interface to connect directly to OPC Server Items is you just need to gain access to the server items without having to create Open Automation Software Tags.

Step 5

Add an OPCWPFButton to the Window.

WPF Expression Blend 273

Set the Content_Tag to Pump.Value.  If the Pump Tag does not exist create a Boolean Tag using Configure-Tags with the name Pump.

Set the Format fields as defined below…

WPF Expression Blend 274

Set the Background01_Tag to Pump.Value.

WPF Expression Blend 275

Set the SetValue_Tag to Pump.Value.

WPF Expression Blend 276

Step 6

Add an OPCWPFTextBox to the Window.

WPF Expression Blend 277

Set the Text_Tag property to Pump.Value. The Format properties for Boolean to Off and On.

WPF Expression Blend 278

Step 7

Add an OPCWPFDashboard360Gauge.

WPF Expression Blend 279

Set the Value_Tag to Ramp.Value.

WPF Expression Blend 280

Step 8

Select Build from the Project Menu to Build the application.

WPF Expression Blend 281

Step 9

Use Windows Explorer to browse for the application located in the binRelease directory and run the application.

WPF Expression Blend 282

Step 10

To deploy the application to remote nodes first make sure the Tags as described in steps 4, 5, and 6 are set to a Network Node or IP Address. Then simply copy the files in the binRelease directory to the target systems or follow the Smart Client deployment section in this help file to deploy your application using Click Once Deployment.

Note: You can also use the OPCWPFNetworkNodes component and assign a network node alias to change all “localhost” tags to the desired remote node. This is done with the AddNetworkNodeAlias method. Refer to the WinForm Example Code on the exact syntax of how to use this method. Notice how all OPC Controls data sources for a particular node can be reassigned to a remote node with one simple call.

Step 11

There are many different properties to each control. In WPF you can convert graphics to an Image Brush. The Image Brush can then be used as a background in most OPCWPF Controls.

The OPC WPF Data component can be used to access data via code with very simple methods.  Refer to the Forms FormReadValues and FormWriteValues in the WinForm Example Code.

Refer to the WPF Example application for demonstration example of all properties of all controls.

Getting Started – WPF Visual Studio

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.

The following steps can be used to add visualization to a C#, or Visual Basic.NET application. Refer to the VB.NET example for programmatic interface of using the OPC Controls components. All properties are programmatically accessible.

Note: Visual Studio 2022 design time properties no longer support custom property editors for WPF applications.  Use Visual Studio 2019 to develop WPF applications.

If you do not have a copy of Visual Studio 2019  you can download a free version of Visual Studio Community Edition for VB and C# from https://visualstudio.microsoft.com/vs/older-downloads/. If you have no experience with either Visual Basic or C# choose Visual Basic, no programming is required to use WPF HMI .NET or WinForm HMI.

  • 00:00 – Introduction
  • 00:14 – OAS Download
  • 00:40 – Build a visual studio app
  • 01:11 – Install OAS
  • 01:54 – View Box
  • 02:48 – Properties Window
  • 03:07 – Demo Tag Configuration
  • 03:28 – Tag Refencing Examples
  • 03:39 – Value Property
  • 03:53 – Add a Button to the window
  • 04:05 – Set content tag in the properties window
  • 04:34 – Change the color of the button
  • 05:06 – Radio gauge
  • 05:46 – Control Visualization
  • 06:15 – More Information

The following example demonstrates the use of OAS WPF HMI .NET with no code required:

Step 1

Load the default DemoTags Tag configuration if you have replaced your tag configuration with your own tags.

Start Visual Studio and select File->New->Project to create a new C#, or VB.

WPF Visual Studio 245

Step 2

Select WPF App (.NET Framework) as the project type.

WPF App (>NET Framework)

Set the Target Framework to 4.6.1 or greater.

Step 3

If you have installed Open Automation Software after installing Visual Studio you should see the Open Automation Software group in your toolbox.  If you see the tools, you can skip this step.

Note: If you have installed Visual Studio after Open Automation Software you can either Browse and include the OPCWPFDashboard.dll assembly from C:\Program Files\Open Automation Software\OAS\Controls\NetFramework\ or uninstall Open Automation Software and reinstall to register the OPCWPFDashboard.dll assembly with Visual Studio.

WPF Visual Studio 250

From the WPF Components select all of the OPCWPFDashboard Controls components and then select OK. For 4.0 Framework solutions use OPCWPFDashboard Namespace controls.

WPF Visual Studio 251

Step 4

If you want to make your Window adjustable for different screen resolutions and a sizeable Window with all controls automatically scaling specify a View Box.

When you create a WPF application by default the first container in the window is a Grid. Each container has an opening and closing statement in the XAML file.

For example:

<Window x:Class="MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow" Height="350" Width="525">
    <Grid>
        .....
    </Grid>
</Window>

All of your content will be in the grid.

To create a window with resizeable content add a ViewBox to the window and put the grid in the ViewBox.

Example:

<Window x:Class="MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow" Height="350" Width="525">
    <Viewbox>
        <Grid>
              ....
        </Grid>
    </Viewbox>
</Window>

Select the view box and set the stretch property the way you want the application to respond. The options are None, Fill, Uniform and Uniform to Fill. The default is Uniform.  I find it easiest to develop with it set to None and change it to Uniform when I am done.

Step 5

Add an OPCWPFLabel component onto the Window.

WPF Visual Studio 252

Right click on the OPCWPFLabel and select Properties.

WPF Visual Studio 253

Select the Content_Tag property and use the browse button at the right to set the Open Automation Software Tag to Ramp.Value.

WPF Visual Studio 254

Note: If you wish to run this application on remote PCs make sure to include the Network Node or IP Address of the OAS Engine.  Select your Network Node or IP Address in the Browse Tags window. 

Value is the most commonly used Variable.  See Tag Variables for a complete list of all variables possible.

Local Tag

myGroup.myTag.Value

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

The following is an example of accessing an element of an array as a read only variable.

myGroup.myTag.Value[0]

Note: All Tag names are case sensitive. Ramp.Value is valid, ramp.value is not.

Step 6

Add an OPCWPFButton to the Form.

WPF Visual Studio 255

Set the Content_Tag to Pump.Value.  If the Pump Tag does not exist create a Boolean Tag using Configure-Tags with the name Pump.

Set the Format fields as defined below…

WPF Visual Studio 256

Set the Background01_Tag to Pump.Value.

WPF Visual Studio 257

Set the SetValue_Tag to Pump.Value.

WPF Visual Studio 258

Step 7

Add an OPCWPFTextBox to the Form.

WPF Visual Studio 259

Set the Text_Tag property to Pump.Value. The Format properties for Boolean to Off and On.

WPF Visual Studio 260

Step 8

Select the Configuration Manager from the Build Menu.

WPF Visual Studio 261

Set the compile mode in the Configuration Manager to Release.

WPF Visual Studio 262

Step 9

Select Build from the VS menu and select to Build the application.

WPF Visual Studio 263

Step 10

Use Windows Explorer to browse for the application located in the bin\Release directory and run the application.

WPF Visual Studio 264

Step 11

To deploy the application to remote nodes first make sure the Tags as described in Steps 4, 5, and 6 are set to a Network Node or IP Address. Then simply copy the files in the bin\Release directory to the target systems or follow the Smart Client deployment section in this help file to deploy your application using Click Once Deployment.

Note: You can also use the OPCWPFNetworkNodes component and assign a network node alias to change all “localhost” tags to the desired remote node. This is done with the AddNetworkNodeAlias method. Refer to the WinForm Example Code on the exact syntax of how to use this method. Notice how all controls data sources for a particular node can be reassigned to a remote node with one simple call.

Step 12

There are many different properties to each control. In WPF you can convert graphics to an Image Brush. The Image Brush can then be used as a background in most OPCWPF and OPCWPFDashboard Controls.

The OPC WPF Data component can be used to access data via code with very simple methods. Refer to the .NET Real Time Data Access Programmatic Interface.

Getting Started – Security

Security is implemented to restrict modifying configuration parameters and limit real-time and historical data access.

The OAS Engine can have multiple security groups defined, each with a different level of access.

Each security group can have multiple users associated with it.

Users and Security Groups

Each user can only belong to one security group that is not the Default group.

In each OAS Engine there is a Default security group that is used to determine access level without a user specified.  If the feature is protected in the Default group then the security group defined to the User will be used to allow or deny access for the call made to the OAS Engine.

Security Flowchart

Following are the steps to setup security in the OAS platform.

Step 1 – Define Administrator User

An admin credential is created or reset using the AdminCreate utility located in the OAS Engine directory.

On Windows, the AdminCreate utility is automatically launched on the first attempt to login.
On Linux, an admin credential is created or reset using the AdminCreate utility found in the OAS installation directory.

To use the AdminCreate utility, execute the following:

chmod +x AdminCreate

./AdminCreate

You will then be prompted for the credential details.

NOTE: On Linux, if you used the installation script, it will create a user under which the OAS service will be running (default username of oasuser).
Running AdminCreate under the root user account will not update the security settings for the installed OASEngine. AdminCreate needs to be run while logged in as oasuser, and from within the installation path of that user.

After an admin credential has been created, select Log In from the menu and log in with the admin user you have just added.

OAS Log In

Log In

Step 2 – Set Default Security Access

Warning: Make certain to first add an Admin User in step 1 to all access and modification to the security configuration before disabling access and modification of Security in the Default Group.

The Default Security Group contains all of the security settings if a remote client application is not logged and is connected to the service.

Select Configure-Security.

Configure Security

Select the Default security group.

Select Default Security Group

All features of the Default security group are disabled by default.

Step 3 Create Additional Security Groups

Create security groups for customized access level to associate with a user or multiple users.

Change the Group Name property to the new desired security group name.

Group Name

Select Enable All Features to provide full access to all features or disable and set the desired access level for the security group under each of the tabs.

Click on the question mark next to the property to see a description of what the security property restricts.

Show Help Topic

Security Tabs

  • The Common properties are general features that are common to the entire OAS Service that can be restricted.
  • The Tags properties limit the creation, modification, removal, and browsing of tags.  Use Disable All Tags from Browsing to restrict which tags are available to users.
  • The Read Tags properties provide the feature to disable or enable real-time data access to Tags. You can either Disable All Tags From Reading and then Enable specific Tags, or leave all Tags for reading, but just Disable specific Tags.  The Read Tags properties affect real-time data access from HMI controls like OAS WPF HMI .NET, OAS WinForm HMI .NET and OAS Web HMI and also restrict real-time Trending and Data Logging on remote OAS Engines.
  • The Write Tags properties limit client applications from writing to Tags.
  • The Trends properties are for a few specific name retrieval functions for browsing trend tags and history fields.
  • The Trend RealTime properties help to limit access for real-time trending.
  • The Trend History properties allow restriction of history replay from clients.
  • The Data Log properties limit data logging configuration parameters from access and modification.
  • The Alarms properties limit obtaining the Alarm Group Names and adding alarms programmatically or editing alarm comments.
  • The Alarm Ack properties limit the ability to acknowledge alarms based on alarm priority and Alarm Groups.
  • The Alarm RealTime properties limit the ability to access the current alarms based on alarm priority and Alarm Groups.  This also restricts Alarm Logging and Alarm Notification of alarms on this OAS Engine on other remote OAS Engines.
  • The Alarm History properties limit the ability to access historical alarms from a database based on alarm priority and Alarm Groups.
  • The Alarm Log properties limit alarm logging configuration parameters from access and modification. To limit the actual alarms being logged use the Alarm RealTime properties.
  • The Alarm Notification properties limit alarm notification configuration parameters from access and modification.
  • The Dashboard properties determine what level of access is provided in the Web HMI Dashboard.
  • The Reports properties limit report configuration parameters from access and modification.
  • The Recipes properties limit the recipe configuration parameters from access and modification.
  • The Options properties limit the options configuration parameters from access and modification.
  • The Security properties limit the security configuration parameters from access and modification.

Select Add Group to add the new security group.

Add Group

Note: To define multiple security groups you can use CSV Export / Import.

CSV Import and Export

Step 4 Define Additional Users

Define Security Users with Configure-Users to assign a Security Group to each User. You cannot define the Default Security Group to a User.

Configure Users

Similar to Step 1 above with different user names, unique passwords, and the desired security group to use for each user.

Note: To define multiple users you can use CSV Export / Import.

CSV Import and Export

Step 5 Implement User Credentials in Client Applications

LogIn Method in .NET Applications

Each of the OAS .NET Assemblies have a LogIn method to call within your application to provide authentication to data in the OAS Engine.  If the Read Tags security feature is restricted and the LogIn is not specified the data quality on the client applications will be bad quality.  Other features may be restricted to acknowledge alarms or receive with the alarm control, view live or historical trend data, history, or access or set configuration properties in the OAS Engine.

Example use the OPCWPFDashboard assembly:

C#

OPCWPFDashboard.OPCWPFLogIn oasLogIn = new OPCWPFDashboard.OPCWPFLogIn();
oasLogIn.LogIn("UserName", "Password");
// Alternatively use the ShowUserLogIn method to prompt the user for a user name and password.
oasLogIn.ShowUserLogIn();

VB

Dim oasLogIn As New OPCWPFDashboard.OPCWPFLogIn
oasLogIn.LogIn("UserName", "Password")
' Alternatively use the ShowUserLogIn method to prompt the user for a user name and password.
oasLogIn.ShowUserLogIn()

Use the LogOff() method to clear the user credentials.

The above methods are applicable for the following assemblies and components.

  • OPCWPFDashboard.OPCWPFLogIn visualization in WPF .NET Framework applications.
  • OPCWPFDashboard.OPCWPFTrend for realtime and historical trending in WPF .NET Framework applications.  There is also a LogIn icon on the toolbar.
  • OPCWPFDashboard.OPCWPFAlarm for realtime and historical alarming in WPF .NET Framework applications.  There is also a LogIn icon on the toolbar.
  • OPCControls.OPCControlsLogin visualization in WinForm .NET Framework applications.
  • OPCTrendControl for realtime and historical trending in WinForm .NET Framework applications.  There is also a LogIn icon on the toolbar.
  • OPCAlarmControl for realtime and historical alarming in WinForm .NET Framework applications.  There is also a LogIn icon on the toolbar.
  • OPCSystems.OPCSystemsComponent for programmatic server configuration in .NET Framework applications.
  • OASConfig for programmatic server configuration in .NET Core, .NET 5, and .NET 6 applications.
  • OPCSystemsDataConnector.OPCSystemsDataLogin for programmatic data access in .NET Framework applications.
  • OASData for programmatic data access in .NET Core, .NET 5, and .NET 6 applications.
  • OPCTrendDataOnly for programmatic live and historical trend data in .NET Framework applications.
  • OASTrends for programmatic live and historical trend data in .NET Core, .NET 5, and .NET 6 applications.
  • OPCAlarmDataOnly for programmatic live and historical alarms in .NET Framework applications.
  • OASAlarms for programmatic live and historical alarms in .NET Core, .NET 5, and .NET 6 applications.

REST Authenticate

Use the Authenticate call with a user name and password of the OAS REST API to return a clientID and token from the OAS Engine.  the clientID and token are used in all subsequent calls to the OAS Engine.

Note: A blank user name and password cannot be used in the REST API for any of the configuration calls.

Web Authentication

Refer to Web UI Programming-Authentication Overview and Examples of how to return a token from the OAS Engine.

Remote Service Credentials

For all remote OAS Engines that will communicate to this OAS Engine go to Configure-Options-Remote Services for the remote nodes and set the Security User Name and Security Password.

Configure Options

Remote OAS Engine Security

These properties will allow the OAS Engine to run under this defined user account to give remote client access privileges for Read Tags for Calculations and Data Logging, and for Realtime Alarms for Alarm Logging and Alarm Notification. This is important if the remote OAS Engines have Security restrictions for these features.

OPCSystems.NET DA OPC Server Credentials

To set the user name and password credentials of the classic OPC DA OPC Server OPCSystems.NET edit the file DANSrv.exe.config at set the UserName and Password properties.

<add key="UserName" value=""/>
<add key="Password" value=""/>

OAS OPC UA Server Access

To provide authentication to remote OAS Engines of the OPC UA Server go to Configure-Options and set the OPC UA Security Access to either OASServiceUser or OPCClientUser.

Configure Options

You can view the OAS Security video to familiarize yourself with the following steps to setup security.

  • 00:00 – Introduction
  • 00:19 – What Security is implemented for?
  • 00:27 – Security Groups
  • 00:44 – Creating an Admin User
  • 01:18 – Security Configuration
  • 01:44 – Configuring the Default Security Group
  • 02:29 – Creating a New Security Group
  • 04:26 – Set Up Alarms
  • 05:13 – Dashboard Tab
  • 05:22 – Reports Tab
  • 05:29 – Recipes Tab
  • 05:34 – UDP Broadcast Tab
  • 05:39 – Live Data Cloud
  • 05:46 – Security Tab
  • 05:57 – Options Tab
  • 06:03 – New Security Group
  • 06:43 – Saving the Configuration File
  • 07:31 – Restrict Tag Access
  • 010:59 – Implementing Security in a Client Application
  • 011:57 – Logins Methods
  • 012:08 – Tag Access Demonstration
  • 013:18 – Login Method
  • 014:15 – Log Off Method
  • 014:28 – Logging into Rest API
  • 015:12 – Web Applications
  • 015:34 – Provide Security to a remote OAS Service
  • 016:05 – Pass Security to the OAS OPC Server
  • 016:25 – Copy the file out of the directory
  • 017:05 – OAS Excel Security Option
  • 017:23 – More Information

Getting Started – Recipe

View the following video for a step by step tutorial on setting up recipe executions:

Recipes are used to transfer values from a database to Open Automation Software Tags. If the Tags Data Source is set device data or IoT Cloud systems the values will also be written to the source the Tag is defined to. The most common implementation is to have a variable in a PLC trigger the recipe execution.

The PLC will then wait for either the Confirmation or Error Code to be written to the PLC to indicate if the recipe execution has completed. If in Error the PLC can then retry the Trigger.

Follow the steps listed below or view the video on defining recipes.

For a complete list of all Recipe properties refer to the Recipe Properties section in this help file.

Step 1

OASStart Configure OAS application if it is not already running.

Step 2

Select Configure Tags to add some Tags to use with the Recipe execution.

Configure Tags

Step 3

Select the Local OAS Service by selecting the Select button next to the Network Node dropdown.

Network Node

Step 4

If you are working on an existing Tag configuration you want to keep save it now.

Right Click on the Tags Group at the root level of the Tag Tree and select Delete All to clear all Tags.

Delete All

Step 5

Add the following Tags with the specific Data Types:

Trigger as a Boolean

Value01 as an Integer

Value02 as an Integer

Lot as a String with the Value A

Confirmation as a Boolean

Error Code as an Integer

Query String as a String with Data Source of Calculation
“WHERE Lot = ” & “‘” & [Lot.Value] & “‘”

Step 6

Select the Save button on the toolbar at the top and use the file name Recipe Tags.

Save Button

Step 7

Use Microsoft SQL Server, Oracle, Access, mySQL, PostgreSQL, Cassandra, or MongoDB to create the following Table.

Create a Database called OASDemoRecipes

Create a Table called RecipeValues with the following structure.

Recipe

Enter the following values to the Table RecipeValues.

Recipe

Step 8

With the Configure OAS application select Configure-Recipes.

Configure Recipes

Step 9

Select the Local OAS Service by selecting the Select button next to the Network Node dropdown.

Network Node

Step 10

Enter the Recipe Name Recipe 01.

Recipe Name

Set the Recipe Active.  You also have he option to Activate the Recipe with a Tag.  For this tutorial just check the Recipe Active box.

Recipe Active

Set the Recipe Type to Wide Table.

Recipe Type

  • A Wide Table type allows you to map the database fields to read to the OAS tags in the Tags tab of the recipe group.
  • A Queued Wide Table type performs the same as Wide Table type and will delete the top record if the recipe execution is successful.
  • A Narrow Table has only 2 fields, one for the Tag Name to set and one for the Value to write to the Tag.  Using this type you can define the Tags to write to in the database table along with the values.
  • A Queue Narrow Table type performs the same as Narrow Table type and will delete the records obtained if the recipe execution is successful.

Set the Tag to Execute Recipe as Trigger.Value.

Enable Confirmation Tag as Confirmation.Value.

Enable Error Tag as Error Code.Value.

Recipe Properties

When a recipe is executed it will only write to Tags where the desired value from the database is different than the current value of the Tag.  For floating point values use the Float Deadband property under the Common tab to define what is the allowable range to determine if a value is the same or different.

The Timeout property is the amount of time the recipe execution will wait for all values to be returned from the Tags.  If one or more of the values does not read back from the data source the recipe execution will end with an Error Code of Timeout.

The property Write All Values Without Feedback will not wait for the values to be returned and will write all database values to all defined Tags.  This is preferred for a faster execution when using the Execution Type Continuous.

Step 11

Select the Tags Tab

Tags Tab

With the Tags properties you can assign the database table fields to Open Automation Software Tags to write to when the recipe executes.

All OAS Tag Variables that are write capable including configuration parameters can be updated.

If the Data Source of the Open Automation Software Tag is defined to a device or IoT cloud server a write to the Value variable will it will automatically write the database value to the source.

Select the Add Field button.

Add Tags

Select the Tag and Parameter Value01.Value.

Change the Field Name to Value01.

Change the Data Type to Integer.

Recipe Value01

Select OK.

Select the Add Field button.

Add Tags

Select the Tag and Parameter Value02.Value.

Change the Field Name to Value02.

Change the Data Type to Integer.

Recipe Value02

Select OK.

Aggregate SQL Functions

You can use aggregate functions MIN, MAX, AVG, SUM, COUNT, STDEV, STDEVP, VAR, VARP, COUNT_BIG, GROUPING, GROUPING_ID, and CHECKSUM_AGG.
Set the Field Name to the function with the table field. Example = MIN(FieldName)

Dynamic Tag Aliasing

Dynamic Tag Name Aliasing is possible with one or more of the 3 alias types. This is typically used with queries that will return multiple rows, but can used also with just a single row returned.
The alias definition is encapsulated with # and is replaced entirely with the value for the database, zero based row number, or field name.

DB-Value: Changes the Tag Name based on the field value returned for the column name and data type specified.
#DB-Value:FieldName:DBType:TextFormat#
DBType = Integer, Double, Boolean, Date/Time, Single, Long, Short, SByte, String, NChar, Varchar, or NVarchar
TextFormat is optional and is used to convert the native value from the database to a text string
Example = #DB-Value:FieldName:Integer:0000#

DB-Row: Changes the Tag Name based on the zero row number returned from the query.
#DB-Row:TextFormat#
Example = #DB-Row:0000#

DB-Field: Changes the Tag Name based on the field name defined.
#DB-Field#

TAG-Value: Changes the Tag Name based on the tag value of a local tag. Please note this feature does not currently support remote network tags.
#TAG-Value:TagName.Variable:TextFormat#
TextFormat is optional and is used to format the conversion the native tag value to a text string
Example = #TAG-Value:TagName.Value:0000#

Full example using dynamic tag aliasing: #DB-FIELD#Row#DB-ROW:0000#id#DB-VALUE:id:Integer:0000#.Value
The tag name will be changed to Value1Row0000#id1234.Value for row 0 if the field name is Value1, and the value of Integer id column is 1234
The tag name will be changed to Value1Row0001#id5678.Value for row 1 if the field name is Value1, and the value of Integer id column is 5678

Stored Procedures

When obtaining values from Stored Procedure set the Field Name to the Stored Procedure Return Name.

Step 12

Select the Database Tab.

Database Tab

Define the proper database connection.

Enable the property Set Query String with Tag and set to Query String.Value.

Recipe Database Configuration

Note: A View can be used in replace of the Table.

Step 13

Select the Add button in the lower left to add the Recipe.

Add Recipe

Step 14

Select the Save button on the toolbar at the top.

Save

Save the file RecipeExample.Recipes in the directory OASDemo.

Go to Configure-Options and select the Default Files tab and set the default Recipe Configuration file to the file you just saved.

To track details of recipe execution go to Configure-Options and select the System Logging tab to enable Log Recipe Transactions and specify where the recipe transactions will be save.

Step 15

At this point you are ready to execute the recipe which you can do with Configure-Tags to set the Lot to A, B, or C, then set the Trigger Value from False to True.

You can then see that the Confirmation Tag will be set to True and Value01 and Value02 update if the Recipe is successful or the Error Code Tag will be a positive number if there is an error. Review the Recipe Transaction Log for details of the transaction.