| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102 |
- // Copyright 2014 Quoc-Viet Nguyen. All rights reserved.
- // This software may be modified and distributed under the terms
- // of the BSD license. See the LICENSE file for details.
- package modbus
- import (
- "io"
- "log"
- "sync"
- "time"
- "github.com/goburrow/serial"
- )
- const (
- // Default timeout
- serialTimeout = 5 * time.Second
- serialIdleTimeout = 60 * time.Second
- )
- // serialPort has configuration and I/O controller.
- type serialPort struct {
- // Serial port configuration.
- serial.Config
- Logger *log.Logger
- IdleTimeout time.Duration
- mu sync.Mutex
- // port is platform-dependent data structure for serial port.
- port io.ReadWriteCloser
- lastActivity time.Time
- closeTimer *time.Timer
- }
- func (mb *serialPort) Connect() (err error) {
- mb.mu.Lock()
- defer mb.mu.Unlock()
- return mb.connect()
- }
- // connect connects to the serial port if it is not connected. Caller must hold the mutex.
- func (mb *serialPort) connect() error {
- if mb.port == nil {
- port, err := serial.Open(&mb.Config)
- if err != nil {
- return err
- }
- mb.port = port
- }
- return nil
- }
- func (mb *serialPort) Close() (err error) {
- mb.mu.Lock()
- defer mb.mu.Unlock()
- return mb.close()
- }
- // close closes the serial port if it is connected. Caller must hold the mutex.
- func (mb *serialPort) close() (err error) {
- if mb.port != nil {
- err = mb.port.Close()
- mb.port = nil
- }
- return
- }
- func (mb *serialPort) logf(format string, v ...interface{}) {
- if mb.Logger != nil {
- mb.Logger.Printf(format, v...)
- }
- }
- func (mb *serialPort) startCloseTimer() {
- if mb.IdleTimeout <= 0 {
- return
- }
- if mb.closeTimer == nil {
- mb.closeTimer = time.AfterFunc(mb.IdleTimeout, mb.closeIdle)
- } else {
- mb.closeTimer.Reset(mb.IdleTimeout)
- }
- }
- // closeIdle closes the connection if last activity is passed behind IdleTimeout.
- func (mb *serialPort) closeIdle() {
- mb.mu.Lock()
- defer mb.mu.Unlock()
- if mb.IdleTimeout <= 0 {
- return
- }
- idle := time.Now().Sub(mb.lastActivity)
- if idle >= mb.IdleTimeout {
- mb.logf("modbus: closing connection due to idle timeout: %v", idle)
- mb.close()
- }
- }
|