Example 6 - Full Transactional Data Flow (OPC UA)

This example demonstrates how to integrate an external DNS service with an OPC UA method using FlowSync. The configuration connects dns.google on the north side with a custom OPC UA method on the south side. The OPC UA server uses a getIpForDomain method 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.

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?