You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@plc4x.apache.org by cd...@apache.org on 2020/10/18 19:22:01 UTC

[plc4x] branch feature/plc4go updated: - Got the SPI parts of processing the read requests finished - Continued implementing the Modbus driver

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

cdutz pushed a commit to branch feature/plc4go
in repository https://gitbox.apache.org/repos/asf/plc4x.git


The following commit(s) were added to refs/heads/feature/plc4go by this push:
     new fa7d5c6  - Got the SPI parts of processing the read requests finished - Continued implementing the Modbus driver
fa7d5c6 is described below

commit fa7d5c6b45b2bccf7f8f4d7041c183b8bb4acf9f
Author: Christofer Dutz <ch...@c-ware.de>
AuthorDate: Sun Oct 18 21:21:54 2020 +0200

    - Got the SPI parts of processing the read requests finished
    - Continued implementing the Modbus driver
---
 sandbox/plc4go/cmd/main/drivers/modbus_test.go     | 50 ++++++++++++-
 .../examples/read/hello_world_plc4go_read.go       |  5 +-
 .../internal/plc4go/modbus/ModbusConnection.go     | 55 ++++++++------
 .../plc4go/internal/plc4go/modbus/ModbusDriver.go  | 18 ++---
 .../plc4go/internal/plc4go/modbus/ModbusField.go   | 54 ++++++++++++++
 .../internal/plc4go/modbus/ModbusFieldHandler.go   | 83 ++++++++++++++++++++--
 .../iec61131/TIME.go => modbus/ModbusReader.go}    | 26 +++----
 ...ModbusFieldHandler.go => ModbusValueHandler.go} | 12 ++--
 .../iec61131/TIME.go => modbus/ModbusWriter.go}    | 24 +++----
 .../internal/plc4go/model/DefaultPlcReadRequest.go | 10 +--
 .../plc4go/model/DefaultPlcWriteRequest.go         |  8 +--
 .../plc4go/{spi => model}/values/PlcList.go        |  0
 .../{spi => model}/values/PlcSimpleValueAdapter.go |  0
 .../plc4go/{spi => model}/values/PlcStruct.go      |  0
 .../{spi => model}/values/PlcValueAdapter.go       |  0
 .../plc4go/{spi => model}/values/iec61131/BOOL.go  |  2 +-
 .../plc4go/{spi => model}/values/iec61131/BYTE.go  |  2 +-
 .../plc4go/{spi => model}/values/iec61131/CHAR.go  |  2 +-
 .../plc4go/{spi => model}/values/iec61131/DATE.go  |  2 +-
 .../values/iec61131/DATE_AND_TIME.go               |  2 +-
 .../plc4go/{spi => model}/values/iec61131/DINT.go  |  2 +-
 .../plc4go/{spi => model}/values/iec61131/DWORD.go |  2 +-
 .../values/iec61131/IEC61131ValueHandler.go        |  0
 .../plc4go/{spi => model}/values/iec61131/INT.go   |  2 +-
 .../plc4go/{spi => model}/values/iec61131/LINT.go  |  2 +-
 .../plc4go/{spi => model}/values/iec61131/LREAL.go |  2 +-
 .../plc4go/{spi => model}/values/iec61131/LTIME.go |  2 +-
 .../plc4go/{spi => model}/values/iec61131/LWORD.go |  2 +-
 .../plc4go/{spi => model}/values/iec61131/NULL.go  |  2 +-
 .../plc4go/{spi => model}/values/iec61131/REAL.go  |  2 +-
 .../plc4go/{spi => model}/values/iec61131/SINT.go  |  2 +-
 .../{spi => model}/values/iec61131/STRING.go       |  2 +-
 .../plc4go/{spi => model}/values/iec61131/TIME.go  |  2 +-
 .../{spi => model}/values/iec61131/TIME_OF_DAY.go  |  2 +-
 .../plc4go/{spi => model}/values/iec61131/UDINT.go |  2 +-
 .../plc4go/{spi => model}/values/iec61131/UINT.go  |  2 +-
 .../plc4go/{spi => model}/values/iec61131/ULINT.go |  2 +-
 .../plc4go/{spi => model}/values/iec61131/USINT.go |  2 +-
 .../plc4go/{spi => model}/values/iec61131/WCHAR.go |  2 +-
 .../plc4go/{spi => model}/values/iec61131/WORD.go  |  2 +-
 .../{spi => model}/values/iec61131/WSTRING.go      |  2 +-
 .../internal/plc4go/{model => spi}/PlcReader.go    |  4 +-
 .../internal/plc4go/{model => spi}/PlcWriter.go    |  4 +-
 .../internal/plc4go/spi/model/PlcReadRequest.go    | 32 ---------
 sandbox/plc4go/pkg/plc4go/driverManager.go         | 17 ++---
 .../plc4go/pkg/plc4go/model/plc_read_request.go    |  2 +-
 .../plc4go/pkg/plc4go/model/plc_write_request.go   |  2 +-
 47 files changed, 301 insertions(+), 155 deletions(-)

diff --git a/sandbox/plc4go/cmd/main/drivers/modbus_test.go b/sandbox/plc4go/cmd/main/drivers/modbus_test.go
index 217eee0..830af7c 100644
--- a/sandbox/plc4go/cmd/main/drivers/modbus_test.go
+++ b/sandbox/plc4go/cmd/main/drivers/modbus_test.go
@@ -20,12 +20,15 @@ package drivers
 
 import (
 	"encoding/hex"
+	"encoding/json"
 	"fmt"
 	"net"
 	"os"
+	"plc4x.apache.org/plc4go-modbus-driver/0.8.0/internal/plc4go/modbus"
 	"plc4x.apache.org/plc4go-modbus-driver/0.8.0/internal/plc4go/modbus/readwrite/model"
 	"plc4x.apache.org/plc4go-modbus-driver/0.8.0/internal/plc4go/spi"
 	"plc4x.apache.org/plc4go-modbus-driver/0.8.0/internal/plc4go/testutils"
+	"plc4x.apache.org/plc4go-modbus-driver/0.8.0/pkg/plc4go"
 	"strings"
 	"testing"
 )
