Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: Add support for opcua datetime values #12101

Merged
merged 8 commits into from
Nov 7, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions plugins/common/opcua/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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
}

Expand Down
30 changes: 21 additions & 9 deletions plugins/common/opcua/input/input_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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 {
Expand All @@ -68,6 +70,10 @@ func (o *InputClientConfig) Validate() error {
return err
}

if o.TimestampFormat == "" {
o.TimestampFormat = time.RFC3339Nano
}

return nil
}

Expand Down Expand Up @@ -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
Expand Down
6 changes: 4 additions & 2 deletions plugins/inputs/opcua/opcua_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,16 @@ package opcua

import (
"fmt"
"testing"
"time"

"github.com/docker/go-connections/nat"
"github.com/influxdata/telegraf/config"
"github.com/influxdata/telegraf/plugins/common/opcua"
"github.com/influxdata/telegraf/plugins/common/opcua/input"
"github.com/influxdata/telegraf/testutil"
"github.com/stretchr/testify/require"
"github.com/testcontainers/testcontainers-go/wait"
"testing"
"time"
)

const servicePort = "4840"
Expand Down Expand Up @@ -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{
Expand Down
6 changes: 6 additions & 0 deletions plugins/inputs/opcua_listener/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,12 @@ Plugin minimum tested version: 1.25
## "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)
Expand Down
7 changes: 5 additions & 2 deletions plugins/inputs/opcua_listener/opcua_listener_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,16 @@ 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"
"github.com/influxdata/telegraf/plugins/common/opcua/input"
"github.com/influxdata/telegraf/testutil"
"github.com/stretchr/testify/require"
"github.com/testcontainers/testcontainers-go/wait"
"testing"
"time"
)

const servicePort = "4840"
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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 = [
Expand Down
6 changes: 6 additions & 0 deletions plugins/inputs/opcua_listener/sample.conf
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down