Goals
To move data from one or more data sources (PLCs, databases, IoT devices, or any other source supported by OAS) to an external REST API for data logging, analytics, or any other function supported by the endpoint.
Supported Data Sources
- Allen Bradley PLCs
- Siemens PLCs
- Modbus Devices
- OPC Servers
- Applications
- OPTO Devices
- MQTT Brokers
- Amazon IoT
- Azure IoT Hub
- Databases
Solution Description
Any data source that can be connected to an OAS Universal Data Connector can have its data transferred to an external REST API. Once the data is in Tags, it can be used directly, transformed, or even be used as an input to new Calculation Tags.
Real time tag data can then be extracted from OAS using any of the available APIs. For .NET developers, the .NET Data Connector provides programmatic access and an event-driven model for updating applications when Tags change within the OAS Service. Developers who choose not to use .NET, or for developers not targeting Windows as the execution platform, the OAS REST API exposes real time Tag data as JSON structures over HTTP.
Tag data can then be further transformed and encapsulated into REST API calls required by the external system.
OAS Components Used
This example Use Case utilizes the following OAS Platform Components and can be deployed in many different configurations to achieve the best performance and reliability:
Example Solution
The example below demonstrates connectivity to a generic REST API using our .NET Data Connector in a .NET console application. This same logic can be used in any .NET app, including desktop applications, Windows services, and even .NET Core apps deployed to other platforms.
The OASData Component : Event-based data updates
Connecting your .NET application to an OAS Server for data updates is as simple as including the OASData component. This .NET assembly ships with the OAS Platform and is compatible with .NET Framework 4.6+ as well as .NET Core 2.0+, so you have the flexibility of deployment to any supported environment.
Module Module1 ' real time data access component Dim WithEvents osd As New OASData.Data() Sub Main() ' your code here End Sub End Module
Once you’ve included the OASData component in your application, you create and configure an event handler for the ValuesChangedAll event.
Public Sub ValuesChangedAll(Tags As String(), Values As Object(), Qualities As Boolean(), Timestamps As DateTime()) Handles osd.ValuesChangedAll ' read changed values End Sub
Next, you add a list of OAS Tags to monitor. The ValuesChangedAll even will fire every time any of the Tag values change on the OAS server. When the even fires, it will be passed a set of arrays containing the list of Tags, their Values, the Data Qualities of each, as well as Timestamps when the respective values changed on the server.
Sub Main() osd.AddTag("Sine.Value") ' single tag osd.AddTags(New String() {"Ramp.Value", "Random.Value"}) ' multiple tags ' issue a ReadLine to keep the console app running Console.WriteLine("Listening for Tag updates...") Console.ReadLine() End Sub
This completes the code necessary to monitor tags on the OAS server. You can then use these tag values and write them to an external REST API. To do this, you use the built-in .NET HTTP communications classes to make calls to your remote API. Alternatively, if your 3rd party API provides a .NET SDK, you can use it here as well. Below, we illustrate taking the OAS Tag data, putting it into a JSON structure and posting it to a remote server. Your remote API data structures and authentication requirements will vary.
Posting values to a REST API
Below is an example of how you could read Tag values updating from the OAS Platform and post them to an external REST API immediately as they change. Every time values change, a JSON string is constructed and passed to a function SendMessage that POSTs to a REST API.
Public Sub ValuesChangedAll(Tags As String(), Values As Object(), Qualities As Boolean(), Timestamps As DateTime()) Handles osd.ValuesChangedAll If (Not Tags Is Nothing AndAlso Tags.Length > 0) Then ' build JSON string Dim taglist As New List(Of String) For idx As Integer = 0 To Tags.Length - 1 Dim t As String = Tags(idx) Dim v As Object = Values(idx) Dim q As Boolean = Qualities(idx) Dim ts As DateTime = Timestamps(idx) If (q) Then taglist.Add("{" + String.Format(" ""tag"":""{0}"",""value"":""{1}"",""time"":""{2}"" ", t, v, ts) + "}") End If Next Dim json As String = "{""tags"": [ " json += String.Join(",", taglist.ToArray()) json += "]}" 'POST to external API Try Dim result As String = SendMessage(json) Catch ex As Exception ' handle exceptions End Try End If End Sub
The contents of SendMessage create an HTTPClient, POST the data, and return the result as a string. This is all done synchronously in this example, but could be performed asynchronously as well. You could also parse the result from the server and handle errors accordingly.
Public Function SendMessage(message As String) As String Dim c As New System.Net.Http.HttpClient() Dim url As String = "http://someserver.com/REST/endpoint" 'address of external 3rd party API Dim resp As System.Net.Http.HttpResponseMessage Dim content As New System.Net.Http.StringContent(message, Text.Encoding.UTF8, "application/json") 'execute HTTP POST - your API may vary or require pre-authorization resp = c.PostAsync(url, content).Result 'convert response to String Dim rs As System.IO.Stream = resp.Content.ReadAsStreamAsync().Result Dim reader As New System.IO.StreamReader(rs, Text.Encoding.UTF8) Dim rstring As String = reader.ReadToEnd() Return rstring End Function
Setting OAS Tags from REST API data
If you need to read external REST API data, you would need to first perform a request for data from the API, then parse the result, and set the OAS Tag data based on the values received.
Your external REST API will vary, but the following is an example of requesting data from an API, parsing it using the JSON.Net library, reading values and setting OAS Tags.
Public Sub SetTags(message As String) Dim c As New System.Net.Http.HttpClient() Dim url As String = "http://someserver.com/REST/getvalues" 'address of external 3rd party API 'execute HTTP GET - your API may vary or require pre-authorization Dim resp As System.Net.Http.HttpResponseMessage = c.GetAsync(url).Result 'convert response to String Dim rs As System.IO.Stream = resp.Content.ReadAsStreamAsync().Result Dim reader As New System.IO.StreamReader(rs, Text.Encoding.UTF8) Dim rstring As String = reader.ReadToEnd() 'parse into JObject Dim jobj As Newtonsoft.Json.Linq.JObject = Newtonsoft.Json.Linq.JObject.Parse(message) Dim tags As Newtonsoft.Json.Linq.JArray = jobj("tags") Dim tNames As New List(Of String)() Dim tVals As New List(Of String)() 'gather tags and values from JSON For idx As Integer = 0 To tags.Count - 1 Dim tobj As Newtonsoft.Json.Linq.JObject = tags(idx) tNames.Add(tobj("tag").ToString()) tVals.Add(tobj("value").ToString()) Next 'write Tags and Values to OAS Platform Synchronously osd.SyncWriteTags(tNames.ToArray(), tVals.ToArray()) 'alternatively, use WriteTags to write values asynchronously for better performance osd.WriteTags(tNames.ToArray(), tVals.ToArray()) End Sub