package main import ( "encoding/binary" "flag" "fmt" plc4go "github.com/apache/plc4x/plc4go/pkg/api" "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/apache/plc4x/plc4go/spi/options" "github.com/rs/zerolog" ) var ( ipAddr string address int length int format string ) func init() { flag.StringVar(&ipAddr, "ip", "", "设备ip") flag.StringVar(&format, "format", "hex", "格式化: hex, 十六进制, dec 十进制, str, 字符串") flag.IntVar(&address, "addr", 100, "起始地址") flag.IntVar(&length, "len", 1, "长度") } func main() { flag.Parse() if ipAddr == "" { flag.PrintDefaults() return } // 强制读一个地址 if length == 0 { length = 1 } // 控制日志打印级别 zerolog.SetGlobalLevel(zerolog.FatalLevel) // 创建驱动管理器 driverManager := plc4go.NewPlcDriverManager() // 注册TCP传输 transports.RegisterTcpTransport(driverManager) // 注册UDP传输 //transports.RegisterUdpTransport(driverManager) // 注册串口传输 //transports.RegisterSerialTransport(driverManager) // 注册驱动 //drivers.RegisterKnxDriver(driverManager) drivers.RegisterModbusTcpDriver(driverManager) // 通过TCP连接PLC设备 connectionString := fmt.Sprintf("modbus-tcp://%s", ipAddr) connectionRequestChanel := driverManager.GetConnection(connectionString) // 等待连接响应 connectionResult := <-connectionRequestChanel // 判断是否连接成功 if err := connectionResult.GetErr(); err != nil { fmt.Printf("Error connecting to PLC: %s\n", err.Error()) return } // 已连接, 获取连接实例 connection := connectionResult.GetConnection() defer connection.Close() // 测试是否可以正常通信 //pingResult := <-connection.Ping() //if err := pingResult.GetErr(); err != nil { // fmt.Printf("Couldn't ping device: %s\n", err.Error()) //} // //// 验证是否可读 //if !connection.GetMetadata().CanRead() { // fmt.Printf("This connection doesn't support read operations\n") // return //} // 将长度按60切割, 太长了modbus不返回 for i, len := 0, 60; i < length; i = i + 60 { if i+len > length { len = length - i } tagAddress := fmt.Sprintf("holding-register:%d:DINT[%d]", address+i, len) // 读模式 readRequest, err := connection.ReadRequestBuilder().AddTagAddress("tag0", tagAddress).Build() if err != nil { fmt.Printf("Error preparing read-request:%s\n", err.Error()) return } // 执行 readResult := <-readRequest.Execute() if err := readResult.GetErr(); err != nil { fmt.Printf("Error execting read-request:%s\n", err.Error()) return } // 判断响应码是否正确 if readResult.GetResponse().GetResponseCode("tag0") != apiModel.PlcResponseCode_OK { fmt.Printf("error an non-ok return code: %s", readResult.GetResponse().GetResponseCode("tag0").GetName()) return } // 测试获取变量名称 //names := readResult.GetResponse().GetTagNames() //fmt.Printf("Got tag names %+v", names) value := readResult.GetResponse().GetValue("tag0") //// 按字符串打印变量 //fmt.Printf("val data: %s\n", value.GetRaw()) for idx, val := range value.GetList() { raw := val.GetRaw() if format == "hex" { fmt.Printf("%d:%X\t", address+i+idx, raw) } if format == "dec" { fmt.Printf("%d:%d\t", address+i+idx, binary.BigEndian.Uint16(raw)) } if format == "str" { fmt.Printf("%d:%s\t", address+i+idx, string(raw)) } } } fmt.Printf("\n") }