Files
bj_power/bj_power_mes/internal/camera/client.go
T

155 lines
2.9 KiB
Go

package camera
import (
"bufio"
"bytes"
"context"
"fmt"
"net"
"sync"
"time"
"github.com/zeromicro/go-zero/core/logx"
)
// 命令常量
const (
CmdTakePhoto = "T1"
CmdGetDetectionResult = "GM,2,0"
)
type Client struct {
addr string
conn net.Conn
timeout time.Duration
mu sync.Mutex
}
func NewClient(addr string, timeout ...time.Duration) *Client {
t := 1 * time.Second
if len(timeout) > 0 {
t = timeout[0]
}
return &Client{
addr: addr,
timeout: t,
}
}
func (c *Client) Connect() error {
logx.Infof("正在连接相机: %s", c.addr)
conn, err := net.DialTimeout("tcp", c.addr, c.timeout)
if err != nil {
logx.Errorf("相机连接失败: %v", err)
return fmt.Errorf("相机连接失败: %w", err)
}
c.conn = conn
logx.Infof("相机连接成功: %s", c.addr)
return nil
}
func (c *Client) ConnectWithRetry(maxRetries int, retryInterval time.Duration) error {
var err error
for i := 0; i < maxRetries; i++ {
err = c.Connect()
if err == nil {
return nil
}
logx.Errorf("连接失败,%v后重试...", retryInterval)
time.Sleep(retryInterval)
}
return fmt.Errorf("连接相机失败: %w", err)
}
func (c *Client) IsConnected() bool {
return c.conn != nil
}
func (c *Client) Reconnect() error {
c.Close()
return c.Connect()
}
func (c *Client) SendCommand(cmd string) ([]byte, error) {
c.mu.Lock()
defer c.mu.Unlock()
if c.conn == nil {
return nil, fmt.Errorf("未建立连接")
}
logx.Infof("发送相机指令: %s", cmd)
_, err := c.conn.Write([]byte(cmd + "\r"))
if err != nil {
logx.Errorf("发送指令失败: %v", err)
return nil, fmt.Errorf("发送指令失败: %w", err)
}
resp, err := c.readResponse()
if err != nil {
return nil, err
}
logx.Infof("收到相机响应: %s", string(resp))
return resp, nil
}
func (c *Client) readResponse() ([]byte, error) {
reader := bufio.NewReader(c.conn)
var buffer bytes.Buffer
if err := c.conn.SetReadDeadline(time.Now().Add(c.timeout)); err != nil {
return nil, err
}
for {
b, err := reader.ReadByte()
if err != nil {
return nil, err
}
buffer.WriteByte(b)
if b == '\r' || b == '\n' {
break
}
}
return buffer.Bytes(), nil
}
func (c *Client) SendCommandWithContext(ctx context.Context, cmd string) ([]byte, error) {
type result struct {
resp []byte
err error
}
ch := make(chan result, 1)
go func() {
resp, err := c.SendCommand(cmd)
ch <- result{resp, err}
}()
select {
case <-ctx.Done():
return nil, ctx.Err()
case res := <-ch:
return res.resp, res.err
}
}
func (c *Client) TakePhoto() error {
_, err := c.SendCommand(CmdTakePhoto)
return err
}
func (c *Client) GetDetectionResult() (string, error) {
resp, err := c.SendCommand(CmdGetDetectionResult)
if err != nil {
return "", err
}
return string(resp), nil
}
func (c *Client) Close() {
if c.conn != nil {
c.conn.Close()
c.conn = nil
logx.Infof("相机连接已关闭")
}
}