diff --git a/mocks/GNMIClient.go b/mocks/GNMIClient.go
new file mode 100644
index 0000000000000000000000000000000000000000..255d4a40d68513d1b1125101f8e9cdc12f139dc2
--- /dev/null
+++ b/mocks/GNMIClient.go
@@ -0,0 +1,137 @@
+// Code generated by mockery v2.6.0. DO NOT EDIT.
+
+package mocks
+
+import (
+	context "context"
+
+	gnmi "github.com/openconfig/gnmi/proto/gnmi"
+	grpc "google.golang.org/grpc"
+
+	mock "github.com/stretchr/testify/mock"
+)
+
+// GNMIClient is an autogenerated mock type for the GNMIClient type
+type GNMIClient struct {
+	mock.Mock
+}
+
+// Capabilities provides a mock function with given fields: ctx, in, opts
+func (_m *GNMIClient) Capabilities(ctx context.Context, in *gnmi.CapabilityRequest, opts ...grpc.CallOption) (*gnmi.CapabilityResponse, error) {
+	_va := make([]interface{}, len(opts))
+	for _i := range opts {
+		_va[_i] = opts[_i]
+	}
+	var _ca []interface{}
+	_ca = append(_ca, ctx, in)
+	_ca = append(_ca, _va...)
+	ret := _m.Called(_ca...)
+
+	var r0 *gnmi.CapabilityResponse
+	if rf, ok := ret.Get(0).(func(context.Context, *gnmi.CapabilityRequest, ...grpc.CallOption) *gnmi.CapabilityResponse); ok {
+		r0 = rf(ctx, in, opts...)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*gnmi.CapabilityResponse)
+		}
+	}
+
+	var r1 error
+	if rf, ok := ret.Get(1).(func(context.Context, *gnmi.CapabilityRequest, ...grpc.CallOption) error); ok {
+		r1 = rf(ctx, in, opts...)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// Get provides a mock function with given fields: ctx, in, opts
+func (_m *GNMIClient) Get(ctx context.Context, in *gnmi.GetRequest, opts ...grpc.CallOption) (*gnmi.GetResponse, error) {
+	_va := make([]interface{}, len(opts))
+	for _i := range opts {
+		_va[_i] = opts[_i]
+	}
+	var _ca []interface{}
+	_ca = append(_ca, ctx, in)
+	_ca = append(_ca, _va...)
+	ret := _m.Called(_ca...)
+
+	var r0 *gnmi.GetResponse
+	if rf, ok := ret.Get(0).(func(context.Context, *gnmi.GetRequest, ...grpc.CallOption) *gnmi.GetResponse); ok {
+		r0 = rf(ctx, in, opts...)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*gnmi.GetResponse)
+		}
+	}
+
+	var r1 error
+	if rf, ok := ret.Get(1).(func(context.Context, *gnmi.GetRequest, ...grpc.CallOption) error); ok {
+		r1 = rf(ctx, in, opts...)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// Set provides a mock function with given fields: ctx, in, opts
+func (_m *GNMIClient) Set(ctx context.Context, in *gnmi.SetRequest, opts ...grpc.CallOption) (*gnmi.SetResponse, error) {
+	_va := make([]interface{}, len(opts))
+	for _i := range opts {
+		_va[_i] = opts[_i]
+	}
+	var _ca []interface{}
+	_ca = append(_ca, ctx, in)
+	_ca = append(_ca, _va...)
+	ret := _m.Called(_ca...)
+
+	var r0 *gnmi.SetResponse
+	if rf, ok := ret.Get(0).(func(context.Context, *gnmi.SetRequest, ...grpc.CallOption) *gnmi.SetResponse); ok {
+		r0 = rf(ctx, in, opts...)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*gnmi.SetResponse)
+		}
+	}
+
+	var r1 error
+	if rf, ok := ret.Get(1).(func(context.Context, *gnmi.SetRequest, ...grpc.CallOption) error); ok {
+		r1 = rf(ctx, in, opts...)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// Subscribe provides a mock function with given fields: ctx, opts
+func (_m *GNMIClient) Subscribe(ctx context.Context, opts ...grpc.CallOption) (gnmi.GNMI_SubscribeClient, error) {
+	_va := make([]interface{}, len(opts))
+	for _i := range opts {
+		_va[_i] = opts[_i]
+	}
+	var _ca []interface{}
+	_ca = append(_ca, ctx)
+	_ca = append(_ca, _va...)
+	ret := _m.Called(_ca...)
+
+	var r0 gnmi.GNMI_SubscribeClient
+	if rf, ok := ret.Get(0).(func(context.Context, ...grpc.CallOption) gnmi.GNMI_SubscribeClient); ok {
+		r0 = rf(ctx, opts...)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(gnmi.GNMI_SubscribeClient)
+		}
+	}
+
+	var r1 error
+	if rf, ok := ret.Get(1).(func(context.Context, ...grpc.CallOption) error); ok {
+		r1 = rf(ctx, opts...)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
diff --git a/mocks/GNMIServer.go b/mocks/GNMIServer.go
new file mode 100644
index 0000000000000000000000000000000000000000..0628c5b31fe2c971810f5a2c9f7be3a8326ee40c
--- /dev/null
+++ b/mocks/GNMIServer.go
@@ -0,0 +1,98 @@
+// Code generated by mockery v2.6.0. DO NOT EDIT.
+
+package mocks
+
+import (
+	context "context"
+
+	gnmi "github.com/openconfig/gnmi/proto/gnmi"
+	mock "github.com/stretchr/testify/mock"
+)
+
+// GNMIServer is an autogenerated mock type for the GNMIServer type
+type GNMIServer struct {
+	mock.Mock
+}
+
+// Capabilities provides a mock function with given fields: _a0, _a1
+func (_m *GNMIServer) Capabilities(_a0 context.Context, _a1 *gnmi.CapabilityRequest) (*gnmi.CapabilityResponse, error) {
+	ret := _m.Called(_a0, _a1)
+
+	var r0 *gnmi.CapabilityResponse
+	if rf, ok := ret.Get(0).(func(context.Context, *gnmi.CapabilityRequest) *gnmi.CapabilityResponse); ok {
+		r0 = rf(_a0, _a1)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*gnmi.CapabilityResponse)
+		}
+	}
+
+	var r1 error
+	if rf, ok := ret.Get(1).(func(context.Context, *gnmi.CapabilityRequest) error); ok {
+		r1 = rf(_a0, _a1)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// Get provides a mock function with given fields: _a0, _a1
+func (_m *GNMIServer) Get(_a0 context.Context, _a1 *gnmi.GetRequest) (*gnmi.GetResponse, error) {
+	ret := _m.Called(_a0, _a1)
+
+	var r0 *gnmi.GetResponse
+	if rf, ok := ret.Get(0).(func(context.Context, *gnmi.GetRequest) *gnmi.GetResponse); ok {
+		r0 = rf(_a0, _a1)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*gnmi.GetResponse)
+		}
+	}
+
+	var r1 error
+	if rf, ok := ret.Get(1).(func(context.Context, *gnmi.GetRequest) error); ok {
+		r1 = rf(_a0, _a1)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// Set provides a mock function with given fields: _a0, _a1
+func (_m *GNMIServer) Set(_a0 context.Context, _a1 *gnmi.SetRequest) (*gnmi.SetResponse, error) {
+	ret := _m.Called(_a0, _a1)
+
+	var r0 *gnmi.SetResponse
+	if rf, ok := ret.Get(0).(func(context.Context, *gnmi.SetRequest) *gnmi.SetResponse); ok {
+		r0 = rf(_a0, _a1)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*gnmi.SetResponse)
+		}
+	}
+
+	var r1 error
+	if rf, ok := ret.Get(1).(func(context.Context, *gnmi.SetRequest) error); ok {
+		r1 = rf(_a0, _a1)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// Subscribe provides a mock function with given fields: _a0
+func (_m *GNMIServer) Subscribe(_a0 gnmi.GNMI_SubscribeServer) error {
+	ret := _m.Called(_a0)
+
+	var r0 error
+	if rf, ok := ret.Get(0).(func(gnmi.GNMI_SubscribeServer) error); ok {
+		r0 = rf(_a0)
+	} else {
+		r0 = ret.Error(0)
+	}
+
+	return r0
+}
diff --git a/mocks/GNMI_SubscribeClient.go b/mocks/GNMI_SubscribeClient.go
new file mode 100644
index 0000000000000000000000000000000000000000..456be898e5d92171a26add0d03e863f08f302d24
--- /dev/null
+++ b/mocks/GNMI_SubscribeClient.go
@@ -0,0 +1,151 @@
+// Code generated by mockery v2.6.0. DO NOT EDIT.
+
+package mocks
+
+import (
+	context "context"
+
+	gnmi "github.com/openconfig/gnmi/proto/gnmi"
+	metadata "google.golang.org/grpc/metadata"
+
+	mock "github.com/stretchr/testify/mock"
+)
+
+// GNMI_SubscribeClient is an autogenerated mock type for the GNMI_SubscribeClient type
+type GNMI_SubscribeClient struct {
+	mock.Mock
+}
+
+// CloseSend provides a mock function with given fields:
+func (_m *GNMI_SubscribeClient) CloseSend() error {
+	ret := _m.Called()
+
+	var r0 error
+	if rf, ok := ret.Get(0).(func() error); ok {
+		r0 = rf()
+	} else {
+		r0 = ret.Error(0)
+	}
+
+	return r0
+}
+
+// Context provides a mock function with given fields:
+func (_m *GNMI_SubscribeClient) Context() context.Context {
+	ret := _m.Called()
+
+	var r0 context.Context
+	if rf, ok := ret.Get(0).(func() context.Context); ok {
+		r0 = rf()
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(context.Context)
+		}
+	}
+
+	return r0
+}
+
+// Header provides a mock function with given fields:
+func (_m *GNMI_SubscribeClient) Header() (metadata.MD, error) {
+	ret := _m.Called()
+
+	var r0 metadata.MD
+	if rf, ok := ret.Get(0).(func() metadata.MD); ok {
+		r0 = rf()
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(metadata.MD)
+		}
+	}
+
+	var r1 error
+	if rf, ok := ret.Get(1).(func() error); ok {
+		r1 = rf()
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// Recv provides a mock function with given fields:
+func (_m *GNMI_SubscribeClient) Recv() (*gnmi.SubscribeResponse, error) {
+	ret := _m.Called()
+
+	var r0 *gnmi.SubscribeResponse
+	if rf, ok := ret.Get(0).(func() *gnmi.SubscribeResponse); ok {
+		r0 = rf()
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*gnmi.SubscribeResponse)
+		}
+	}
+
+	var r1 error
+	if rf, ok := ret.Get(1).(func() error); ok {
+		r1 = rf()
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// RecvMsg provides a mock function with given fields: m
+func (_m *GNMI_SubscribeClient) RecvMsg(m interface{}) error {
+	ret := _m.Called(m)
+
+	var r0 error
+	if rf, ok := ret.Get(0).(func(interface{}) error); ok {
+		r0 = rf(m)
+	} else {
+		r0 = ret.Error(0)
+	}
+
+	return r0
+}
+
+// Send provides a mock function with given fields: _a0
+func (_m *GNMI_SubscribeClient) Send(_a0 *gnmi.SubscribeRequest) error {
+	ret := _m.Called(_a0)
+
+	var r0 error
+	if rf, ok := ret.Get(0).(func(*gnmi.SubscribeRequest) error); ok {
+		r0 = rf(_a0)
+	} else {
+		r0 = ret.Error(0)
+	}
+
+	return r0
+}
+
+// SendMsg provides a mock function with given fields: m
+func (_m *GNMI_SubscribeClient) SendMsg(m interface{}) error {
+	ret := _m.Called(m)
+
+	var r0 error
+	if rf, ok := ret.Get(0).(func(interface{}) error); ok {
+		r0 = rf(m)
+	} else {
+		r0 = ret.Error(0)
+	}
+
+	return r0
+}
+
+// Trailer provides a mock function with given fields:
+func (_m *GNMI_SubscribeClient) Trailer() metadata.MD {
+	ret := _m.Called()
+
+	var r0 metadata.MD
+	if rf, ok := ret.Get(0).(func() metadata.MD); ok {
+		r0 = rf()
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(metadata.MD)
+		}
+	}
+
+	return r0
+}
diff --git a/mocks/GNMI_SubscribeServer.go b/mocks/GNMI_SubscribeServer.go
new file mode 100644
index 0000000000000000000000000000000000000000..e19a9379ffc57345b30141b757dbd5d57327a82a
--- /dev/null
+++ b/mocks/GNMI_SubscribeServer.go
@@ -0,0 +1,131 @@
+// Code generated by mockery v2.6.0. DO NOT EDIT.
+
+package mocks
+
+import (
+	context "context"
+
+	gnmi "github.com/openconfig/gnmi/proto/gnmi"
+	metadata "google.golang.org/grpc/metadata"
+
+	mock "github.com/stretchr/testify/mock"
+)
+
+// GNMI_SubscribeServer is an autogenerated mock type for the GNMI_SubscribeServer type
+type GNMI_SubscribeServer struct {
+	mock.Mock
+}
+
+// Context provides a mock function with given fields:
+func (_m *GNMI_SubscribeServer) Context() context.Context {
+	ret := _m.Called()
+
+	var r0 context.Context
+	if rf, ok := ret.Get(0).(func() context.Context); ok {
+		r0 = rf()
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(context.Context)
+		}
+	}
+
+	return r0
+}
+
+// Recv provides a mock function with given fields:
+func (_m *GNMI_SubscribeServer) Recv() (*gnmi.SubscribeRequest, error) {
+	ret := _m.Called()
+
+	var r0 *gnmi.SubscribeRequest
+	if rf, ok := ret.Get(0).(func() *gnmi.SubscribeRequest); ok {
+		r0 = rf()
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*gnmi.SubscribeRequest)
+		}
+	}
+
+	var r1 error
+	if rf, ok := ret.Get(1).(func() error); ok {
+		r1 = rf()
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// RecvMsg provides a mock function with given fields: m
+func (_m *GNMI_SubscribeServer) RecvMsg(m interface{}) error {
+	ret := _m.Called(m)
+
+	var r0 error
+	if rf, ok := ret.Get(0).(func(interface{}) error); ok {
+		r0 = rf(m)
+	} else {
+		r0 = ret.Error(0)
+	}
+
+	return r0
+}
+
+// Send provides a mock function with given fields: _a0
+func (_m *GNMI_SubscribeServer) Send(_a0 *gnmi.SubscribeResponse) error {
+	ret := _m.Called(_a0)
+
+	var r0 error
+	if rf, ok := ret.Get(0).(func(*gnmi.SubscribeResponse) error); ok {
+		r0 = rf(_a0)
+	} else {
+		r0 = ret.Error(0)
+	}
+
+	return r0
+}
+
+// SendHeader provides a mock function with given fields: _a0
+func (_m *GNMI_SubscribeServer) SendHeader(_a0 metadata.MD) error {
+	ret := _m.Called(_a0)
+
+	var r0 error
+	if rf, ok := ret.Get(0).(func(metadata.MD) error); ok {
+		r0 = rf(_a0)
+	} else {
+		r0 = ret.Error(0)
+	}
+
+	return r0
+}
+
+// SendMsg provides a mock function with given fields: m
+func (_m *GNMI_SubscribeServer) SendMsg(m interface{}) error {
+	ret := _m.Called(m)
+
+	var r0 error
+	if rf, ok := ret.Get(0).(func(interface{}) error); ok {
+		r0 = rf(m)
+	} else {
+		r0 = ret.Error(0)
+	}
+
+	return r0
+}
+
+// SetHeader provides a mock function with given fields: _a0
+func (_m *GNMI_SubscribeServer) SetHeader(_a0 metadata.MD) error {
+	ret := _m.Called(_a0)
+
+	var r0 error
+	if rf, ok := ret.Get(0).(func(metadata.MD) error); ok {
+		r0 = rf(_a0)
+	} else {
+		r0 = ret.Error(0)
+	}
+
+	return r0
+}
+
+// SetTrailer provides a mock function with given fields: _a0
+func (_m *GNMI_SubscribeServer) SetTrailer(_a0 metadata.MD) {
+	_m.Called(_a0)
+}
diff --git a/mocks/isSubscribeRequest_Request.go b/mocks/isSubscribeRequest_Request.go
new file mode 100644
index 0000000000000000000000000000000000000000..73f763981ed7bd4586787e88694c844885b2b843
--- /dev/null
+++ b/mocks/isSubscribeRequest_Request.go
@@ -0,0 +1,15 @@
+// Code generated by mockery v2.6.0. DO NOT EDIT.
+
+package mocks
+
+import mock "github.com/stretchr/testify/mock"
+
+// isSubscribeRequest_Request is an autogenerated mock type for the isSubscribeRequest_Request type
+type isSubscribeRequest_Request struct {
+	mock.Mock
+}
+
+// isSubscribeRequest_Request provides a mock function with given fields:
+func (_m *isSubscribeRequest_Request) isSubscribeRequest_Request() {
+	_m.Called()
+}
diff --git a/mocks/isSubscribeResponse_Response.go b/mocks/isSubscribeResponse_Response.go
new file mode 100644
index 0000000000000000000000000000000000000000..ba10966e2703113f5fc03233883022efb7843b4b
--- /dev/null
+++ b/mocks/isSubscribeResponse_Response.go
@@ -0,0 +1,15 @@
+// Code generated by mockery v2.6.0. DO NOT EDIT.
+
+package mocks
+
+import mock "github.com/stretchr/testify/mock"
+
+// isSubscribeResponse_Response is an autogenerated mock type for the isSubscribeResponse_Response type
+type isSubscribeResponse_Response struct {
+	mock.Mock
+}
+
+// isSubscribeResponse_Response provides a mock function with given fields:
+func (_m *isSubscribeResponse_Response) isSubscribeResponse_Response() {
+	_m.Called()
+}
diff --git a/mocks/isTypedValue_Value.go b/mocks/isTypedValue_Value.go
new file mode 100644
index 0000000000000000000000000000000000000000..a49fc787f9dbe7f24023258d180371a5bcd42c7b
--- /dev/null
+++ b/mocks/isTypedValue_Value.go
@@ -0,0 +1,15 @@
+// Code generated by mockery v2.6.0. DO NOT EDIT.
+
+package mocks
+
+import mock "github.com/stretchr/testify/mock"
+
+// isTypedValue_Value is an autogenerated mock type for the isTypedValue_Value type
+type isTypedValue_Value struct {
+	mock.Mock
+}
+
+// isTypedValue_Value provides a mock function with given fields:
+func (_m *isTypedValue_Value) isTypedValue_Value() {
+	_m.Called()
+}
diff --git a/nucleus/errors.go b/nucleus/errors.go
new file mode 100644
index 0000000000000000000000000000000000000000..32fdb47733ddc1e44cf8c458c8bf8c67133e94f3
--- /dev/null
+++ b/nucleus/errors.go
@@ -0,0 +1,11 @@
+package nucleus
+
+import "fmt"
+
+type ErrNilClient struct {
+
+}
+
+func (e *ErrNilClient)Error() string {
+	return fmt.Sprintf("client cannot be nil")
+}
\ No newline at end of file
diff --git a/nucleus/gnmi_transport.go b/nucleus/gnmi_transport.go
index 964c22d89ccced928bc7fef7c0e923e4fb255f4a..edb7662a032033a05fa1c8f7237689fb461f2e0a 100644
--- a/nucleus/gnmi_transport.go
+++ b/nucleus/gnmi_transport.go
@@ -2,6 +2,7 @@ package nucleus
 
 import (
 	"code.fbi.h-da.de/cocsn/gosdn/forks/goarista/gnmi"
+	"code.fbi.h-da.de/cocsn/gosdn/nucleus/util"
 	"context"
 	"errors"
 	gpb "github.com/openconfig/gnmi/proto/gnmi"
@@ -10,12 +11,33 @@ import (
 	"github.com/openconfig/ygot/ytypes"
 	log "github.com/sirupsen/logrus"
 	"strings"
+	"time"
 )
 
+func init() {
+	// tapProto taps get responses and requests to binary file
+	// CAUTION only set true if you know what you do
+	tapProto = true
+}
+
+func NewGnmiTransport(config *gnmi.Config) (*Gnmi, error) {
+	c, err := gnmi.Dial(config)
+	if err != nil {
+		return nil, err
+	}
+	return &Gnmi{
+		SetNode:  nil,
+		RespChan: nil,
+		config:   config,
+		client:   c,
+	}, nil
+}
+
 type Gnmi struct {
 	SetNode  func(schema *yang.Entry, root interface{}, path *gpb.Path, val interface{}, opts ...ytypes.SetNodeOpt) error
 	RespChan chan *gpb.SubscribeResponse
 	config   *gnmi.Config
+	client   gpb.GNMIClient
 }
 
 func (g *Gnmi) SetConfig(config *gnmi.Config) {
@@ -29,11 +51,23 @@ func (g *Gnmi) GetConfig() *gnmi.Config {
 // interface satisfaction for now
 // TODO: Convert to meaningfiul calls
 func (g *Gnmi) Get(ctx context.Context, params ...string) (interface{}, error) {
+	if g.client == nil {
+		return nil, &ErrNilClient{}
+	}
 	paths := gnmi.SplitPaths(params)
 	return g.get(ctx, paths, "")
 }
-func (g *Gnmi) Set(ctx context.Context, params ...string) (interface{}, error) { return nil, nil }
+func (g *Gnmi) Set(ctx context.Context, params ...string) (interface{}, error) {
+	if g.client == nil {
+		return nil, &ErrNilClient{}
+	}
+	return nil, nil
+}
+
 func (g *Gnmi) Subscribe(ctx context.Context, params ...string) error {
+	if g.client == nil {
+		return &ErrNilClient{}
+	}
 	return g.subscribe(ctx)
 }
 
@@ -65,7 +99,7 @@ func (g *Gnmi) ProcessResponse(resp interface{}, root interface{}, s *ytypes.Sch
 
 			schema := models["Device"]
 			if err := g.SetNode(schema, root, update.Path, update.Val, opts...); err != nil {
-				log.Error(err)
+				return err
 			}
 		}
 	}
@@ -102,11 +136,7 @@ func gnmiFullPath(prefix, path *gpb.Path) (*gpb.Path, error) {
 
 // Capabilities calls GNMI capabilities
 func (g *Gnmi) Capabilities(ctx context.Context) (interface{}, error) {
-	client, err := gnmi.Dial(g.config)
-	if err != nil {
-		return nil, err
-	}
-	resp, err := client.Capabilities(ctx, &gpb.CapabilityRequest{})
+	resp, err := g.client.Capabilities(ctx, &gpb.CapabilityRequest{})
 	if err != nil {
 		return nil, err
 	}
@@ -127,11 +157,15 @@ func (g *Gnmi) get(ctx context.Context, paths [][]string, origin string) (interf
 // getWithRequest takes a fully formed GetRequest, performs the Get,
 // and returns any response.
 func (g *Gnmi) getWithRequest(ctx context.Context, req *gpb.GetRequest) (interface{}, error) {
-	client, err := gnmi.Dial(g.config)
-	if err != nil {
-		return nil, err
+	resp, err := g.client.Get(ctx, req)
+	if tapProto {
+		if err := util.Write(req, "req-" + time.Now().String()); err != nil {
+			log.Errorf("error while writing request: %v", err)
+		}
+		if err := util.Write(resp, "resp-" + time.Now().String()); err != nil {
+			log.Errorf("error while writing request: %v", err)
+		}
 	}
-	resp, err := client.Get(ctx, req)
 	if err != nil {
 		return nil, err
 	}
@@ -142,20 +176,12 @@ func (g *Gnmi) getWithRequest(ctx context.Context, req *gpb.GetRequest) (interfa
 func (g *Gnmi) set(ctx context.Context, setOps []*gnmi.Operation,
 	exts ...*gnmi_ext.Extension) error {
 	ctx = gnmi.NewContext(ctx, g.config)
-	client, err := gnmi.Dial(g.config)
-	if err != nil {
-		return err
-	}
-	return gnmi.Set(ctx, client, setOps, exts...)
+	return gnmi.Set(ctx, g.client, setOps, exts...)
 }
 
 // Subscribe calls GNMI subscribe
 func (g *Gnmi) subscribe(ctx context.Context) error {
 	ctx = gnmi.NewContext(ctx, g.config)
-	client, err := gnmi.Dial(g.config)
-	if err != nil {
-		return err
-	}
 	opts := ctx.Value("opts").(*gnmi.SubscribeOptions)
 	go func() {
 		for {
@@ -165,7 +191,7 @@ func (g *Gnmi) subscribe(ctx context.Context) error {
 			}
 		}
 	}()
-	return gnmi.SubscribeErr(ctx, client, opts, g.RespChan)
+	return gnmi.SubscribeErr(ctx, g.client, opts, g.RespChan)
 }
 
 // Close calls GNMI close
diff --git a/nucleus/util/message_tools.go b/nucleus/util/message_tools.go
new file mode 100644
index 0000000000000000000000000000000000000000..c8633e5a323fab0518aa1dd7f7dbb37bfd357599
--- /dev/null
+++ b/nucleus/util/message_tools.go
@@ -0,0 +1,41 @@
+package util
+
+import (
+	"fmt"
+	"github.com/golang/protobuf/proto"
+	"io/ioutil"
+)
+
+/*
+Copycat source: https://dev.to/techschoolguru/go-generate-serialize-protobuf-message-4m7a
+ */
+
+// Write writes protocol buffer message to binary file
+func Write(message proto.Message, filename string) error {
+	data, err := proto.Marshal(message)
+	if err != nil {
+		return fmt.Errorf("cannot marshal proto message to binary: %w", err)
+	}
+
+	err = ioutil.WriteFile(filename, data, 0644)
+	if err != nil {
+		return fmt.Errorf("cannot write binary data to file: %w", err)
+	}
+
+	return nil
+}
+
+
+func Read(filename string, message proto.Message) error {
+	data, err := ioutil.ReadFile(filename)
+	if err != nil {
+		return fmt.Errorf("cannot read binary data from file: %w", err)
+	}
+
+	err = proto.Unmarshal(data, message)
+	if err != nil {
+		return fmt.Errorf("cannot unmarshal binary to proto message: %w", err)
+	}
+
+	return nil
+}
\ No newline at end of file