@@ -69,7 +72,6 @@ func test(t *testing.T, rawMessage string, response bool) {
 // Test that actually sends a read-request to a remote Modbus Slave
 //
 func Connection(t *testing.T) {
-
 	pdu := model.ModbusPDUReadInputRegistersRequest{
 		StartingAddress: 1,
 		Quantity:        1,
@@ -121,3 +123,49 @@ func Connection(t *testing.T) {
 
 	conn.Close()
 }
+
+func TestPlc4goDriver(t *testing.T) {
+	driverManager := plc4go.NewPlcDriverManager()
+	driverManager.RegisterDriver(modbus.NewModbusDriver())
+
+	// Get a connection to a remote PLC
+	crc := driverManager.GetConnectedConnection("modbus:tcp://192.168.23.30")
+
+	// Wait for the driver to connect (or not)
+	connectionResult := <-crc
+	if connectionResult.Err != nil {
+		t.Errorf("error connecting to PLC: %s", connectionResult.Err.Error())
+		return
+	}
+	connection := connectionResult.Connection
+
+	// Make sure the connection is closed at the end
+	defer connection.Close()
+
+	// Prepare a read-request
+	rrb := connection.ReadRequestBuilder()
+	rrb.AddItem("field", "holding-register:1:REAL[2]")
+	readRequest, err := rrb.Build()
+	if err != nil {
+		t.Errorf("error preparing read-request: %s", connectionResult.Err.Error())
+		return
+	}
+
+	// Execute a read-request
+	rrc := readRequest.Execute()
+
+	// Wait for the response to finish
+	rrr := <-rrc
+	if rrr.Err != nil {
+		t.Errorf("error executing read-request: %s", rrr.Err.Error())
+		return
+	}
+
+	// Do something with the response
+	readResponseJson, err := json.Marshal(rrr.Response)
+	if err != nil {
+		t.Errorf("error serializing read-response: %s", err.Error())
+		return
+	}
+	fmt.Printf("Result: %s\n", string(readResponseJson))
+}
diff --git a/sandbox/plc4go/examples/read/hello_world_plc4go_read.go b/sandbox/plc4go/examples/read/hello_world_plc4go_read.go
index 1281c50..6fb6e16 100644
--- a/sandbox/plc4go/examples/read/hello_world_plc4go_read.go
+++ b/sandbox/plc4go/examples/read/hello_world_plc4go_read.go
@@ -8,7 +8,7 @@ import (
 
 func main() int {
 	// Get a connection to a remote PLC
-	crc := plc4go.NewPlcDriverManager().GetConnectedConnection("s7://192.168.23.30")
+	crc := plc4go.NewPlcDriverManager().GetConnectedConnection("modbus:tcp://192.168.23.30")
 
 	// Wait for the driver to connect (or not)
 	connectionResult := <-crc
@@ -23,8 +23,7 @@ func main() int {
 
 	// Prepare a read-request
 	rrb := connection.ReadRequestBuilder()
-	rrb.AddField("output-field", "%Q0.0:BOOL")
-	rrb.AddField("input-field", "%I0.0:BOOL")
+	rrb.AddField("field", "holding-register:1:REAL[2]")
 	readRequest, err := rrb.Build()
 	if err != nil {
 		_ = fmt.Errorf("error preparing read-request: %s", connectionResult.Err.Error())
diff --git a/sandbox/plc4go/internal/plc4go/modbus/ModbusConnection.go b/sandbox/plc4go/internal/plc4go/modbus/ModbusConnection.go
index d254d7b..e378d12 100644
--- a/sandbox/plc4go/internal/plc4go/modbus/ModbusConnection.go
+++ b/sandbox/plc4go/internal/plc4go/modbus/ModbusConnection.go
@@ -25,66 +25,77 @@ import (
 	"plc4x.apache.org/plc4go-modbus-driver/0.8.0/pkg/plc4go/model"
 )
 
-type ModbusConnectionMetadata struct {
+type ConnectionMetadata struct {
 	model.PlcConnectionMetadata
 }
 
-func (m ModbusConnectionMetadata) CanRead() bool {
+func (m ConnectionMetadata) CanRead() bool {
 	return true
 }
 
-func (m ModbusConnectionMetadata) CanWrite() bool {
+func (m ConnectionMetadata) CanWrite() bool {
 	return true
 }
 
-func (m ModbusConnectionMetadata) CanSubscribe() bool {
+func (m ConnectionMetadata) CanSubscribe() bool {
 	return false
 }
 
-type ModbusConnection struct {
+type Connection struct {
 	fieldHandler spi.PlcFieldHandler
+	valueHandler spi.PlcValueHandler
 	plc4go.PlcConnection
 }
 
-func NewModbusConnection(fieldHandler spi.PlcFieldHandler) ModbusConnection {
-	return ModbusConnection{
+func NewConnection(fieldHandler spi.PlcFieldHandler, valueHandler spi.PlcValueHandler) Connection {
+	return Connection{
 		fieldHandler: fieldHandler,
+		valueHandler: valueHandler,
 	}
 }
 
-func (m ModbusConnection) Connect() <-chan plc4go.PlcConnectionConnectResult {
-	panic("implement me")
+func (m Connection) Connect() <-chan plc4go.PlcConnectionConnectResult {
+	// TODO: Implement ...
+	ch := make(chan plc4go.PlcConnectionConnectResult)
+	go func() {
+		ch <- plc4go.NewPlcConnectionConnectResult(m, nil)
+	}()
+	return ch
 }
 
-func (m ModbusConnection) Close() <-chan plc4go.PlcConnectionCloseResult {
-	panic("implement me")
+func (m Connection) Close() <-chan plc4go.PlcConnectionCloseResult {
+	// TODO: Implement ...
+	ch := make(chan plc4go.PlcConnectionCloseResult)
+	go func() {
+		ch <- plc4go.NewPlcConnectionCloseResult(m, nil)
+	}()
+	return ch
 }
 
-func (m ModbusConnection) IsConnected() bool {
+func (m Connection) IsConnected() bool {
 	panic("implement me")
 }
 
-func (m ModbusConnection) Ping() <-chan plc4go.PlcConnectionPingResult {
+func (m Connection) Ping() <-chan plc4go.PlcConnectionPingResult {
 	panic("implement me")
 }
 
-func (m ModbusConnection) GetMetadata() model.PlcConnectionMetadata {
-	return ModbusConnectionMetadata{}
+func (m Connection) GetMetadata() model.PlcConnectionMetadata {
+	return ConnectionMetadata{}
 }
 
-func (m ModbusConnection) ReadRequestBuilder() model.PlcReadRequestBuilder {
-	// TODO: Pass a real reader in here ...
-	return internalModel.NewDefaultPlcReadRequestBuilder(m.fieldHandler, nil)
+func (m Connection) ReadRequestBuilder() model.PlcReadRequestBuilder {
+	return internalModel.NewDefaultPlcReadRequestBuilder(m.fieldHandler, NewModbusReader())
 }
 
-func (m ModbusConnection) WriteRequestBuilder() model.PlcWriteRequestBuilder {
-	panic("implement me")
+func (m Connection) WriteRequestBuilder() model.PlcWriteRequestBuilder {
+	return internalModel.NewDefaultPlcWriteRequestBuilder(m.fieldHandler, m.valueHandler, NewModbusWriter())
 }
 
-func (m ModbusConnection) SubscriptionRequestBuilder() model.PlcSubscriptionRequestBuilder {
+func (m Connection) SubscriptionRequestBuilder() model.PlcSubscriptionRequestBuilder {
 	panic("implement me")
 }
 
-func (m ModbusConnection) UnsubscriptionRequestBuilder() model.PlcUnsubscriptionRequestBuilder {
+func (m Connection) UnsubscriptionRequestBuilder() model.PlcUnsubscriptionRequestBuilder {
 	panic("implement me")
 }
diff --git a/sandbox/plc4go/internal/plc4go/modbus/ModbusDriver.go b/sandbox/plc4go/internal/plc4go/modbus/ModbusDriver.go
index 5a0fb9b..4ae599b 100644
--- a/sandbox/plc4go/internal/plc4go/modbus/ModbusDriver.go
+++ b/sandbox/plc4go/internal/plc4go/modbus/ModbusDriver.go
@@ -23,30 +23,32 @@ import (
 	"plc4x.apache.org/plc4go-modbus-driver/0.8.0/pkg/plc4go"
 )
 
-type modbusDriver struct {
+type Driver struct {
 	fieldHandler spi.PlcFieldHandler
+	valueHandler spi.PlcValueHandler
 	plc4go.PlcDriver
 }
 
 func NewModbusDriver() plc4go.PlcDriver {
-	return modbusDriver{
-		fieldHandler: NewModbusFieldHandler(),
+	return Driver{
+		fieldHandler: NewFieldHandler(),
+		valueHandler: NewValueHandler(),
 	}
 }
 
-func (m modbusDriver) GetProtocolCode() string {
+func (m Driver) GetProtocolCode() string {
 	return "modbus"
 }
 
-func (m modbusDriver) GetProtocolName() string {
+func (m Driver) GetProtocolName() string {
 	return "Modbus"
 }
 
-func (m modbusDriver) CheckQuery(query string) error {
+func (m Driver) CheckQuery(query string) error {
 	_, err := m.fieldHandler.ParseQuery(query)
 	return err
 }
 
-func (m modbusDriver) GetConnection(connectionString string) (plc4go.PlcConnection, error) {
-	return NewModbusConnection(m.fieldHandler), nil
+func (m Driver) GetConnection(connectionString string) (plc4go.PlcConnection, error) {
+	return NewConnection(m.fieldHandler, m.valueHandler), nil
 }
diff --git a/sandbox/plc4go/internal/plc4go/modbus/ModbusField.go b/sandbox/plc4go/internal/plc4go/modbus/ModbusField.go
new file mode 100644
index 0000000..20a2fc1
--- /dev/null
+++ b/sandbox/plc4go/internal/plc4go/modbus/ModbusField.go
@@ -0,0 +1,54 @@
+//
+// 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
+//
+//      http://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 modbus
+
+import (
+	"errors"
+	"plc4x.apache.org/plc4go-modbus-driver/0.8.0/pkg/plc4go/model"
+	"strconv"
+)
+
+type PlcField struct {
+	fieldType uint8
+	address   uint32
+	quantity  uint32
+	datatype  string
+	model.PlcField
+}
+
+func NewModbusPlcField(fieldType uint8, address uint32, quantity uint32, datatype string) PlcField {
+	return PlcField{
+		fieldType: fieldType,
+		address:   address,
+		quantity:  quantity,
+		datatype:  datatype,
+	}
+}
+
+func NewModbusPlcFieldFromStrings(fieldType uint8, addressString string, quantityString string, datatype string) (model.PlcField, error) {
+	address, err := strconv.Atoi(addressString)
+	if err != nil {
+		return nil, errors.New("Couldn't parse address string '" + addressString + "' into an int")
+	}
+	quantity, err := strconv.Atoi(quantityString)
+	if err != nil {
+		quantity = 1
+	}
+	return NewModbusPlcField(fieldType, uint32(address), uint32(quantity), datatype), nil
+}
diff --git a/sandbox/plc4go/internal/plc4go/modbus/ModbusFieldHandler.go b/sandbox/plc4go/internal/plc4go/modbus/ModbusFieldHandler.go
index 1cf36af..6f0b7e4 100644
--- a/sandbox/plc4go/internal/plc4go/modbus/ModbusFieldHandler.go
+++ b/sandbox/plc4go/internal/plc4go/modbus/ModbusFieldHandler.go
@@ -18,12 +18,87 @@
 //
 package modbus
 
-import "plc4x.apache.org/plc4go-modbus-driver/0.8.0/internal/plc4go/spi"
+import (
+	"errors"
+	"plc4x.apache.org/plc4go-modbus-driver/0.8.0/internal/plc4go/spi"
+	"plc4x.apache.org/plc4go-modbus-driver/0.8.0/pkg/plc4go/model"
+	"regexp"
+)
 
-type ModbusFieldHandler struct {
+const (
+	MODBUS_FIELD_COIL              = uint8(0)
+	MODBUS_FIELD_DISCRETE_INPUT    = uint8(1)
+	MODBUS_FIELD_INPUT_REGISTER    = uint8(3)
+	MODBUS_FIELD_HOLDING_REGISTER  = uint8(4)
+	MODBUS_FIELD_EXTENDED_REGISTER = uint8(6)
+)
+
+type FieldHandler struct {
+	plc4xCoilPattern               *regexp.Regexp
+	numericCoilPattern             *regexp.Regexp
+	plc4xDiscreteInputPattern      *regexp.Regexp
+	numericDiscreteInputPattern    *regexp.Regexp
+	plc4xInputRegisterPattern      *regexp.Regexp
+	numericInputRegisterPattern    *regexp.Regexp
+	plc4xHoldingRegisterPattern    *regexp.Regexp
+	numericHoldingRegisterPattern  *regexp.Regexp
+	plc4xExtendedRegisterPattern   *regexp.Regexp
+	numericExtendedRegisterPattern *regexp.Regexp
 	spi.PlcFieldHandler
 }
 
-func NewModbusFieldHandler() ModbusFieldHandler {
-	return ModbusFieldHandler{}
+func NewFieldHandler() FieldHandler {
+	generalAddressPattern := `(?P<address>\d+)(:(?P<datatype>[a-zA-Z_]+))?(\[(?P<quantity>\d+)])?$`
+	generalFixedDigitAddressPattern := `(?P<address>\d{4,5})?(:(?P<datatype>[a-zA-Z_]+))?(\[(?P<quantity>\d+)])?$`
+	return FieldHandler{
+		plc4xCoilPattern:               regexp.MustCompile("^coil:" + generalAddressPattern),
+		numericCoilPattern:             regexp.MustCompile("^0[xX]?" + generalFixedDigitAddressPattern),
+		plc4xDiscreteInputPattern:      regexp.MustCompile("^discrete-input:" + generalAddressPattern),
+		numericDiscreteInputPattern:    regexp.MustCompile("^1[xX]?" + generalFixedDigitAddressPattern),
+		plc4xInputRegisterPattern:      regexp.MustCompile("^input-register:" + generalAddressPattern),
+		numericInputRegisterPattern:    regexp.MustCompile("^3[xX]?" + generalFixedDigitAddressPattern),
+		plc4xHoldingRegisterPattern:    regexp.MustCompile("^holding-register:" + generalAddressPattern),
+		numericHoldingRegisterPattern:  regexp.MustCompile("^4[xX]?" + generalFixedDigitAddressPattern),
+		plc4xExtendedRegisterPattern:   regexp.MustCompile("^extended-register:" + generalAddressPattern),
+		numericExtendedRegisterPattern: regexp.MustCompile("^6[xX]?" + generalFixedDigitAddressPattern),
+	}
+}
+
+func (m FieldHandler) ParseQuery(query string) (model.PlcField, error) {
+	if match := GetSubgropMatches(m.plc4xCoilPattern, query); match != nil {
+		return NewModbusPlcFieldFromStrings(MODBUS_FIELD_COIL, match["address"], match["quantity"], match["datatype"])
+	} else if match := GetSubgropMatches(m.numericCoilPattern, query); match != nil {
+		return NewModbusPlcFieldFromStrings(MODBUS_FIELD_COIL, match["address"], match["quantity"], match["datatype"])
+	} else if match := GetSubgropMatches(m.plc4xDiscreteInputPattern, query); match != nil {
+		return NewModbusPlcFieldFromStrings(MODBUS_FIELD_DISCRETE_INPUT, match["address"], match["quantity"], match["datatype"])
+	} else if match := GetSubgropMatches(m.numericDiscreteInputPattern, query); match != nil {
+		return NewModbusPlcFieldFromStrings(MODBUS_FIELD_DISCRETE_INPUT, match["address"], match["quantity"], match["datatype"])
+	} else if match := GetSubgropMatches(m.plc4xInputRegisterPattern, query); match != nil {
+		return NewModbusPlcFieldFromStrings(MODBUS_FIELD_INPUT_REGISTER, match["address"], match["quantity"], match["datatype"])
+	} else if match := GetSubgropMatches(m.numericInputRegisterPattern, query); match != nil {
+		return NewModbusPlcFieldFromStrings(MODBUS_FIELD_INPUT_REGISTER, match["address"], match["quantity"], match["datatype"])
+	} else if match := GetSubgropMatches(m.plc4xHoldingRegisterPattern, query); match != nil {
+		return NewModbusPlcFieldFromStrings(MODBUS_FIELD_HOLDING_REGISTER, match["address"], match["quantity"], match["datatype"])
+	} else if match := GetSubgropMatches(m.numericHoldingRegisterPattern, query); match != nil {
+		return NewModbusPlcFieldFromStrings(MODBUS_FIELD_HOLDING_REGISTER, match["address"], match["quantity"], match["datatype"])
+	} else if match := GetSubgropMatches(m.plc4xExtendedRegisterPattern, query); match != nil {
+		return NewModbusPlcFieldFromStrings(MODBUS_FIELD_EXTENDED_REGISTER, match["address"], match["quantity"], match["datatype"])
+	} else if match := GetSubgropMatches(m.numericExtendedRegisterPattern, query); match != nil {
+		return NewModbusPlcFieldFromStrings(MODBUS_FIELD_EXTENDED_REGISTER, match["address"], match["quantity"], match["datatype"])
+	}
+	return nil, errors.New("Invalid address format for address '" + query + "'")
+}
+
+func GetSubgropMatches(r *regexp.Regexp, query string) map[string]string {
+	match := r.FindStringSubmatch(query)
+	if match == nil {
+		return nil
+	}
+	subMatchMap := make(map[string]string)
+	for i, name := range r.SubexpNames() {
+		if i != 0 {
+			subMatchMap[name] = match[i]
+		}
+	}
+	return subMatchMap
 }
diff --git a/sandbox/plc4go/internal/plc4go/spi/values/iec61131/TIME.go b/sandbox/plc4go/internal/plc4go/modbus/ModbusReader.go
similarity index 70%
copy from sandbox/plc4go/internal/plc4go/spi/values/iec61131/TIME.go
copy to sandbox/plc4go/internal/plc4go/modbus/ModbusReader.go
index 3d1253e..b840c35 100644
--- a/sandbox/plc4go/internal/plc4go/spi/values/iec61131/TIME.go
+++ b/sandbox/plc4go/internal/plc4go/modbus/ModbusReader.go
@@ -16,27 +16,23 @@
 // specific language governing permissions and limitations
 // under the License.
 //
-package iec61131
+package modbus
 
 import (
-	"plc4x.apache.org/plc4go-modbus-driver/0.8.0/internal/plc4go/spi/values"
-	"time"
+	"fmt"
+	"plc4x.apache.org/plc4go-modbus-driver/0.8.0/internal/plc4go/spi"
+	"plc4x.apache.org/plc4go-modbus-driver/0.8.0/pkg/plc4go/model"
 )
 
-type PlcTIME struct {
-	value uint32
-	values.PlcSimpleValueAdapter
+type ModbusReader struct {
+	spi.PlcReader
 }
 
-func NewPlcTIME(value uint32) PlcTIME {
-	return PlcTIME{
-		value: value,
-	}
+func NewModbusReader() ModbusReader {
+	return ModbusReader{}
 }
 
-func (m PlcTIME) IsDuration() bool {
-	return true
-}
-func (m PlcTIME) GetDuration() time.Duration {
-	return time.Duration(m.value)
+func (m ModbusReader) Read(readRequest model.PlcReadRequest) <-chan model.PlcReadRequestResult {
+	fmt.Printf("Read Request %s", readRequest)
+	return make(chan model.PlcReadRequestResult)
 }
diff --git a/sandbox/plc4go/internal/plc4go/modbus/ModbusFieldHandler.go b/sandbox/plc4go/internal/plc4go/modbus/ModbusValueHandler.go
similarity index 79%
copy from sandbox/plc4go/internal/plc4go/modbus/ModbusFieldHandler.go
copy to sandbox/plc4go/internal/plc4go/modbus/ModbusValueHandler.go
index 1cf36af..a7a6a87 100644
--- a/sandbox/plc4go/internal/plc4go/modbus/ModbusFieldHandler.go
+++ b/sandbox/plc4go/internal/plc4go/modbus/ModbusValueHandler.go
@@ -18,12 +18,14 @@
 //
 package modbus
 
-import "plc4x.apache.org/plc4go-modbus-driver/0.8.0/internal/plc4go/spi"
+import (
+	"plc4x.apache.org/plc4go-modbus-driver/0.8.0/internal/plc4go/model/values/iec61131"
+)
 
-type ModbusFieldHandler struct {
-	spi.PlcFieldHandler
+type ValueHandler struct {
+	iec61131.IEC61131ValueHandler
 }
 
-func NewModbusFieldHandler() ModbusFieldHandler {
-	return ModbusFieldHandler{}
+func NewValueHandler() ValueHandler {
+	return ValueHandler{}
 }
diff --git a/sandbox/plc4go/internal/plc4go/spi/values/iec61131/TIME.go b/sandbox/plc4go/internal/plc4go/modbus/ModbusWriter.go
similarity index 72%
copy from sandbox/plc4go/internal/plc4go/spi/values/iec61131/TIME.go
copy to sandbox/plc4go/internal/plc4go/modbus/ModbusWriter.go
index 3d1253e..073ec64 100644
--- a/sandbox/plc4go/internal/plc4go/spi/values/iec61131/TIME.go
+++ b/sandbox/plc4go/internal/plc4go/modbus/ModbusWriter.go
@@ -16,27 +16,21 @@
 // specific language governing permissions and limitations
 // under the License.
 //
-package iec61131
+package modbus
 
 import (
-	"plc4x.apache.org/plc4go-modbus-driver/0.8.0/internal/plc4go/spi/values"
-	"time"
+	"plc4x.apache.org/plc4go-modbus-driver/0.8.0/internal/plc4go/spi"
+	"plc4x.apache.org/plc4go-modbus-driver/0.8.0/pkg/plc4go/model"
 )
 
-type PlcTIME struct {
-	value uint32
-	values.PlcSimpleValueAdapter
+type ModbusWriter struct {
+	spi.PlcWriter
 }
 
-func NewPlcTIME(value uint32) PlcTIME {
-	return PlcTIME{
-		value: value,
-	}
+func NewModbusWriter() ModbusWriter {
+	return ModbusWriter{}
 }
 
-func (m PlcTIME) IsDuration() bool {
-	return true
-}
-func (m PlcTIME) GetDuration() time.Duration {
-	return time.Duration(m.value)
+func (m ModbusWriter) Write(writeRequest model.PlcWriteRequest) <-chan model.PlcWriteRequestResult {
+	return make(chan model.PlcWriteRequestResult)
 }
diff --git a/sandbox/plc4go/internal/plc4go/model/DefaultPlcReadRequest.go b/sandbox/plc4go/internal/plc4go/model/DefaultPlcReadRequest.go
index c68a14b..b2a296d 100644
--- a/sandbox/plc4go/internal/plc4go/model/DefaultPlcReadRequest.go
+++ b/sandbox/plc4go/internal/plc4go/model/DefaultPlcReadRequest.go
@@ -25,13 +25,13 @@ import (
 )
 
 type DefaultPlcReadRequestBuilder struct {
-	reader       PlcReader
+	reader       spi.PlcReader
 	fieldHandler spi.PlcFieldHandler
 	queries      map[string]string
 	model.PlcReadRequestBuilder
 }
 
-func NewDefaultPlcReadRequestBuilder(fieldHandler spi.PlcFieldHandler, reader PlcReader) *DefaultPlcReadRequestBuilder {
+func NewDefaultPlcReadRequestBuilder(fieldHandler spi.PlcFieldHandler, reader spi.PlcReader) *DefaultPlcReadRequestBuilder {
 	return &DefaultPlcReadRequestBuilder{
 		reader:       reader,
 		fieldHandler: fieldHandler,
@@ -45,7 +45,7 @@ func (m *DefaultPlcReadRequestBuilder) AddItem(name string, query string) {
 
 func (m *DefaultPlcReadRequestBuilder) Build() (model.PlcReadRequest, error) {
 	fields := make(map[string]model.PlcField)
-	for _, name := range m.queries {
+	for name := range m.queries {
 		query := m.queries[name]
 		field, err := m.fieldHandler.ParseQuery(query)
 		if err != nil {
@@ -61,10 +61,10 @@ func (m *DefaultPlcReadRequestBuilder) Build() (model.PlcReadRequest, error) {
 
 type DefaultPlcReadRequest struct {
 	fields map[string]model.PlcField
-	reader PlcReader
+	reader spi.PlcReader
 	model.PlcReadRequest
 }
 
 func (m DefaultPlcReadRequest) Execute() <-chan model.PlcReadRequestResult {
-	return m.reader.Read()
+	return m.reader.Read(m)
 }
diff --git a/sandbox/plc4go/internal/plc4go/model/DefaultPlcWriteRequest.go b/sandbox/plc4go/internal/plc4go/model/DefaultPlcWriteRequest.go
index 2ecf9df..3996adc 100644
--- a/sandbox/plc4go/internal/plc4go/model/DefaultPlcWriteRequest.go
+++ b/sandbox/plc4go/internal/plc4go/model/DefaultPlcWriteRequest.go
@@ -26,14 +26,14 @@ import (
 )
 
 type DefaultPlcWriteRequestBuilder struct {
-	writer       PlcWriter
+	writer       spi.PlcWriter
 	fieldHandler spi.PlcFieldHandler
 	valueHandler spi.PlcValueHandler
 	queries      map[string]string
 	values       map[string]interface{}
 }
 
-func NewDefaultPlcWriteRequestBuilder(fieldHandler spi.PlcFieldHandler, valueHandler spi.PlcValueHandler, writer PlcWriter) *DefaultPlcWriteRequestBuilder {
+func NewDefaultPlcWriteRequestBuilder(fieldHandler spi.PlcFieldHandler, valueHandler spi.PlcValueHandler, writer spi.PlcWriter) *DefaultPlcWriteRequestBuilder {
 	return &DefaultPlcWriteRequestBuilder{
 		writer:       writer,
 		fieldHandler: fieldHandler,
@@ -74,10 +74,10 @@ func (m *DefaultPlcWriteRequestBuilder) Build() (model.PlcWriteRequest, error) {
 type DefaultPlcWriteRequest struct {
 	fields map[string]model.PlcField
 	values map[string]values.PlcValue
-	writer PlcWriter
+	writer spi.PlcWriter
 	model.PlcWriteRequest
 }
 
 func (m DefaultPlcWriteRequest) Execute() <-chan model.PlcWriteRequestResult {
-	return m.writer.Write()
+	return m.writer.Write(m)
 }
diff --git a/sandbox/plc4go/internal/plc4go/spi/values/PlcList.go b/sandbox/plc4go/internal/plc4go/model/values/PlcList.go
similarity index 100%
rename from sandbox/plc4go/internal/plc4go/spi/values/PlcList.go
rename to sandbox/plc4go/internal/plc4go/model/values/PlcList.go
diff --git a/sandbox/plc4go/internal/plc4go/spi/values/PlcSimpleValueAdapter.go b/sandbox/plc4go/internal/plc4go/model/values/PlcSimpleValueAdapter.go
similarity index 100%
rename from sandbox/plc4go/internal/plc4go/spi/values/PlcSimpleValueAdapter.go
rename to sandbox/plc4go/internal/plc4go/model/values/PlcSimpleValueAdapter.go
diff --git a/sandbox/plc4go/internal/plc4go/spi/values/PlcStruct.go b/sandbox/plc4go/internal/plc4go/model/values/PlcStruct.go
similarity index 100%
rename from sandbox/plc4go/internal/plc4go/spi/values/PlcStruct.go
rename to sandbox/plc4go/internal/plc4go/model/values/PlcStruct.go
diff --git a/sandbox/plc4go/internal/plc4go/spi/values/PlcValueAdapter.go b/sandbox/plc4go/internal/plc4go/model/values/PlcValueAdapter.go
similarity index 100%
rename from sandbox/plc4go/internal/plc4go/spi/values/PlcValueAdapter.go
rename to sandbox/plc4go/internal/plc4go/model/values/PlcValueAdapter.go
diff --git a/sandbox/plc4go/internal/plc4go/spi/values/iec61131/BOOL.go b/sandbox/plc4go/internal/plc4go/model/values/iec61131/BOOL.go
similarity index 94%
rename from sandbox/plc4go/internal/plc4go/spi/values/iec61131/BOOL.go
rename to sandbox/plc4go/internal/plc4go/model/values/iec61131/BOOL.go
index 08ed846..58aaf3f 100644
--- a/sandbox/plc4go/internal/plc4go/spi/values/iec61131/BOOL.go
+++ b/sandbox/plc4go/internal/plc4go/model/values/iec61131/BOOL.go
@@ -19,7 +19,7 @@
 package iec61131
 
 import (
-	"plc4x.apache.org/plc4go-modbus-driver/0.8.0/internal/plc4go/spi/values"
+	"plc4x.apache.org/plc4go-modbus-driver/0.8.0/internal/plc4go/model/values"
 )
 
 type PlcBOOL struct {
diff --git a/sandbox/plc4go/internal/plc4go/spi/values/iec61131/BYTE.go b/sandbox/plc4go/internal/plc4go/model/values/iec61131/BYTE.go
similarity index 98%
rename from sandbox/plc4go/internal/plc4go/spi/values/iec61131/BYTE.go
rename to sandbox/plc4go/internal/plc4go/model/values/iec61131/BYTE.go
index 0f6cb6d..28ec703 100644
--- a/sandbox/plc4go/internal/plc4go/spi/values/iec61131/BYTE.go
+++ b/sandbox/plc4go/internal/plc4go/model/values/iec61131/BYTE.go
@@ -18,7 +18,7 @@
 //
 package iec61131
 
-import "plc4x.apache.org/plc4go-modbus-driver/0.8.0/internal/plc4go/spi/values"
+import "plc4x.apache.org/plc4go-modbus-driver/0.8.0/internal/plc4go/model/values"
 
 type PlcBYTE struct {
 	value uint8
diff --git a/sandbox/plc4go/internal/plc4go/spi/values/iec61131/CHAR.go b/sandbox/plc4go/internal/plc4go/model/values/iec61131/CHAR.go
similarity index 98%
rename from sandbox/plc4go/internal/plc4go/spi/values/iec61131/CHAR.go
rename to sandbox/plc4go/internal/plc4go/model/values/iec61131/CHAR.go
index 40ee2b9..bef82ee 100644
--- a/sandbox/plc4go/internal/plc4go/spi/values/iec61131/CHAR.go
+++ b/sandbox/plc4go/internal/plc4go/model/values/iec61131/CHAR.go
@@ -18,7 +18,7 @@
 //
 package iec61131
 
-import "plc4x.apache.org/plc4go-modbus-driver/0.8.0/internal/plc4go/spi/values"
+import "plc4x.apache.org/plc4go-modbus-driver/0.8.0/internal/plc4go/model/values"
 
 type PlcCHAR struct {
 	value []byte
diff --git a/sandbox/plc4go/internal/plc4go/spi/values/iec61131/DATE.go b/sandbox/plc4go/internal/plc4go/model/values/iec61131/DATE.go
similarity index 94%
rename from sandbox/plc4go/internal/plc4go/spi/values/iec61131/DATE.go
rename to sandbox/plc4go/internal/plc4go/model/values/iec61131/DATE.go
index b5c282f..08d00c0 100644
--- a/sandbox/plc4go/internal/plc4go/spi/values/iec61131/DATE.go
+++ b/sandbox/plc4go/internal/plc4go/model/values/iec61131/DATE.go
@@ -19,7 +19,7 @@
 package iec61131
 
 import (
-	"plc4x.apache.org/plc4go-modbus-driver/0.8.0/internal/plc4go/spi/values"
+	"plc4x.apache.org/plc4go-modbus-driver/0.8.0/internal/plc4go/model/values"
 	"time"
 )
 
diff --git a/sandbox/plc4go/internal/plc4go/spi/values/iec61131/DATE_AND_TIME.go b/sandbox/plc4go/internal/plc4go/model/values/iec61131/DATE_AND_TIME.go
similarity index 93%
rename from sandbox/plc4go/internal/plc4go/spi/values/iec61131/DATE_AND_TIME.go
rename to sandbox/plc4go/internal/plc4go/model/values/iec61131/DATE_AND_TIME.go
index 30aa13a..0ffa84b 100644
--- a/sandbox/plc4go/internal/plc4go/spi/values/iec61131/DATE_AND_TIME.go
+++ b/sandbox/plc4go/internal/plc4go/model/values/iec61131/DATE_AND_TIME.go
@@ -19,7 +19,7 @@
 package iec61131
 
 import (
-	"plc4x.apache.org/plc4go-modbus-driver/0.8.0/internal/plc4go/spi/values"
+	"plc4x.apache.org/plc4go-modbus-driver/0.8.0/internal/plc4go/model/values"
 	"time"
 )
 
diff --git a/sandbox/plc4go/internal/plc4go/spi/values/iec61131/DINT.go b/sandbox/plc4go/internal/plc4go/model/values/iec61131/DINT.go
similarity index 97%
rename from sandbox/plc4go/internal/plc4go/spi/values/iec61131/DINT.go
rename to sandbox/plc4go/internal/plc4go/model/values/iec61131/DINT.go
index d72a03b..279aa97 100644
--- a/sandbox/plc4go/internal/plc4go/spi/values/iec61131/DINT.go
+++ b/sandbox/plc4go/internal/plc4go/model/values/iec61131/DINT.go
@@ -20,7 +20,7 @@ package iec61131
 
 import (
 	"math"
-	"plc4x.apache.org/plc4go-modbus-driver/0.8.0/internal/plc4go/spi/values"
+	"plc4x.apache.org/plc4go-modbus-driver/0.8.0/internal/plc4go/model/values"
 )
 
 type PlcDINT struct {
diff --git a/sandbox/plc4go/internal/plc4go/spi/values/iec61131/DWORD.go b/sandbox/plc4go/internal/plc4go/model/values/iec61131/DWORD.go
similarity index 99%
rename from sandbox/plc4go/internal/plc4go/spi/values/iec61131/DWORD.go
rename to sandbox/plc4go/internal/plc4go/model/values/iec61131/DWORD.go
index cc63ac6..eed46df 100644
--- a/sandbox/plc4go/internal/plc4go/spi/values/iec61131/DWORD.go
+++ b/sandbox/plc4go/internal/plc4go/model/values/iec61131/DWORD.go
@@ -18,7 +18,7 @@
 //
 package iec61131
 
-import "plc4x.apache.org/plc4go-modbus-driver/0.8.0/internal/plc4go/spi/values"
+import "plc4x.apache.org/plc4go-modbus-driver/0.8.0/internal/plc4go/model/values"
 
 type PlcDWORD struct {
 	value uint32
diff --git a/sandbox/plc4go/internal/plc4go/spi/values/iec61131/IEC61131ValueHandler.go b/sandbox/plc4go/internal/plc4go/model/values/iec61131/IEC61131ValueHandler.go
similarity index 100%
rename from sandbox/plc4go/internal/plc4go/spi/values/iec61131/IEC61131ValueHandler.go
rename to sandbox/plc4go/internal/plc4go/model/values/iec61131/IEC61131ValueHandler.go
diff --git a/sandbox/plc4go/internal/plc4go/spi/values/iec61131/INT.go b/sandbox/plc4go/internal/plc4go/model/values/iec61131/INT.go
similarity index 96%
rename from sandbox/plc4go/internal/plc4go/spi/values/iec61131/INT.go
rename to sandbox/plc4go/internal/plc4go/model/values/iec61131/INT.go
index e053dcc..e0d1299 100644
--- a/sandbox/plc4go/internal/plc4go/spi/values/iec61131/INT.go
+++ b/sandbox/plc4go/internal/plc4go/model/values/iec61131/INT.go
@@ -20,7 +20,7 @@ package iec61131
 
 import (
 	"math"
-	"plc4x.apache.org/plc4go-modbus-driver/0.8.0/internal/plc4go/spi/values"
+	"plc4x.apache.org/plc4go-modbus-driver/0.8.0/internal/plc4go/model/values"
 )
 
 type PlcINT struct {
diff --git a/sandbox/plc4go/internal/plc4go/spi/values/iec61131/LINT.go b/sandbox/plc4go/internal/plc4go/model/values/iec61131/LINT.go
similarity index 97%
rename from sandbox/plc4go/internal/plc4go/spi/values/iec61131/LINT.go
rename to sandbox/plc4go/internal/plc4go/model/values/iec61131/LINT.go
index 798c7d9..9abe8cf 100644
--- a/sandbox/plc4go/internal/plc4go/spi/values/iec61131/LINT.go
+++ b/sandbox/plc4go/internal/plc4go/model/values/iec61131/LINT.go
@@ -20,7 +20,7 @@ package iec61131
 
 import (
 	"math"
-	"plc4x.apache.org/plc4go-modbus-driver/0.8.0/internal/plc4go/spi/values"
+	"plc4x.apache.org/plc4go-modbus-driver/0.8.0/internal/plc4go/model/values"
 )
 
 type PlcLINT struct {
diff --git a/sandbox/plc4go/internal/plc4go/spi/values/iec61131/LREAL.go b/sandbox/plc4go/internal/plc4go/model/values/iec61131/LREAL.go
similarity index 97%
rename from sandbox/plc4go/internal/plc4go/spi/values/iec61131/LREAL.go
rename to sandbox/plc4go/internal/plc4go/model/values/iec61131/LREAL.go
index 9626702..7f21a18 100644
--- a/sandbox/plc4go/internal/plc4go/spi/values/iec61131/LREAL.go
+++ b/sandbox/plc4go/internal/plc4go/model/values/iec61131/LREAL.go
@@ -20,7 +20,7 @@ package iec61131
 
 import (
 	"math"
-	"plc4x.apache.org/plc4go-modbus-driver/0.8.0/internal/plc4go/spi/values"
+	"plc4x.apache.org/plc4go-modbus-driver/0.8.0/internal/plc4go/model/values"
 )
 
 type PlcLREAL struct {
diff --git a/sandbox/plc4go/internal/plc4go/spi/values/iec61131/LTIME.go b/sandbox/plc4go/internal/plc4go/model/values/iec61131/LTIME.go
similarity index 93%
rename from sandbox/plc4go/internal/plc4go/spi/values/iec61131/LTIME.go
rename to sandbox/plc4go/internal/plc4go/model/values/iec61131/LTIME.go
index 71fa5e9..788e28b 100644
--- a/sandbox/plc4go/internal/plc4go/spi/values/iec61131/LTIME.go
+++ b/sandbox/plc4go/internal/plc4go/model/values/iec61131/LTIME.go
@@ -19,7 +19,7 @@
 package iec61131
 
 import (
-	"plc4x.apache.org/plc4go-modbus-driver/0.8.0/internal/plc4go/spi/values"
+	"plc4x.apache.org/plc4go-modbus-driver/0.8.0/internal/plc4go/model/values"
 	"time"
 )
 
diff --git a/sandbox/plc4go/internal/plc4go/spi/values/iec61131/LWORD.go b/sandbox/plc4go/internal/plc4go/model/values/iec61131/LWORD.go
similarity index 99%
rename from sandbox/plc4go/internal/plc4go/spi/values/iec61131/LWORD.go
rename to sandbox/plc4go/internal/plc4go/model/values/iec61131/LWORD.go
index 9b88f17..aa38383 100644
--- a/sandbox/plc4go/internal/plc4go/spi/values/iec61131/LWORD.go
+++ b/sandbox/plc4go/internal/plc4go/model/values/iec61131/LWORD.go
@@ -18,7 +18,7 @@
 //
 package iec61131
 
-import "plc4x.apache.org/plc4go-modbus-driver/0.8.0/internal/plc4go/spi/values"
+import "plc4x.apache.org/plc4go-modbus-driver/0.8.0/internal/plc4go/model/values"
 
 type PlcLWORD struct {
 	value uint64
diff --git a/sandbox/plc4go/internal/plc4go/spi/values/iec61131/NULL.go b/sandbox/plc4go/internal/plc4go/model/values/iec61131/NULL.go
similarity index 98%
rename from sandbox/plc4go/internal/plc4go/spi/values/iec61131/NULL.go
rename to sandbox/plc4go/internal/plc4go/model/values/iec61131/NULL.go
index c56fb62..d2086c5 100644
--- a/sandbox/plc4go/internal/plc4go/spi/values/iec61131/NULL.go
+++ b/sandbox/plc4go/internal/plc4go/model/values/iec61131/NULL.go
@@ -18,7 +18,7 @@
 //
 package iec61131
 
-import "plc4x.apache.org/plc4go-modbus-driver/0.8.0/internal/plc4go/spi/values"
+import "plc4x.apache.org/plc4go-modbus-driver/0.8.0/internal/plc4go/model/values"
 
 type PlcNULL struct {
 	values.PlcValueAdapter
diff --git a/sandbox/plc4go/internal/plc4go/spi/values/iec61131/REAL.go b/sandbox/plc4go/internal/plc4go/model/values/iec61131/REAL.go
similarity index 97%
rename from sandbox/plc4go/internal/plc4go/spi/values/iec61131/REAL.go
rename to sandbox/plc4go/internal/plc4go/model/values/iec61131/REAL.go
index e43b164..7177e6f 100644
--- a/sandbox/plc4go/internal/plc4go/spi/values/iec61131/REAL.go
+++ b/sandbox/plc4go/internal/plc4go/model/values/iec61131/REAL.go
@@ -20,7 +20,7 @@ package iec61131
 
 import (
 	"math"
-	"plc4x.apache.org/plc4go-modbus-driver/0.8.0/internal/plc4go/spi/values"
+	"plc4x.apache.org/plc4go-modbus-driver/0.8.0/internal/plc4go/model/values"
 )
 
 type PlcREAL struct {
diff --git a/sandbox/plc4go/internal/plc4go/spi/values/iec61131/SINT.go b/sandbox/plc4go/internal/plc4go/model/values/iec61131/SINT.go
similarity index 99%
rename from sandbox/plc4go/internal/plc4go/spi/values/iec61131/SINT.go
rename to sandbox/plc4go/internal/plc4go/model/values/iec61131/SINT.go
index a376a57..cbd8413 100644
--- a/sandbox/plc4go/internal/plc4go/spi/values/iec61131/SINT.go
+++ b/sandbox/plc4go/internal/plc4go/model/values/iec61131/SINT.go
@@ -18,7 +18,7 @@
 //
 package iec61131
 
-import "plc4x.apache.org/plc4go-modbus-driver/0.8.0/internal/plc4go/spi/values"
+import "plc4x.apache.org/plc4go-modbus-driver/0.8.0/internal/plc4go/model/values"
 
 type PlcSINT struct {
 	value int8
diff --git a/sandbox/plc4go/internal/plc4go/spi/values/iec61131/STRING.go b/sandbox/plc4go/internal/plc4go/model/values/iec61131/STRING.go
similarity index 98%
rename from sandbox/plc4go/internal/plc4go/spi/values/iec61131/STRING.go
rename to sandbox/plc4go/internal/plc4go/model/values/iec61131/STRING.go
index 4b69eed..2314238 100644
--- a/sandbox/plc4go/internal/plc4go/spi/values/iec61131/STRING.go
+++ b/sandbox/plc4go/internal/plc4go/model/values/iec61131/STRING.go
@@ -18,7 +18,7 @@
 //
 package iec61131
 
-import "plc4x.apache.org/plc4go-modbus-driver/0.8.0/internal/plc4go/spi/values"
+import "plc4x.apache.org/plc4go-modbus-driver/0.8.0/internal/plc4go/model/values"
 
 type PlcSTRING struct {
 	value []byte
diff --git a/sandbox/plc4go/internal/plc4go/spi/values/iec61131/TIME.go b/sandbox/plc4go/internal/plc4go/model/values/iec61131/TIME.go
similarity index 93%
rename from sandbox/plc4go/internal/plc4go/spi/values/iec61131/TIME.go
rename to sandbox/plc4go/internal/plc4go/model/values/iec61131/TIME.go
index 3d1253e..b95ccb3 100644
--- a/sandbox/plc4go/internal/plc4go/spi/values/iec61131/TIME.go
+++ b/sandbox/plc4go/internal/plc4go/model/values/iec61131/TIME.go
@@ -19,7 +19,7 @@
 package iec61131
 
 import (
-	"plc4x.apache.org/plc4go-modbus-driver/0.8.0/internal/plc4go/spi/values"
+	"plc4x.apache.org/plc4go-modbus-driver/0.8.0/internal/plc4go/model/values"
 	"time"
 )
 
diff --git a/sandbox/plc4go/internal/plc4go/spi/values/iec61131/TIME_OF_DAY.go b/sandbox/plc4go/internal/plc4go/model/values/iec61131/TIME_OF_DAY.go
similarity index 94%
rename from sandbox/plc4go/internal/plc4go/spi/values/iec61131/TIME_OF_DAY.go
rename to sandbox/plc4go/internal/plc4go/model/values/iec61131/TIME_OF_DAY.go
index c2fcb6b..df7ace2 100644
--- a/sandbox/plc4go/internal/plc4go/spi/values/iec61131/TIME_OF_DAY.go
+++ b/sandbox/plc4go/internal/plc4go/model/values/iec61131/TIME_OF_DAY.go
@@ -19,7 +19,7 @@
 package iec61131
 
 import (
-	"plc4x.apache.org/plc4go-modbus-driver/0.8.0/internal/plc4go/spi/values"
+	"plc4x.apache.org/plc4go-modbus-driver/0.8.0/internal/plc4go/model/values"
 	"time"
 )
 
diff --git a/sandbox/plc4go/internal/plc4go/spi/values/iec61131/UDINT.go b/sandbox/plc4go/internal/plc4go/model/values/iec61131/UDINT.go
similarity index 96%
rename from sandbox/plc4go/internal/plc4go/spi/values/iec61131/UDINT.go
rename to sandbox/plc4go/internal/plc4go/model/values/iec61131/UDINT.go
index 7e53158..2216747 100644
--- a/sandbox/plc4go/internal/plc4go/spi/values/iec61131/UDINT.go
+++ b/sandbox/plc4go/internal/plc4go/model/values/iec61131/UDINT.go
@@ -20,7 +20,7 @@ package iec61131
 
 import (
 	"math"
-	"plc4x.apache.org/plc4go-modbus-driver/0.8.0/internal/plc4go/spi/values"
+	"plc4x.apache.org/plc4go-modbus-driver/0.8.0/internal/plc4go/model/values"
 )
 
 type PlcUDINT struct {
diff --git a/sandbox/plc4go/internal/plc4go/spi/values/iec61131/UINT.go b/sandbox/plc4go/internal/plc4go/model/values/iec61131/UINT.go
similarity index 96%
rename from sandbox/plc4go/internal/plc4go/spi/values/iec61131/UINT.go
rename to sandbox/plc4go/internal/plc4go/model/values/iec61131/UINT.go
index 55b90d1..94535a2 100644
--- a/sandbox/plc4go/internal/plc4go/spi/values/iec61131/UINT.go
+++ b/sandbox/plc4go/internal/plc4go/model/values/iec61131/UINT.go
@@ -20,7 +20,7 @@ package iec61131
 
 import (
 	"math"
-	"plc4x.apache.org/plc4go-modbus-driver/0.8.0/internal/plc4go/spi/values"
+	"plc4x.apache.org/plc4go-modbus-driver/0.8.0/internal/plc4go/model/values"
 )
 
 type PlcUINT struct {
diff --git a/sandbox/plc4go/internal/plc4go/spi/values/iec61131/ULINT.go b/sandbox/plc4go/internal/plc4go/model/values/iec61131/ULINT.go
similarity index 97%
rename from sandbox/plc4go/internal/plc4go/spi/values/iec61131/ULINT.go
rename to sandbox/plc4go/internal/plc4go/model/values/iec61131/ULINT.go
index 97de4c8..fcb7797 100644
--- a/sandbox/plc4go/internal/plc4go/spi/values/iec61131/ULINT.go
+++ b/sandbox/plc4go/internal/plc4go/model/values/iec61131/ULINT.go
@@ -20,7 +20,7 @@ package iec61131
 
 import (
 	"math"
-	"plc4x.apache.org/plc4go-modbus-driver/0.8.0/internal/plc4go/spi/values"
+	"plc4x.apache.org/plc4go-modbus-driver/0.8.0/internal/plc4go/model/values"
 )
 
 type PlcULINT struct {
diff --git a/sandbox/plc4go/internal/plc4go/spi/values/iec61131/USINT.go b/sandbox/plc4go/internal/plc4go/model/values/iec61131/USINT.go
similarity index 96%
rename from sandbox/plc4go/internal/plc4go/spi/values/iec61131/USINT.go
rename to sandbox/plc4go/internal/plc4go/model/values/iec61131/USINT.go
index 9c6da1b..918b162 100644
--- a/sandbox/plc4go/internal/plc4go/spi/values/iec61131/USINT.go
+++ b/sandbox/plc4go/internal/plc4go/model/values/iec61131/USINT.go
@@ -20,7 +20,7 @@ package iec61131
 
 import (
 	"math"
-	"plc4x.apache.org/plc4go-modbus-driver/0.8.0/internal/plc4go/spi/values"
+	"plc4x.apache.org/plc4go-modbus-driver/0.8.0/internal/plc4go/model/values"
 )
 
 type PlcUSINT struct {
diff --git a/sandbox/plc4go/internal/plc4go/spi/values/iec61131/WCHAR.go b/sandbox/plc4go/internal/plc4go/model/values/iec61131/WCHAR.go
similarity index 93%
rename from sandbox/plc4go/internal/plc4go/spi/values/iec61131/WCHAR.go
rename to sandbox/plc4go/internal/plc4go/model/values/iec61131/WCHAR.go
index 29bb2f7..9739d57 100644
--- a/sandbox/plc4go/internal/plc4go/spi/values/iec61131/WCHAR.go
+++ b/sandbox/plc4go/internal/plc4go/model/values/iec61131/WCHAR.go
@@ -19,7 +19,7 @@
 package iec61131
 
 import (
-	"plc4x.apache.org/plc4go-modbus-driver/0.8.0/internal/plc4go/spi/values"
+	"plc4x.apache.org/plc4go-modbus-driver/0.8.0/internal/plc4go/model/values"
 	"unicode/utf16"
 )
 
diff --git a/sandbox/plc4go/internal/plc4go/spi/values/iec61131/WORD.go b/sandbox/plc4go/internal/plc4go/model/values/iec61131/WORD.go
similarity index 98%
rename from sandbox/plc4go/internal/plc4go/spi/values/iec61131/WORD.go
rename to sandbox/plc4go/internal/plc4go/model/values/iec61131/WORD.go
index d459d60..6155a65 100644
--- a/sandbox/plc4go/internal/plc4go/spi/values/iec61131/WORD.go
+++ b/sandbox/plc4go/internal/plc4go/model/values/iec61131/WORD.go
@@ -18,7 +18,7 @@
 //
 package iec61131
 
-import "plc4x.apache.org/plc4go-modbus-driver/0.8.0/internal/plc4go/spi/values"
+import "plc4x.apache.org/plc4go-modbus-driver/0.8.0/internal/plc4go/model/values"
 
 type PlcWORD struct {
 	value uint16
diff --git a/sandbox/plc4go/internal/plc4go/spi/values/iec61131/WSTRING.go b/sandbox/plc4go/internal/plc4go/model/values/iec61131/WSTRING.go
similarity index 93%
rename from sandbox/plc4go/internal/plc4go/spi/values/iec61131/WSTRING.go
rename to sandbox/plc4go/internal/plc4go/model/values/iec61131/WSTRING.go
index 14c5566..fb608da 100644
--- a/sandbox/plc4go/internal/plc4go/spi/values/iec61131/WSTRING.go
+++ b/sandbox/plc4go/internal/plc4go/model/values/iec61131/WSTRING.go
@@ -19,7 +19,7 @@
 package iec61131
 
 import (
-	"plc4x.apache.org/plc4go-modbus-driver/0.8.0/internal/plc4go/spi/values"
+	"plc4x.apache.org/plc4go-modbus-driver/0.8.0/internal/plc4go/model/values"
 	"unicode/utf16"
 )
 
diff --git a/sandbox/plc4go/internal/plc4go/model/PlcReader.go b/sandbox/plc4go/internal/plc4go/spi/PlcReader.go
similarity index 91%
rename from sandbox/plc4go/internal/plc4go/model/PlcReader.go
rename to sandbox/plc4go/internal/plc4go/spi/PlcReader.go
index 398e02b..fc50bfd 100644
--- a/sandbox/plc4go/internal/plc4go/model/PlcReader.go
+++ b/sandbox/plc4go/internal/plc4go/spi/PlcReader.go
@@ -16,10 +16,10 @@
 // specific language governing permissions and limitations
 // under the License.
 //
-package model
+package spi
 
 import "plc4x.apache.org/plc4go-modbus-driver/0.8.0/pkg/plc4go/model"
 
 type PlcReader interface {
-	Read() <-chan model.PlcReadRequestResult
+	Read(readRequest model.PlcReadRequest) <-chan model.PlcReadRequestResult
 }
diff --git a/sandbox/plc4go/internal/plc4go/model/PlcWriter.go b/sandbox/plc4go/internal/plc4go/spi/PlcWriter.go
similarity index 91%
rename from sandbox/plc4go/internal/plc4go/model/PlcWriter.go
rename to sandbox/plc4go/internal/plc4go/spi/PlcWriter.go
index b0cdfc5..5cb2090 100644
--- a/sandbox/plc4go/internal/plc4go/model/PlcWriter.go
+++ b/sandbox/plc4go/internal/plc4go/spi/PlcWriter.go
@@ -16,10 +16,10 @@
 // specific language governing permissions and limitations
 // under the License.
 //
-package model
+package spi
 
 import "plc4x.apache.org/plc4go-modbus-driver/0.8.0/pkg/plc4go/model"
 
 type PlcWriter interface {
-	Write() <-chan model.PlcWriteRequestResult
+	Write(writeRequest model.PlcWriteRequest) <-chan model.PlcWriteRequestResult
 }
diff --git a/sandbox/plc4go/internal/plc4go/spi/model/PlcReadRequest.go b/sandbox/plc4go/internal/plc4go/spi/model/PlcReadRequest.go
deleted file mode 100644
index 4de764b..0000000
--- a/sandbox/plc4go/internal/plc4go/spi/model/PlcReadRequest.go
+++ /dev/null
@@ -1,32 +0,0 @@
-//
-// 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
-//
-//      http://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 "plc4x.apache.org/plc4go-modbus-driver/0.8.0/pkg/plc4go/model"
-
-type PlcReadRequest struct {
-	fields map[string]model.PlcField
-	model.PlcReadRequest
-}
-
-func NewPlcReadRequest(fields map[string]model.PlcField) PlcReadRequest {
-	return PlcReadRequest{
-		fields: fields,
-	}
-}
diff --git a/sandbox/plc4go/pkg/plc4go/driverManager.go b/sandbox/plc4go/pkg/plc4go/driverManager.go
index 6756b82..94dcea7 100644
--- a/sandbox/plc4go/pkg/plc4go/driverManager.go
+++ b/sandbox/plc4go/pkg/plc4go/driverManager.go
@@ -21,14 +21,12 @@ package plc4go
 import (
 	"errors"
 	"net/url"
-	"plc4x.apache.org/plc4go-modbus-driver/0.8.0/internal/plc4go/bacnetip"
-	"plc4x.apache.org/plc4go-modbus-driver/0.8.0/internal/plc4go/knxnetip"
-	"plc4x.apache.org/plc4go-modbus-driver/0.8.0/internal/plc4go/modbus"
-	"plc4x.apache.org/plc4go-modbus-driver/0.8.0/internal/plc4go/s7"
 )
 
 // This is the main entry point for PLC4Go applications
 type PlcDriverManager interface {
+	// Manually register a new driver
+	RegisterDriver(driver PlcDriver)
 	// List the names of all drivers registered in the system
 	ListDriverNames() []string
 	// Get access to a driver instance for a given driver-name
@@ -40,12 +38,7 @@ type PlcDriverManager interface {
 
 func NewPlcDriverManager() PlcDriverManager {
 	return plcDriverManger{
-		drivers: map[string]PlcDriver{
-			"bacnetip": bacnetip.NewBacnetIpDriver(),
-			"knxnetip": knxnetip.NewKnxNetIpDriver(),
-			"modbus":   modbus.NewModbusDriver(),
-			"s7":       s7.NewS7Driver(),
-		},
+		drivers: map[string]PlcDriver{},
 	}
 }
 
@@ -53,6 +46,10 @@ type plcDriverManger struct {
 	drivers map[string]PlcDriver
 }
 
+func (m plcDriverManger) RegisterDriver(driver PlcDriver) {
+	m.drivers[driver.GetProtocolCode()] = driver
+}
+
 func (m plcDriverManger) ListDriverNames() []string {
 	driverNames := make([]string, len(m.drivers))
 	for driverName := range m.drivers {
diff --git a/sandbox/plc4go/pkg/plc4go/model/plc_read_request.go b/sandbox/plc4go/pkg/plc4go/model/plc_read_request.go
index 09fced2..0e1932b 100644
--- a/sandbox/plc4go/pkg/plc4go/model/plc_read_request.go
+++ b/sandbox/plc4go/pkg/plc4go/model/plc_read_request.go
@@ -19,7 +19,7 @@
 package model
 
 type PlcReadRequestBuilder interface {
-	AddField(name string, query string) error
+	AddItem(name string, query string)
 	Build() (PlcReadRequest, error)
 }
 
diff --git a/sandbox/plc4go/pkg/plc4go/model/plc_write_request.go b/sandbox/plc4go/pkg/plc4go/model/plc_write_request.go
index 8cab980..952e1d3 100644
--- a/sandbox/plc4go/pkg/plc4go/model/plc_write_request.go
+++ b/sandbox/plc4go/pkg/plc4go/model/plc_write_request.go
@@ -19,7 +19,7 @@
 package model
 
 type PlcWriteRequestBuilder interface {
-	AddField(name string, query string, value interface{})
+	AddItem(name string, query string, value interface{})
 	Build() (PlcWriteRequest, error)
 }