com.go

package main

import (
	"encoding/hex"
	"errors"
	"io"
	"strings"
	"time"

	"github.com/jacobsa/go-serial/serial"
	log "github.com/sirupsen/logrus"
)

/*
定义串口客户端
*/

type SerialClient struct {
	readWriter io.ReadWriteCloser
	OutBuffer  chan string
	PortName   string
	baudRate   uint
}

func NewSerialClient(portName string, baudRate uint) (*SerialClient, error) {
	c := &SerialClient{
		readWriter: nil,
		OutBuffer:  make(chan string, 1024),
		PortName:   portName,
		baudRate:   baudRate,
	}

	r, err := c.open(portName, baudRate)
	if err != nil {
		return nil, err
	}
	c.readWriter = r
	return c, nil
}

func (c *SerialClient) Start() {
	for {
		buf := make([]byte, 1024)
		n, err := c.readWriter.Read(buf)
		if err != nil {
			if err != io.EOF {
				//尝试重新打开
				r, err := c.open(c.PortName, c.baudRate)
				if err != nil {
					time.Sleep(2 * time.Second)
					continue
				}
				c.readWriter = r
			}
			continue
		}

		buf = buf[:n]
		res := hex.EncodeToString(buf)
		if strings.TrimSpace(res) == "" {
			continue
		}
		log.Info("Rx: ", res)
		c.OutBuffer <- res
	}
}

func (c *SerialClient) open(portName string, baudRate uint) (io.ReadWriteCloser, error) {
	options := serial.OpenOptions{
		PortName:        portName,
		BaudRate:        baudRate,
		DataBits:        8,
		StopBits:        1,
		MinimumReadSize: 4,
	}
	r, err := serial.Open(options)
	if err != nil {
		return nil, err
	}
	c.readWriter = r
	return r, err
}

func (c *SerialClient) SendMsg(data string) (int, error) {
	var (
		err error
	)
	if c.readWriter == nil {
		return 0, errors.New("serial port is closed")
	}

	bytes, err := hex.DecodeString(data)
	if err != nil {
		return 0, err
	}

	return c.readWriter.Write(bytes)
}

main.go

package main

import (
	"time"

	"github.com/gogf/gf/frame/g"
)

func main() {
	// 打开端口
	c, err := NewSerialClient("COM4", 1500000)
	if err != nil {
		g.Log().Errorf("打开端口失败, %v", err)
		return
	}

	// 启动
	go c.Start()

	// 发送消息
	c.SendMsg(utils.TrimHexStr("55 00 0A 00 00 00 00 00 42 00 00 E2 03"))

	go func() {
		tick := time.NewTicker(2 * time.Second)
		for {
			select {
			case <-tick.C:
				data := "55 00 0E 00 00 00 00 00 7A 00 04 00 00 00 00 DA 03"
				c.SendMsg(utils.TrimHexStr(data))
			}
		}
	}()

	for {
		select {
		case res := <-c.OutBuffer:
			g.Log().Infof("接收: %v", res)
		default:

		}
	}
}