awcullen / opcua Goto Github PK
View Code? Open in Web Editor NEWOPC Unified Architecture (OPC UA) in Go.
License: MIT License
OPC Unified Architecture (OPC UA) in Go.
License: MIT License
We use your SDK to construct a client which must read a ByteString of 27Mb.
The server use Unified Automation SDK. We construct this server and we modify it to support ByteString of 32M.
We can read ByteString of 27Mb on server but I must modify defaultMaxMessageSize in pkg/mod/github.com/awcullen/[email protected]/client/client_secure_channel.go :
Is it possible to set a parameter to modify by software defaultMaxMessageSize ?
Hi Andrew,
I have the following scenario: several subscriptions for the same server and each subscription is handling its monitored items in its own goroutine.
The problem is that I'm receiving from one subscription to another subscription (I'm checking this by subscription Id).
I've oversimplified the scenario by using the sample from the src and attached the file. I've tested it also using UAExpert demo server and ProSys sim server, and it's the same.
Any suggestions on how to fix this?
run.go.zip
When running go test -race ./...
the error fatal error: checkptr: pointer arithmetic result points to invalid allocation
occurs.
This is a typical error when unsafe.Pointer
rules are not respected (https://pkg.go.dev/unsafe#Pointer).
Running go vet ./...
points into the direction of ua/binary_decoder.go:356:27: method ReadByte(value *byte) error should have signature ReadByte() (byte, error)
hi,
my opc server:
host := "0.0.0.0"
if err = global.EnsurePKI(); err != nil {
log.Println("Error creating PKI.")
return
}
permissions, rules := s.userAuthority()
endpointURL := fmt.Sprintf("opc.tcp://%s:%d", host, s.OpcTemplate.Port)
// create server
srv, err := server.New(
ua.ApplicationDescription{
ApplicationURI: fmt.Sprintf("urn:%s:testserver", host),
ProductURI: "https://www.opcua.com",
ApplicationName: ua.LocalizedText{
Text: fmt.Sprintf("testserver@%s", host),
Locale: "en",
},
ApplicationType: ua.ApplicationTypeServer,
GatewayServerURI: "",
DiscoveryProfileURI: "",
DiscoveryURLs: []string{endpointURL},
},
path.Join(system.PkiPath(),"server.crt" ),
path.Join(system.PkiPath(),"server.key" ),
endpointURL,
server.WithBuildInfo(
ua.BuildInfo{
ProductURI: "https://www.opcua.com",
ManufacturerName: "opcua",
ProductName: "testserver",
SoftwareVersion: "0.3.0",
}),
s.userOptions(),
server.WithAnonymousIdentity(s.OpcTemplate.AllowAnonymous),
server.WithRolePermissions(permissions),
server.WithRolesProvider(server.NewRulesBasedRolesProvider(rules)),
server.WithSecurityPolicyNone(true),
server.WithInsecureSkipVerify(),
)
my host name is :LAPTOP-8IKMN32G
I can connect the server use: opc.tcp://LAPTOP-8IKMN32G:46010
. but cannot use opc.tcp://127.0.0.1:46010
.
when i use opc.tcp://127.0.0.1:46010
, the client response:
How can I use IP to connect to the OPC server?
Thanks.
Hello,
is there a easy way to add objects like variables or folders by code at the moment?
If yes it would be great if you can give an example.
Thanks
I was facing an issue to read/write dimensional array in the variant variable with direct node access.
It looks like there was a TODO placeholder for dimensional arrays in the decoder. But encoding is also missing it.
Lines 1294 to 1296 in 387afc9
I have made a comit 348ab93 in a forked branch with read/write example working.
It would be useful to have some kind of a structure to keep the information about additional properties of the Variant like this to be part of the variant.:
type VariantMetadata struct {
//mask contains the type and the array flags
//bits 0:5: built-in type id 1-25
//bit 6: array dimensions
//bit 7: array values
EncodingMask byte
ArrayLength int32
ArrayDimensionsLength int32
ArrayDimensions []int32
}
I looked into https://github.com/gopcua/opcua library as alternative solution and used some of its array reconstruction method as well as flattened array read/write.
I hope my fork can help to add it here to the master branch eventually.
What do you think?
Let me know how you see it in the end, so I can adapt it for merging...
Hello, I would like to ask if the OPCUA server supports histroy-read?Can you guide me how to achieve it?
I launch an OpcUa server with srv.ListenAndServe().
When an OpcUa client connect, I would have an event or retreive information.
I try with :
if srv.ChannelManager().Len() > 0 {
ssc, ret := srv.ChannelManager().Get(0)
if ret {
fmt.Printf("ssc: %d; SecurityMode: TODO\n", ssc.ChannelID())
} else {
fmt.Printf("ssc: NIL !!!\n")
}
}
But, it's always retrun NIL :-(
What is the id in Get method: Get(id uint32)?
How can I retrieve it ?
Thank's a lot for your response and your job on OpcUa in Go :-)
call Server.Close but the function "requestWorker" is not ending
Exception has occurred: panic
"send on closed channel"
Stack:
4 0x0000000000e7d146 in github.com/gammazero/workerpool.(*WorkerPool).Submit
at github.com/gammazero/[email protected]/workerpool.go:109
5 0x0000000000ee0ef7 in github.com/awcullen/opcua/server.(*Server).handleRead
at github.com/awcullen/[email protected]/server/server_service_set.go:2249
6 0x0000000000eadf8b in github.com/awcullen/opcua/server.(*Server).handleRequest
at github.com/awcullen/[email protected]/server/server.go:444
7 0x0000000000ead294 in github.com/awcullen/opcua/server.(*Server).requestWorker
A client try to connect without security mode while server only accept securised session.
Dial return BadUnexpectedError but the response should be Bad_SecurityModeRejected.
It's appear here in client.go::Dial :
if selectedEndpoint == nil {
return nil, ua.BadUnexpectedError
}
Awesome work with the library, I really love it. I want to be able to read arbitrary Extension objects in the format of map[string]interface{}. Arrays too :) Do you have some ideas about where should I start, what would be the best approach that would fit in the whole idea of the architecture? Maybe you even have some code snippets? Thank you.
Hi @awcullen
I tried to connect from node-opcua to my server based on your implementation. Node-opcua has a default message size which is AFAIK the minimum required message size for a secure channel of 8192.
Unfortunately the connection did not succeed until I increased the message size to a higher value. Node-opcua could connect to a open62541 based server with a message size of 8192.
So my question, is this a intended behavior? I did some debugging and found out that a message is not sent if its length exceed the max message size. so does your implementation require a bigger message size then say open62541 or is there an issue chunking the messages (if this is even possible)?
Not sure if someone else noticed this yet and I haven't started debugging either. But I noticed a curious behaviour: after a couple of days of running great, the OPC UA server stops responding to OpenSecureChannelRequest
. Looking at the Wireshark dump, I can see that the HEL
and ACK
messages of UACP are exchanged correctly, then the client sends the OpenSecureChannelRequest
but doesn't receive an answer.
There is lots of RAM and CPU available but the process looks idle and there is no error message in the logs either.
From a go client based on opcua go sdk, I can't connect to an OPCUA server (where only Basic256Sha256 is opened) built on UnifiedAutomation SDK with our AC certs.
The server have certs/pem/crl, we could access to it with UaExpert.
If I use same certs as UaExpert there the error:
'An error occured verifying security'
On server, it seems that client require SecutityPolicy#none which is forbidden.
If I try with AutoSigned certificates, I have no problem, only with AC certs.
Thank's for your help.
When trying to read the discription of an object,
I get the following response: The attribute is not supported for the specified Node.
The snippet works for other nodes (variables)
It also doesn't work when refering to the the object through its identifier
req := &ua.ReadRequest{
NodesToRead: []ua.ReadValueID{
{
NodeID: ua.ParseNodeID("ns=4;s=IdentificationData"),
AttributeID: ua.AttributeIDDescription,
},
},
}
Hi Andrew,
As the final step in push certificate management on a GDS server, I am calling the ApplyChanges method from a client application currently being set up using Go. Unfortunately, nothing really happens, whereas the method call using UaExpert or a python implementation yields the expected results. As the certificate writing, signing and updating otherwise works perfrectly fine using Go, I'm unsure where to start looking.
A selection of the trace looks as follows:
2024/05/30 15:49:18 CallRequest{ "AuthenticationToken": "i=3041481013", "Timestamp": "2024-05-30T15:49:18.8335444+02:00", "RequestHandle": 5, "ReturnDiagnostics": 0, "AuditEntryID": "", "TimeoutHint": 15000, "AdditionalHeader": null, "MethodsToCall": [ { "ObjectID": "i=12637", "MethodID": "i=12740", "InputArguments": null } ] } 2024/05/30 15:49:18 CallResponse{ "Timestamp": "2024-05-30T13:49:25.9168499Z", "RequestHandle": 5, "ServiceResult": 0, "ServiceDiagnostics": {}, "StringTable": null, "AdditionalHeader": null, "Results": [ { "StatusCode": 0, "InputArgumentResults": null, "InputArgumentDiagnosticInfos": null, "OutputArguments": null } ], "DiagnosticInfos": null }
The method call is set up as:
req := &ua.CallRequest{ MethodsToCall: []ua.CallMethodRequest{ { ObjectID: ua.ObjectIDServerConfiguration, MethodID: ua.MethodIDServerConfigurationApplyChanges, }, }, }
It doesn't really seem to matter whether InputArguments is nil, an empty ua.Variant slice, or omitted altogether.
Would you have any suggestion on where to start looking, or on what other information to share?
Is it in the roadmap to pass the CTT (compliance test tools) of the fondation OPC UA: https://opcfoundation.org/developer-tools/certification-test-tools/opc-ua-compliance-test-tool-uactt/ on opcua server part?
Hi Andrew,
The more we test with this library, the more we enjoy and like it.
Still have a question though;
How do we write a go struct to a variable (either nested, array or otherwise).
Convert a struct to a byte array and then send it to the server, like the reverse of the struct read?
Hello,
I have a problem when i want to write a value with anonymous authentication settings. I have read access to my server but when i want to override a value i get a BadUserAccessDenied error.
My server looks like this:
srv, err := server.New(
ua.ApplicationDescription{
ApplicationURI: fmt.Sprintf("urn:%s:testserver", host),
ProductURI: "http://github.com/awcullen/opcua",
ApplicationName: ua.LocalizedText{
Text: fmt.Sprintf("testserver@%s", host),
Locale: "en",
},
ApplicationType: ua.ApplicationTypeServer,
GatewayServerURI: "",
DiscoveryProfileURI: "",
DiscoveryURLs: []string{endpointURL},
},
"./pki/server.crt",
"./pki/server.key",
endpointURL,
server.WithBuildInfo(
ua.BuildInfo{
ProductURI: "http://github.com/awcullen/opcua",
ManufacturerName: "awcullen",
ProductName: "testserver",
SoftwareVersion: SoftwareVersion,
}),
server.WithInsecureSkipVerify(),
server.WithAnonymousIdentity(true),
server.WithSecurityPolicyNone(true),
)
I am facing an issue with a Golang OPC-UA client when trying to establish a connection with a PLC (S7-1515). The PLC is in a sub-network behind a router and has its own local IP address.
In the Dial function of the OPC-UA client, I pass an endpointURL that points to the PLC. During the connection process, the client fetches available endpoints from the PLC using the GetEndpoints method. The client then sorts and selects one of these endpoints based on security levels and other criteria.
The issue arises when the client replaces the endpointURL I provided with one from the selected endpoint returned by GetEndpoints. This becomes problematic because the selected endpoint often has a local IP address, rendering it inaccessible from my network.
Suspected Cause:
I suspect that the problem might be due to the way the endpoints are ordered and selected within the Dial function. Specifically, it is this block of code that sets the endpointURL based on the selected endpoint:
Client.go, dial function
if selectedEndpoint == nil {
return nil, ua.BadSecurityModeRejected
}
cli.endpointURL = selectedEndpoint.EndpointURL
My current fix is that if the passed endpointurl is totally unequal to the ordered/selected endpoint url -> then take the passed endpoint url.
This works, but is not a nice solution
hi, custom dataType can not be loaded using the NodeSet file below:
https://github.com/Pro/opcua-animal-cs/blob/master/Published/animal/animal.NodeSet2.xml
while using c# opcua server :
Method Dial proposed by awcullen/opcua is 3 OPCUA services combined : OpenSecureChannel, CreateSession and ActivateSession.
Each of theses 3 services aren't offered.
I can't have acces to server response: I would like to have access to ServiceResult and to RevisedSessionTimeout and MaxRequestMessageSize (from CreateSession).
Thank's for your job on OPCUA
I have a opcua server running for several week now. Today I noticed a occasional crash of the server. Surprisingly it was at night when no client is expected to connect to except maybe some nasty scripts looking for open services (the server is currently publicly teachable).
Here's the stack trace:
panic: runtime error: slice bounds out of range [:1414012975] with capacity 65536
goroutine 13 [running]:
github.com/awcullen/opcua/server.(*serverSecureChannel).read(0x400d896700, {0x4006532000, 0x0?, 0x10000})
/source/vendor/github.com/awcullen/opcua/server/server_secure_channel.go:1636 +0x1c4
github.com/awcullen/opcua/server.(*serverSecureChannel).Open(0x400d896700)
/source/vendor/github.com/awcullen/opcua/server/server_secure_channel.go:209 +0x150
github.com/awcullen/opcua/server.(*Server).serve.func1({0x99fda0?, 0x400b1b2008?})
/source/vendor/github.com/awcullen/opcua/server/server.go:403 +0x8c
created by github.com/awcullen/opcua/server.(*Server).serve
/source/vendor/github.com/awcullen/opcua/server/server.go:400 +0x100
if suppose there should be a length check (count
should never exceed len(p)
) in
opcua/server/server_secure_channel.go
Lines 1633 to 1642 in 5cd564e
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.