Example 6 - Full Transactional Data Flow (OPC UA)

This example demonstrates a flow starting with an OPC UA method call, performing an HTTP request and giving back the HTTP request result as method call result via OPC UA.

The configuration connects dns.google on the north side with a custom OPC UA method on the south side. The OPC UA server provides a method getIpForDomain that accepts a domain name (e.g., cybus.io) as input and returns the corresponding IP address as output.

You can access the OPC UA server via opc.tcp://127.0.0.1:4841/UA/CybusOpcuaServer.

  • If the domain is successfully resolved, the method returns the IP address.

  • If no DNS record is found, it returns a BadNotFound error.

For more information on the FlowSync configuration properties, see Cybus:Node.

flowsync-example-6-full-transactional-data-flow-opc-ua.yaml
description: FlowSync - Example 6
metadata:
  name: example 6
  version: 1.0.0
resources:
  # ------------------------------------------------
  # Our Endpoints for dns.google (north side)
  # ------------------------------------------------

  googleDnsConnection:
    type: Cybus::Connection
    properties:
      protocol: Http
      connection:
        scheme: https
        host: dns.google

  dnsEndpoint:
    type: Cybus::Endpoint
    properties:
      topic: dns
      protocol: Http
      connection: !ref googleDnsConnection
      publishError: true
      read:
        path: /resolve

  # ---------------------------------------
  # Our OPCUA Server and Nodes  (south side)
  # ---------------------------------------

  opcuaServer:
    type: Cybus::Server::Opcua
    properties:
      hostname: 127.0.0.1
      allowAnonymous: true
      securityPolicies: ['None']
      securityModes: ['None']

  rootNode:
    type: Cybus::Node::Opcua
    properties:
      browseName: Cybus
      nodeId: ns=1;s=Cybus
      parent: !ref opcuaServer
      nodeType: Object

  getIpForDomainNode:
    type: Cybus::Node::Opcua
    properties:
      topic: getIpForDomain
      browseName: getIpForDomain
      nodeId: ns=1;s=getIpForDomain
      parent: !ref rootNode
      nodeType: Method # mark node as method
      operation: transaction
      inputArguments:
        - name: domain
          dataType: String
          description: the domain to resolve
      outputArguments:
        - name: ip
          dataType: String
          description: the IP address of the domain

  # ------------------------------------------------
  # The mappings forwarding requests and responses
  # ------------------------------------------------

  Mapping:
    type: Cybus::Mapping
    properties:
      mappings:
        - subscribe:
            endpoint: !ref getIpForDomainNode
          publish:
            endpoint: !ref dnsEndpoint
          rules:
            - transform:
                expression: >-
                  (
                    {
                      "id": $.id,
                      "query": {
                         "name": $.value.inputArguments[0].value
                      }
                    }
                  )
        - subscribe:
            endpoint: !ref dnsEndpoint
          publish:
            endpoint: !ref getIpForDomainNode
          rules:
            - transform:
                expression: >-
                  (
                    {
                      "id": $.id,
                      "timestamp": $.timestamp,
                      "value" : $.value.Status = 0 ? { 
                         "outputArguments": [
                            {
                              "value": $.value.Answer[0].data
                            }
                         ]
                      } : undefined,
                      "error" : $.value.Status != 0 ? {
                        "code": "BadNotFound",
                        "message": "Domain not found"
                      } : undefined
                    }
                  )

Last updated

Was this helpful?