python tcp协议_modbus-tcp协议学习-python

原文链接:http://blog.csdn.net/qq_20101209/article/details/62055069

1. 前言

modbus_tk是使用python语言实现的modbus协议栈,该库函数及支持主机也支持从机,同时支持RTU串口通信和TCP范式通信。

2. 准备工作

查阅modbus相关资料

下载modbus-tcp tester,这里面有server-tester和client-tester,能加速测试程序过程

3. modbus_tk安装

环境:python2.7, win10 & 树莓派

操作:直接 pip install modbus_tk 或者采用 easy_install

4. 基础示例

从机程序,需要先运行从机程序,才能启动master

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48#!/usr/bin/env python

# -*- coding: utf_8 -*-

''' 作者:raphael 时间:2017/3/10 简介:modbus协议从机测试脚本 '''

import sys

import logging

import threading

import modbus_tk

import modbus_tk.defines as cst

import modbus_tk.modbus as modbus

import modbus_tk.modbus_tcp as modbus_tcp

LOGGER = modbus_tk.utils.create_logger(name="console", record_format="%(message)s")

if __name__ == "__main__":

try:

# server里的address需要写的树莓派的IP和需要开放的端口,注意开放相应的端口

SERVER = modbus_tcp.TcpServer(address="192.168.1.111", port=1100)

LOGGER.info("running...")

LOGGER.info("enter 'quit' for closing the server")

# 服务启动

SERVER.start()

# 建立第一个从机

SLAVE1 = SERVER.add_slave(1)

SLAVE1.add_block('A', cst.HOLDING_REGISTERS, 0, 4)#地址0,长度4

SLAVE1.add_block('B', cst.HOLDING_REGISTERS, 4, 14)

#建立另一个从机2

SLAVE2 = SERVER.add_slave(2)

SLAVE2.add_block('C', cst.COILS, 0, 10) #地址0,长度10

SLAVE2.add_block('D', cst.HOLDING_REGISTERS, 0, 10)#地址0,长度10

SLAVE1.set_values('A', 0, 4) #改变在地址0处的寄存器的值

SLAVE1.set_values('B', 4, [1, 2, 3, 4, 5, 5, 12, 1232]) #改变在地址4处的寄存器的值

SLAVE2.set_values('C', 0, [1, 1, 1, 1, 1, 1])

SLAVE2.set_values('D', 0, 10)

while True:

CMD = sys.stdin.readline()

if CMD.find('quit') == 0:

sys.stdout.write('bye-bye\r\n')

break

else:

sys.stdout.write("unknown command %s\r\n" % (args[0]))

finally:

SERVER.stop()

主机程序

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36#!/usr/bin/env python

# -*- coding: utf_8 -*-

'''

作者:raphael

时间:2017/3/10

简介:modbus协议主机测试脚本

'''

import sys

import logging

import modbus_tk

import modbus_tk.defines as cst

import modbus_tk.modbus_tcp as modbus_tcp

LOGGER = modbus_tk.utils.create_logger("console")

if __name__ == "__main__":

try:

#连接从机地址,这里要注意端口号和IP与从机一致

MASTER = modbus_tcp.TcpMaster(host="192.168.1.111", port=1100)

MASTER.set_timeout(5.0)

LOGGER.info("connected")

#读取从机1的0-4保持寄存器

LOGGER.info(MASTER.execute(1, cst.READ_HOLDING_REGISTERS, 0, 4))

#读取从机1的4-14保持寄存器,因为寄存器独立分块了,所以不能直接连通读取,强行结果是会出现数据越界

LOGGER.info(MASTER.execute(1, cst.READ_HOLDING_REGISTERS, 4, 14))

# 需要按照execute格式

LOGGER.info(MASTER.execute(1, cst.WRITE_MULTIPLE_REGISTERS, 0, output_value=[0, 1, 2]))

LOGGER.info(MASTER.execute(1, cst.READ_HOLDING_REGISTERS, 0, 4))

LOGGER.info(MASTER.execute(2, cst.READ_COILS, 0, 8))

LOGGER.info(MASTER.execute(2, cst.WRITE_MULTIPLE_COILS, 0, output_value=[1, 0, 0, 0, 1]))

