fix: Add support for opcua datetime values (#12101)

This commit is contained in:
Viraj Sinha 2022-11-07 11:35:53 -08:00 committed by GitHub
parent e305973731
commit e42b0832e0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 47 additions and 16 deletions

View File

@ -3,13 +3,14 @@ package opcua
import (
"context"
"fmt"
"net/url"
"strconv"
"time"
"github.com/gopcua/opcua"
"github.com/gopcua/opcua/ua"
"github.com/influxdata/telegraf"
"github.com/influxdata/telegraf/config"
"net/url"
"strconv"
"time"
)
type OpcUAWorkarounds struct {
@ -56,6 +57,7 @@ func (o *OpcUAClientConfig) validateEndpoint() error {
default:
return fmt.Errorf("invalid security type '%s' in '%s'", o.SecurityMode, o.Endpoint)
}
return nil
}

View File

@ -3,15 +3,16 @@ package input
import (
"context"
"fmt"
"sort"
"strconv"
"strings"
"time"
"github.com/gopcua/opcua/ua"
"github.com/influxdata/telegraf"
"github.com/influxdata/telegraf/internal/choice"
"github.com/influxdata/telegraf/metric"
"github.com/influxdata/telegraf/plugins/common/opcua"
"sort"
"strconv"
"strings"
"time"
)
// NodeSettings describes how to map from a OPC UA node to a Metric
@ -52,10 +53,11 @@ const (
// InputClientConfig a configuration for the input client
type InputClientConfig struct {
opcua.OpcUAClientConfig
MetricName string `toml:"name"`
Timestamp TimestampSource `toml:"timestamp"`
RootNodes []NodeSettings `toml:"nodes"`
Groups []NodeGroupSettings `toml:"group"`
MetricName string `toml:"name"`
Timestamp TimestampSource `toml:"timestamp"`
TimestampFormat string `toml:"timestamp_format"`
RootNodes []NodeSettings `toml:"nodes"`
Groups []NodeGroupSettings `toml:"group"`
}
func (o *InputClientConfig) Validate() error {
@ -68,6 +70,10 @@ func (o *InputClientConfig) Validate() error {
return err
}
if o.TimestampFormat == "" {
o.TimestampFormat = time.RFC3339Nano
}
return nil
}
@ -356,8 +362,14 @@ func (o *OpcUAInputClient) UpdateNodeValue(nodeIdx int, d *ua.DataValue) {
}
if d.Value != nil {
o.LastReceivedData[nodeIdx].Value = d.Value.Value()
o.LastReceivedData[nodeIdx].DataType = d.Value.Type()
o.LastReceivedData[nodeIdx].Value = d.Value.Value()
if o.LastReceivedData[nodeIdx].DataType == ua.TypeIDDateTime {
if t, ok := d.Value.Value().(time.Time); ok {
o.LastReceivedData[nodeIdx].Value = t.Format(o.Config.TimestampFormat)
}
}
}
o.LastReceivedData[nodeIdx].ServerTime = d.ServerTimestamp
o.LastReceivedData[nodeIdx].SourceTime = d.SourceTimestamp

View File

@ -2,6 +2,9 @@ package opcua
import (
"fmt"
"testing"
"time"
"github.com/docker/go-connections/nat"
"github.com/influxdata/telegraf/config"
"github.com/influxdata/telegraf/plugins/common/opcua"
@ -9,8 +12,6 @@ import (
"github.com/influxdata/telegraf/testutil"
"github.com/stretchr/testify/require"
"github.com/testcontainers/testcontainers-go/wait"
"testing"
"time"
)
const servicePort = "4840"
@ -119,6 +120,7 @@ func TestReadClientIntegration(t *testing.T) {
{"ManufacturerName", "0", "i", "2263", "open62541"},
{"badnode", "1", "i", "1337", nil},
{"goodnode", "1", "s", "the.answer", int32(42)},
{"DateTime", "1", "i", "51037", "0001-01-01T00:00:00Z"},
}
readConfig := ReadClientConfig{

View File

@ -65,6 +65,12 @@ See the [CONFIGURATION.md][CONFIGURATION.md] for more details.
## "source" -- uses the timestamp provided by the source
# timestamp = "gather"
#
## The default timetsamp format is RFC3339Nano
# Other timestamp layouts can be configured using the Go language time
# layout specification from https://golang.org/pkg/time/#Time.Format
# e.g.: json_timestamp_format = "2006-01-02T15:04:05Z07:00"
#timestamp_format = ""
#
## Node ID configuration
## name - field name to use in the output
## namespace - OPC UA namespace of the node (integer value 0 thru 3)

View File

@ -3,6 +3,9 @@ package opcua_listener
import (
"context"
"fmt"
"testing"
"time"
"github.com/docker/go-connections/nat"
"github.com/influxdata/telegraf/config"
"github.com/influxdata/telegraf/plugins/common/opcua"
@ -10,8 +13,6 @@ import (
"github.com/influxdata/telegraf/testutil"
"github.com/stretchr/testify/require"
"github.com/testcontainers/testcontainers-go/wait"
"testing"
"time"
)
const servicePort = "4840"
@ -54,6 +55,7 @@ func TestSubscribeClientIntegration(t *testing.T) {
{"ManufacturerName", "0", "i", "2263", "open62541"},
{"badnode", "1", "i", "1337", nil},
{"goodnode", "1", "s", "the.answer", int32(42)},
{"DateTime", "1", "i", "51037", "0001-01-01T00:00:00Z"},
}
var tagsRemaining = make([]string, 0, len(testopctags))
for i, tag := range testopctags {
@ -152,6 +154,7 @@ security_mode = "auto"
certificate = "/etc/telegraf/cert.pem"
private_key = "/etc/telegraf/key.pem"
auth_method = "Anonymous"
timestamp_format = "2006-01-02T15:04:05Z07:00"
username = ""
password = ""
nodes = [

View File

@ -46,6 +46,12 @@
## "source" -- uses the timestamp provided by the source
# timestamp = "gather"
#
## The default timetsamp format is RFC3339Nano
# Other timestamp layouts can be configured using the Go language time
# layout specification from https://golang.org/pkg/time/#Time.Format
# e.g.: json_timestamp_format = "2006-01-02T15:04:05Z07:00"
#timestamp_format = ""
#
## Node ID configuration
## name - field name to use in the output
## namespace - OPC UA namespace of the node (integer value 0 thru 3)