fix(inputs.opcua): Ensure we are connected after reconnect (#13514)

This commit is contained in:
Sven Rebhan 2023-06-30 20:49:26 +02:00 committed by GitHub
parent 96b9845853
commit 261e0223a7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 32 additions and 35 deletions

View File

@ -18,6 +18,20 @@ type OpcUAWorkarounds struct {
AdditionalValidStatusCodes []string `toml:"additional_valid_status_codes"`
}
type ConnectionState opcua.ConnState
const (
Closed ConnectionState = ConnectionState(opcua.Closed)
Connected ConnectionState = ConnectionState(opcua.Connected)
Connecting ConnectionState = ConnectionState(opcua.Connecting)
Disconnected ConnectionState = ConnectionState(opcua.Disconnected)
Reconnecting ConnectionState = ConnectionState(opcua.Reconnecting)
)
func (c ConnectionState) String() string {
return opcua.ConnState(c).String()
}
type OpcUAClientConfig struct {
Endpoint string `toml:"endpoint"`
SecurityPolicy string `toml:"security_policy"`
@ -73,29 +87,15 @@ func (o *OpcUAClientConfig) CreateClient(log telegraf.Logger) (*OpcUAClient, err
Log: log,
}
c.Log.Debug("Initialising OpcUAClient")
c.State = Disconnected
err = c.setupWorkarounds()
return c, err
}
// ConnectionState used for constants
type ConnectionState int
const (
// Disconnected constant State 0
Disconnected ConnectionState = iota
// Connecting constant State 1
Connecting
// Connected constant State 2
Connected
)
type OpcUAClient struct {
Config *OpcUAClientConfig
Log telegraf.Logger
State ConnectionState
Client *opcua.Client
opts []opcua.Option
@ -164,10 +164,7 @@ func (o *OpcUAClient) Connect() error {
switch u.Scheme {
case "opc.tcp":
o.State = Connecting
err = o.SetupOptions()
if err != nil {
if err := o.SetupOptions(); err != nil {
return err
}
@ -184,11 +181,8 @@ func (o *OpcUAClient) Connect() error {
ctx, cancel := context.WithTimeout(context.Background(), time.Duration(o.Config.ConnectTimeout))
defer cancel()
if err := o.Client.Connect(ctx); err != nil {
o.State = Disconnected
return fmt.Errorf("error in Client Connection: %w", err)
}
o.State = Connected
o.Log.Debug("Connected to OPC UA Server")
default:
@ -206,7 +200,6 @@ func (o *OpcUAClient) Disconnect(ctx context.Context) error {
switch u.Scheme {
case "opc.tcp":
o.State = Disconnected
// We can't do anything about failing to close a connection
err := o.Client.CloseWithContext(ctx)
o.Client = nil
@ -215,3 +208,10 @@ func (o *OpcUAClient) Disconnect(ctx context.Context) error {
return fmt.Errorf("invalid controller")
}
}
func (o *OpcUAClient) State() ConnectionState {
if o.Client == nil {
return Disconnected
}
return ConnectionState(o.Client.State())
}

View File

@ -90,29 +90,26 @@ func (o *ReadClient) Connect() error {
}
func (o *ReadClient) ensureConnected() error {
if o.State == opcua.Disconnected {
err := o.Connect()
if err != nil {
return err
}
if o.State() == opcua.Disconnected {
return o.Connect()
}
return nil
}
func (o *ReadClient) CurrentValues() ([]telegraf.Metric, error) {
err := o.ensureConnected()
if err != nil {
if err := o.ensureConnected(); err != nil {
return nil, err
}
err = o.read()
if err != nil && o.State == opcua.Connected {
if state := o.State(); state != opcua.Connected {
return nil, fmt.Errorf("not connected, in state %q", state)
}
if err := o.read(); err != nil {
// We do not return the disconnect error, as this would mask the
// original problem, but we do log it
disconnectErr := o.Disconnect(context.Background())
if disconnectErr != nil {
o.Log.Debug("Error while disconnecting: ", disconnectErr)
if derr := o.Disconnect(context.Background()); derr != nil {
o.Log.Debug("Error while disconnecting: ", derr)
}
return nil, err