You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@plc4x.apache.org by sr...@apache.org on 2023/05/16 13:48:21 UTC

[plc4x] branch develop updated: test(plc4go/spi): add test for DefaultPlcWriteRequest

This is an automated email from the ASF dual-hosted git repository.

sruehl pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/plc4x.git


The following commit(s) were added to refs/heads/develop by this push:
     new 9c5232d494 test(plc4go/spi): add test for DefaultPlcWriteRequest
9c5232d494 is described below

commit 9c5232d4943e0a559630c13b0856c9126d0746b2
Author: Sebastian Rühl <sr...@apache.org>
AuthorDate: Tue May 16 15:48:13 2023 +0200

    test(plc4go/spi): add test for DefaultPlcWriteRequest
---
 plc4go/spi/model/DefaultPlcWriteRequest.go         |   5 +-
 plc4go/spi/model/DefaultPlcWriteRequest_test.go    | 748 +++++++++++++++++++++
 plc4go/spi/model/mock_PlcValueHandler_test.go      | 112 +++
 plc4go/spi/model/mock_PlcWriter_test.go            | 103 +++
 .../spi/model/mock_WriteRequestInterceptor_test.go | 149 ++++
 plc4go/spi/model/mock_requirements.go              |  15 +
 6 files changed, 1131 insertions(+), 1 deletion(-)