LOGGER.info(MASTER.execute(2, cst.READ_COILS, 0, 8))

LOGGER.info(MASTER.execute(2, cst.READ_HOLDING_REGISTERS, 0, 4))

# 线圈和寄存器地址不是同一区块的

except modbus_tk.modbus.ModbusError, err:

LOGGER.error("%s- Code=%d" % (err, err.get_exception_code()))

5.结果截图

主机

从机

6. 相关函数说明

add_slave(self, slave_id, unsigned=True, memory=None)

注意id区间

1

2

3

4

5

6

7

8

9

10def add_slave(self, slave_id, unsigned=True, memory=None):

"""Add a new slave with the given id"""

with self._lock:

if (slave_id <= 0) or (slave_id > 255):

raise Exception("Invalid slave id {0}".format(slave_id))

if slave_id not in self._slaves:

self._slaves[slave_id] = Slave(slave_id, unsigned, memory)

return self._slaves[slave_id]

else:

raise DuplicatedKeyError("Slave {0} already exists".format(slave_id))

set_values(self, block_name, address, values)

If values is a number, only one value is written,对于这个函数, values是我已开始没清楚的

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29def set_values(self, block_name, address, values):

""" Set the values of the items at the given address If values is a list or a tuple, the value of every item is written If values is a number, only one value is written """

# thread safe

with self._data_lock:

block = self._get_block(block_name)

# the block has been found

# check that it doesn't write out of the block

offset = address-block.starting_address

size = 1

if isinstance(values, list) or isinstance(values, tuple):

size = len(values)

if (offset < 0) or ((offset + size) > block.size):

raise OutOfModbusBlockError(

"address {0} size {1} is out of block {2}".format(address, size, block_name)

)

# if Ok: write the values

if isinstance(values, list) or isinstance(values, tuple):

block[offset:offset+len(values)] = values

else:

block[offset] = values

execute(  self, slave, function_code, starting_address, quantity_of_x=0, output_value=0, data_format=”“, expected_length=-1)

参数

注释

备注

slave

从机地址

modbus_tcp时可以忽略

function_code

功能码

看定义

starting_address

寄存器初始地址

要注意块界限

quantity_of_x

寄存器或者线圈数量

output_value

输出内容

注意写的类型

1

2

3

4

5

6

7

8

9

10@threadsafe_function

def execute( self, slave, function_code, starting_address, quantity_of_x=0, output_value=0, data_format="", expected_length=-1):

""" Execute a modbus query and returns the data part of the answer as a tuple The returned tuple depends on the query function code. see modbus protocol specification for details data_format makes possible to extract the data like defined in the struct python module documentation """

7.modbus 功能代码: defines.py

modbus 异常代码

ILLEGAL_FUNCTION = 1 功能代码不合法

ILLEGAL_DATA_ADDRESS = 2 数据地址不合法

ILLEGAL_DATA_VALUE = 3 数据值不合法

SLAVE_DEVICE_FAILURE = 4 slave设备失败

COMMAND_ACKNOWLEDGE = 5 命令已收到

SLAVE_DEVICE_BUSY = 6 slave设备忙

MEMORY_PARITY_ERROR = 8 内存奇偶误差

supported modbus 功能代码

READ_COILS = 1 读线圈

READ_DISCRETE_INPUTS = 2 读离散输入

READ_HOLDING_REGISTERS = 3 【读乘法寄存器】

READ_INPUT_REGISTERS = 4 读输入寄存器

WRITE_SINGLE_COIL = 5 写单一线圈

WRITE_SINGLE_REGISTER = 6 写单一寄存器

WRITE_MULTIPLE_COILS = 15 写多个线圈 【强制多点线圈】

WRITE_MULTIPLE_REGISTERS = 16 写多寄存器 【写乘法寄存器】

supported block types 支持的块类型

COILS = 1 线圈

DISCRETE_INPUTS = 2 离散输入(数字量输入)

HOLDING_REGISTERS = 3 乘法寄存器

ANALOG_INPUTS = 4 模拟量输入

8.参考网址

你可能感兴趣的:(python,tcp协议)