zhangqian
2023-10-26 2df84cdc7faf29cc8a2512b627a36a3881276b9f
plc4x读写加入长度
2个文件已修改
487 ■■■■ 已修改文件
pkg/plc/apacheplc4x/modbus.go 20 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pkg/plc/com.go 467 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pkg/plc/apacheplc4x/modbus.go
@@ -10,6 +10,7 @@
    "github.com/apache/plc4x/plc4go/pkg/api/drivers"
    apiModel "github.com/apache/plc4x/plc4go/pkg/api/model"
    "github.com/apache/plc4x/plc4go/pkg/api/transports"
    "github.com/spf13/cast"
    "sync/atomic"
    "time"
)
@@ -53,7 +54,7 @@
func readHoldingRegisterSingle(connection plc4go.PlcConnection, address int) ([]byte, error) {
    tag := fmt.Sprintf("tag:%v", address)
    tagAddress := getTagAddress(address)
    tagAddress := getTagAddress(address, 1)
    // 读模式
    readRequest, err := connection.ReadRequestBuilder().AddTagAddress(tag, tagAddress).Build()
@@ -83,7 +84,7 @@
func readHoldingRegisterList(connection plc4go.PlcConnection, address, length int) ([]byte, error) {
    tag := fmt.Sprintf("tag:%v:%v", address, length)
    tagAddress := getTagAddress(address)
    tagAddress := getTagAddress(address, length)
    // 读模式
    readRequest, err := connection.ReadRequestBuilder().AddTagAddress(tag, tagAddress).Build()
@@ -130,12 +131,16 @@
    return readHoldingRegisterSingle(connection, address)
}
func getTagAddress(address int) string {
func getTagAddress(address int, length int) string {
    intType := conf.Conf.PLC.ModbusIntType
    if intType == "" {
        intType = "DINT"
    }
    return fmt.Sprintf("holding-register:%d:%v", address, intType)
    if length == 1 {
        return fmt.Sprintf("holding-register:%d:%v", address, intType)
    } else {
        return fmt.Sprintf("holding-register:%d:%v[%d]", address, intType, length)
    }
}
func WriteHoldingRegister(ipAddr string, address int, value any) (string, error) {
@@ -146,7 +151,12 @@
    }
    defer connection.Close()
    tag := fmt.Sprintf("tag:%v:w", address)
    tagAddress := getTagAddress(address)
    var tagAddress string
    if cast.ToInt32(value) > 2<<16 {
        tagAddress = getTagAddress(address, 2)
    } else {
        tagAddress = getTagAddress(address, 1)
    }
    // 写模式
    writeRequest, err := connection.WriteRequestBuilder().AddTagAddress(tag, tagAddress, value).Build()
pkg/plc/com.go
@@ -1,235 +1,236 @@
package plc
import (
    "encoding/hex"
    "errors"
    "fmt"
    "io"
    "strings"
    "time"
    "github.com/jacobsa/go-serial/serial"
)
/*
定义串口客户端
*/
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
        }
        fmt.Printf("Rx: %s\n", res)
        c.OutBuffer <- res
    }
}
func (c *SerialClient) open(portName string, baudRate uint) (io.ReadWriteCloser, error) {
    options := serial.OpenOptions{
        PortName:        portName,
        BaudRate:        baudRate,
        DataBits:        7,
        StopBits:        1,
        MinimumReadSize: 4,
        ParityMode:      serial.PARITY_EVEN,
    }
    r, err := serial.Open(options)
    if err != nil {
        return nil, err
    }
    c.readWriter = r
    return r, err
}
func (c *SerialClient) Close() {
    if c.readWriter != nil {
        c.readWriter.Close()
    }
}
func (c *SerialClient) SendMsg(data string) (int, 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)
}
func (c *SerialClient) ReadHoldRegister(addr string) (int, error) {
    if c.readWriter == nil {
        return 0, errors.New("serial port is closed")
    }
    // 三菱fn系列串口协议
    // 02 表示开始 + 30 表示读数据 + 4位地址位 + 02 数据长度 + 03 停止 + 偶校验
    // 先组装数据
    // 读取的地址
    dataBytes := append([]byte{0x30}, []byte(addr)...)
    // 读取的长度
    dataBytes = append(dataBytes, []byte("02")...)
    // 停止
    dataBytes = append(dataBytes, []byte{0x03}...)
    // 计算校验码, 30 + 地址编码 + 数据长度 + 03 , 十六进制结果取后两位.
    var sum uint8
    for _, d := range dataBytes {
        sum += d
    }
    sumStr := fmt.Sprintf("%x", sum)
    fmt.Printf("sumStr: %s\n", sumStr)
    var checkCode string
    if len(sumStr) < 2 {
        checkCode = "0" + sumStr
    } else {
        checkCode = sumStr[len(sumStr)-2:]
    }
    var bytes = []byte{0x02}
    // 添加数据
    bytes = append(bytes, dataBytes...)
    // 添加校验
    bytes = append(bytes, []byte(checkCode)...)
    fmt.Printf("Tx: %X \n", bytes)
    // 写
    if n, err := c.readWriter.Write(bytes); err != nil {
        return n, err
    } else {
        fmt.Printf("Tx:len:%d\n", n)
    }
    // 读
    buf := make([]byte, 1024)
    n, err := c.readWriter.Read(buf)
    if err != nil {
        return n, err
    }
    buf = buf[:n]
    fmt.Printf("Rx: %X\nRx len:%d", buf, n)
    fmt.Printf("value: %d\n", buf[2:6])
    return n, nil
}
func (c *SerialClient) WriteHoldRegister(addr string) (int, error) {
    if c.readWriter == nil {
        return 0, errors.New("serial port is closed")
    }
    // 三菱fn系列串口协议
    // 02 表示开始 + 31 表示写数据 + 4位地址位 + 02 数据长度 + 03 停止 + 偶校验
    // 先组装数据
    // 读取的地址
    dataBytes := append([]byte{0x31}, []byte(addr)...)
    // 读取的长度
    dataBytes = append(dataBytes, []byte("02")...)
    // 停止
    dataBytes = append(dataBytes, []byte{0x03}...)
    // 计算校验码, 30 + 地址编码 + 数据长度 + 03 , 十六进制结果取后两位.
    var sum uint8
    for _, d := range dataBytes {
        sum += d
    }
    sumStr := fmt.Sprintf("%x", sum)
    fmt.Printf("sumStr: %s\n", sumStr)
    var checkCode string
    if len(sumStr) < 2 {
        checkCode = "0" + sumStr
    } else {
        checkCode = sumStr[len(sumStr)-2:]
    }
    var bytes = []byte{0x02}
    // 添加数据
    bytes = append(bytes, dataBytes...)
    // 添加校验
    bytes = append(bytes, []byte(checkCode)...)
    fmt.Printf("Tx: %X \n", bytes)
    // 写
    if n, err := c.readWriter.Write(bytes); err != nil {
        return n, err
    } else {
        fmt.Printf("Tx:len:%d\n", n)
    }
    // 读
    buf := make([]byte, 1024)
    n, err := c.readWriter.Read(buf)
    if err != nil {
        return n, err
    }
    buf = buf[:n]
    fmt.Printf("Rx: %X\nRx len:%d", buf, n)
    fmt.Printf("value: %d\n", buf[2:6])
    return n, nil
}
//
//import (
//    "encoding/hex"
//    "errors"
//    "fmt"
//    "io"
//    "strings"
//    "time"
//
//    "github.com/jacobsa/go-serial/serial"
//)
//
///*
//定义串口客户端
//*/
//
//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
//        }
//        fmt.Printf("Rx: %s\n", res)
//        c.OutBuffer <- res
//    }
//}
//
//func (c *SerialClient) open(portName string, baudRate uint) (io.ReadWriteCloser, error) {
//    options := serial.OpenOptions{
//        PortName:        portName,
//        BaudRate:        baudRate,
//        DataBits:        7,
//        StopBits:        1,
//        MinimumReadSize: 4,
//        ParityMode:      serial.PARITY_EVEN,
//    }
//
//    r, err := serial.Open(options)
//    if err != nil {
//        return nil, err
//    }
//
//    c.readWriter = r
//
//    return r, err
//}
//
//func (c *SerialClient) Close() {
//    if c.readWriter != nil {
//        c.readWriter.Close()
//    }
//}
//
//func (c *SerialClient) SendMsg(data string) (int, 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)
//}
//
//func (c *SerialClient) ReadHoldRegister(addr string) (int, error) {
//    if c.readWriter == nil {
//        return 0, errors.New("serial port is closed")
//    }
//
//    // 三菱fn系列串口协议
//    // 02 表示开始 + 30 表示读数据 + 4位地址位 + 02 数据长度 + 03 停止 + 偶校验
//
//    // 先组装数据
//    // 读取的地址
//    dataBytes := append([]byte{0x30}, []byte(addr)...)
//
//    // 读取的长度
//    dataBytes = append(dataBytes, []byte("02")...)
//
//    // 停止
//    dataBytes = append(dataBytes, []byte{0x03}...)
//
//    // 计算校验码, 30 + 地址编码 + 数据长度 + 03 , 十六进制结果取后两位.
//    var sum uint8
//    for _, d := range dataBytes {
//        sum += d
//    }
//
//    sumStr := fmt.Sprintf("%x", sum)
//
//    fmt.Printf("sumStr: %s\n", sumStr)
//
//    var checkCode string
//    if len(sumStr) < 2 {
//        checkCode = "0" + sumStr
//    } else {
//        checkCode = sumStr[len(sumStr)-2:]
//    }
//
//    var bytes = []byte{0x02}
//    // 添加数据
//    bytes = append(bytes, dataBytes...)
//    // 添加校验
//    bytes = append(bytes, []byte(checkCode)...)
//
//    fmt.Printf("Tx: %X \n", bytes)
//
//    // 写
//    if n, err := c.readWriter.Write(bytes); err != nil {
//        return n, err
//    } else {
//        fmt.Printf("Tx:len:%d\n", n)
//    }
//
//    // 读
//    buf := make([]byte, 1024)
//    n, err := c.readWriter.Read(buf)
//    if err != nil {
//        return n, err
//    }
//
//    buf = buf[:n]
//
//    fmt.Printf("Rx: %X\nRx len:%d", buf, n)
//    fmt.Printf("value: %d\n", buf[2:6])
//
//    return n, nil
//}
//
//func (c *SerialClient) WriteHoldRegister(addr string) (int, error) {
//    if c.readWriter == nil {
//        return 0, errors.New("serial port is closed")
//    }
//
//    // 三菱fn系列串口协议
//    // 02 表示开始 + 31 表示写数据 + 4位地址位 + 02 数据长度 + 03 停止 + 偶校验
//
//    // 先组装数据
//    // 读取的地址
//    dataBytes := append([]byte{0x31}, []byte(addr)...)
//
//    // 读取的长度
//    dataBytes = append(dataBytes, []byte("02")...)
//
//    // 停止
//    dataBytes = append(dataBytes, []byte{0x03}...)
//
//    // 计算校验码, 30 + 地址编码 + 数据长度 + 03 , 十六进制结果取后两位.
//    var sum uint8
//    for _, d := range dataBytes {
//        sum += d
//    }
//
//    sumStr := fmt.Sprintf("%x", sum)
//
//    fmt.Printf("sumStr: %s\n", sumStr)
//
//    var checkCode string
//    if len(sumStr) < 2 {
//        checkCode = "0" + sumStr
//    } else {
//        checkCode = sumStr[len(sumStr)-2:]
//    }
//
//    var bytes = []byte{0x02}
//    // 添加数据
//    bytes = append(bytes, dataBytes...)
//    // 添加校验
//    bytes = append(bytes, []byte(checkCode)...)
//
//    fmt.Printf("Tx: %X \n", bytes)
//
//    // 写
//    if n, err := c.readWriter.Write(bytes); err != nil {
//        return n, err
//    } else {
//        fmt.Printf("Tx:len:%d\n", n)
//    }
//
//    // 读
//    buf := make([]byte, 1024)
//    n, err := c.readWriter.Read(buf)
//    if err != nil {
//        return n, err
//    }
//
//    buf = buf[:n]
//
//    fmt.Printf("Rx: %X\nRx len:%d", buf, n)
//    fmt.Printf("value: %d\n", buf[2:6])
//
//    return n, nil
//}