Skip to content

Commit

Permalink
feat: add support for FindServers and FindServersOnNetwork
Browse files Browse the repository at this point in the history
  • Loading branch information
sruehl committed Aug 21, 2023
1 parent 41d44f4 commit 868add3
Show file tree
Hide file tree
Showing 4 changed files with 120 additions and 2 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@ build/
dist/
__pycache__/
.vscode/
.idea/
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -172,8 +172,8 @@ The current set of supported services is only for the high-level client.

| Service Set | Service | Supported | Notes |
|-----------------------------|-------------------------------|-----------|--------------|
| Discovery Service Set | FindServers | | |
| | FindServersOnNetwork | | |
| Discovery Service Set | FindServers | Yes | |
| | FindServersOnNetwork | Yes | |
| | GetEndpoints | Yes | |
| | RegisterServer | | |
| | RegisterServer2 | | |
Expand Down
64 changes: 64 additions & 0 deletions client.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,44 @@ import (
"github.com/gopcua/opcua/uasc"
)

// FindServers returns the Servers known to a Server or Discovery Server.
func FindServers(ctx context.Context, endpoint string, opts ...Option) ([]*ua.ApplicationDescription, error) {
opts = append(opts, AutoReconnect(false))
c := NewClient(endpoint, opts...)
if err := c.Dial(ctx); err != nil {
return nil, err
}
defer func(c *Client, ctx context.Context) {
if err := c.Close(ctx); err != nil {
// TODO(sruehl): log error
}
}(c, ctx)
res, err := c.FindServers(ctx)
if err != nil {
return nil, err
}
return res.Servers, nil
}

// FindServersOnNetwork returns the Servers known to a Server or Discovery Server. Unlike FindServers, this Service is only implemented by Discovery Servers.
func FindServersOnNetwork(ctx context.Context, endpoint string, opts ...Option) ([]*ua.ServerOnNetwork, error) {
opts = append(opts, AutoReconnect(false))
c := NewClient(endpoint, opts...)
if err := c.Dial(ctx); err != nil {
return nil, err
}
defer func(c *Client, ctx context.Context) {
if err := c.Close(ctx); err != nil {
// TODO(sruehl): log error
}
}(c, ctx)
res, err := c.FindServersOnNetwork(ctx)
if err != nil {
return nil, err
}
return res.Servers, nil
}

// GetEndpoints returns the available endpoint descriptions for the server.
func GetEndpoints(ctx context.Context, endpoint string, opts ...Option) ([]*ua.EndpointDescription, error) {
opts = append(opts, AutoReconnect(false))
Expand Down Expand Up @@ -936,6 +974,32 @@ func (c *Client) Node(id *ua.NodeID) *Node {
return &Node{ID: id, c: c}
}

// FindServers finds the servers available at an endpoint
func (c *Client) FindServers(ctx context.Context) (*ua.FindServersResponse, error) {
stats.Client().Add("FindServers", 1)

req := &ua.FindServersRequest{
EndpointURL: c.endpointURL,
}
var res *ua.FindServersResponse
err := c.Send(ctx, req, func(v interface{}) error {
return safeAssign(v, &res)
})
return res, err
}

// FindServersOnNetwork finds the servers available at an endpoint
func (c *Client) FindServersOnNetwork(ctx context.Context) (*ua.FindServersOnNetworkResponse, error) {
stats.Client().Add("FindServers", 1)

req := &ua.FindServersOnNetworkRequest{}
var res *ua.FindServersOnNetworkResponse
err := c.Send(ctx, req, func(v interface{}) error {
return safeAssign(v, &res)
})
return res, err
}

// GetEndpoints returns the list of available endpoints of the server.
func (c *Client) GetEndpoints(ctx context.Context) (*ua.GetEndpointsResponse, error) {
stats.Client().Add("GetEndpoints", 1)
Expand Down
53 changes: 53 additions & 0 deletions examples/discovery/discovery.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
// Copyright 2018-2020 opcua authors. All rights reserved.
// Use of this source code is governed by a MIT-style license that can be
// found in the LICENSE file.

package main

import (
"context"
"flag"
"fmt"
"github.com/gopcua/opcua"
"github.com/gopcua/opcua/debug"
"log"
)

func main() {
endpoint := flag.String("endpoint", "opc.tcp://localhost:4840", "OPC UA Endpoint URL")
flag.BoolVar(&debug.Enable, "debug", false, "enable debug logging")
flag.Parse()
log.SetFlags(0)

ctx := context.Background()

log.Println("Finding servers on network")
serversOnNetwork, err := opcua.FindServersOnNetwork(ctx, *endpoint)
if err == nil {
for i, server := range serversOnNetwork {
fmt.Printf("%d Server on network:\n", i)
fmt.Printf(" -- RecordID: %v\n", server.RecordID)
fmt.Printf(" -- ServerName: %v\n", server.ServerName)
fmt.Printf(" -- DiscoveryURL: %v\n", server.DiscoveryURL)
fmt.Printf(" -- ServerCapabilities: %v\n", server.ServerCapabilities)
}
} else {
log.Printf("Error calling find servers on network: %v", err)
}

log.Println("Finding servers")
servers, err := opcua.FindServers(ctx, *endpoint)
if err != nil {
log.Fatal(err)
}
for i, server := range servers {
fmt.Printf("%dth Server:\n", i+1)
fmt.Printf(" -- ApplicationURI: %v\n", server.ApplicationURI)
fmt.Printf(" -- ProductURI: %v\n", server.ProductURI)
fmt.Printf(" -- ApplicationName: %v\n", server.ApplicationName)
fmt.Printf(" -- ApplicationType: %v\n", server.ApplicationType)
fmt.Printf(" -- GatewayServerURI: %v\n", server.GatewayServerURI)
fmt.Printf(" -- DiscoveryProfileURI: %v\n", server.DiscoveryProfileURI)
fmt.Printf(" -- DiscoveryURLs: %v\n", server.DiscoveryURLs)
}
}

0 comments on commit 868add3

Please sign in to comment.