GithubHelp home page GithubHelp logo

gopcua / opcua Goto Github PK

View Code? Open in Web Editor NEW
832.0 56.0 253.0 10.34 MB

Native Go OPC-UA library

License: MIT License

Go 98.63% Shell 0.19% Makefile 0.11% Python 1.07%
opc-ua golang protocol ics scada

opcua's Introduction

Artwork by Ashley McNamara
Inspired by Renee French
Taken from https://gopherize.me by Mat Ryer

OPC/UA

A native Go implementation of the OPC/UA Binary Protocol.

We support the current and previous major Go release. See below for a list of Tested Platforms and Supported Features.

GitHub Go Reference License Version

v0.5.x BREAKING CHANGES

  • v0.5.0 released on 14 Aug 2023: all Client methods must have a context
  • v0.5.1 released on 22 Aug 2023: the NewClient function returns an error

In v0.3.0 on 21 Jan 2022 release we added WithContext variants for all methods to avoid a breaking change. All existing methods without a context had a disclaimer that with v0.5.0 their signature would change to include the context and that the WithContext method would be removed.

We missed to update the NewClient function in v0.5.0 which was fixed in v0.5.1.

Please update your code and let us know if there are any issues!

Thank you!

Your GOPCUA Team

Quickstart

# install library
go get -u github.com/gopcua/opcua

# 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

# checkout examples/ for more examples...

Sponsors

The gopcua project is sponsored by the following organizations by supporting the active committers to the project:

Northvolt evosoft Intelecy AS

Users

We would also like to list organizations which use gopcua in production:

strateos united manufacturing hub Wolfram Manufacturing Technologies Please open a PR to include your logo here.

Projects using gopcua

gopcua is not only utilized in production environments, but it also serves as a critical component in other larger projects. Here are some projects that rely on gopcua for their functionality:

  • Telegraf: This plugin-driven server agent is used for collecting and sending metrics. It leverages gopcua to extract data from OPC-UA servers and insert it into InfluxDB. Telegraf supports both polling and subscribing methods for data acquisition.
  • benthos-umh: This project is built upon the benthos stream-processing framework. It utilizes gopcua to extract data from OPC-UA servers and forwards the information to MQTT or Kafka brokers. benthos-umh currently supports polling for data collection.

Disclaimer

We are still actively working on this project and the APIs will change.

However, you can safely assume that we are aiming to make the APIs as stable as possible since the code is in use in several large scale production environments.

The Current State was moved to the Wiki.

Your Help is Appreciated

If you are looking for ways to contribute you can

  • test the high-level client against real OPC/UA servers
  • add functions to the client or tell us which functions you need for gopcua to be useful
  • work on the security layer, server and other components
  • and last but not least, file issues, review code and write/update documentation

Also, if the library is already useful please spread the word as a motivation.

Tested Platforms

gopcua is run in production by several companies and with different equipment. The table below is an incomplete list of where and how gopcua is used to provide some guidance on the level of testing.

We would be happy if you can add your equipment to the list. Just open a PR :)

Device gopcua version Environment By
Siemens S7-1500 v0.1.x..latest production Northvolt
Beckhoff C6015-0010,C6030-0060 on OPC/UA server 4.3.x v0.1.x..latest production Northvolt
Kepware 6.x v0.1.x..latest production Northvolt
Kepware 6.x v0.1.x, v0.2.x production Intelecy
Cogent DataHub 9.x v0.1.x, v0.2.x production Intelecy
ABB Ability EdgeInsight 1.8.X v0.1.x, v0.2.x production Intelecy
GE Digital Historian 2022 HDA Server v0.3.x production Intelecy
B&R Automation PC 3100 v0.3.x production ACS
Siemens S7-1200 v0.3.x CI/CD testing UMH
WAGO 750-8101 v0.3.x CI/CD testing UMH
Microsoft OPC UA simulator v2.9.11 v0.3.x CI/CD testing UMH
Prosys OPC UA Simulation Server v5.4.6-148 v0.3.x manual testing UMH
InfluxDB Telegraf plugin v0.3.x ? Community

Supported Features

The current focus is on the OPC UA Binary protocol over TCP. No other protocols are supported at this point.

