func (s *FailoverSerialConn) Read(b []byte) (int, error) {
	defer func() {
		s.lock.Lock()
		s.lastRead = time.Now()
		s.lock.Unlock()
	}()
	if s.isClient {
		return s.clientRead(b)
	}
	return s.serverRead(b)
}
Read reads the serial port.
package modbusone
import (
	"bytes"
	"errors"
	"strings"
	"sync"
	"time"
)
type FailoverSerialConn struct {
	SerialContext  
	PacketReader
	isClient   bool  
	isFailover bool  
	isActive   bool  
	lock       sync.Mutex
	requestTime time.Time  
	reqPacket   bytes.Buffer
	lastRead    time.Time
	PrimaryDisconnectDelay time.Duration
	PrimaryForceBackDelay time.Duration
	startTime             time.Time
	SecondaryDelay time.Duration
	MissDelay time.Duration
	MissesMax int32
	misses    int32
}
func NewFailoverConn(sc SerialContext, isFailover, isClient bool) *FailoverSerialConn {
	c := &FailoverSerialConn{
		SerialContext:          sc,
		isClient:               isClient,
		isFailover:             isFailover,
		PrimaryDisconnectDelay: 10 * time.Second,
		PrimaryForceBackDelay:  10 * time.Minute,
		SecondaryDelay:         time.Second / 10,
		MissDelay:              time.Second / 5,
		startTime:              time.Now(),
		MissesMax:              2,
	}
	if isFailover {
		c.MissesMax += 2
	}
	c.PacketReader = NewRTUBidirectionalPacketReader(c.SerialContext)
	return c
}
func (s *FailoverSerialConn) BytesDelay(n int) time.Duration {
	return s.SerialContext.BytesDelay(n)
}
func (s *FailoverSerialConn) serverRead(b []byte) (int, error) {
	locked := false
	defer func() {
		if locked {
			s.lock.Unlock()
		}
	}()
	for {
		if locked {
			s.lock.Unlock()
			locked = false
		}
		n, err := s.PacketReader.Read(b)
		if err != nil {
			return n, err  
		}
		s.lock.Lock()
		locked = true
		if !s.isFailover {
			if !s.isActive {
				if s.startTime.Add(s.PrimaryForceBackDelay).Before(time.Now()) {
					debugf("force active of primary/n")
					s.isActive = true
				}
			}
			if s.isActive {
				if s.lastRead.Add(s.PrimaryDisconnectDelay).Before(time.Now()) {
					debugf("primary was disconnected for too long/n")
					s.isActive = false
					s.startTime = time.Now()
				} else {
					return n, nil
				}
			}
		}
		rtu := RTU(b[:n])
		pdu, err := rtu.GetPDU()
		if err != nil {
			debugf("failover serverRead internal GetPDU error : %v", err)
			s.misses = 0
			debugf("reset misses\n")
			continue  
		}
		if rtu[0] == 0 {
			s.resetRequestTime()
			return n, nil
		}
		if s.isActive {
			if !s.isFailover {
				return 0, errors.New("assert isFailover")
			}
			if s.requestTime.IsZero() {
				s.setLastReqTime(pdu, time.Now())  
				return n, nil
			}
			s.isActive = false
			s.misses = 0
			s.resetRequestTime()
			debugf("primary found, going from active to passive\n")
			debugf("reset misses\n")
			continue  
		} else {
			now := time.Now()
			if s.requestTime.IsZero() {
				s.setLastReqTime(pdu, now)
				return n, nil
			}
			incMisses := func() {
				s.misses++
				debugf("%v misses\n", s.misses)
				if s.misses > s.MissesMax {
					s.isActive = true
				} else {
					s.setLastReqTime(pdu, now)
				}
			}
			if now.Sub(s.requestTime) > s.MissDelay+s.BytesDelay(n) {
				incMisses()
				return n, nil
			}
			if IsRequestReply(s.reqPacket.Bytes(), pdu) {
				s.resetRequestTime()
				debugf("ignore read of reply from the other server")
				s.misses = 0
				debugf("reset misses (server passive read)\n")
				continue
			}
			debugf("switch around request and reply pairs")
			s.setLastReqTime(pdu, now)
			incMisses()
			return n, nil
		}
	}
}
func (s *FailoverSerialConn) IsActive() bool {
	s.lock.Lock()
	a := s.isActive
	s.lock.Unlock()
	return a
}
func (s *FailoverSerialConn) describe() string {
	b := strings.Builder{}
	b.WriteString("FailoverSerialConn")
	if s.isClient {
		b.WriteString(" Client")
	} else {
		b.WriteString(" Server")
	}
	if s.isFailover {
		b.WriteString(" Failover")
	} else {
		b.WriteString(" Primary")
	}
	if s.isActive {
		b.WriteString(" Active")
	} else {
		b.WriteString(" Passive")
	}
	return b.String()
}
func (s *FailoverSerialConn) clientRead(b []byte) (int, error) {
	n, err := s.PacketReader.Read(b)
	if err != nil {
		return n, err
	}
	now := time.Now()
	rtu := RTU(b[:n])
	pdu, err := rtu.GetPDU()
	s.lock.Lock()
	defer func() {
		s.misses = 0
		debugf("reset misses (client read)\n")
		s.lock.Unlock()
	}()
	if err != nil {
		debugf("failover clientRead internal GetPDU error : %v", err)
		return n, err  
	}
	isReply := now.Sub(s.requestTime) < s.MissDelay+s.BytesDelay(n) && IsRequestReply(s.reqPacket.Bytes(), pdu)
	if !isReply {
		debugf("got request from other client")
		s.setLastReqTime(pdu, now)
		if s.isFailover && s.isActive {
			debugf("deactivates failover client")
			s.isActive = false
		}
		return n, nil  
	}
	s.resetRequestTime()
	return n, nil
}