package main import ( "bytes" "errors" "fmt" "log/slog" "net" "strings" "sync" "time" "unicode" "golang.org/x/text/encoding/japanese" ) const ( STX = 0x02 ETX = 0x03 ACK = 0x06 NAK = 0x15 ) type Client struct { host string conn net.Conn mtx sync.Mutex } func NewClient(host string) *Client { return &Client{ host: host, } } func main() { c := NewClient("192.168.2.33:1024") err := c.SetText(1, "123456789A") if err != nil { slog.Error(err.Error()) return } slog.Info("OK") resp, err := c.GetText(1) if err != nil { slog.Error(err.Error()) return } //0:1:A2001000010:023312332233323342335233623372338: //0:1:A2001000010:282508251825282538254825582568257: slog.Info(resp) } func (c *Client) sendCommand(cmd string) (string, error) { c.mtx.Lock() defer c.mtx.Unlock() conn, err := net.DialTimeout("tcp", c.host, 3*time.Second) if err != nil { return "", fmt.Errorf("喷码机连接失败: %w", err) } defer conn.Close() // 构造完整指令: STX + CMD + parameters + ETX var buffer bytes.Buffer buffer.WriteByte(STX) buffer.WriteString(cmd) buffer.WriteByte(ETX) // 计算校验和 checksum := calcChecksum(buffer.Bytes()[1:]) // 排除STX的data部分 // 添加校验和到buffer buffer.WriteString(fmt.Sprintf("%02X", checksum)) message := buffer.Bytes() // 发送指令 _, err = conn.Write(message) if err != nil { return "", fmt.Errorf("喷码机发送指令失败: %w", err) } // 接收响应 resp, err := readResponse(conn) if err != nil { return "", fmt.Errorf("喷码机接收响应失败: %w", err) } // 解析响应 return parseResponse(resp) } func readResponse(conn net.Conn) ([]byte, error) { _ = conn.SetReadDeadline(time.Now().Add(5 * time.Second)) buffer := make([]byte, 256) n, err := conn.Read(buffer) if err != nil { return nil, err } return buffer[:n], nil } func parseResponse(resp []byte) (body string, err error) { if len(resp) == 0 { return "", errors.New("empty response") } switch resp[0] { case ACK: // 处理带数据的响应(例如查询命令的响应) if len(resp) > 3 && resp[1] == STX && resp[len(resp)-1] == ETX { // 返回有效数据(示例处理) return string(resp[2 : len(resp)-1]), nil } return "", nil case NAK: if len(resp) >= 7 && resp[1] == STX && resp[len(resp)-1] == ETX { errorCode := string(resp[2:6]) msg, exists := errorCodeMap[errorCode] if !exists { msg = "Unknown error" } return "", fmt.Errorf("NAK error %s: %s", errorCode, msg) } return "", errors.New("NAK received without error details") } return } func calcChecksum(data []byte) byte { var sum byte for _, b := range data { sum += b } return sum } func (c *Client) SetText(model int, text string) error { //0:JIS、1:ASCII、2:SHIFT JIS、 //3:ASCII+SHIFT JIS、4:UNICODE、6:GB、 //7:ASCII+GB、8:KS、9:ASCII+KS、 //A:BIG5、B:ASCII+BIG5 bb, err := japanese.ShiftJIS.NewEncoder().Bytes([]byte(text)) if err != nil { return fmt.Errorf("编码失败: %w", err) } //纵点数 (1位) //1:5点、 2:7点、 3:9点、 //4:10点、 5:12点、 6:16点、 //7:20点、 8:22点、 9:24点、 //A:26点、 E:11点、 F:15点 //字体尺寸 (1位) //2:24x24、 3:24x18、 4:16x16、 5:16x12、 //6:12x10、 7:10x8、 8:9x9、 9:9x7、 //A:7x8、 B:7x5、 C:5x5、 D:5xN、 //E:7xN //字体底部位置 (2位) // 00~25:配置于最下行开始0~25点 //倍角 (1位) // 1~8:1~8倍 //文字方向 (1位) // 0:↑、 1:←、 2:→、 3:↓、 4:镜面 //文字间点 (1位) // 00~31:0~31点 //最终文字的文字间 (1位) // 0:无效、 1:有效 //文字间点的倍角处理 (1位) // 0:无效、 1:有效 //黑白反转 (1位) // 0:无效、 1:有效 cmd := fmt.Sprintf("STM:0:%d:A2001000010:3%s:", model, bb) _, err = c.sendCommand(cmd) if err != nil { return err } return nil } // 0:JIS、2:shift JIS、3:ASCII+shift JIS、 // 4:UNICODE、6:GB、7:ASCII+GB、8:KS、 // 9:ASCII+KS、A:BIG5、B:ASCII+BIG5 func (c *Client) GetText(model int) (text string, err error) { conn, err := net.DialTimeout("tcp", "192.168.2.33:1024", 5*time.Second) if err != nil { panic(err) } defer conn.Close() cmd := fmt.Sprintf("GTM:0:%d:%d:", model, 3) response, err := c.sendCommand(cmd) if err != nil { return } fields := strings.Split(response, ":") content := fields[3] //coding, _ := strconv.Atoi(string([]rune(content)[0])) //var re string //switch coding { //case 0, 3: //case 1: // re = content[1:] //case 2: // re, err = japanese.ShiftJIS.NewDecoder().String(content[1:]) //case 4: // bb, _ := hex.DecodeString(content[1:]) // re, err = unicodex.UTF16(unicodex.LittleEndian, unicodex.IgnoreBOM).NewDecoder().String(string(bb)) //} re, err := japanese.ShiftJIS.NewDecoder().String(content[1:]) if err != nil { return "", fmt.Errorf("解码失败: %w", err) } re = strings.ToLowerSpecial(numConv, re) return re, nil } var numConv = unicode.SpecialCase{ { Lo: 0x3002, // Lo 全角句号 Hi: 0x3002, // Hi 全角句号 Delta: [unicode.MaxCase]rune{ 0, // UpperCase 0x002e - 0x3002, // LowerCase 转成半角句号 0, // TitleCase }, }, { Lo: 0xff01, // Lo: 全角! Hi: 0xFF19, // Hi:到全角 9 Delta: [unicode.MaxCase]rune{ 0, // UpperCase 0x0021 - 0xff01, // LowerCase 转成半角 0, // TitleCase }, }, }