Categories Features Supported Notes
Encoding OPC UA Binary Yes
OPC UA JSON not planned
OPC UA XML not planned
Transport UA-TCP UA-SC UA Binary Yes
OPC UA HTTPS not planned
SOAP-HTTP WS-SC UA Binary not planned
SOAP-HTTP WS-SC UA XML not planned
SOAP-HTTP WS-SC UA XML-UA Binary not planned
Encryption None Yes
Basic128Rsa15 Yes
Basic256 Yes
Basic256Sha256 Yes
Authentication Anonymous Yes
User Name Password Yes
X509 Certificate Yes

Services

Here is the current set of supported services. For low-level access use the client Send function directly.

Service Set Service Client Notes
Discovery Service Set FindServers Yes
FindServersOnNetwork Yes
GetEndpoints Yes
RegisterServer
RegisterServer2
Secure Channel Service Set OpenSecureChannel Yes
CloseSecureChannel Yes
Session Service Set CreateSession Yes
CloseSession Yes
ActivateSession Yes
Cancel
Node Management Service Set AddNodes
AddReferences
DeleteNodes
DeleteReferences
View Service Set Browse Yes
BrowseNext Yes
TranslateBrowsePathsToNodeIds
RegisterNodes Yes
UnregisterNodes Yes
Query Service Set QueryFirst
QueryNext
Attribute Service Set Read Yes
Write Yes
HistoryRead Yes
HistoryUpdate
Method Service Set Call Yes
MonitoredItems Service Set CreateMonitoredItems Yes
DeleteMonitoredItems Yes
ModifyMonitoredItems Yes
SetMonitoringMode Yes
SetTriggering
Subscription Service Set CreateSubscription Yes
ModifySubscription
SetPublishingMode
Publish Yes
Republish
DeleteSubscriptions Yes
TransferSubscriptions

Authors

The Gopcua Team.

If you need to get in touch with us directly you may find us on Keybase.io but try to create an issue first.

License

MIT

opcua's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

opcua's Issues

Opcua Client reads server data

Hi I've been looking at your code recently, but I'm not sure how you read server data with client, and I haven't found the location to set the identifier, identifier type, and Namespace Index parameters, can you tell me?

Add ApplicationInstanceCertificate

Currently certificates are handled as []byte, but it should actually be ApplicationInstanceCertificate.
Need to add ApplicationInstanceCertificate as described in Part4, 7.2.

There are some issues when run examples as default config

when we config our opcua server and run examples as default config, we should change fllow func, we should delete :

opt = AuthPolicyID("Anonymous")
opt(c.cfg, c.sessionCfg)

if not, the server will return : The user identity token is not valid.

func NewClient(endpoint string, opts ...Option) *Client {
	c := &Client{
		endpointURL: endpoint,
		cfg:         DefaultClientConfig(),
		sessionCfg:  DefaultSessionConfig(),
	}
	for _, opt := range opts {
		opt(c.cfg, c.sessionCfg)
	}

	// UserIdentityToken was removed from DefaultSessionConfig() so ensure a default still is set
	if c.sessionCfg.UserIdentityToken == nil {
		opt := AuthAnonymous()
		opt(c.cfg, c.sessionCfg)
		opt = AuthPolicyID("Anonymous")
		opt(c.cfg, c.sessionCfg)
	}
	return c
}

Cleanup tests in services

Now the tests for each service in service_test.go is becoming too big. Need to split tests for each service and write more efficient tests.

  • OpenSecureChannelRequest
  • OpenSecureChannelResponse
  • CloseSecureChannelRequest
  • CloseSecureChannelResponse
  • GetEndpointsRequest
  • GetEndpointsResponse
  • CreateSessionRequest
  • CreateSessionResponse
  • ActivateSessionRequest
  • ActivateSessionResponse
  • CloseSessionRequest
  • CloseSessionResponse
  • ReadRequest

Server Support

I've pushed a WIP branch for the first kick at a server implementation. The focus on this initial code is to show the uacp package changes that need to occur to support listening for unsolicited messages and how that integrates into both the client and the server code. I anticipate these changes being the first to be merged, then the server code can follow once it's fleshed out.
The primary difference is that I moved the goroutine read loop out of the uasc package and into each of the client and server packages. The uasc package still deals with decoding/decrypting the messages, but returns the service up to the application layer. The exception to this are the Open and Close SecureChannel requests; those are dealt with directly in the uasc package without notifying the client/server.

