From c78139c8b9baa2db38502f00a559164aafc0f933 Mon Sep 17 00:00:00 2001 From: R290 <46033588+R290@users.noreply.github.com> Date: Mon, 26 Sep 2022 19:33:59 +0200 Subject: [PATCH] feat(inputs.opcua): add use regular reads workaround (#11630) --- plugins/inputs/opcua/README.md | 7 ++++++ plugins/inputs/opcua/opcua.go | 37 +++++++++++++++++++++--------- plugins/inputs/opcua/opcua_test.go | 25 ++++++++++++++++++++ plugins/inputs/opcua/sample.conf | 3 +++ 4 files changed, 61 insertions(+), 11 deletions(-) diff --git a/plugins/inputs/opcua/README.md b/plugins/inputs/opcua/README.md index 3cd8e270c..972fea50b 100644 --- a/plugins/inputs/opcua/README.md +++ b/plugins/inputs/opcua/README.md @@ -95,6 +95,9 @@ Plugin minimum tested version: 1.16 # [inputs.opcua.workarounds] ## Set additional valid status codes, StatusOK (0x0) is always considered valid # additional_valid_status_codes = ["0xC0"] + + ## Use regular reads instead of registered reads + # use_regular_reads = false ``` ## Node Configuration @@ -152,6 +155,10 @@ This example group configuration has two groups with two nodes each: ] ``` +## Metrics + +Metrics are produced according to the defined node ID and group configuration. + ## Example Output ```text diff --git a/plugins/inputs/opcua/opcua.go b/plugins/inputs/opcua/opcua.go index 88b601112..134b3d405 100644 --- a/plugins/inputs/opcua/opcua.go +++ b/plugins/inputs/opcua/opcua.go @@ -26,6 +26,7 @@ var sampleConfig string type OpcuaWorkarounds struct { AdditionalValidStatusCodes []string `toml:"additional_valid_status_codes"` + UseRegularReads bool `toml:"use_regular_reads"` } // OpcUA type @@ -365,17 +366,31 @@ func Connect(o *OpcUA) error { return fmt.Errorf("error in Client Connection: %s", err) } - regResp, err := o.client.RegisterNodes(&ua.RegisterNodesRequest{ - NodesToRegister: o.nodeIDs, - }) - if err != nil { - return fmt.Errorf("registerNodes failed: %v", err) - } + if !o.Workarounds.UseRegularReads { + regResp, err := o.client.RegisterNodes(&ua.RegisterNodesRequest{ + NodesToRegister: o.nodeIDs, + }) + if err != nil { + return fmt.Errorf("registerNodes failed: %v", err) + } - o.req = &ua.ReadRequest{ - MaxAge: 2000, - NodesToRead: readvalues(regResp.RegisteredNodeIDs), - TimestampsToReturn: ua.TimestampsToReturnBoth, + o.req = &ua.ReadRequest{ + MaxAge: 2000, + TimestampsToReturn: ua.TimestampsToReturnBoth, + NodesToRead: readvalues(regResp.RegisteredNodeIDs), + } + } else { + var nodesToRead []*ua.ReadValueID + + for _, nid := range o.nodeIDs { + nodesToRead = append(nodesToRead, &ua.ReadValueID{NodeID: nid}) + } + + o.req = &ua.ReadRequest{ + MaxAge: 2000, + TimestampsToReturn: ua.TimestampsToReturnBoth, + NodesToRead: nodesToRead, + } } err = o.getData() @@ -438,7 +453,7 @@ func (o *OpcUA) getData() error { resp, err := o.client.Read(o.req) if err != nil { o.ReadError.Incr(1) - return fmt.Errorf("RegisterNodes Read failed: %v", err) + return fmt.Errorf("Read failed: %w", err) } o.ReadSuccess.Incr(1) for i, d := range resp.Results { diff --git a/plugins/inputs/opcua/opcua_test.go b/plugins/inputs/opcua/opcua_test.go index 25ab74963..d5b206ae0 100644 --- a/plugins/inputs/opcua/opcua_test.go +++ b/plugins/inputs/opcua/opcua_test.go @@ -136,6 +136,31 @@ func TestClient1Integration(t *testing.T) { t.Errorf("Tag: %s has value: %v", o.nodes[i].tag.FieldName, v.Value) } } + + // test regular reads workaround + o.Workarounds.UseRegularReads = true + + for i := range o.nodeData { + o.nodeData[i] = OPCData{} + } + + err = Connect(&o) + if err != nil { + t.Fatalf("Connect Error: %s", err) + } + + for i, v := range o.nodeData { + if v.Value != nil { + types := reflect.TypeOf(v.Value) + value := reflect.ValueOf(v.Value) + compare := fmt.Sprintf("%v", value.Interface()) + if compare != testopctags[i].Want { + t.Errorf("Tag %s: Values %v for type %s does not match record", o.nodes[i].tag.FieldName, value.Interface(), types) + } + } else if testopctags[i].Want != nil { + t.Errorf("Tag: %s has value: %v", o.nodes[i].tag.FieldName, v.Value) + } + } } func MapOPCTag(tags OPCTags) (out NodeSettings) { diff --git a/plugins/inputs/opcua/sample.conf b/plugins/inputs/opcua/sample.conf index 0e44d1d6c..e24b65985 100644 --- a/plugins/inputs/opcua/sample.conf +++ b/plugins/inputs/opcua/sample.conf @@ -85,3 +85,6 @@ # [inputs.opcua.workarounds] ## Set additional valid status codes, StatusOK (0x0) is always considered valid # additional_valid_status_codes = ["0xC0"] + + ## Use regular reads instead of registered reads + # use_regular_reads = false