From 7335d19846ad4f5b0a61541a992d61763c5cf35b Mon Sep 17 00:00:00 2001 From: zhangqian <zhangqian@123.com> Date: 星期五, 03 十一月 2023 17:17:44 +0800 Subject: [PATCH] 串口支持大数读写 --- service/plc.go | 2 pkg/plccom/plccom.go | 32 +++++++++- pkg/plccom/mitsubishi/protocol.go | 97 ++++++++++++++++++++++++++++++++ 3 files changed, 126 insertions(+), 5 deletions(-) diff --git a/pkg/plccom/mitsubishi/protocol.go b/pkg/plccom/mitsubishi/protocol.go index 3f7a12a..f6238bd 100644 --- a/pkg/plccom/mitsubishi/protocol.go +++ b/pkg/plccom/mitsubishi/protocol.go @@ -44,6 +44,28 @@ return proto } +// MakeReadProtocolBits 涓夎彵璇诲崗璁�, addr 鏄璇诲彇鐨勫瘎瀛樺櫒鍦板潃 +func (p *ProtocolMitsubishi) MakeReadProtocolBits(bits int, addr string) []byte { + // 02 琛ㄧず寮�濮� + 30 琛ㄧず璇绘暟鎹� + 4浣嶅湴鍧�浣� + 02 鏁版嵁闀垮害 + 03 鍋滄 + 鍋舵牎楠� + + pro := []byte{0x30} + pro = append(pro, []byte(addr)...) + if bits == 16 { + pro = append(pro, []byte("02")...) + } else if bits == 32 { + pro = append(pro, []byte("04")...) + } + pro = append(pro, []byte{0x03}...) + + crc := crc(pro) + + proto := []byte{0x02} + proto = append(proto, pro...) + proto = append(proto, []byte(crc)...) + + return proto +} + // MakeWriteProtocol 鍒涘缓鍐欏叆鏁版嵁鐨勫崗璁� func (p *ProtocolMitsubishi) MakeWriteProtocol(addr string, value int) []byte { valueStr := fmt.Sprintf("000%X", value) @@ -66,6 +88,46 @@ return proto } +func (p *ProtocolMitsubishi) MakeWriteProtocolBits(bits int, addr string, ival int) []byte { + + // 02 琛ㄧず寮�濮� + 31 琛ㄧず鍐欐暟鎹� + 4浣嶅湴鍧�浣� + 02 鏁版嵁闀垮害 + 03 鍋滄 + 鍋舵牎楠� + proto := []byte{0x31} + proto = append(proto, []byte(addr)...) + if bits == 16 { + proto = append(proto, []byte("02")...) + + vstr := fmt.Sprintf("000%X", ival) + val := vstr[len(vstr)-2:] + val += vstr[len(vstr)-4 : len(vstr)-2] + proto = append(proto, val...) + } else if bits == 32 { + proto = append(proto, []byte("04")...) + + vstr := fmt.Sprintf("0000000%X", ival) + // 浣�16浣� + low := vstr[len(vstr)-4:] + // 楂�16浣� + high := vstr[len(vstr)-8 : len(vstr)-4] + // 鍏堝瓨鍌ㄤ綆16浣� + val := low[2:] + val += low[0:2] + proto = append(proto, val...) + val = high[2:] + val += high[0:2] + proto = append(proto, val...) + } + + proto = append(proto, []byte{0x03}...) + + crc := crc(proto) + + pro := []byte{0x02} + pro = append(pro, proto...) + pro = append(pro, []byte(crc)...) + + return pro +} + // ParseReadValue 瑙f瀽浠庤澶囪鍙栫殑鍊� func (p *ProtocolMitsubishi) ParseReadValue(data []byte) int { if len(data) < 6 { @@ -82,6 +144,41 @@ return int(bint) } +func (p *ProtocolMitsubishi) ParseReadValueBits(data []byte) int { + if len(data) < 6 { + return -1 + } + + // 0x2 [xxxxxxxx] 0x3 crc1 crc2 + // 鍙栧嚭鏁版嵁 + + fmt.Printf("ParseReadValueBits %X\n", data) + + var num int64 + vhex := data[1 : len(data)-3] + for i := len(vhex); i > 0; i -= 4 { + tmp := vhex[i-4 : i] + v := tmp[2:] + v = append(v, tmp[0:2]...) + var bint int64 + + bint, _ = strconv.ParseInt(string(v), 16, 32) + if num == 0 { + num = 0x10000 * bint + } else { + num += bint + } + } + + // v := vhex[2:] + // v = append(v, vhex[0:2]...) + // vstr := string(v) + // var bint int64 + // bint, _ = strconv.ParseInt(vstr, 16, 32) + + return int(num) +} + // ParseWriteValue 瑙f瀽鍐欏叆璁惧鐨勭粨鏋� func (p *ProtocolMitsubishi) ParseWriteValue(data []byte) (v int, ok bool) { if len(data) == 0 { diff --git a/pkg/plccom/plccom.go b/pkg/plccom/plccom.go index eca7403..43e2b9b 100644 --- a/pkg/plccom/plccom.go +++ b/pkg/plccom/plccom.go @@ -19,11 +19,18 @@ // MakeReadProtocol 鍒涘缓璇诲彇鏁版嵁鐨勫崗璁� MakeReadProtocol(addr string) []byte + // MakeReadProtocolBits 鍒涘缓璇诲彇鏁版嵁鐨勫崗璁� + MakeReadProtocolBits(bits int, addr string) []byte + // MakeWriteProtocol 鍒涘缓鍐欏叆鏁版嵁鐨勫崗璁� MakeWriteProtocol(addr string, value int) []byte + MakeWriteProtocolBits(bits int, addr string, ival int) []byte + // ParseReadValue 瑙f瀽浠庤澶囪鍙栫殑鍊� ParseReadValue(data []byte) int + + ParseReadValueBits(data []byte) int // ParseWriteValue 瑙f瀽鍐欏叆璁惧鐨勭粨鏋滐紝骞惰繑鍥炵粨鏋滃拰鏄惁鎴愬姛 ParseWriteValue(data []byte) (int, bool) @@ -49,13 +56,19 @@ return protocol, nil } -func ReadPLC(deviceType, url, label string) (val int, err error) { +func ReadPLC(deviceType, url, label string, length int) (val int, err error) { protocol, err := LoadProtocol(deviceType) if err != nil { return 0, err } addr := protocol.ConvertLabelToAddress(label) - proto := protocol.MakeReadProtocol(addr) + var proto []byte + if length == 1 { + proto = protocol.MakeReadProtocol(addr) + } else { + proto = protocol.MakeReadProtocolBits(length*16, addr) + } + bp := base64.StdEncoding.EncodeToString(proto) fullUrl := fmt.Sprintf("%v?proto=%v", url, bp) resp, err := http.Get(fullUrl) @@ -69,7 +82,12 @@ logx.Errorf("ReadPLC base64.StdEncoding.DecodeString failed: %v, data: %v", err, string(body)) return 0, err } - val = protocol.ParseReadValue(data) + if length == 1 { + val = protocol.ParseReadValue(data) + } else { + val = protocol.ParseReadValueBits(data) + } + fmt.Println("read PLC:", val) return val, nil @@ -91,7 +109,13 @@ return err } addr := protocol.ConvertLabelToAddress(label) - proto := protocol.MakeWriteProtocol(addr, val) + var proto []byte + if val < 65536 { + proto = protocol.MakeWriteProtocol(addr, val) + } else { + proto = protocol.MakeWriteProtocolBits(32, addr, val) + } + bp := base64.StdEncoding.EncodeToString(proto) resp, err := http.Post(url, "text/plain", strings.NewReader(bp)) if err != nil { diff --git a/service/plc.go b/service/plc.go index 386c8d3..42ad54d 100644 --- a/service/plc.go +++ b/service/plc.go @@ -112,7 +112,7 @@ return nil, errors.New("conf.Conf.Services.Serial config not set yet") } label := fmt.Sprintf("D%d", address) - return plccom.ReadPLC(plccom.DeviceTypeMitsubishi, ipAddr, label) + return plccom.ReadPLC(plccom.DeviceTypeMitsubishi, ipAddr, label, dataLength) } return } -- Gitblit v1.8.0