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))
|
}
|
}
|
}
|
fmt.Printf("\n")
|
|
}
|