golang 实现modbus设备通讯

经过前面golang的基础学习,我们开始写点东西吧

一, modbus设备

我拿到一台冷链设备,是浙港智能的无线测温监控系统,带了一个windows上的二进制程序,可以使用。但是我们的目标是,windows和linux都能使用啊,联系厂家也没能拿到芯片手册,坑爹呀。 无奈之下,反编译之,顺利搞定。正确拿到了温度的起始地址。初始条件已经具备,可以开发了。

二,golang准备

我们采用已有的modbus库来实现。 目前modbus有三种实现方式:RTU/ASCII/TCP 我根据我的设备情况选择了RTU方式,即串口连接方式。 golang的modbus库提供了底层api的支持,我们只需要做好下面几件事: 1,因为要支持文件配置,定义了如下:

// 定义了EnvMap,其目的是存放各个配置项,便于程序随时使用,下面紧跟的是每个具体的配置项的key
var EnvMap = make(map[string]string)
var RtuDevice = "rtudevice"
var BaudRate = "baudrate"
var DataBits = "databits"
var Parity = "parity"
var StopBits = "stopbits"
var SlaveId = "slaveid"
var SerialTimeout = "serialtimeout"
var Address = "address"
var Len = "len"

// 定义上面每个key的初始化值
const(
	DefaultRtuDevcie = "/dev/ttyUSB0"
	DefaultBaudRate = "19200"
	DefaultDataBits = "8"
	DefaultParity = "N"
	DefaultStopBits = "1"
	DefaultSlaveId = "1"
	DefaultSerialTimeout = "5"
	DefaultAddress = "1105"
	DefaultLen = "20"
)

// 定义配置文件的名称
const (
	workerConf = "modbus.conf"
)

2,初始化配置项,如果配置文件存在,就读取,按照文件内容配置,如果不存在使用我们配置的默认值。

func initConfMap() {
	strs := ReadFile(workerConf)
	if strs != "" {
		result := []string{}
		for _, lineStr := range strings.Split(strs, "\n") {
			lineStr = strings.TrimSpace(lineStr)
			if lineStr == "" {
				continue
			}
			result = strings.Split(lineStr, "=")
			k := result[0]
			v := result[1]
			EnvMap[k] = v
		}
	}

	// give a default value
	if EnvMap[RtuDevice] == "" {
		EnvMap[RtuDevice] = DefaultRtuDevcie
	}
	if EnvMap[BaudRate] == "" {
		EnvMap[BaudRate] = DefaultBaudRate
	}
	if EnvMap[DataBits] == "" {
		EnvMap[DataBits] = DefaultDataBits
	}
	if EnvMap[Parity] == "" {
		EnvMap[Parity] = DefaultParity
	}
	if EnvMap[StopBits] == "" {
		EnvMap[StopBits] = DefaultStopBits
	}
	if EnvMap[SlaveId] == "" {
		EnvMap[SlaveId] = DefaultSlaveId
	}
	if EnvMap[SerialTimeout] == "" {
		EnvMap[SerialTimeout] = DefaultSerialTimeout
	}
	if EnvMap[Address] == "" {
		EnvMap[Address] = DefaultAddress
	}
	if EnvMap[Len] == "" {
		EnvMap[Len] = DefaultLen
	}
}


3,串口的配置

// 根据串口设备初始化一个handler
handler := modbus.NewRTUClientHandler(EnvMap[RtuDevice])
// 配置handler的波特率
baudRate, _ := strconv.Atoi(EnvMap[BaudRate])
handler.BaudRate = baudRate
// 数据位
dataBits, _ := strconv.Atoi(EnvMap[DataBits])
handler.DataBits = dataBits
// 校验位
handler.Parity = EnvMap[Parity]
// 停止位
stopBits, _ := strconv.Atoi(EnvMap[StopBits])
handler.StopBits = stopBits
// modbus SlaveId
slaveId, _ := strconv.Atoi(EnvMap[SlaveId])
handler.SlaveId = byte(slaveId)
// 超时时间
serialTimeout, _ := strconv.Atoi(EnvMap[SerialTimeout])
handler.Timeout = time.Duration(serialTimeout) * time.Second

4,串口连接

err := handler.Connect()
defer handler.Close()

5,根据handler创建client

client := modbus.NewClient(handler)

6,读取冷链设备的20个无线温度标签的温度值

var i uint16
inputLen, _ := strconv.ParseInt(EnvMap[Len], 10, 16)
len := uint16(inputLen)
inputAddr, _ := strconv.Atoi(EnvMap[Address])
address := uint16(inputAddr)
//log.Println("len: ", len)
myS1 := make([]string, len)
for i=0; i

至此,我们得到了一个关于温度的string数组,在此数组上可以架构我们的业务了。

有不清楚的地方随时可以咨询我,此外,闲来没事,还实现了一版java版的代码,篇幅关系就不多介绍了,有兴趣的可以私信我。

mail:[email protected]


你可能感兴趣的:(技术)