6 Commits

2 changed files with 42 additions and 27 deletions

View File

@@ -465,7 +465,8 @@ func (rt *rtuTransport) readRTUFrameWithRes() (res *pdu, err error) {
// 标准modbus响应已读取完成现在读取自定义数据
// 设置5秒超时来读取自定义数据
customDataTimeout := 5 * time.Second
err = rt.link.SetDeadline(time.Now().Add(customDataTimeout))
deadline := time.Now().Add(customDataTimeout)
err = rt.link.SetDeadline(deadline)
if err != nil {
return
}
@@ -477,6 +478,16 @@ func (rt *rtuTransport) readRTUFrameWithRes() (res *pdu, err error) {
var lastErr error // 记录最后一次非超时错误
for {
// 检查是否已经超时
if time.Now().After(deadline) {
// 超时时间到,退出循环
// 如果有之前记录的错误使用它否则err保持为nil超时是正常的
if lastErr != nil {
err = lastErr
}
break
}
// 检查缓冲区是否还有空间
if startPos+totalRead+len(tempBuf) > len(rxbuf) {
// 如果缓冲区不够,扩展它
@@ -497,7 +508,7 @@ func (rt *rtuTransport) readRTUFrameWithRes() (res *pdu, err error) {
if readErr != nil {
if os.IsTimeout(readErr) {
// 超时时间到,退出循环
// 如果有之前记录的错误,使用它;否则使用超时错误
// 如果有之前记录的错误,使用它;否则err保持为nil超时是正常的
if lastErr != nil {
err = lastErr
}

View File

@@ -1,6 +1,6 @@
package modbus
import (
import (
"time"
"github.com/goburrow/serial"
@@ -10,43 +10,46 @@ import (
// 1) satisfy the rtuLink interface and
// 2) add Read() deadline/timeout support.
type serialPortWrapper struct {
conf *serialPortConfig
port serial.Port
deadline time.Time
conf *serialPortConfig
port serial.Port
deadline time.Time
}
type serialPortConfig struct {
Device string
Speed uint
DataBits uint
Parity uint
StopBits uint
Device string
Speed uint
DataBits uint
Parity uint
StopBits uint
}
func newSerialPortWrapper(conf *serialPortConfig) (spw *serialPortWrapper) {
spw = &serialPortWrapper{
conf: conf,
conf: conf,
}
return
}
func (spw *serialPortWrapper) Open() (err error) {
var parity string
var parity string
switch spw.conf.Parity {
case PARITY_NONE: parity = "N"
case PARITY_EVEN: parity = "E"
case PARITY_ODD: parity = "O"
case PARITY_NONE:
parity = "N"
case PARITY_EVEN:
parity = "E"
case PARITY_ODD:
parity = "O"
}
spw.port, err = serial.Open(&serial.Config{
Address: spw.conf.Device,
BaudRate: int(spw.conf.Speed),
DataBits: int(spw.conf.DataBits),
Parity: parity,
StopBits: int(spw.conf.StopBits),
Timeout: 10 * time.Millisecond,
Address: spw.conf.Device,
BaudRate: int(spw.conf.Speed),
DataBits: int(spw.conf.DataBits),
Parity: parity,
StopBits: int(spw.conf.StopBits),
Timeout: 100 * time.Millisecond,
})
return
@@ -64,11 +67,12 @@ func (spw *serialPortWrapper) Close() (err error) {
// attempting to read from the serial port.
// If Read() is called before the deadline, a read attempt to the serial port
// is made. At this point, one of two things can happen:
// - the serial port's receive buffer has one or more bytes and port.Read()
// returns immediately (partial or full read),
// - the serial port's receive buffer is empty: port.Read() blocks for
// up to 10ms and returns serial.ErrTimeout. The serial timeout error is
// masked and Read() returns with no data.
// - the serial port's receive buffer has one or more bytes and port.Read()
// returns immediately (partial or full read),
// - the serial port's receive buffer is empty: port.Read() blocks for
// up to 10ms and returns serial.ErrTimeout. The serial timeout error is
// masked and Read() returns with no data.
//
// As the higher-level methods use io.ReadFull(), Read() will be called
// as many times as necessary until either enough bytes have been read or an
// error is returned (ErrRequestTimedOut or any other i/o error).