Skip to content

OPC Router Tutorial Backend

Following the eleventh part of the OPC Router tutorial, I’m presenting how to implement more advanced backend features for our recently created REST API. Remember, we’re configuring and running a project for “Papín”, a fictional potato bread factory.

Why an OPC Router tutorial with Backend?

Because “learning by doing” with examples is fun. Also, this functionality can provide us with a unique use case: the power to deploy the backend for a web-enabled application in a very intuitive visual way, which is an outstanding option when we want to implement some business logic simpler and faster. See below a list of posts that complete this tutorial:

  1. Getting Started with OPC Router
  2. Connect an OPC DA server to Microsoft SQL Server
  3. Connect an MQTT data source to InfluxDB Cloud
  4. Perform multiple calculations within OPC Router
  5. Run an OPC Router application with Linux and Docker
  6. Build a process data simulator with Python, CSV and OPC Router
  7. Explore basic RESTful web services within OPC Router
  8. Build a Telegram basic interaction within OPC Router
  9. Build an SMS basic interaction within OPC Router
  10. Build a WhatsApp basic interaction within OPC Router
  11. Build a Teams basic interaction within OPC Router
  12. Explore advanced RESTful web services within OPC Router (this post)
  13. Run an OPC Router application with Portainer

Considerations

From this point on, we must download and install OPC Router v4.27.5016.75 or later to make this feature work appropriately. Also, OPC Router Config was renamed to OPC Router Management.

Prerequisites

Firstly, you’ll need:

  • Google Chrome, Mozilla Firefox, or Microsoft Edge web browser 🌐
  • Microsoft SQL Server database 🧱
  • Microsoft SQL Server Management Studio (SSMS) 🎙️ (or equivalent application)
  • FactoryTalk Linx Gateway as OPC DA server 🛤️
  • ControlLogix 1756-L61 as Programmable Automation Controller (PAC) 🤖
  • Schematic diagram 📝
  • OPC Router Management application 💻

User Story

We want to build a REST interface that allows us to take some calculated values from a SQL Server database, and send them back to an industrial automation controller through an OPC DA server.

Schematic Diagram

To illustrate this new approach better, look at this:

opc router tutorial backend 1

Additionally, make sure to complete the previous post here.

Updates to our REST API design

At this point, add the new resources that will be exposed by this service:

HTTP MethodResource NameResource Action
GET/AvgValueMCurrPln01Average value of MCurr at PLN01.
GET/MinValueMTorqPln02Minimum value of MTorq at PLN02.
GET/MaxValueMSpdPln03Maximum value of MSpd at PLN03.
GET/OptimalValueMSpdPln03Optimal value of MSpd at PLN03.

Check your output data channel

  • At this instant, make sure to check OPC topic “P_PBF19_PA01” for 1756-L61 controller through Factory Talk Linx Gateway OPC DA interface.
opc router tutorial backend 2
  • In order to check the transfer, monitor variables within “Controller Tags” tab:
opc router tutorial backend 3
opc router tutorial backend 4
opc router tutorial backend 5
opc router tutorial backend 6

Create and Test Stored Procedures

sp_avg_mcurr_pln01

  • To begin with, consider saved MCurr values at PLN01:
opc router tutorial backend 7
  • Then, the idea I propose here is for the database engine to calculate the average value of MCurr at PLN01:
AVERAGE(
108.70000
109.17000
106.33000
108.70000
109.17000
106.33000
108.70000
109.17000
106.33000
108.70000
109.17000
)
  • With this in mind, notice that you should expect an average value of 108.224545.
AVERAGE(MCurr) = 108.224545
  • At this point, let’s create and test our first database stored procedure as “dbo.sp_avg_mcurr_pln01“:
opc router tutorial backend 8
  • Initially, run SSMS and connect to the database server.
opc router tutorial backend 9
opc router tutorial backend 10
  • Press “Ctrl +N” or click the “New Query” button to start this process:
opc router tutorial backend 11
  • Enter the SQL code below:
