Framer

pymodbus.framer.ascii_framer module

Ascii_framer.

class pymodbus.framer.ascii_framer.ModbusAsciiFramer(decoder, client=None)

Bases: ModbusFramer

Modbus ASCII Frame Controller.

[ Start ][Address ][ Function ][ Data ][ LRC ][ End ]

1c 2c 2c Nc 2c 2c

  • data can be 0 - 2x252 chars

  • end is “\r\n” (Carriage return line feed), however the line feed character can be changed via a special command

  • start is “:”

This framer is used for serial transmission. Unlike the RTU protocol, the data in this framer is transferred in plain text ascii.

buildPacket(message)

Create a ready to send modbus packet.

Parameters:

message – The request/response to send

Returns:

The encoded packet

decode_data(data)

Decode data.

frameProcessIncomingPacket(single, callback, slave, _tid=None, **kwargs)

Process new packet pattern.

method = 'ascii'

pymodbus.framer.binary_framer module

Binary framer.

class pymodbus.framer.binary_framer.ModbusBinaryFramer(decoder, client=None)

Bases: ModbusFramer

Modbus Binary Frame Controller.

[ Start ][Address ][ Function ][ Data ][ CRC ][ End ]

1b 1b 1b Nb 2b 1b

  • data can be 0 - 2x252 chars

  • end is “}”

  • start is “{”

The idea here is that we implement the RTU protocol, however, instead of using timing for message delimiting, we use start and end of message characters (in this case { and }). Basically, this is a binary framer.

The only case we have to watch out for is when a message contains the { or } characters. If we encounter these characters, we simply duplicate them. Hopefully we will not encounter those characters that often and will save a little bit of bandwitch without a real-time system.

Protocol defined by jamod.sourceforge.net.

buildPacket(message)

Create a ready to send modbus packet.

Parameters:

message – The request/response to send

Returns:

The encoded packet

decode_data(data)

Decode data.

frameProcessIncomingPacket(single, callback, slave, _tid=None, **kwargs)

Process new packet pattern.

method = 'binary'

pymodbus.framer.rtu_framer module

RTU framer.

class pymodbus.framer.rtu_framer.ModbusRtuFramer(decoder, client=None)

Bases: ModbusFramer

Modbus RTU Frame controller.

[ Start Wait ] [Address ][ Function Code] [ Data ][ CRC ][ End Wait ]

3.5 chars 1b 1b Nb 2b 3.5 chars

Wait refers to the amount of time required to transmit at least x many characters. In this case it is 3.5 characters. Also, if we receive a wait of 1.5 characters at any point, we must trigger an error message. Also, it appears as though this message is little endian. The logic is simplified as the following:

block-on-read:
    read until 3.5 delay
    check for errors
    decode

The following table is a listing of the baud wait times for the specified baud rates:

------------------------------------------------------------------
 Baud  1.5c (18 bits)   3.5c (38 bits)
------------------------------------------------------------------
 1200   13333.3 us       31666.7 us
 4800    3333.3 us        7916.7 us
 9600    1666.7 us        3958.3 us
19200     833.3 us        1979.2 us
38400     416.7 us         989.6 us
------------------------------------------------------------------
1 Byte = start + 8 bits + parity + stop = 11 bits
(1/Baud)(bits) = delay seconds
buildPacket(message)

Create a ready to send modbus packet.

Parameters:

message – The populated request/response to send

decode_data(data)

Decode data.

frameProcessIncomingPacket(_single, callback, slave, _tid=None, **kwargs)

Process new packet pattern.

method = 'rtu'
recvPacket(size)

Receive packet from the bus with specified len.

Parameters:

size – Number of bytes to read

Returns:

sendPacket(message)

Send packets on the bus with 3.5char delay between frames.

Parameters:

message – Message to be sent over the bus

Returns:

pymodbus.framer.socket_framer module

Socket framer.

class pymodbus.framer.socket_framer.ModbusSocketFramer(decoder, client=None)

Bases: ModbusFramer

Modbus Socket Frame controller.

Before each modbus TCP message is an MBAP header which is used as a message frame. It allows us to easily separate messages as follows:

[         MBAP Header         ] [ Function Code] [ Data ]         [ tid ][ pid ][ length ][ uid ]
  2b     2b     2b        1b           1b           Nb

while len(message) > 0:
    tid, pid, length`, uid = struct.unpack(">HHHB", message)
    request = message[0:7 + length - 1`]
    message = [7 + length - 1:]

* length = uid + function code + data
* The -1 is to account for the uid byte
buildPacket(message)

Create a ready to send modbus packet.

Parameters:

message – The populated request/response to send

decode_data(data)

Decode data.

frameProcessIncomingPacket(single, callback, slave, tid=None, **kwargs)

Process new packet pattern.

This takes in a new request packet, adds it to the current packet stream, and performs framing on it. That is, checks for complete messages, and once found, will process all that exist. This handles the case when we read N + 1 or 1 // N messages at a time instead of 1.

The processed and decoded messages are pushed to the callback function to process and send.

method = 'socket'