diff --git a/plc4go/spi/model/DefaultPlcWriteRequest.go b/plc4go/spi/model/DefaultPlcWriteRequest.go
index c0146e0e83..f065fc5764 100644
--- a/plc4go/spi/model/DefaultPlcWriteRequest.go
+++ b/plc4go/spi/model/DefaultPlcWriteRequest.go
@@ -109,7 +109,10 @@ func (m *DefaultPlcWriteRequestBuilder) Build() (apiModel.PlcWriteRequest, error
 	for name, tag := range m.tags {
 		value, err := m.valueHandler.NewPlcValue(tag, m.values[name])
 		if err != nil {
-			//			return nil, errors.Wrapf(err, "Error parsing value of type: %s", tag.GetTypeName())
+			if tag == nil {
+				return nil, errors.New("Error parsing value for nil tag")
+			}
+			return nil, errors.Wrapf(err, "Error parsing value of type: %s", tag.GetValueType())
 		}
 		plcValues[name] = value
 	}
diff --git a/plc4go/spi/model/DefaultPlcWriteRequest_test.go b/plc4go/spi/model/DefaultPlcWriteRequest_test.go
new file mode 100644
index 0000000000..d4e1066e40
--- /dev/null
+++ b/plc4go/spi/model/DefaultPlcWriteRequest_test.go
@@ -0,0 +1,748 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package model
+
+import (
+	"context"
+	"fmt"
+	"github.com/apache/plc4x/plc4go/spi/utils"
+	"github.com/pkg/errors"
+	"github.com/stretchr/testify/mock"
+	"testing"
+	"time"
+
+	apiModel "github.com/apache/plc4x/plc4go/pkg/api/model"
+	apiValues "github.com/apache/plc4x/plc4go/pkg/api/values"
+	"github.com/apache/plc4x/plc4go/spi"
+	"github.com/apache/plc4x/plc4go/spi/interceptors"
+
+	"github.com/stretchr/testify/assert"
+)
+
+func TestDefaultPlcWriteRequestBuilder_AddTag(t *testing.T) {
+	type fields struct {
+		writer                  spi.PlcWriter
+		tagHandler              spi.PlcTagHandler
+		valueHandler            spi.PlcValueHandler
+		tagNames                []string
+		tagAddresses            map[string]string
+		tags                    map[string]apiModel.PlcTag
+		values                  map[string]any
+		writeRequestInterceptor interceptors.WriteRequestInterceptor
+	}
+	type args struct {
+		name  string
+		tag   apiModel.PlcTag
+		value any
+	}
+	tests := []struct {
+		name   string
+		fields fields
+		args   args
+		want   apiModel.PlcWriteRequestBuilder
+	}{
+		{
+			name: "add it",
+			fields: fields{
+				tagAddresses: map[string]string{},
+				tags:         map[string]apiModel.PlcTag{},
+				values:       map[string]any{},
+			},
+			want: &DefaultPlcWriteRequestBuilder{
+				tagNames:     []string{""},
+				tagAddresses: map[string]string{},
+				tags:         map[string]apiModel.PlcTag{"": nil},
+				values:       map[string]any{"": nil},
+			},
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			m := &DefaultPlcWriteRequestBuilder{
+				writer:                  tt.fields.writer,
+				tagHandler:              tt.fields.tagHandler,
+				valueHandler:            tt.fields.valueHandler,
+				tagNames:                tt.fields.tagNames,
+				tagAddresses:            tt.fields.tagAddresses,
+				tags:                    tt.fields.tags,
+				values:                  tt.fields.values,
+				writeRequestInterceptor: tt.fields.writeRequestInterceptor,
+			}
+			assert.Equalf(t, tt.want, m.AddTag(tt.args.name, tt.args.tag, tt.args.value), "AddTag(%v, %v, %v)", tt.args.name, tt.args.tag, tt.args.value)
+		})
+	}
+}
+
+func TestDefaultPlcWriteRequestBuilder_AddTagAddress(t *testing.T) {
+	type fields struct {
+		writer                  spi.PlcWriter
+		tagHandler              spi.PlcTagHandler
+		valueHandler            spi.PlcValueHandler
+		tagNames                []string
+		tagAddresses            map[string]string
+		tags                    map[string]apiModel.PlcTag
+		values                  map[string]any
+		writeRequestInterceptor interceptors.WriteRequestInterceptor
+	}
+	type args struct {
+		name       string
+		tagAddress string
+		value      any
+	}
+	tests := []struct {
+		name   string
+		fields fields
+		args   args
+		want   apiModel.PlcWriteRequestBuilder
+	}{
+		{
+			name: "add it",
+			fields: fields{
+				tagAddresses: map[string]string{},
+				tags:         map[string]apiModel.PlcTag{},
+				values:       map[string]any{},
+			},
+			want: &DefaultPlcWriteRequestBuilder{
+				tagNames:     []string{""},
+				tagAddresses: map[string]string{"": ""},
+				tags:         map[string]apiModel.PlcTag{},
+				values:       map[string]any{"": nil},
+			},
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			m := &DefaultPlcWriteRequestBuilder{
+				writer:                  tt.fields.writer,
+				tagHandler:              tt.fields.tagHandler,
+				valueHandler:            tt.fields.valueHandler,
+				tagNames:                tt.fields.tagNames,
+				tagAddresses:            tt.fields.tagAddresses,
+				tags:                    tt.fields.tags,
+				values:                  tt.fields.values,
+				writeRequestInterceptor: tt.fields.writeRequestInterceptor,
+			}
+			assert.Equalf(t, tt.want, m.AddTagAddress(tt.args.name, tt.args.tagAddress, tt.args.value), "AddTagAddress(%v, %v, %v)", tt.args.name, tt.args.tagAddress, tt.args.value)
+		})
+	}
+}
+
+func TestDefaultPlcWriteRequestBuilder_Build(t *testing.T) {
+	type fields struct {
+		writer                  spi.PlcWriter
+		tagHandler              spi.PlcTagHandler
+		valueHandler            spi.PlcValueHandler
+		tagNames                []string
+		tagAddresses            map[string]string
+		tags                    map[string]apiModel.PlcTag
+		values                  map[string]any
+		writeRequestInterceptor interceptors.WriteRequestInterceptor
+	}
+	tests := []struct {
+		name      string
+		fields    fields
+		mockSetup func(t *testing.T, fields *fields)
+		want      apiModel.PlcWriteRequest
+		wantErr   assert.ErrorAssertionFunc
+	}{
+		{
+			name:    "build it",
+			want:    NewDefaultPlcWriteRequest(nil, nil, map[string]apiValues.PlcValue{}, nil, nil),
+			wantErr: assert.NoError,
+		},
+		{
+			name: "build it with tags",
+			fields: fields{
+				tagNames:     []string{"a"},
+				tagAddresses: map[string]string{"a": ""},
+				tags:         map[string]apiModel.PlcTag{},
+			},
+			mockSetup: func(t *testing.T, fields *fields) {
+				handler := NewMockPlcTagHandler(t)
+				handler.EXPECT().ParseTag(mock.Anything).Return(nil, nil)
+				fields.tagHandler = handler
+				valueHandler := NewMockPlcValueHandler(t)
+				valueHandler.EXPECT().NewPlcValue(mock.Anything, mock.Anything).Return(nil, nil)
+				fields.valueHandler = valueHandler
+			},
+			want:    NewDefaultPlcWriteRequest(map[string]apiModel.PlcTag{"a": nil}, []string{"a"}, map[string]apiValues.PlcValue{"a": nil}, nil, nil),
+			wantErr: assert.NoError,
+		},
+		{
+			name: "build it with value error",
+			fields: fields{
+				tagNames:     []string{"a"},
+				tagAddresses: map[string]string{"a": ""},
+				tags:         map[string]apiModel.PlcTag{},
+			},
+			mockSetup: func(t *testing.T, fields *fields) {
+				handler := NewMockPlcTagHandler(t)
+				handler.EXPECT().ParseTag(mock.Anything).Return(nil, nil)
+				fields.tagHandler = handler
+				valueHandler := NewMockPlcValueHandler(t)
+				valueHandler.EXPECT().NewPlcValue(mock.Anything, mock.Anything).Return(nil, errors.New("nope"))
+				fields.valueHandler = valueHandler
+			},
+			want:    NewDefaultPlcWriteRequest(map[string]apiModel.PlcTag{"a": nil}, []string{"a"}, map[string]apiValues.PlcValue{"a": nil}, nil, nil),
+			wantErr: assert.Error,
+		},
+		{
+			name: "build it with parse error",
+			fields: fields{
+				tagNames:     []string{"a"},
+				tagAddresses: map[string]string{"a": ""},
+				tags:         map[string]apiModel.PlcTag{},
+			},
+			mockSetup: func(t *testing.T, fields *fields) {
+				handler := NewMockPlcTagHandler(t)
+				handler.EXPECT().ParseTag(mock.Anything).Return(nil, errors.New("nope"))
+				fields.tagHandler = handler
+			},
+			wantErr: assert.Error,
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			if tt.mockSetup != nil {
+				tt.mockSetup(t, &tt.fields)
+			}
+			m := &DefaultPlcWriteRequestBuilder{
+				writer:                  tt.fields.writer,
+				tagHandler:              tt.fields.tagHandler,
+				valueHandler:            tt.fields.valueHandler,
+				tagNames:                tt.fields.tagNames,
+				tagAddresses:            tt.fields.tagAddresses,
+				tags:                    tt.fields.tags,
+				values:                  tt.fields.values,
+				writeRequestInterceptor: tt.fields.writeRequestInterceptor,
+			}
+			got, err := m.Build()
+			if !tt.wantErr(t, err, fmt.Sprintf("Build()")) {
+				return
+			}
+			assert.Equalf(t, tt.want, got, "Build()")
+		})
+	}
+}
+
+func TestDefaultPlcWriteRequestBuilder_GetWriteRequestInterceptor(t *testing.T) {
+	type fields struct {
+		writer                  spi.PlcWriter
+		tagHandler              spi.PlcTagHandler
+		valueHandler            spi.PlcValueHandler
+		tagNames                []string
+		tagAddresses            map[string]string
+		tags                    map[string]apiModel.PlcTag
+		values                  map[string]any
+		writeRequestInterceptor interceptors.WriteRequestInterceptor
+	}
+	tests := []struct {
+		name   string
+		fields fields
+		want   interceptors.WriteRequestInterceptor
+	}{
+		{
+			name: "get it",
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			m := &DefaultPlcWriteRequestBuilder{
+				writer:                  tt.fields.writer,
+				tagHandler:              tt.fields.tagHandler,
+				valueHandler:            tt.fields.valueHandler,
+				tagNames:                tt.fields.tagNames,
+				tagAddresses:            tt.fields.tagAddresses,
+				tags:                    tt.fields.tags,
+				values:                  tt.fields.values,
+				writeRequestInterceptor: tt.fields.writeRequestInterceptor,
+			}
+			assert.Equalf(t, tt.want, m.GetWriteRequestInterceptor(), "GetWriteRequestInterceptor()")
+		})
+	}
+}
+
+func TestDefaultPlcWriteRequestBuilder_GetWriter(t *testing.T) {
+	type fields struct {
+		writer                  spi.PlcWriter
+		tagHandler              spi.PlcTagHandler
+		valueHandler            spi.PlcValueHandler
+		tagNames                []string
+		tagAddresses            map[string]string
+		tags                    map[string]apiModel.PlcTag
+		values                  map[string]any
+		writeRequestInterceptor interceptors.WriteRequestInterceptor
+	}
+	tests := []struct {
+		name   string
+		fields fields
+		want   spi.PlcWriter
+	}{
+		{
+			name: "get it",
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			m := &DefaultPlcWriteRequestBuilder{
+				writer:                  tt.fields.writer,
+				tagHandler:              tt.fields.tagHandler,
+				valueHandler:            tt.fields.valueHandler,
+				tagNames:                tt.fields.tagNames,
+				tagAddresses:            tt.fields.tagAddresses,
+				tags:                    tt.fields.tags,
+				values:                  tt.fields.values,
+				writeRequestInterceptor: tt.fields.writeRequestInterceptor,
+			}
+			assert.Equalf(t, tt.want, m.GetWriter(), "GetWriter()")
+		})
+	}
+}
+
+func TestDefaultPlcWriteRequest_Execute(t *testing.T) {
+	type fields struct {
+		DefaultPlcTagRequest    *DefaultPlcTagRequest
+		values                  map[string]apiValues.PlcValue
+		writer                  spi.PlcWriter
+		writeRequestInterceptor interceptors.WriteRequestInterceptor
+	}
+	tests := []struct {
+		name      string
+		fields    fields
+		mockSetup func(t *testing.T, fields *fields)
+		want      <-chan apiModel.PlcWriteRequestResult
+	}{
+		{
+			name: "execute it",
+			mockSetup: func(t *testing.T, fields *fields) {
+				writer := NewMockPlcWriter(t)
+				writer.EXPECT().Write(mock.Anything, mock.Anything).Return(nil)
+				fields.writer = writer
+			},
+			want: nil,
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			if tt.mockSetup != nil {
+				tt.mockSetup(t, &tt.fields)
+			}
+			d := &DefaultPlcWriteRequest{
+				DefaultPlcTagRequest:    tt.fields.DefaultPlcTagRequest,
+				values:                  tt.fields.values,
+				writer:                  tt.fields.writer,
+				writeRequestInterceptor: tt.fields.writeRequestInterceptor,
+			}
+			assert.Equalf(t, tt.want, d.Execute(), "Execute()")
+		})
+	}
+}
+
+func TestDefaultPlcWriteRequest_ExecuteWithContext(t *testing.T) {
+	type fields struct {
+		DefaultPlcTagRequest    *DefaultPlcTagRequest
+		values                  map[string]apiValues.PlcValue
+		writer                  spi.PlcWriter
+		writeRequestInterceptor interceptors.WriteRequestInterceptor
+	}
+	type args struct {
+		ctx context.Context
+	}
+	tests := []struct {
+		name         string
+		fields       fields
+		args         args
+		mockSetup    func(t *testing.T, fields *fields)
+		wantAsserter func(t *testing.T, results <-chan apiModel.PlcWriteRequestResult) bool
+	}{
+		{
+			name: "execute it",
+			mockSetup: func(t *testing.T, fields *fields) {
+				writer := NewMockPlcWriter(t)
+				writer.EXPECT().Write(mock.Anything, mock.Anything).Return(nil)
+				fields.writer = writer
+			},
+		},
+		{
+			name: "execute it with interceptor with one request",
+			mockSetup: func(t *testing.T, fields *fields) {
+				{
+					writer := NewMockPlcWriter(t)
+					results := make(chan apiModel.PlcWriteRequestResult, 1)
+					results <- NewDefaultPlcWriteRequestResult(
+						NewDefaultPlcWriteRequest(nil, nil, nil, nil, nil),
+						NewDefaultPlcWriteResponse(nil, nil),
+						nil,
+					)
+					writer.EXPECT().Write(mock.Anything, mock.Anything).Return(results)
+					fields.writer = writer
+				}
+				{
+					interceptor := NewMockWriteRequestInterceptor(t)
+					interceptor.EXPECT().InterceptWriteRequest(mock.Anything, mock.Anything).Return([]apiModel.PlcWriteRequest{
+						NewDefaultPlcWriteRequest(nil, nil, nil, nil, nil),
+					})
+					fields.writeRequestInterceptor = interceptor
+				}
+			},
+			wantAsserter: func(t *testing.T, results <-chan apiModel.PlcWriteRequestResult) bool {
+				timeout := time.NewTimer(100 * time.Millisecond)
+				t.Cleanup(func() {
+					utils.CleanupTimer(timeout)
+				})
+				select {
+				case result := <-results:
+					assert.NoError(t, result.GetErr())
+					assert.NotNil(t, result.GetRequest())
+					assert.NotNil(t, result.GetResponse())
+				case <-timeout.C:
+					t.Error("timeout getting a response")
+				}
+				return true
+			},
+		},
+		{
+			name: "execute it with interceptor with three request (panics)",
+			mockSetup: func(t *testing.T, fields *fields) {
+				{
+					writer := NewMockPlcWriter(t)
+					results := make(chan apiModel.PlcWriteRequestResult, 1)
+					results <- NewDefaultPlcWriteRequestResult(nil, nil, nil)
+					writer.EXPECT().Write(mock.Anything, mock.Anything).Return(results)
+					fields.writer = writer
+				}
+				{
+					interceptor := NewMockWriteRequestInterceptor(t)
+					interceptor.EXPECT().InterceptWriteRequest(mock.Anything, mock.Anything).Return([]apiModel.PlcWriteRequest{
+						NewDefaultPlcWriteRequest(nil, nil, nil, nil, nil),
+						NewDefaultPlcWriteRequest(nil, nil, nil, nil, nil),
+						NewDefaultPlcWriteRequest(nil, nil, nil, nil, nil),
+					})
+					fields.writeRequestInterceptor = interceptor
+				}
+			},
+			wantAsserter: func(t *testing.T, results <-chan apiModel.PlcWriteRequestResult) bool {
+				timeout := time.NewTimer(100 * time.Millisecond)
+				t.Cleanup(func() {
+					utils.CleanupTimer(timeout)
+				})
+				select {
+				case result := <-results:
+					assert.Error(t, result.GetErr())
+					assert.NotNil(t, result.GetRequest())
+					assert.Nil(t, result.GetResponse())
+				case <-timeout.C:
+					t.Error("timeout getting a response")
+				}
+				return true
+			},
+		},
+		{
+			name: "execute it with interceptor with three request (context done)",
+			args: args{
+				ctx: func() context.Context {
+					timeout, cancelFunc := context.WithCancel(context.Background())
+					cancelFunc()
+					return timeout
+				}(),
+			},
+			mockSetup: func(t *testing.T, fields *fields) {
+				{
+					writer := NewMockPlcWriter(t)
+					results := make(chan apiModel.PlcWriteRequestResult, 1)
+					results <- NewDefaultPlcWriteRequestResult(nil, nil, nil)
+					writer.EXPECT().Write(mock.Anything, mock.Anything).Return(results)
+					fields.writer = writer
+				}
+				{
+					interceptor := NewMockWriteRequestInterceptor(t)
+					interceptor.EXPECT().InterceptWriteRequest(mock.Anything, mock.Anything).Return([]apiModel.PlcWriteRequest{
+						NewDefaultPlcWriteRequest(nil, nil, nil, nil, nil),
+						NewDefaultPlcWriteRequest(nil, nil, nil, nil, nil),
+						NewDefaultPlcWriteRequest(nil, nil, nil, nil, nil),
+					})
+					fields.writeRequestInterceptor = interceptor
+				}
+			},
+			wantAsserter: func(t *testing.T, results <-chan apiModel.PlcWriteRequestResult) bool {
+				timeout := time.NewTimer(100 * time.Millisecond)
+				t.Cleanup(func() {
+					utils.CleanupTimer(timeout)
+				})
+				select {
+				case result := <-results:
+					assert.Error(t, result.GetErr())
+					assert.NotNil(t, result.GetRequest())
+					assert.Nil(t, result.GetResponse())
+				case <-timeout.C:
+					t.Error("timeout getting a response")
+				}
+				return true
+			},
+		},
+		{
+			name: "execute it with interceptor with three request",
+			args: args{
+				ctx: func() context.Context {
+					timeout, cancelFunc := context.WithTimeout(context.Background(), 1*time.Second)
+					t.Cleanup(cancelFunc)
+					return timeout
+				}(),
+			},
+			mockSetup: func(t *testing.T, fields *fields) {
+				{
+					writer := NewMockPlcWriter(t)
+					results := make(chan apiModel.PlcWriteRequestResult, 1)
+					results <- NewDefaultPlcWriteRequestResult(nil, nil, nil)
+					writer.EXPECT().
+						Write(mock.Anything, mock.Anything).
+						Return(results)
+					close(results)
+					fields.writer = writer
+				}
+				{
+					interceptor := NewMockWriteRequestInterceptor(t)
+					interceptor.EXPECT().InterceptWriteRequest(mock.Anything, mock.Anything).Return([]apiModel.PlcWriteRequest{
+						NewDefaultPlcWriteRequest(nil, nil, nil, nil, nil),
+						NewDefaultPlcWriteRequest(nil, nil, nil, nil, nil),
+						NewDefaultPlcWriteRequest(nil, nil, nil, nil, nil),
+					})
+					interceptor.EXPECT().
+						ProcessWriteResponses(mock.Anything, mock.Anything, mock.Anything).
+						Return(
+							NewDefaultPlcWriteRequestResult(
+								NewDefaultPlcWriteRequest(nil, nil, nil, nil, nil),
+								NewDefaultPlcWriteResponse(nil, nil),
+								nil,
+							),
+						).Maybe()
+					fields.writeRequestInterceptor = interceptor
+				}
+			},
+			wantAsserter: func(t *testing.T, results <-chan apiModel.PlcWriteRequestResult) bool {
+				timeout := time.NewTimer(100 * time.Millisecond)
+				t.Cleanup(func() {
+					utils.CleanupTimer(timeout)
+				})
+				select {
+				case result := <-results:
+					assert.NoError(t, result.GetErr())
+					assert.NotNil(t, result.GetRequest())
+					assert.NotNil(t, result.GetResponse())
+				case <-timeout.C:
+					t.Error("timeout getting a response")
+				}
+				return true
+			},
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			if tt.mockSetup != nil {
+				tt.mockSetup(t, &tt.fields)
+			}
+			d := &DefaultPlcWriteRequest{
+				DefaultPlcTagRequest:    tt.fields.DefaultPlcTagRequest,
+				values:                  tt.fields.values,
+				writer:                  tt.fields.writer,
+				writeRequestInterceptor: tt.fields.writeRequestInterceptor,
+			}
+			result := d.ExecuteWithContext(tt.args.ctx)
+			if tt.wantAsserter != nil {
+				assert.Truef(t, tt.wantAsserter(t, result), "ExecuteWithContext(%v)", tt.args.ctx)
+			}
+		})
+	}
+}
+
+func TestDefaultPlcWriteRequest_GetValue(t *testing.T) {
+	type fields struct {
+		DefaultPlcTagRequest    *DefaultPlcTagRequest
+		values                  map[string]apiValues.PlcValue
+		writer                  spi.PlcWriter
+		writeRequestInterceptor interceptors.WriteRequestInterceptor
+	}
+	type args struct {
+		name string
+	}
+	tests := []struct {
+		name   string
+		fields fields
+		args   args
+		want   apiValues.PlcValue
+	}{
+		{
+			name: "get it",
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			d := &DefaultPlcWriteRequest{
+				DefaultPlcTagRequest:    tt.fields.DefaultPlcTagRequest,
+				values:                  tt.fields.values,
+				writer:                  tt.fields.writer,
+				writeRequestInterceptor: tt.fields.writeRequestInterceptor,
+			}
+			assert.Equalf(t, tt.want, d.GetValue(tt.args.name), "GetValue(%v)", tt.args.name)
+		})
+	}
+}
+
+func TestDefaultPlcWriteRequest_GetWriteRequestInterceptor(t *testing.T) {
+	type fields struct {
+		DefaultPlcTagRequest    *DefaultPlcTagRequest
+		values                  map[string]apiValues.PlcValue
+		writer                  spi.PlcWriter
+		writeRequestInterceptor interceptors.WriteRequestInterceptor
+	}
+	tests := []struct {
+		name   string
+		fields fields
+		want   interceptors.WriteRequestInterceptor
+	}{
+		{
+			name: "get it",
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			d := &DefaultPlcWriteRequest{
+				DefaultPlcTagRequest:    tt.fields.DefaultPlcTagRequest,
+				values:                  tt.fields.values,
+				writer:                  tt.fields.writer,
+				writeRequestInterceptor: tt.fields.writeRequestInterceptor,
+			}
+			assert.Equalf(t, tt.want, d.GetWriteRequestInterceptor(), "GetWriteRequestInterceptor()")
+		})
+	}
+}
+
+func TestDefaultPlcWriteRequest_GetWriter(t *testing.T) {
+	type fields struct {
+		DefaultPlcTagRequest    *DefaultPlcTagRequest
+		values                  map[string]apiValues.PlcValue
+		writer                  spi.PlcWriter
+		writeRequestInterceptor interceptors.WriteRequestInterceptor
+	}
+	tests := []struct {
+		name   string
+		fields fields
+		want   spi.PlcWriter
+	}{
+		{
+			name: "get it",
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			d := &DefaultPlcWriteRequest{
+				DefaultPlcTagRequest:    tt.fields.DefaultPlcTagRequest,
+				values:                  tt.fields.values,
+				writer:                  tt.fields.writer,
+				writeRequestInterceptor: tt.fields.writeRequestInterceptor,
+			}
+			assert.Equalf(t, tt.want, d.GetWriter(), "GetWriter()")
+		})
+	}
+}
+
+func TestNewDefaultPlcWriteRequest(t *testing.T) {
+	type args struct {
+		tags                    map[string]apiModel.PlcTag
+		tagNames                []string
+		values                  map[string]apiValues.PlcValue
+		writer                  spi.PlcWriter
+		writeRequestInterceptor interceptors.WriteRequestInterceptor
+	}
+	tests := []struct {
+		name string
+		args args
+		want apiModel.PlcWriteRequest
+	}{
+		{
+			name: "create it",
+			want: &DefaultPlcWriteRequest{
+				DefaultPlcTagRequest: NewDefaultPlcTagRequest(nil, nil),
+			},
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			assert.Equalf(t, tt.want, NewDefaultPlcWriteRequest(tt.args.tags, tt.args.tagNames, tt.args.values, tt.args.writer, tt.args.writeRequestInterceptor), "NewDefaultPlcWriteRequest(%v, %v, %v, %v, %v)", tt.args.tags, tt.args.tagNames, tt.args.values, tt.args.writer, tt.args.writeRequestInterceptor)
+		})
+	}
+}
+
+func TestNewDefaultPlcWriteRequestBuilder(t *testing.T) {
+	type args struct {
+		tagHandler   spi.PlcTagHandler
+		valueHandler spi.PlcValueHandler
+		writer       spi.PlcWriter
+	}
+	tests := []struct {
+		name string
+		args args
+		want apiModel.PlcWriteRequestBuilder
+	}{
+		{
+			name: "create it",
+			want: &DefaultPlcWriteRequestBuilder{
+				tagNames:     []string{},
+				tagAddresses: map[string]string{},
+				tags:         map[string]apiModel.PlcTag{},
+				values:       map[string]any{},
+			},
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			assert.Equalf(t, tt.want, NewDefaultPlcWriteRequestBuilder(tt.args.tagHandler, tt.args.valueHandler, tt.args.writer), "NewDefaultPlcWriteRequestBuilder(%v, %v, %v)", tt.args.tagHandler, tt.args.valueHandler, tt.args.writer)
+		})
+	}
+}
+
+func TestNewDefaultPlcWriteRequestBuilderWithInterceptor(t *testing.T) {
+	type args struct {
+		tagHandler              spi.PlcTagHandler
+		valueHandler            spi.PlcValueHandler
+		writer                  spi.PlcWriter
+		writeRequestInterceptor interceptors.WriteRequestInterceptor
+	}
+	tests := []struct {
+		name string
+		args args
+		want apiModel.PlcWriteRequestBuilder
+	}{
+		{
+			name: "create it",
+			want: &DefaultPlcWriteRequestBuilder{
+				tagNames:     []string{},
+				tagAddresses: map[string]string{},
+				tags:         map[string]apiModel.PlcTag{},
+				values:       map[string]any{},
+			},
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			assert.Equalf(t, tt.want, NewDefaultPlcWriteRequestBuilderWithInterceptor(tt.args.tagHandler, tt.args.valueHandler, tt.args.writer, tt.args.writeRequestInterceptor), "NewDefaultPlcWriteRequestBuilderWithInterceptor(%v, %v, %v, %v)", tt.args.tagHandler, tt.args.valueHandler, tt.args.writer, tt.args.writeRequestInterceptor)
+		})
+	}
+}
diff --git a/plc4go/spi/model/mock_PlcValueHandler_test.go b/plc4go/spi/model/mock_PlcValueHandler_test.go
new file mode 100644
index 0000000000..0813aec7b9
--- /dev/null
+++ b/plc4go/spi/model/mock_PlcValueHandler_test.go
@@ -0,0 +1,112 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+// Code generated by mockery v2.27.1. DO NOT EDIT.
+
+package model
+
+import (
+	apimodel "github.com/apache/plc4x/plc4go/pkg/api/model"
+	mock "github.com/stretchr/testify/mock"
+
+	values "github.com/apache/plc4x/plc4go/pkg/api/values"
+)
+
+// MockPlcValueHandler is an autogenerated mock type for the PlcValueHandler type
+type MockPlcValueHandler struct {
+	mock.Mock
+}
+
+type MockPlcValueHandler_Expecter struct {
+	mock *mock.Mock
+}
+
+func (_m *MockPlcValueHandler) EXPECT() *MockPlcValueHandler_Expecter {
+	return &MockPlcValueHandler_Expecter{mock: &_m.Mock}
+}
+
+// NewPlcValue provides a mock function with given fields: tag, value
+func (_m *MockPlcValueHandler) NewPlcValue(tag apimodel.PlcTag, value interface{}) (values.PlcValue, error) {
+	ret := _m.Called(tag, value)
+
+	var r0 values.PlcValue
+	var r1 error
+	if rf, ok := ret.Get(0).(func(apimodel.PlcTag, interface{}) (values.PlcValue, error)); ok {
+		return rf(tag, value)
+	}
+	if rf, ok := ret.Get(0).(func(apimodel.PlcTag, interface{}) values.PlcValue); ok {
+		r0 = rf(tag, value)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(values.PlcValue)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(apimodel.PlcTag, interface{}) error); ok {
+		r1 = rf(tag, value)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// MockPlcValueHandler_NewPlcValue_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'NewPlcValue'
+type MockPlcValueHandler_NewPlcValue_Call struct {
+	*mock.Call
+}
+
+// NewPlcValue is a helper method to define mock.On call
+//   - tag apimodel.PlcTag
+//   - value interface{}
+func (_e *MockPlcValueHandler_Expecter) NewPlcValue(tag interface{}, value interface{}) *MockPlcValueHandler_NewPlcValue_Call {
+	return &MockPlcValueHandler_NewPlcValue_Call{Call: _e.mock.On("NewPlcValue", tag, value)}
+}
+
+func (_c *MockPlcValueHandler_NewPlcValue_Call) Run(run func(tag apimodel.PlcTag, value interface{})) *MockPlcValueHandler_NewPlcValue_Call {
+	_c.Call.Run(func(args mock.Arguments) {
+		run(args[0].(apimodel.PlcTag), args[1].(interface{}))
+	})
+	return _c
+}
+
+func (_c *MockPlcValueHandler_NewPlcValue_Call) Return(_a0 values.PlcValue, _a1 error) *MockPlcValueHandler_NewPlcValue_Call {
+	_c.Call.Return(_a0, _a1)
+	return _c
+}
+
+func (_c *MockPlcValueHandler_NewPlcValue_Call) RunAndReturn(run func(apimodel.PlcTag, interface{}) (values.PlcValue, error)) *MockPlcValueHandler_NewPlcValue_Call {
+	_c.Call.Return(run)
+	return _c
+}
+
+type mockConstructorTestingTNewMockPlcValueHandler interface {
+	mock.TestingT
+	Cleanup(func())
+}
+
+// NewMockPlcValueHandler creates a new instance of MockPlcValueHandler. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
+func NewMockPlcValueHandler(t mockConstructorTestingTNewMockPlcValueHandler) *MockPlcValueHandler {
+	mock := &MockPlcValueHandler{}
+	mock.Mock.Test(t)
+
+	t.Cleanup(func() { mock.AssertExpectations(t) })
+
+	return mock
+}
diff --git a/plc4go/spi/model/mock_PlcWriter_test.go b/plc4go/spi/model/mock_PlcWriter_test.go
new file mode 100644
index 0000000000..de44ed32bd
--- /dev/null
+++ b/plc4go/spi/model/mock_PlcWriter_test.go
@@ -0,0 +1,103 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+// Code generated by mockery v2.27.1. DO NOT EDIT.
+
+package model
+
+import (
+	context "context"
+
+	apimodel "github.com/apache/plc4x/plc4go/pkg/api/model"
+
+	mock "github.com/stretchr/testify/mock"
+)
+
+// MockPlcWriter is an autogenerated mock type for the PlcWriter type
+type MockPlcWriter struct {
+	mock.Mock
+}
+
+type MockPlcWriter_Expecter struct {
+	mock *mock.Mock
+}
+
+func (_m *MockPlcWriter) EXPECT() *MockPlcWriter_Expecter {
+	return &MockPlcWriter_Expecter{mock: &_m.Mock}
+}
+
+// Write provides a mock function with given fields: ctx, writeRequest
+func (_m *MockPlcWriter) Write(ctx context.Context, writeRequest apimodel.PlcWriteRequest) <-chan apimodel.PlcWriteRequestResult {
+	ret := _m.Called(ctx, writeRequest)
+
+	var r0 <-chan apimodel.PlcWriteRequestResult
+	if rf, ok := ret.Get(0).(func(context.Context, apimodel.PlcWriteRequest) <-chan apimodel.PlcWriteRequestResult); ok {
+		r0 = rf(ctx, writeRequest)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(<-chan apimodel.PlcWriteRequestResult)
+		}
+	}
+
+	return r0
+}
+
+// MockPlcWriter_Write_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Write'
+type MockPlcWriter_Write_Call struct {
+	*mock.Call
+}
+
+// Write is a helper method to define mock.On call
+//   - ctx context.Context
+//   - writeRequest apimodel.PlcWriteRequest
+func (_e *MockPlcWriter_Expecter) Write(ctx interface{}, writeRequest interface{}) *MockPlcWriter_Write_Call {
+	return &MockPlcWriter_Write_Call{Call: _e.mock.On("Write", ctx, writeRequest)}
+}
+
+func (_c *MockPlcWriter_Write_Call) Run(run func(ctx context.Context, writeRequest apimodel.PlcWriteRequest)) *MockPlcWriter_Write_Call {
+	_c.Call.Run(func(args mock.Arguments) {
+		run(args[0].(context.Context), args[1].(apimodel.PlcWriteRequest))
+	})
+	return _c
+}
+
+func (_c *MockPlcWriter_Write_Call) Return(_a0 <-chan apimodel.PlcWriteRequestResult) *MockPlcWriter_Write_Call {
+	_c.Call.Return(_a0)
+	return _c
+}
+
+func (_c *MockPlcWriter_Write_Call) RunAndReturn(run func(context.Context, apimodel.PlcWriteRequest) <-chan apimodel.PlcWriteRequestResult) *MockPlcWriter_Write_Call {
+	_c.Call.Return(run)
+	return _c
+}
+
+type mockConstructorTestingTNewMockPlcWriter interface {
+	mock.TestingT
+	Cleanup(func())
+}
+
+// NewMockPlcWriter creates a new instance of MockPlcWriter. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
+func NewMockPlcWriter(t mockConstructorTestingTNewMockPlcWriter) *MockPlcWriter {
+	mock := &MockPlcWriter{}
+	mock.Mock.Test(t)
+
+	t.Cleanup(func() { mock.AssertExpectations(t) })
+
+	return mock
+}
diff --git a/plc4go/spi/model/mock_WriteRequestInterceptor_test.go b/plc4go/spi/model/mock_WriteRequestInterceptor_test.go
new file mode 100644
index 0000000000..e79ae2dd15
--- /dev/null
+++ b/plc4go/spi/model/mock_WriteRequestInterceptor_test.go
@@ -0,0 +1,149 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+// Code generated by mockery v2.27.1. DO NOT EDIT.
+
+package model
+
+import (
+	context "context"
+
+	apimodel "github.com/apache/plc4x/plc4go/pkg/api/model"
+
+	mock "github.com/stretchr/testify/mock"
+)
+
+// MockWriteRequestInterceptor is an autogenerated mock type for the WriteRequestInterceptor type
+type MockWriteRequestInterceptor struct {
+	mock.Mock
+}
+
+type MockWriteRequestInterceptor_Expecter struct {
+	mock *mock.Mock
+}
+
+func (_m *MockWriteRequestInterceptor) EXPECT() *MockWriteRequestInterceptor_Expecter {
+	return &MockWriteRequestInterceptor_Expecter{mock: &_m.Mock}
+}
+
+// InterceptWriteRequest provides a mock function with given fields: ctx, writeRequest
+func (_m *MockWriteRequestInterceptor) InterceptWriteRequest(ctx context.Context, writeRequest apimodel.PlcWriteRequest) []apimodel.PlcWriteRequest {
+	ret := _m.Called(ctx, writeRequest)
+
+	var r0 []apimodel.PlcWriteRequest
+	if rf, ok := ret.Get(0).(func(context.Context, apimodel.PlcWriteRequest) []apimodel.PlcWriteRequest); ok {
+		r0 = rf(ctx, writeRequest)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).([]apimodel.PlcWriteRequest)
+		}
+	}
+
+	return r0
+}
+
+// MockWriteRequestInterceptor_InterceptWriteRequest_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'InterceptWriteRequest'
+type MockWriteRequestInterceptor_InterceptWriteRequest_Call struct {
+	*mock.Call
+}
+
+// InterceptWriteRequest is a helper method to define mock.On call
+//   - ctx context.Context
+//   - writeRequest apimodel.PlcWriteRequest
+func (_e *MockWriteRequestInterceptor_Expecter) InterceptWriteRequest(ctx interface{}, writeRequest interface{}) *MockWriteRequestInterceptor_InterceptWriteRequest_Call {
+	return &MockWriteRequestInterceptor_InterceptWriteRequest_Call{Call: _e.mock.On("InterceptWriteRequest", ctx, writeRequest)}
+}
+
+func (_c *MockWriteRequestInterceptor_InterceptWriteRequest_Call) Run(run func(ctx context.Context, writeRequest apimodel.PlcWriteRequest)) *MockWriteRequestInterceptor_InterceptWriteRequest_Call {
+	_c.Call.Run(func(args mock.Arguments) {
+		run(args[0].(context.Context), args[1].(apimodel.PlcWriteRequest))
+	})
+	return _c
+}
+
+func (_c *MockWriteRequestInterceptor_InterceptWriteRequest_Call) Return(_a0 []apimodel.PlcWriteRequest) *MockWriteRequestInterceptor_InterceptWriteRequest_Call {
+	_c.Call.Return(_a0)
+	return _c
+}
+
+func (_c *MockWriteRequestInterceptor_InterceptWriteRequest_Call) RunAndReturn(run func(context.Context, apimodel.PlcWriteRequest) []apimodel.PlcWriteRequest) *MockWriteRequestInterceptor_InterceptWriteRequest_Call {
+	_c.Call.Return(run)
+	return _c
+}
+
+// ProcessWriteResponses provides a mock function with given fields: ctx, writeRequest, writeResults
+func (_m *MockWriteRequestInterceptor) ProcessWriteResponses(ctx context.Context, writeRequest apimodel.PlcWriteRequest, writeResults []apimodel.PlcWriteRequestResult) apimodel.PlcWriteRequestResult {
+	ret := _m.Called(ctx, writeRequest, writeResults)
+
+	var r0 apimodel.PlcWriteRequestResult
+	if rf, ok := ret.Get(0).(func(context.Context, apimodel.PlcWriteRequest, []apimodel.PlcWriteRequestResult) apimodel.PlcWriteRequestResult); ok {
+		r0 = rf(ctx, writeRequest, writeResults)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(apimodel.PlcWriteRequestResult)
+		}
+	}
+
+	return r0
+}
+
+// MockWriteRequestInterceptor_ProcessWriteResponses_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ProcessWriteResponses'
+type MockWriteRequestInterceptor_ProcessWriteResponses_Call struct {
+	*mock.Call
+}
+
+// ProcessWriteResponses is a helper method to define mock.On call
+//   - ctx context.Context
+//   - writeRequest apimodel.PlcWriteRequest
+//   - writeResults []apimodel.PlcWriteRequestResult
+func (_e *MockWriteRequestInterceptor_Expecter) ProcessWriteResponses(ctx interface{}, writeRequest interface{}, writeResults interface{}) *MockWriteRequestInterceptor_ProcessWriteResponses_Call {
+	return &MockWriteRequestInterceptor_ProcessWriteResponses_Call{Call: _e.mock.On("ProcessWriteResponses", ctx, writeRequest, writeResults)}
+}
+
+func (_c *MockWriteRequestInterceptor_ProcessWriteResponses_Call) Run(run func(ctx context.Context, writeRequest apimodel.PlcWriteRequest, writeResults []apimodel.PlcWriteRequestResult)) *MockWriteRequestInterceptor_ProcessWriteResponses_Call {
+	_c.Call.Run(func(args mock.Arguments) {
+		run(args[0].(context.Context), args[1].(apimodel.PlcWriteRequest), args[2].([]apimodel.PlcWriteRequestResult))
+	})
+	return _c
+}
+
+func (_c *MockWriteRequestInterceptor_ProcessWriteResponses_Call) Return(_a0 apimodel.PlcWriteRequestResult) *MockWriteRequestInterceptor_ProcessWriteResponses_Call {
+	_c.Call.Return(_a0)
+	return _c
+}
+
+func (_c *MockWriteRequestInterceptor_ProcessWriteResponses_Call) RunAndReturn(run func(context.Context, apimodel.PlcWriteRequest, []apimodel.PlcWriteRequestResult) apimodel.PlcWriteRequestResult) *MockWriteRequestInterceptor_ProcessWriteResponses_Call {
+	_c.Call.Return(run)
+	return _c
+}
+
+type mockConstructorTestingTNewMockWriteRequestInterceptor interface {
+	mock.TestingT
+	Cleanup(func())
+}
+
+// NewMockWriteRequestInterceptor creates a new instance of MockWriteRequestInterceptor. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
+func NewMockWriteRequestInterceptor(t mockConstructorTestingTNewMockWriteRequestInterceptor) *MockWriteRequestInterceptor {
+	mock := &MockWriteRequestInterceptor{}
+	mock.Mock.Test(t)
+
+	t.Cleanup(func() { mock.AssertExpectations(t) })
+
+	return mock
+}
diff --git a/plc4go/spi/model/mock_requirements.go b/plc4go/spi/model/mock_requirements.go
index 48edb5c6a1..2b6934a84f 100644
--- a/plc4go/spi/model/mock_requirements.go
+++ b/plc4go/spi/model/mock_requirements.go
@@ -37,11 +37,21 @@ type PlcReader interface {
 	spi.PlcReader
 }
 
+// Deprecated: don't use it in productive code
+type PlcWriter interface {
+	spi.PlcWriter
+}
+
 // Deprecated: don't use it in productive code
 type PlcTagHandler interface {
 	spi.PlcTagHandler
 }
 
+// Deprecated: don't use it in productive code
+type PlcValueHandler interface {
+	spi.PlcValueHandler
+}
+
 // Deprecated: don't use it in productive code
 type PlcTag interface {
 	apiModel.PlcTag
@@ -61,3 +71,8 @@ type PlcQuery interface {
 type ReadRequestInterceptor interface {
 	interceptors.ReadRequestInterceptor
 }
+
+// Deprecated: don't use it in productive code
+type WriteRequestInterceptor interface {
+	interceptors.WriteRequestInterceptor
+}