The server implementation has preliminary support for opening and closing secure channels, auto-builds endpoints, and opening/closing/activating sessions. Authorization has config for the purpose of endpoint generation, but is otherwise not implemented yet. The session management is still in a very early state and should be normalized with the client implementation (they're currently totally separate). Other services are just placeholders for now. To properly implement further services, the server needs to implement an address space, which is what I've started looking into next.

Simplify error types

Custom errors in errors should not be too many.
e.g. implement ErrDecoding instead of ErrTooShortToDecode and make the message more flexible.

Discussion on compliance tests

In #170 @maurocordioli referenced a test case from the OPC/UA compliance test suite. I think it would be useful to have a framework for writing tests for this suite. Since we don't have a server yet we can pick a reference implementation and run it in a Docker container or as a subprocess.

https://apps.opcfoundation.org/ProfileReporting/testcases/Client/SessionClientGeneralServiceBehaviour.html

I think having a framework for writing tests is more important than test coverage at this point. If we have a framework then others can help filling in the gaps. It would also be useful if we can swap out the server implementation essentially to run integration tests but I don't know how the whole OPC/UA certification process works and whether it matters.

@dwhutchison since you wanted to start working on a server as well we could use this as a testbed for these tests.

What do you all think? Who has experience with this?

Default installation path conflicts with default expectation

By default from sources all would be installed
https://opcuastack.readthedocs.io/en/latest/getting_started/installation.html
to
~/.ASNeG
, which would require from user to do something like

export PATH=$HOME/.ASNeG/usr/bin:$PATH
export LD_LIBRARY_PATH=$HOME/.ASNeG/usr/lib:$LD_LIBRARY_PATH

and it still would not really help, because when doing
https://opcuastack.readthedocs.io/en/latest/getting_started/hello_world.html
user would get the

CMake Error at CMakeLists.txt:82 (include):
  include could not find load file:

    /usr/share/cmake/OpcUaStack3/CMakeOpenSSL.txt

So either detailed explanation how to not get rid of these problems should be included in documentation (what to add to .bashrc, how to configure currently opened shell, etc) or default path should be / instead ~/.ASNeG. It seems that application is designed to be installed to root...

Change Request/ResponseHeader handling in constructors of service

In the current implementation, params inside RequestHeader in each service is given respectively, but it should be given with *RequestHeader to be more flexible and consice in handling services with constructor.

For example,

func NewActivateSessionRequest(ts time.Time, authToken datatypes.NodeID, handle, diag, timeout uint32, auditID string, sig *SignatureData, certs []*SignedSoftwareCertificate, locales []string, userToken *datatypes.ExtensionObject, tokenSig *SignatureData) *ActivateSessionRequest {

should be;

func NewActivateSessionRequest(reqHeader *RequestHeader, sig *SignatureData, certs []*SignedSoftwareCertificate, locales []string, userToken *datatypes.ExtensionObject, tokenSig *SignatureData) *ActivateSessionRequest {

Change ExtensionObject to ExtensibleParameter?

In specification parameters like UserIdentityToken is described as ExtensibleParameter, not ExtensionParameter, while Wireshark calls it ExtensionObject.

  • Investigate which one to be used.
  • Fix if needed.

Discussion on crypto support

Creating this issue for a place for discussion outside of a PR.

While trying to implement the crypto functions for the server path, I noticed a few functions which didn't work for receiving messages. Primarily, the recv() and SendAsync() functions within the uasc package were tailored for sending client messages and not capable of receiving messages. The majority of the code is fine and the problems weren't major, but they do need some adjustment. For example, the SendAsync method would panic while trying to copy the reqHdr field into a ResponseHeader and the recv method could only handle messages with existing handlers (which are tied to client-generated requestIDs).

I'm preparing a PR for three things:

  1. Generalize the above uasc functions to allow for processing both 'Request' and 'Response' types.
  2. Create an initial server application layer to receive and process unsolicited messages.
  3. Incorporate the crypto functions into the transport layer
    I'm working on all three simultaneously but if I can extract parts of each, I'll try publish them individually.

Within the server logic I'm working on a concept of a 'Channel Broker' to manage multiple secure channels on one listener. With this, I'm hoping to have a method of accepting connections, creating secure channels, and handling requests from multiple connections as well as slightly decoupling the secure channel from the uacp.Conn. This is because clients are allowed to reconnect to a server provided the secure channel hasn't expired so this should allow for a means to 'reattach' a new Conn to an existing secure channel. Having a system monitoring all active secure channels will also allow for a means to prune expired connections.

I anticipate client logic remaining the same as it is now; i.e. the application controlling the creation and use of SecureChannels. One thing I'm aware of, but unsure exactly how to implement it at this time, is that clients will also need a way to reconnect to a server utilizing an existing SecureChannel if the uacp.Conn is broken. I don't anticipate this being too difficult (try to send, fail, close the uacp.Conn, open a new one, replace the old conn reference with the new one, continue on). Also need to check the spec to see if the full HEL/ACK sequence needs to be repeated in this case.

#156 was a proof of concept that the crypo functions themselves are functional, but will need more work to allow for both sending and receiving messages, decent secret management, etc. Now that I've looked closer at what it'll take to implement the server component of the logic, I should be able to clean up that sequencing.

Comments are welcome; when I have things cleaned up a bit I'll push a WIP branch for review.

Development timeline

Hi gopcua team,

I really like your implementation in this package.
I would also like to use the browse services and I also need support for some more datatypes of the variant.
I regularly run into this error while decoding the ReadResponse message: cannot decode as uint8: got undefined type

Can you share your timeline? Are there any plans to complete the list of services and available datatypes?

Thanks
Felix

Method to retrieve Identifier value in NodeID

When handling each type of NodeID, the main concern of the user is to retrieve values in Identifier field.
So, I'm considering to implement Value() or Payload() method on each NodeID, which makes the NodeID interface to return the value without asserting.

Design in my mind

  • Modify interface
type NodeID interface {
	Serialize() ([]byte, error)
	SerializeTo([]byte) error
	DecodeFromBytes([]byte) error
	Len() int
	String() string
	EncodingMaskValue() uint8
	SetURIFlag()
	SetIndexFlag()
	Value() ([]byte, error) // Add this line
}
  • Basic method
func (n *NumericNodeID) Value() ([]byte, error) {
	if n == nil {
		return nil, errors.NewErrReceiverNil(n)
	}

	// return identifier as it is
	return n.Identifier, nil
}
  • Special case for GUIDNodeID
func (g *GUIDNodeID) Value() ([]byte, error) {
	if n == nil {
		return nil, errors.NewErrReceiverNil(g)
	}

	// return serialized GUID instead of GUID structure
	return n.GUID.Serialize()
}

Implement automated Session handling

Session creation and activation should be done automatically with smallest user inputs.

  • Implement Session which implements net.Conn interface
  • ...

encoder should be smart about empty structs

The OPC/UA binary protocol has no mechanism to express a nil struct. This means that all struct fields at least represent a Go zero value for that struct. Additionally, the current code generator creates struct fields as pointers which has the effect that all struct fields need to be initialized with at least an empty value.

Here is an example from the ua/write_response_test.go.

Struct: &WriteResponse{
	ResponseHeader: &ResponseHeader{
		Timestamp:     time.Date(2018, time.August, 10, 23, 0, 0, 0, time.UTC),
		RequestHandle: 1,
		ServiceDiagnostics: &DiagnosticInfo{},
		StringTable:        []string{},
		AdditionalHeader:   NewExtensionObject(nil),
	},
	Results: []StatusCode{StatusOK},
},

This behavior was also the cause for a discrepancy in #162 where a field of the session configuration had not been initialized.

One fix is to make the encoder smart about nil values. That has the effect that tests can no longer use the same structs for encoding and decoding since a nil silently turns into an empty struct.

A better approach might be not to generate struct fields as pointers since they cannot be nil anyway. Then the codec just works.

Add tests for connection-related funcs

Currently no tests implemented for networking feature which communicates with other OPC UA entity.
Those funcs should not be left untested, so I need to find the way to test it in simple and CI-friendly manner.

Build in 32 bit environment fails

When crosscompiling for a 32 bit environment, I get the following two issues:

.../src/github.com/gopcua/opcua/ua/node_id.go:133:22: constant 4294967295 overflows int
.../src/github.com/gopcua/opcua/ua/node_id.go:250:10: constant 4294967295 overflows int

The first issue arises since strconv.Atoi a few lines earlier returns an int which in my system is 32 bit and thus cannot be compared to an uint32. Using ParseUint instead solved the problem:

id, err := strconv.ParseUint(idval[2:], 10, 32)

The second issue is similar, but for that I made an uglier solution to get it to work by changing the input argument of SetIntID to an uint32 and fiddling a bit with casting etc in the code below.

This relates to commit b9119dc of ua/node_id.go

Validate config

In SecureChannel and Session handling, large part of the required parameters depends on each Config, which is to be created and passed by users.

It causes crash if the parameters in each Config are not properly set. Thus the parameters should be validated when opening SecureChannel/Creating Session and we should notify users of the invalid parameters.

Fix array size encoding

With current implementation, ArraySize will be encoded as 0xffffffff when the array contains nothing.
This should be corrected as 0x00000000.

Example: Array of String (should be applied to some other constructors)

// NewStringArray creates a new StringArray from multiple strings.
func NewStringArray(strs []string) *StringArray {
	if strs == nil {
		s := &StringArray{
			ArraySize: -1, // <= This should be 0.
		}
		return s
	}

	s := &StringArray{
		ArraySize: int32(len(strs)),
	}
	for _, ss := range strs {
		s.Strings = append(s.Strings, NewString(ss))
	}

	return s
}

RequestedSessionTimeout not set in func (c *Client) CreateSession

I was tring to connect to an Siemens S7, using the datetime example I was unable to create a session..

the error returned was StatusBadSessionIDInvalid.
so logging the tcp packets with wireshark and matching the results with a working client I noticed that the message CreateSessionRequest has a
opcua.RequestedSessionTimeout = 0
so the S7 replied with
aopcua.RevisedSessionTimeout=1

when at next step we call ActivateSession the session is already expired.

in the source code client.go I noticed that in
func (c *Client) CreateSession the RequestedSessionTimeout of the struct ua.CreateSessionRequest is not set so it has 0 value.

for me worked adding RequestedSessionTimeout: cfg.SessionTimeout

req := &ua.CreateSessionRequest{

   	ClientDescription:       cfg.ClientDescription,

   	EndpointURL:             c.endpointURL,

   	SessionName:             fmt.Sprintf("gopcua-%d", time.Now().UnixNano()),

   	ClientNonce:             nonce,

   	ClientCertificate:       c.cfg.Certificate,

   	RequestedSessionTimeout: cfg.SessionTimeout,
   }

Add contributing guidelines

For those who is interested in contribution, we need to provide guideline.

  • Consider what it should be like
  • Write docs in CONTRIBUTING.md
    • (Optional) Add ISSUE_TEMPLATE.md
    • (Optional) Add PULL_REQUEST_TEMPLATE.md
  • ...

error: unsupported uint16: unsupported or not implemented yet.

Hi!

I'm trying to connect from prosys opcua client (osx) to your example/server (with my changes of course).

Have an issue while connect:

2018/10/01 00:30:44 main.go:79: D Successfully established connection with 172.21.0.1:60570
2018/10/01 00:30:44 main.go:89: D Successfully opened secure channel with 172.21.0.1:60570
2018/10/01 00:30:44 main.go:95: E ReadService error: unsupported uint16: unsupported or not implemented yet.

Any Ideas?

Ready to collaborate.

Move datatypes in services directory to datatypes directory

Currently some of the (non-primitive) datatypes are in services directory but they should actually be in datatypes.
This issue is to track the problem. At some point of implementation before v1.0 release, I'll work on moving them and revise some codes.

SecureChannel 'monitor' goroutine panics after calling SecureChannel.Close()

I've run across an issue when trying to close and create another SecureChannel inside a client. After I call Close() on the first instance of a SecureChannel, the program quickly panics due to a nil pointer deference inside func (s *SecureChannel) monitor(ctx context.Context).

I think the issue is this goroutine stays blocked on
n, err := s.lowerConn.Read(s.rcvBuf)
so it never sees that the context finishes and returns cleanly. Inside the call to close, s.lowerConn gets assigned to nil, resulting in the panic.

Simply commenting out the lowerConn nil assignment in SecureChannel.close() stops this, but I haven't looked to see if there are other impacts of doing so.

Code Generation

Hi @wmnsk, I had started working on a pure go opcua implementation in April but didn't make much headway until recently but you've beaten me to the punch :)

My code is roughly in the same state (encoder, decoder, uacp, session, ...) but I think having a larger and active community is more important and your project has gained some good traction. I have some experience from that with my own open-source projects.

The one big thing I can contribute is a code generator for all OPC/UA service objects and array types and I'm also thinking of writing a reflection based Encoder/Decoder to reduce the boilerplate even further.

The generated code looks like the one below and also generates all length encoded Array variants of objects like []*ReadValueId.

Would you be interested in this? If yes, then we can discuss what the interfaces should look like since the generated code isn't a drop-in replacement for the current structures. I'll attach a PR with the code generator so that you can have a look.

package service

import (
	"bytes"

	ua "github.com/northvolt/go-opcua/datatypes"
)

type CreateSubscriptionRequest struct {
	RequestHeader               *RequestHeader
	RequestedPublishingInterval float64
	RequestedLifetimeCount      uint32
	RequestedMaxKeepAliveCount  uint32
	MaxNotificationsPerPublish  uint32
	PublishingEnabled           bool
	Priority                    uint8
}

func NewCreateSubscriptionRequest() *CreateSubscriptionRequest {
	return &CreateSubscriptionRequest{
		RequestHeader: NewRequestHeader(),
	}
}

func (m *CreateSubscriptionRequest) ID() uint16 {
	return 787
}

func (m *CreateSubscriptionRequest) GetName() string {
	return "CreateSubscriptionRequest"
}

func (m *CreateSubscriptionRequest) Read(b *bytes.Buffer) error {
	var err error
	if m.RequestHeader, err = ReadRequestHeader(b); err != nil {
		return err
	}
	if m.RequestedPublishingInterval, err = ua.ReadDouble(b); err != nil {
		return err
	}
	if m.RequestedLifetimeCount, err = ua.ReadUInt32(b); err != nil {
		return err
	}
	if m.RequestedMaxKeepAliveCount, err = ua.ReadUInt32(b); err != nil {
		return err
	}
	if m.MaxNotificationsPerPublish, err = ua.ReadUInt32(b); err != nil {
		return err
	}
	if m.PublishingEnabled, err = ua.ReadBoolean(b); err != nil {
		return err
	}
	if m.Priority, err = ua.ReadByte(b); err != nil {
		return err
	}
	return nil
}

func (m *CreateSubscriptionRequest) Write(b *bytes.Buffer) error {
	if err := WriteRequestHeader(b, m.RequestHeader); err != nil {
		return err
	}
	if err := ua.WriteDouble(b, m.RequestedPublishingInterval); err != nil {
		return err
	}
	if err := ua.WriteUInt32(b, m.RequestedLifetimeCount); err != nil {
		return err
	}
	if err := ua.WriteUInt32(b, m.RequestedMaxKeepAliveCount); err != nil {
		return err
	}
	if err := ua.WriteUInt32(b, m.MaxNotificationsPerPublish); err != nil {
		return err
	}
	if err := ua.WriteBoolean(b, m.PublishingEnabled); err != nil {
		return err
	}
	if err := ua.WriteByte(b, m.Priority); err != nil {
		return err
	}
	return nil
}

func ReadCreateSubscriptionRequest(b *bytes.Buffer) (*CreateSubscriptionRequest, error) {
	m := new(CreateSubscriptionRequest)
	if err := m.Read(b); err != nil {
		return nil, err
	}
	return m, nil
}

func WriteCreateSubscriptionRequest(b *bytes.Buffer, m *CreateSubscriptionRequest) error {
	return m.Write(b)
}
package service

import (
	"bytes"

	ua "github.com/northvolt/go-opcua/datatypes"
)

type ReadValueIdArray []*ReadValueId

func (m ReadValueIdArray) GetName() string {
	return "ReadValueIdArray"
}

func ReadReadValueIdArray(b *bytes.Buffer) ([]*ReadValueId, error) {
	n, err := ua.ReadUInt32(b)
	if err != nil {
		return nil, err
	}
	if n == ua.NilValue {
		return nil, nil
	}
	m := make([]*ReadValueId, n)
	for i := uint32(0); i < n; i++ {
		if m[i], err = ReadReadValueId(b); err != nil {
			return nil, err
		}
	}
	return m, nil
}

func WriteReadValueIdArray(b *bytes.Buffer, m []*ReadValueId) error {
	if m == nil {
		return ua.WriteUInt32(b, ua.NilValue)
	}
	if err := ua.WriteUInt32(b, uint32(len(m))); err != nil {
		return err
	}
	for i := range m {
		if err := WriteReadValueId(b, m[i]); err != nil {
			return err
		}
	}
	return nil
}

GopherCon 2018: Matt Layher - Implementing a Network Protocol in Go

This is a great talk https://www.youtube.com/watch?v=pUaFW98V1Sc. The topic is very similar to what we're building. He even talks about go-fuzz.

One thing that came to mind. Our interface names are Decode and Serialize. He's using Marshal and Unmarshal like the json package https://golang.org/pkg/encoding/json/ and the proto package https://godoc.org/github.com/golang/protobuf/proto.

Therefore I'd like to propose changing our interface before releasing version 1.

Clarify supported features

I cannot understand - is x509 Authentication supported or not?
It seems to be presented in code
https://github.com/wmnsk/gopcua/blob/72c87ce6fabe6993089b948be572e56fe94670c5/datatypes/user-identity-token.go#L253
and even tested, but supported features do not mention it as supported.
So I'm confused - was it supported not fully or it's just not working code or it's just a documentation issue?

If it's the last one I think other features should be checked too (maybe more of them supported already).
Thanks!

ReadResponse service

Hello,
question regards to #130 (comment)

Please could you help me with clarifying "Retrieve values in ReadResponse from server"
Did you mean, getting data from services.DecodeReadResponse(buf) and then getting from the struct of ReadResponse.Result?
I did session.Read() and variant EncodingMask shows the right type from server. But other parameters are &{10 <nil> <nil> <nil> []}

Update README.md

Before first release, we need to make README.md more friendly for users.

  • Implementation status compared to the spec
  • Good-looking Badges
  • Wording
  • ...

Work in progress in PR #30.

Change parameters in Constructors

Parameters in constructors in each Service should be given as a defined types instead of respective values in the types.

e.g., Pass SignatureData instead of alg and sig in CreateSession.

Value nil with ReadResponse service in new version

Hi,

I tried to implement the new version you released in my current project here
https://github.com/felix-lessoer/Machinebeat/blob/v2/beater/client.go

The problem is:
After changing the implementation to use your new client implementation I got no value from ReadResponse anymore.
Trying to get ReadResponse.Results[].Value always leads into nil.

I'm using this public server to test:
endpoint: "opc.tcp://opcuaserver.com:48010"

Node:
id: "AirConditioner_1.Temperature"
namespace: 3

How do you expect to build the ReadRequest?

`
node = client.Node(nodeID)

rh := ua.RequestHeader{}

rv := ua.ReadValueID{}

rv.NodeID = nodeID
rv.AttributeID = 0
rv.IndexRange = ""

qn, err := node.BrowseName()
if err != nil {
	return nil, err
}
rv.DataEncoding = qn

rr := ua.ReadRequest{}
rr.MaxAge = 2000
rr.NodesToRead = []*ua.ReadValueID{&rv}
rr.TimestampsToReturn = ua.TimestampsToReturnBoth
rr.RequestHeader = &rh

m, err := client.Read(&rr)
if err != nil {
	return nil, err
}
value, status := handleReadResponse(m)

`

Fix CircleCI

After transferred the repo CCI has not been working.

Unfollow/Stop Building => Setup again did not resolve the issue. Maybe pushing something refleshes it?

Open the Wiki

Hey,

I tried adding some stuff to the wiki. Looks like it's not activated or I'm not allowed to use it. Could you change that?

Today I experimented with gopcua in the browser. I have a working example compiling it to webassembly and decoding raw messages in the browser.

The idea is to use gopcua in the browser and communicate with OPC UA servers that support websockets.

Fix AuthToken handling

In OPC UA Session, client should set AuthenticationToken told by server, and the type of data varies within NodeId.
In current implementation it is hard-coded in some fixed types like FourByteNodeID. It should be NodeID interface to be able to set any type of NodeId given from server.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.