gopcua

repository·main·Indexed 22 days ago

https://github.com/gopcua/opcua

A native Go implementation of the OPC/UA Binary Protocol for interacting with OPC/UA servers. It supports UA-TCP, UA-SC, and UA Binary transports, with encryption options including Basic128Rsa15, Basic256, and Basic256Sha256. The library provides a high-level Client interface for session management, synchronous Read, Write, Browse, and Call operations, as well as a Node abstraction and subscription mechanisms for monitoring data changes and events.

Tokens
12.6K
Snippets
41
Records
67
Agent score
74%

What's inside gopcua

  1. Specify user identity with UserIdentityToken

    main

    The UserIdentityToken structure allows clients to specify the identity of the user they are acting on behalf of. The specific mechanism depends on the server configuration. Supported token types include:

    • AnonymousIdentityToken: Indicates the client has no user credentials.
    • UserNameIdentityToken: Passes simple username/password credentials. If a SecurityPolicy is required by the UserTokenPolicy, the password must be encrypted.
    • X509IdentityToken: Passes an X.509 v3 certificate issued by the user. This usually requires a signature in the userTokenSignature parameter during ActivateSession.
    • IssuedIdentityToken: Passes security tokens issued by an external authorization service (e.g., JWTs via OAuth2).
  2. Understand ActivateSessionResponse behavior

    main

    The ActivateSessionResponse is the server's response to an ActivateSessionRequest.

    Key behaviors to note:

    • Nonce Reuse: Once an ActivateSessionResponse is used, the serverNonce contained within it cannot be used again. The server will return a new serverNonce for every subsequent ActivateSession service call.
    • SecureChannel Transitions:
      • On the first call, the SecureChannel must match the one used in the CreateSession request.
      • For subsequent calls, if a different SecureChannel is used, the server verifies that the Client's Certificate is identical to the one used for the original channel and that the UserIdentityToken matches the one currently associated with the session.
      • Once a new SecureChannel is accepted, the server will reject requests sent via the old SecureChannel.
  3. Quickstart examples

    main

    The repository includes several examples to demonstrate common OPC/UA tasks. You can run these directly using go run after installing the library.

    Get current date and time

    To retrieve the current date and time from a server (using the node ID ns=0;i=2258):

    go run examples/datetime/datetime.go -endpoint opc.tcp://localhost:4840

    Read the server version

    To read the server version (using the node ID ns=0;i=2261):

    go run examples/read/read.go -endpoint opc.tcp://localhost:4840 -node 'ns=0;i=2261'

    Use security and authentication modes

    To connect using specific security policies and certificates:

    go run examples/crypto/*.go -endpoint opc.tcp://localhost:4840 -cert path/to/cert.pem -key path/to/key.pem -sec-policy Basic256 -sec-mode SignAndEncrypt
    # get current date and time 'ns=0;i=2258'
    go run examples/datetime/datetime.go -endpoint opc.tcp://localhost:4840
    
    # read the server version
    go run examples/read/read.go -endpoint opc.tcp://localhost:4840 -node 'ns=0;i=2261'
    
    # get the current date time using different security and authentication modes
    go run examples/crypto/*.go -endpoint opc.tcp://localhost:4840 -cert path/to/cert.pem -key path/to/key.pem -sec-policy Basic256 -sec-mode SignAndEncrypt
  4. Server Capabilities and Operational Limits

    main

    The server's capabilities are defined via the ServerCapabilities struct. A key part of this is OperationalLimits, which defines constraints for service requests.

    Currently, the default implementation includes:

    • MaxNodesPerRead: A uint32 value limiting the number of nodes allowed in a single Read service request (default is 32).
    type ServerCapabilities struct {
        OperationalLimits OperationalLimits
    }
    
    type OperationalLimits struct {
        MaxNodesPerRead uint32
    }
  5. How client configuration options work

    main

    The library uses a functional options pattern. You pass Option functions to ApplyConfig. Each Option is a function that modifies the internal Config struct, which contains:

    • dialer: Configuration for the underlying network connection (uacp.Dialer).
    • sechan: Configuration for the Secure Channel (uasc.Config).
    • session: Configuration for the OPC UA Session (uasc.SessionConfig).

    Common categories of options include:

    • Identity/Session: ApplicationName, ApplicationURI, ProductURI, Locales, SessionTimeout.
    • Secure Channel: SecurityMode, SecurityPolicy, Lifetime, AutoReconnect, ReconnectInterval, RequestTimeout.
    • Security/Certificates: PrivateKey, PrivateKeyFile, Certificate, CertificateFile, RemoteCertificate.
    • Authentication: AuthAnonymous, AuthUsername, AuthCertificate, AuthIssuedToken, AuthPrivateKey.
    • Connection/Dialer: DialTimeout, MaxMessageSize, MaxChunkCount, ReceiveBufferSize, SendBufferSize.
  6. How OPC UA Subscriptions and Notifications work

    main

    An OPC UA Subscription is a mechanism where the client requests the server to monitor specific items and notify the client when they change.

    Lifecycle & Flow:

    1. Creation: Subscribe creates the subscription on the server and returns a *Subscription object.
    2. Monitoring: The client runs a background monitorSubscriptions loop that periodically sends PublishRequest messages to the server.
    3. Notifications: When the server has data changes, events, or status changes, it includes them in a PublishResponse.
    4. Dispatch: The client parses the NotificationMessage and sends a *PublishNotificationData object into the notifyCh provided during subscription creation.
    5. Acknowledgements: The client tracks pendingAcks to ensure the server knows which messages have been successfully received, preventing unnecessary retransmissions.
  7. Initialize and connect a Client

    main

    The Client is the primary high-level interface for interacting with an OPC UA server. It manages the secure channel and session lifecycle.

    1. Create a Client: Use NewClient(endpoint, ...opts) to initialize a client. If no options are provided, it uses default configurations. If no authentication is configured, it defaults to anonymous authentication.
    2. Connect: Call Connect(ctx) to establish a secure channel and create/activate a session. This method also starts background monitoring for connection maintenance and automatic reconnection.
    3. Close: Call Close(ctx) to gracefully shut down the session, secure channel, and underlying connection.
    import "github.com/gopcua/opcua/opcua"
    
    client, err := opcua.NewClient("opc.tcp://localhost:4840")
    if err != nil {
        log.Fatal(err)
    }
    
    // Establish connection and session
    if err := client.Connect(ctx); err != nil {
        log.Fatal(err)
    }
    
    // Ensure cleanup
    defer client.Close(ctx)
  8. Discover servers and endpoints

    main

    Use the following package-level functions to discover available OPC UA servers and their endpoints without manually managing a client lifecycle:

    • FindServers(ctx, endpoint, ...opts): Returns a list of *ua.ApplicationDescription for servers known to a discovery server.
    • FindServersOnNetwork(ctx, endpoint, ...opts): Returns a list of *ua.ServerOnNetwork. This is typically only implemented by discovery servers.
    • GetEndpoints(ctx, endpoint, ...opts): Returns the available *ua.EndpointDescription for a specific server.

    To select the best endpoint from a list, use SelectEndpoint(endpoints, policy, mode). It sorts endpoints by security level and returns the one that best matches the provided security policy URI and ua.MessageSecurityMode.

    import "github.com/gopcua/opcua/opcua"
    
    // Example: Getting endpoints
    endpoints, err := opcua.GetEndpoints(ctx, "opc.tcp://localhost:4840")
    if err != nil {
        log.Fatal(err)
    }
    
    // Example: Selecting an endpoint
    endpoint, err := opcua.SelectEndpoint(endpoints, "http://opcfoundation.org/UA/SecurityPolicy#Basic256Sha256", ua.MessageSecurityModeSignAndEncrypt)
    if err != nil {
        log.Fatal(err)
    }
  9. Use FindServersRequest to discover servers

    main

    The FindServersRequest is used to retrieve a list of servers known to a specific Server or Discovery Server.

    • Filtering: Clients can provide filter criteria within the request to reduce the number of results returned.
    • Empty Results: If no servers match the specified filter criteria, the Discovery Server will return an empty list.
  10. Activate a session with ActivateSessionRequest

    main

    After calling CreateSession, a client must call ActivateSessionRequest to specify the user identity associated with the session. Failure to do this before issuing other service requests (except CloseSession) will cause the server to close the session.

    To prove identity, the client must create a signature using the private key associated with the clientCertificate specified in the CreateSession request. The signature is created by appending the last serverNonce provided by the server to the serverCertificate and calculating the signature of the resulting bytes.

  11. Manage secure channels and sessions

    main

    Use the following services to manage the lifecycle of connections:

    • CloseSecureChannelRequest: Used to terminate a SecureChannel.
    • CloseSessionRequest: Used to terminate a Session.
    • GetEndpointsRequest: Returns the endpoints supported by a server and the configuration required to establish a SecureChannel and a Session.