Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 18 additions & 9 deletions ascii_over_tcp_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,25 +8,34 @@ import (
"time"
)

// ASCIIOverTCPClient creates ASCII over TCP client with default handler and given connect string.
func ASCIIOverTCPClient(address string) Client {
handler := NewASCIIOverTCPClientHandler(address)
return NewClient(handler)
}

// ASCIIOverTCPClientHandler implements Packager and Transporter interface.
type ASCIIOverTCPClientHandler struct {
asciiPackager
asciiTCPTransporter
*asciiTCPTransporter
}

// NewASCIIOverTCPClientHandler allocates and initializes a ASCIIOverTCPClientHandler.
func NewASCIIOverTCPClientHandler(address string) *ASCIIOverTCPClientHandler {
handler := &ASCIIOverTCPClientHandler{}
handler.Address = address
handler.Timeout = tcpTimeout
handler.IdleTimeout = tcpIdleTimeout
handler := &ASCIIOverTCPClientHandler{
asciiTCPTransporter: &asciiTCPTransporter{
defaultTCPTransporter(address),
},
}
return handler
}

// ASCIIOverTCPClient creates ASCII over TCP client with default handler and given connect string.
func ASCIIOverTCPClient(address string) Client {
handler := NewASCIIOverTCPClientHandler(address)
return NewClient(handler)
// Clone creates a new client handler with the same underlying shared transport.
func (mb *ASCIIOverTCPClientHandler) Clone() *ASCIIOverTCPClientHandler {
h := &ASCIIOverTCPClientHandler{
asciiTCPTransporter: mb.asciiTCPTransporter,
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since tcpTransporter doesnt only contain native values, do we need to add a Clone() method for that too?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure I understand the question (native values?). The purpose of this PR is to share the transporter. The private asciiTCPTransporter etc transporter fields have been converter to pointers to allow this. I didn't see a case for cloning a transporter.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@frzifus does that answer the question? Or is there anything specific to the tcpTransporter that I'm missing?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In other words: the tcpTransporter is a pointer now that gets copied.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TCP is actually a special case that required adjustments to the packager too, see evcc-io#6

}
return h
}

// asciiTCPTransporter implements Transporter interface.
Expand Down
27 changes: 18 additions & 9 deletions asciiclient.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,26 +22,35 @@ const (
// Modbus ASCII defines ':' but in the field often '>' is seen.
var asciiStart = []string{":", ">"}

// ASCIIClient creates ASCII client with default handler and given connect string.
func ASCIIClient(address string) Client {
handler := NewASCIIClientHandler(address)
return NewClient(handler)
}

// ASCIIClientHandler implements Packager and Transporter interface.
type ASCIIClientHandler struct {
asciiPackager
asciiSerialTransporter
*asciiSerialTransporter
}

// NewASCIIClientHandler allocates and initializes a ASCIIClientHandler.
func NewASCIIClientHandler(address string) *ASCIIClientHandler {
handler := &ASCIIClientHandler{}
handler.Address = address
handler.Timeout = serialTimeout
handler.IdleTimeout = serialIdleTimeout
handler := &ASCIIClientHandler{
asciiSerialTransporter: &asciiSerialTransporter{
serialPort: defaultSerialPort(address),
},
}
handler.serialPort.Logger = handler // expose the logger
return handler
}

// ASCIIClient creates ASCII client with default handler and given connect string.
func ASCIIClient(address string) Client {
handler := NewASCIIClientHandler(address)
return NewClient(handler)
// Clone creates a new client handler with the same underlying shared transport.
func (mb *ASCIIClientHandler) Clone() *ASCIIClientHandler {
h := &ASCIIClientHandler{
asciiSerialTransporter: mb.asciiSerialTransporter,
}
return h
}

// asciiPackager implements Packager interface.
Expand Down
28 changes: 19 additions & 9 deletions rtu_over_tcp_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,25 +9,35 @@ import (
"time"
)

// RTUOverTCPClient creates RTU over TCP client with default handler and given connect string.
func RTUOverTCPClient(address string) Client {
handler := NewRTUOverTCPClientHandler(address)
return NewClient(handler)
}

// RTUOverTCPClientHandler implements Packager and Transporter interface.
type RTUOverTCPClientHandler struct {
rtuPackager
rtuTCPTransporter
*rtuTCPTransporter
}

// NewRTUOverTCPClientHandler allocates and initializes a RTUOverTCPClientHandler.
func NewRTUOverTCPClientHandler(address string) *RTUOverTCPClientHandler {
handler := &RTUOverTCPClientHandler{}
handler.Address = address
handler.Timeout = tcpTimeout
handler.IdleTimeout = tcpIdleTimeout
handler := &RTUOverTCPClientHandler{
rtuTCPTransporter: &rtuTCPTransporter{
defaultTCPTransporter(address),
},
}

return handler
}

// RTUOverTCPClient creates RTU over TCP client with default handler and given connect string.
func RTUOverTCPClient(address string) Client {
handler := NewRTUOverTCPClientHandler(address)
return NewClient(handler)
// Clone creates a new client handler with the same underlying shared transport.
func (mb *RTUOverTCPClientHandler) Clone() *RTUOverTCPClientHandler {
h := &RTUOverTCPClientHandler{
rtuTCPTransporter: mb.rtuTCPTransporter,
}
return h
}

// rtuTCPTransporter implements Transporter interface.
Expand Down
28 changes: 19 additions & 9 deletions rtuclient.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,26 +42,36 @@ const (
readFifoQueueFunctionCode = 0x18
)

// RTUClient creates RTU client with default handler and given connect string.
func RTUClient(address string) Client {
handler := NewRTUClientHandler(address)
return NewClient(handler)
}

// RTUClientHandler implements Packager and Transporter interface.
type RTUClientHandler struct {
rtuPackager
rtuSerialTransporter
*rtuSerialTransporter
}

// NewRTUClientHandler allocates and initializes a RTUClientHandler.
func NewRTUClientHandler(address string) *RTUClientHandler {
handler := &RTUClientHandler{}
handler.Address = address
handler.Timeout = serialTimeout
handler.IdleTimeout = serialIdleTimeout
handler := &RTUClientHandler{
rtuSerialTransporter: &rtuSerialTransporter{
serialPort: defaultSerialPort(address),
},
}

handler.serialPort.Logger = handler // expose the logger
return handler
}

// RTUClient creates RTU client with default handler and given connect string.
func RTUClient(address string) Client {
handler := NewRTUClientHandler(address)
return NewClient(handler)
// Clone creates a new client handler with the same underlying shared transport.
func (mb *RTUClientHandler) Clone() *RTUClientHandler {
h := &RTUClientHandler{
rtuSerialTransporter: mb.rtuSerialTransporter,
}
return h
}

// rtuPackager implements Packager interface.
Expand Down
11 changes: 11 additions & 0 deletions serial.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,17 @@ type serialPort struct {
closeTimer *time.Timer
}

// defaultSerialPort creates a serialPort with default configuration.
func defaultSerialPort(address string) serialPort {
return serialPort{
Config: serial.Config{
Address: address,
Timeout: serialTimeout,
},
IdleTimeout: serialIdleTimeout,
}
}

func (mb *serialPort) Connect() (err error) {
mb.mu.Lock()
defer mb.mu.Unlock()
Expand Down
35 changes: 26 additions & 9 deletions tcpclient.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,25 +33,33 @@ func (length ErrTCPHeaderLength) Error() string {
length, tcpMaxLength-tcpHeaderSize+1)
}

// TCPClient creates TCP client with default handler and given connect string.
func TCPClient(address string) Client {
handler := NewTCPClientHandler(address)
return NewClient(handler)
}

// TCPClientHandler implements Packager and Transporter interface.
type TCPClientHandler struct {
tcpPackager
tcpTransporter
*tcpTransporter
}

// NewTCPClientHandler allocates a new TCPClientHandler.
func NewTCPClientHandler(address string) *TCPClientHandler {
h := &TCPClientHandler{}
h.Address = address
h.Timeout = tcpTimeout
h.IdleTimeout = tcpIdleTimeout
transport := defaultTCPTransporter(address)
h := &TCPClientHandler{
tcpTransporter: &transport,
}
return h
}

// TCPClient creates TCP client with default handler and given connect string.
func TCPClient(address string) Client {
handler := NewTCPClientHandler(address)
return NewClient(handler)
// Clone creates a new client handler with the same underlying shared transport.
func (mb *TCPClientHandler) Clone() *TCPClientHandler {
h := &TCPClientHandler{
tcpTransporter: mb.tcpTransporter,
}
return h
}

// tcpPackager implements Packager interface.
Expand Down Expand Up @@ -148,6 +156,15 @@ type tcpTransporter struct {
lastSuccessfulTransactionID uint16
}

// defaultTCPTransporter creates a new tcpTransporter with default values.
func defaultTCPTransporter(address string) tcpTransporter {
return tcpTransporter{
Address: address,
Timeout: tcpTimeout,
IdleTimeout: tcpIdleTimeout,
}
}

// helper value to signify what to do in Send
type readResult int

Expand Down