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