USE [papinpbf19_db]
GO

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE PROCEDURE [dbo].[sp_avg_mcurr_pln01](
@cd_location1 bigint  OUT,
@cd_location2 bigint  OUT,
@cd_location3 bigint  OUT,
@cd_variable  bigint  OUT,
@avg          DECIMAL(18,5) OUT
)
AS
BEGIN

    SELECT @avg = AVG(qt_value)
      FROM pv.tb_rv_vsd_motor_i
     WHERE (
	   (pv.tb_rv_vsd_motor_i.cd_location1 = @cd_location1)
       AND (pv.tb_rv_vsd_motor_i.cd_location2 = @cd_location2)
       AND (pv.tb_rv_vsd_motor_i.cd_location3 = @cd_location3)
       AND (pv.tb_rv_vsd_motor_i.cd_variable = @cd_variable))
    return @avg
END
opc router tutorial backend 12
  • Press “F5” or click the “Execute” button to run the new SQL query:
opc router tutorial backend 13
  • Following this, refresh the “Stored Procedures” folder:
opc router tutorial backend 14
  • After that, notice the newly created stored procedure:
opc router tutorial backend 15
  • Right click the stored procedure and click the “Execute Stored Procedure…” to begin the test.
opc router tutorial backend 16
  • Later, enter the test data and click “OK”.
opc router tutorial backend 17
  • Lastly, watch the results window and make sure it matches the expected (rounded) value.
opc router tutorial backend 18

sp_min_mtorq_pln02

  • To begin with, consider saved MTorq values at PLN02:
opc router tutorial backend 19
  • Then, the idea I propose here is for the database engine to calculate the minimum value of MTorq at PLN02:
MINIMUM(
361.78000
362.25000
359.97000
350.12000
361.78000
362.25000
359.97000
361.78000
362.25000
359.97000
361.78000
)
  • With this in mind, notice that you should expect a minimum value of 350.12000.
MINIMUM(MTorq) = 350.12000
  • At this point, let’s create and test our second database stored procedure as “dbo.sp_min_mtorq_pln02“:
opc router tutorial backend 20
  • Enter and run the SQL code below:
USE [papinpbf19_db]
GO

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE PROCEDURE [dbo].[sp_min_mtorq_pln02](
@cd_location1 bigint  OUT,
@cd_location2 bigint  OUT,
@cd_location3 bigint  OUT,
@cd_variable  bigint  OUT,
@min          DECIMAL(18,5) OUT
)
AS
BEGIN

    SELECT @min = MIN(qt_value)
      FROM pv.tb_rv_vsd_motor_t
     WHERE (
	   (pv.tb_rv_vsd_motor_t.cd_location1 = @cd_location1)
       AND (pv.tb_rv_vsd_motor_t.cd_location2 = @cd_location2)
       AND (pv.tb_rv_vsd_motor_t.cd_location3 = @cd_location3)
       AND (pv.tb_rv_vsd_motor_t.cd_variable = @cd_variable))
    return @min
END
opc router tutorial backend 21
  • Later, enter the test data for the procedure and click “OK”.
opc router tutorial backend 22
  • Lastly, watch the results window and make sure it matches the expected value.
opc router tutorial backend 23

sp_max_mspd_pln03

  • To begin with, consider saved MSpd values at PLN03:
opc router tutorial backend 24
  • Then, the idea I propose here is for the database engine to calculate the maximum value of MSpd at PLN03:
MAXIMUM(
705.68000
700.15000
703.77000
705.68000
700.15000
703.77000
707.08000
705.68000
700.15000
703.77000
)
  • With this in mind, notice that you should expect a maximum value of 707.08000.
MAXIMUM(MSpd) = 707.08000
  • At this point, let’s create and test our third database stored procedure as “dbo.sp_max_mspd_pln03“:
opc router tutorial backend 25
  • Enter and run the SQL code below:
USE [papinpbf19_db]
GO

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE PROCEDURE [dbo].[sp_max_mspd_pln03](
@cd_location1 bigint  OUT,
@cd_location2 bigint  OUT,
@cd_location3 bigint  OUT,
@cd_variable  bigint  OUT,
@max          DECIMAL(18,5) OUT
)
AS
BEGIN

    SELECT @max = MAX(qt_value)
      FROM pv.tb_rv_vsd_motor_s
     WHERE (
	   (pv.tb_rv_vsd_motor_s.cd_location1 = @cd_location1)
       AND (pv.tb_rv_vsd_motor_s.cd_location2 = @cd_location2)
       AND (pv.tb_rv_vsd_motor_s.cd_location3 = @cd_location3)
       AND (pv.tb_rv_vsd_motor_s.cd_variable = @cd_variable))
    return @max
END
opc router tutorial backend 26
  • Later, enter the test data for the procedure and click “OK”.
opc router tutorial backend 27
  • Lastly, watch the results window and make sure it matches the expected value.
opc router tutorial backend 28

Exploring Other Calculated Values

  • In this case, suppose you have these calculated MCurr, MTorq and MSpd values by a third-party algorithm within the “tb_cv_optimal_value” database table.
opc router tutorial backend 29
  • The idea I propose here is for OPC Router to select the most recent optimal value of MSpd at PLN03, but without the use of any stored procedure.
opc router tutorial backend 30
  • With this in mind, notice that you should expect an optimal value of 639.00000.
LAST_OPT(MSpd) = 639.00000

Creating Resources

/AvgValueMCurrPln01

  • At this time, let’s create the resource to return the average value of MCurr at PLN01 as “GET AvgValueMCurrPln01“:
opc router tutorial backend 31
  • Then, drag and drop these five blocks as shown here:
opc router tutorial backend 32
  • After that, edit the REST trigger block to include the new URL endpoint and the JSON response format:
opc router tutorial backend 33
  • At this point, edit the “Constant Values” block with a fixed location at PLN01 and the appropriate variable code:
  • Furthermore, edit the Database block and make sure it looks like this:
  • Also, edit the JSON Write block:
  • Finally, edit the OPC Data Access block with the specific controller tag:
  • Then, make sure all transfer objects look like these:
  • Following this, make sure to link blocks as shown here to complete the resource:
  • At this point, test the API with Swagger.

/MinValueMTorqPln02

  • At this time, let’s create the resource to return the minimum value of MTorq at PLN02 as “GET MinValueMTorqPln02“. Just copy, paste and rename from the “GET AvgValueMCurrPln01” connection.
  • After that, edit the REST trigger block to include the new URL endpoint and the JSON response format:
  • At this point, edit the “Constant Values” block with a fixed location for PLN02 and the appropriate variable code:
  • Furthermore, edit the Database block and make sure it looks like this:
  • Also, keep the JSON Write block:
  • Finally, edit the OPC Data Access block with the specific controller tag:
  • Following this, make sure to link blocks as shown here to complete the resource:
  • At this point, test the API with Swagger.

/MaxValueMSpdPln03

  • At this time, let’s create the resource to return the maximum value of MSpd at PLN03 as “GET MaxValueMSpdPln03“. Just copy, paste and rename from the “GET MinValueMTorqPln02” connection.
  • After that, edit the REST trigger block to include the new URL endpoint and the JSON response format:
  • At this point, edit the “Constant Values” block with a fixed location for PLN03 and the appropriate variable code:
  • Furthermore, edit the Database block and make sure it looks like this:
  • Also, keep the JSON Write block:
  • Finally, edit the OPC Data Access block with the specific controller tag:
  • Following this, make sure to link blocks as shown here to complete the resource:
  • At this point, test the API with Swagger.

/OptValueMSpdPln03

  • At this time, let’s create the resource to return the optimal value of MSpd at PLN03 as “GET OptValueMSpdPln03“. Just copy, paste and rename from the “GET MaxValueMSpdPln03” connection.
  • After that, edit the REST trigger block to include the new URL endpoint and the JSON response format:
  • At this point, edit the “Constant Values” block with a fixed location for PLN03:
  • Furthermore, edit the Database block so as to use a SELECT command instead of a stored procedure:
  • Also, keep the JSON Write block:
  • Finally, edit the OPC Data Access block with the specific controller tag:
  • Following this, make sure to link blocks as shown here to complete the resource:
  • At this point, test the API with Swagger.

Visualize Online Data in OPC Router

  • Also, you can watch live values here:
  • At this point, you should notice an execution time visually:

Verify Data Transfer to Controller Tags

  • Finally, watch how the OPC Router tutorial allows us to implement a light backend for a web-enabled application by sending calculated values from a SQL Server database to an industrial automation controller.
  • Firstly, watch the calculated average value of MCurr at PLN01 transferred to the controller.
  • Then, watch the calculated minimum value of MTorq at PLN02 transferred to the controller.
  • After that, watch the calculated maximum value of MSpd at PLN03 transferred to the controller.
  • Finally, watch the calculated optimal value of MSpd at PLN03 transferred to the controller.

Did you enjoy this OPC Router tutorial with Backend? I’d love to hear from you.

Stay tuned and follow part 13 of this tutorial! 😎

For other articles like this one in English, click here. To see them in Spanish, click here.

Share this post