Pymodbus package

Submodules

pymodbus.bit_read_message module

Bit Reading Request/Response messages

class pymodbus.bit_read_message.ReadCoilsRequest(address=None, count=None, **kwargs)

Bases: pymodbus.bit_read_message.ReadBitsRequestBase

This function code is used to read from 1 to 2000(0x7d0) contiguous status of coils in a remote device. The Request PDU specifies the starting address, ie the address of the first coil specified, and the number of coils. In the PDU Coils are addressed starting at zero. Therefore coils numbered 1-16 are addressed as 0-15.

execute(context)

Run a read coils request against a datastore

Before running the request, we make sure that the request is in the max valid range (0x001-0x7d0). Next we make sure that the request is valid against the current datastore.

Parameters:context – The datastore to request from
Returns:The initializes response message, exception message otherwise
function_code = 1
class pymodbus.bit_read_message.ReadCoilsResponse(values=None, **kwargs)

Bases: pymodbus.bit_read_message.ReadBitsResponseBase

The coils in the response message are packed as one coil per bit of the data field. Status is indicated as 1= ON and 0= OFF. The LSB of the first data byte contains the output addressed in the query. The other coils follow toward the high order end of this byte, and from low order to high order in subsequent bytes.

If the returned output quantity is not a multiple of eight, the remaining bits in the final data byte will be padded with zeros (toward the high order end of the byte). The Byte Count field specifies the quantity of complete bytes of data.

function_code = 1
class pymodbus.bit_read_message.ReadDiscreteInputsRequest(address=None, count=None, **kwargs)

Bases: pymodbus.bit_read_message.ReadBitsRequestBase

This function code is used to read from 1 to 2000(0x7d0) contiguous status of discrete inputs in a remote device. The Request PDU specifies the starting address, ie the address of the first input specified, and the number of inputs. In the PDU Discrete Inputs are addressed starting at zero. Therefore Discrete inputs numbered 1-16 are addressed as 0-15.

execute(context)

Run a read discrete input request against a datastore

Before running the request, we make sure that the request is in the max valid range (0x001-0x7d0). Next we make sure that the request is valid against the current datastore.

Parameters:context – The datastore to request from
Returns:The initializes response message, exception message otherwise
function_code = 2
class pymodbus.bit_read_message.ReadDiscreteInputsResponse(values=None, **kwargs)

Bases: pymodbus.bit_read_message.ReadBitsResponseBase

The discrete inputs in the response message are packed as one input per bit of the data field. Status is indicated as 1= ON; 0= OFF. The LSB of the first data byte contains the input addressed in the query. The other inputs follow toward the high order end of this byte, and from low order to high order in subsequent bytes.

If the returned input quantity is not a multiple of eight, the remaining bits in the final data byte will be padded with zeros (toward the high order end of the byte). The Byte Count field specifies the quantity of complete bytes of data.

function_code = 2

pymodbus.bit_write_message module

Bit Writing Request/Response

TODO write mask request/response

class pymodbus.bit_write_message.WriteSingleCoilRequest(address=None, value=None, **kwargs)

Bases: pymodbus.pdu.ModbusRequest

This function code is used to write a single output to either ON or OFF in a remote device.

The requested ON/OFF state is specified by a constant in the request data field. A value of FF 00 hex requests the output to be ON. A value of 00 00 requests it to be OFF. All other values are illegal and will not affect the output.

The Request PDU specifies the address of the coil to be forced. Coils are addressed starting at zero. Therefore coil numbered 1 is addressed as 0. The requested ON/OFF state is specified by a constant in the Coil Value field. A value of 0XFF00 requests the coil to be ON. A value of 0X0000 requests the coil to be off. All other values are illegal and will not affect the coil.

decode(data)

Decodes a write coil request

Parameters:data – The packet data to decode
encode()

Encodes write coil request

Returns:The byte encoded message
execute(context)

Run a write coil request against a datastore

Parameters:context – The datastore to request from
Returns:The populated response or exception message
function_code = 5
get_response_pdu_size()

Func_code (1 byte) + Output Address (2 byte) + Output Value (2 Bytes) :return:

class pymodbus.bit_write_message.WriteSingleCoilResponse(address=None, value=None, **kwargs)

Bases: pymodbus.pdu.ModbusResponse

The normal response is an echo of the request, returned after the coil state has been written.

decode(data)

Decodes a write coil response

Parameters:data – The packet data to decode
encode()

Encodes write coil response

Returns:The byte encoded message
function_code = 5
class pymodbus.bit_write_message.WriteMultipleCoilsRequest(address=None, values=None, **kwargs)

Bases: pymodbus.pdu.ModbusRequest

“This function code is used to force each coil in a sequence of coils to either ON or OFF in a remote device. The Request PDU specifies the coil references to be forced. Coils are addressed starting at zero. Therefore coil numbered 1 is addressed as 0.

The requested ON/OFF states are specified by contents of the request data field. A logical ‘1’ in a bit position of the field requests the corresponding output to be ON. A logical ‘0’ requests it to be OFF.”

decode(data)

Decodes a write coils request

Parameters:data – The packet data to decode
encode()

Encodes write coils request

Returns:The byte encoded message
execute(context)

Run a write coils request against a datastore

Parameters:context – The datastore to request from
Returns:The populated response or exception message
function_code = 15
get_response_pdu_size()

Func_code (1 byte) + Output Address (2 byte) + Quantity of Outputs (2 Bytes) :return:

class pymodbus.bit_write_message.WriteMultipleCoilsResponse(address=None, count=None, **kwargs)

Bases: pymodbus.pdu.ModbusResponse

The normal response returns the function code, starting address, and quantity of coils forced.

decode(data)

Decodes a write coils response

Parameters:data – The packet data to decode
encode()

Encodes write coils response

Returns:The byte encoded message
function_code = 15

pymodbus.compat module

Python 2.x/3.x Compatibility Layer

This is mostly based on the jinja2 compat code:

Some py2/py3 compatibility support based on a stripped down version of six so we don’t have to depend on a specific version of it.

copyright:Copyright 2013 by the Jinja team, see AUTHORS.
license:BSD, see LICENSE for details.
pymodbus.compat.get_next(x)
pymodbus.compat.implements_to_string(klass)
pymodbus.compat.iteritems(d)
pymodbus.compat.iterkeys(d)
pymodbus.compat.itervalues(d)

pymodbus.constants module

Constants For Modbus Server/Client

This is the single location for storing default values for the servers and clients.

class pymodbus.constants.Defaults

Bases: pymodbus.interfaces.Singleton

A collection of modbus default values

Port

The default modbus tcp server port (502)

Retries

The default number of times a client should retry the given request before failing (3)

RetryOnEmpty

A flag indicating if a transaction should be retried in the case that an empty response is received. This is useful for slow clients that may need more time to process a requst.

Timeout

The default amount of time a client should wait for a request to be processed (3 seconds)

Reconnects

The default number of times a client should attempt to reconnect before deciding the server is down (0)

TransactionId

The starting transaction identifier number (0)

ProtocolId

The modbus protocol id. Currently this is set to 0 in all but proprietary implementations.

UnitId

The modbus slave addrss. Currently this is set to 0x00 which means this request should be broadcast to all the slave devices (really means that all the devices should respons).

Baudrate

The speed at which the data is transmitted over the serial line. This defaults to 19200.

Parity

The type of checksum to use to verify data integrity. This can be on of the following:

- (E)ven - 1 0 1 0 | P(0)
- (O)dd  - 1 0 1 0 | P(1)
- (N)one - 1 0 1 0 | no parity

This defaults to (N)one.

Bytesize

The number of bits in a byte of serial data. This can be one of 5, 6, 7, or 8. This defaults to 8.

Stopbits

The number of bits sent after each character in a message to indicate the end of the byte. This defaults to 1.

ZeroMode

Indicates if the slave datastore should use indexing at 0 or 1. More about this can be read in section 4.4 of the modbus specification.

IgnoreMissingSlaves

In case a request is made to a missing slave, this defines if an error should be returned or simply ignored. This is useful for the case of a serial server emulater where a request to a non-existant slave on a bus will never respond. The client in this case will simply timeout.

Baudrate = 19200
Bytesize = 8
IgnoreMissingSlaves = False
Parity = 'N'
Port = 502
ProtocolId = 0
ReadSize = 1024
Reconnects = 0
Retries = 3
RetryOnEmpty = False
Stopbits = 1
Timeout = 3
TransactionId = 0
UnitId = 0
ZeroMode = False
class pymodbus.constants.ModbusStatus

Bases: pymodbus.interfaces.Singleton

These represent various status codes in the modbus protocol.

Waiting

This indicates that a modbus device is currently waiting for a given request to finish some running task.

Ready

This indicates that a modbus device is currently free to perform the next request task.

On

This indicates that the given modbus entity is on

Off

This indicates that the given modbus entity is off

SlaveOn

This indicates that the given modbus slave is running

SlaveOff

This indicates that the given modbus slave is not running

Off = 0
On = 65280
Ready = 0
SlaveOff = 0
SlaveOn = 255
Waiting = 65535
class pymodbus.constants.Endian

Bases: pymodbus.interfaces.Singleton

An enumeration representing the various byte endianess.

Auto

This indicates that the byte order is chosen by the current native environment.

Big

This indicates that the bytes are in little endian format

Little

This indicates that the bytes are in big endian format

Note

I am simply borrowing the format strings from the python struct module for my convenience.

Auto = '@'
Big = '>'
Little = '<'
class pymodbus.constants.ModbusPlusOperation

Bases: pymodbus.interfaces.Singleton

Represents the type of modbus plus request

GetStatistics

Operation requesting that the current modbus plus statistics be returned in the response.

ClearStatistics

Operation requesting that the current modbus plus statistics be cleared and not returned in the response.

ClearStatistics = 4
GetStatistics = 3
class pymodbus.constants.DeviceInformation

Bases: pymodbus.interfaces.Singleton

Represents what type of device information to read

Basic

This is the basic (required) device information to be returned. This includes VendorName, ProductCode, and MajorMinorRevision code.

Regular

In addition to basic data objects, the device provides additional and optinoal identification and description data objects. All of the objects of this category are defined in the standard but their implementation is optional.

Extended

In addition to regular data objects, the device provides additional and optional identification and description private data about the physical device itself. All of these data are device dependent.

Specific

Request to return a single data object.

Basic = 1
Extended = 3
Regular = 2
Specific = 4
class pymodbus.constants.MoreData

Bases: pymodbus.interfaces.Singleton

Represents the more follows condition

Nothing

This indiates that no more objects are going to be returned.

KeepReading

This indicates that there are more objects to be returned.

KeepReading = 255
Nothing = 0

pymodbus.device module

Modbus Device Controller

These are the device management handlers. They should be maintained in the server context and the various methods should be inserted in the correct locations.

class pymodbus.device.ModbusAccessControl

Bases: pymodbus.interfaces.Singleton

This is a simple implementation of a Network Management System table. Its purpose is to control access to the server (if it is used). We assume that if an entry is in the table, it is allowed accesses to resources. However, if the host does not appear in the table (all unknown hosts) its connection will simply be closed.

Since it is a singleton, only one version can possible exist and all instances pull from here.

add(host)

Add allowed host(s) from the NMS table

Parameters:host – The host to add
check(host)

Check if a host is allowed to access resources

Parameters:host – The host to check
remove(host)

Remove allowed host(s) from the NMS table

Parameters:host – The host to remove
class pymodbus.device.ModbusPlusStatistics

Bases: object

This is used to maintain the current modbus plus statistics count. As of right now this is simply a stub to complete the modbus implementation. For more information, see the modbus implementation guide page 87.

encode()

Returns a summary of the modbus plus statistics

Returns:54 16-bit words representing the status
reset()

This clears all of the modbus plus statistics

summary()

Returns a summary of the modbus plus statistics

Returns:54 16-bit words representing the status
class pymodbus.device.ModbusDeviceIdentification(info=None)

Bases: object

This is used to supply the device identification for the readDeviceIdentification function

For more information read section 6.21 of the modbus application protocol.

MajorMinorRevision
ModelName
ProductCode
ProductName
UserApplicationName
VendorName
VendorUrl
summary()

Return a summary of the main items

Returns:An dictionary of the main items
update(value)

Update the values of this identity using another identify as the value

Parameters:value – The value to copy values from
class pymodbus.device.DeviceInformationFactory

Bases: pymodbus.interfaces.Singleton

This is a helper factory that really just hides some of the complexity of processing the device information requests (function code 0x2b 0x0e).

classmethod get(control, read_code=1, object_id=0)

Get the requested device data from the system

Parameters:
  • control – The control block to pull data from
  • read_code – The read code to process
  • object_id – The specific object_id to read
Returns:

The requested data (id, length, value)

class pymodbus.device.ModbusControlBlock

Bases: pymodbus.interfaces.Singleton

This is a global singleotn that controls all system information

All activity should be logged here and all diagnostic requests should come from here.

Counter
Delimiter
Events
Identity
ListenOnly
Mode
Plus
addEvent(event)

Adds a new event to the event log

Parameters:event – A new event to add to the log
clearEvents()

Clears the current list of events

getDiagnostic(bit)

This gets the value in the diagnostic register

Parameters:bit – The bit to get
Returns:The current value of the requested bit
getDiagnosticRegister()

This gets the entire diagnostic register

Returns:The diagnostic register collection
getEvents()

Returns an encoded collection of the event log.

Returns:The encoded events packet
reset()

This clears all of the system counters and the diagnostic register

setDiagnostic(mapping)

This sets the value in the diagnostic register

Parameters:mapping – Dictionary of key:value pairs to set

pymodbus.diag_message module

Diagnostic Record Read/Write

These need to be tied into a the current server context or linked to the appropriate data

class pymodbus.diag_message.DiagnosticStatusRequest(**kwargs)

Bases: pymodbus.pdu.ModbusRequest

This is a base class for all of the diagnostic request functions

decode(data)

Base decoder for a diagnostic request

Parameters:data – The data to decode into the function code
encode()

Base encoder for a diagnostic response we encode the data set in self.message

Returns:The encoded packet
function_code = 8
get_response_pdu_size()

Func_code (1 byte) + Sub function code (2 byte) + Data (2 * N bytes) :return:

class pymodbus.diag_message.DiagnosticStatusResponse(**kwargs)

Bases: pymodbus.pdu.ModbusResponse

This is a base class for all of the diagnostic response functions

It works by performing all of the encoding and decoding of variable data and lets the higher classes define what extra data to append and how to execute a request

decode(data)

Base decoder for a diagnostic response

Parameters:data – The data to decode into the function code
encode()

Base encoder for a diagnostic response we encode the data set in self.message

Returns:The encoded packet
function_code = 8
class pymodbus.diag_message.ReturnQueryDataRequest(message=0, **kwargs)

Bases: pymodbus.diag_message.DiagnosticStatusRequest

The data passed in the request data field is to be returned (looped back) in the response. The entire response message should be identical to the request.

execute(*args)

Executes the loopback request (builds the response)

Returns:The populated loopback response message
sub_function_code = 0
class pymodbus.diag_message.ReturnQueryDataResponse(message=0, **kwargs)

Bases: pymodbus.diag_message.DiagnosticStatusResponse

The data passed in the request data field is to be returned (looped back) in the response. The entire response message should be identical to the request.

sub_function_code = 0
class pymodbus.diag_message.RestartCommunicationsOptionRequest(toggle=False, **kwargs)

Bases: pymodbus.diag_message.DiagnosticStatusRequest

The remote device serial line port must be initialized and restarted, and all of its communications event counters are cleared. If the port is currently in Listen Only Mode, no response is returned. This function is the only one that brings the port out of Listen Only Mode. If the port is not currently in Listen Only Mode, a normal response is returned. This occurs before the restart is executed.

execute(*args)

Clear event log and restart

Returns:The initialized response message
sub_function_code = 1
class pymodbus.diag_message.RestartCommunicationsOptionResponse(toggle=False, **kwargs)

Bases: pymodbus.diag_message.DiagnosticStatusResponse

The remote device serial line port must be initialized and restarted, and all of its communications event counters are cleared. If the port is currently in Listen Only Mode, no response is returned. This function is the only one that brings the port out of Listen Only Mode. If the port is not currently in Listen Only Mode, a normal response is returned. This occurs before the restart is executed.

sub_function_code = 1
class pymodbus.diag_message.ReturnDiagnosticRegisterRequest(data=0, **kwargs)

Bases: pymodbus.diag_message.DiagnosticStatusSimpleRequest

The contents of the remote device’s 16-bit diagnostic register are returned in the response

execute(*args)

Execute the diagnostic request on the given device

Returns:The initialized response message
sub_function_code = 2
class pymodbus.diag_message.ReturnDiagnosticRegisterResponse(data=0, **kwargs)

Bases: pymodbus.diag_message.DiagnosticStatusSimpleResponse

The contents of the remote device’s 16-bit diagnostic register are returned in the response

sub_function_code = 2
class pymodbus.diag_message.ChangeAsciiInputDelimiterRequest(data=0, **kwargs)

Bases: pymodbus.diag_message.DiagnosticStatusSimpleRequest

The character ‘CHAR’ passed in the request data field becomes the end of message delimiter for future messages (replacing the default LF character). This function is useful in cases of a Line Feed is not required at the end of ASCII messages.

execute(*args)

Execute the diagnostic request on the given device

Returns:The initialized response message
sub_function_code = 3
class pymodbus.diag_message.ChangeAsciiInputDelimiterResponse(data=0, **kwargs)

Bases: pymodbus.diag_message.DiagnosticStatusSimpleResponse

The character ‘CHAR’ passed in the request data field becomes the end of message delimiter for future messages (replacing the default LF character). This function is useful in cases of a Line Feed is not required at the end of ASCII messages.

sub_function_code = 3
class pymodbus.diag_message.ForceListenOnlyModeRequest(data=0, **kwargs)

Bases: pymodbus.diag_message.DiagnosticStatusSimpleRequest

Forces the addressed remote device to its Listen Only Mode for MODBUS communications. This isolates it from the other devices on the network, allowing them to continue communicating without interruption from the addressed remote device. No response is returned.

execute(*args)

Execute the diagnostic request on the given device

Returns:The initialized response message
sub_function_code = 4
class pymodbus.diag_message.ForceListenOnlyModeResponse(**kwargs)

Bases: pymodbus.diag_message.DiagnosticStatusResponse

Forces the addressed remote device to its Listen Only Mode for MODBUS communications. This isolates it from the other devices on the network, allowing them to continue communicating without interruption from the addressed remote device. No response is returned.

This does not send a response

should_respond = False
sub_function_code = 4
class pymodbus.diag_message.ClearCountersRequest(data=0, **kwargs)

Bases: pymodbus.diag_message.DiagnosticStatusSimpleRequest

The goal is to clear ll counters and the diagnostic register. Also, counters are cleared upon power-up

execute(*args)

Execute the diagnostic request on the given device

Returns:The initialized response message
sub_function_code = 10
class pymodbus.diag_message.ClearCountersResponse(data=0, **kwargs)

Bases: pymodbus.diag_message.DiagnosticStatusSimpleResponse

The goal is to clear ll counters and the diagnostic register. Also, counters are cleared upon power-up

sub_function_code = 10
class pymodbus.diag_message.ReturnBusMessageCountRequest(data=0, **kwargs)

Bases: pymodbus.diag_message.DiagnosticStatusSimpleRequest

The response data field returns the quantity of messages that the remote device has detected on the communications systems since its last restart, clear counters operation, or power-up

execute(*args)

Execute the diagnostic request on the given device

Returns:The initialized response message
sub_function_code = 11
class pymodbus.diag_message.ReturnBusMessageCountResponse(data=0, **kwargs)

Bases: pymodbus.diag_message.DiagnosticStatusSimpleResponse

The response data field returns the quantity of messages that the remote device has detected on the communications systems since its last restart, clear counters operation, or power-up

sub_function_code = 11
class pymodbus.diag_message.ReturnBusCommunicationErrorCountRequest(data=0, **kwargs)

Bases: pymodbus.diag_message.DiagnosticStatusSimpleRequest

The response data field returns the quantity of CRC errors encountered by the remote device since its last restart, clear counter operation, or power-up

execute(*args)

Execute the diagnostic request on the given device

Returns:The initialized response message
sub_function_code = 12
class pymodbus.diag_message.ReturnBusCommunicationErrorCountResponse(data=0, **kwargs)

Bases: pymodbus.diag_message.DiagnosticStatusSimpleResponse

The response data field returns the quantity of CRC errors encountered by the remote device since its last restart, clear counter operation, or power-up

sub_function_code = 12
class pymodbus.diag_message.ReturnBusExceptionErrorCountRequest(data=0, **kwargs)

Bases: pymodbus.diag_message.DiagnosticStatusSimpleRequest

The response data field returns the quantity of modbus exception responses returned by the remote device since its last restart, clear counters operation, or power-up

execute(*args)

Execute the diagnostic request on the given device

Returns:The initialized response message
sub_function_code = 13
class pymodbus.diag_message.ReturnBusExceptionErrorCountResponse(data=0, **kwargs)

Bases: pymodbus.diag_message.DiagnosticStatusSimpleResponse

The response data field returns the quantity of modbus exception responses returned by the remote device since its last restart, clear counters operation, or power-up

sub_function_code = 13
class pymodbus.diag_message.ReturnSlaveMessageCountRequest(data=0, **kwargs)

Bases: pymodbus.diag_message.DiagnosticStatusSimpleRequest

The response data field returns the quantity of messages addressed to the remote device, or broadcast, that the remote device has processed since its last restart, clear counters operation, or power-up

execute(*args)

Execute the diagnostic request on the given device

Returns:The initialized response message
sub_function_code = 14
class pymodbus.diag_message.ReturnSlaveMessageCountResponse(data=0, **kwargs)

Bases: pymodbus.diag_message.DiagnosticStatusSimpleResponse

The response data field returns the quantity of messages addressed to the remote device, or broadcast, that the remote device has processed since its last restart, clear counters operation, or power-up

sub_function_code = 14
class pymodbus.diag_message.ReturnSlaveNoResponseCountRequest(data=0, **kwargs)

Bases: pymodbus.diag_message.DiagnosticStatusSimpleRequest

The response data field returns the quantity of messages addressed to the remote device, or broadcast, that the remote device has processed since its last restart, clear counters operation, or power-up

execute(*args)

Execute the diagnostic request on the given device

Returns:The initialized response message
sub_function_code = 15
class pymodbus.diag_message.ReturnSlaveNoReponseCountResponse(data=0, **kwargs)

Bases: pymodbus.diag_message.DiagnosticStatusSimpleResponse

The response data field returns the quantity of messages addressed to the remote device, or broadcast, that the remote device has processed since its last restart, clear counters operation, or power-up

sub_function_code = 15
class pymodbus.diag_message.ReturnSlaveNAKCountRequest(data=0, **kwargs)

Bases: pymodbus.diag_message.DiagnosticStatusSimpleRequest

The response data field returns the quantity of messages addressed to the remote device for which it returned a Negative Acknowledge (NAK) exception response, since its last restart, clear counters operation, or power-up. Exception responses are described and listed in section 7 .

execute(*args)

Execute the diagnostic request on the given device

Returns:The initialized response message
sub_function_code = 16
class pymodbus.diag_message.ReturnSlaveNAKCountResponse(data=0, **kwargs)

Bases: pymodbus.diag_message.DiagnosticStatusSimpleResponse

The response data field returns the quantity of messages addressed to the remote device for which it returned a Negative Acknowledge (NAK) exception response, since its last restart, clear counters operation, or power-up. Exception responses are described and listed in section 7.

sub_function_code = 16
class pymodbus.diag_message.ReturnSlaveBusyCountRequest(data=0, **kwargs)

Bases: pymodbus.diag_message.DiagnosticStatusSimpleRequest

The response data field returns the quantity of messages addressed to the remote device for which it returned a Slave Device Busy exception response, since its last restart, clear counters operation, or power-up.

execute(*args)

Execute the diagnostic request on the given device

Returns:The initialized response message
sub_function_code = 17
class pymodbus.diag_message.ReturnSlaveBusyCountResponse(data=0, **kwargs)

Bases: pymodbus.diag_message.DiagnosticStatusSimpleResponse

The response data field returns the quantity of messages addressed to the remote device for which it returned a Slave Device Busy exception response, since its last restart, clear counters operation, or power-up.

sub_function_code = 17
class pymodbus.diag_message.ReturnSlaveBusCharacterOverrunCountRequest(data=0, **kwargs)

Bases: pymodbus.diag_message.DiagnosticStatusSimpleRequest

The response data field returns the quantity of messages addressed to the remote device that it could not handle due to a character overrun condition, since its last restart, clear counters operation, or power-up. A character overrun is caused by data characters arriving at the port faster than they can be stored, or by the loss of a character due to a hardware malfunction.

execute(*args)

Execute the diagnostic request on the given device

Returns:The initialized response message
sub_function_code = 18
class pymodbus.diag_message.ReturnSlaveBusCharacterOverrunCountResponse(data=0, **kwargs)

Bases: pymodbus.diag_message.DiagnosticStatusSimpleResponse

The response data field returns the quantity of messages addressed to the remote device that it could not handle due to a character overrun condition, since its last restart, clear counters operation, or power-up. A character overrun is caused by data characters arriving at the port faster than they can be stored, or by the loss of a character due to a hardware malfunction.

sub_function_code = 18
class pymodbus.diag_message.ReturnIopOverrunCountRequest(data=0, **kwargs)

Bases: pymodbus.diag_message.DiagnosticStatusSimpleRequest

An IOP overrun is caused by data characters arriving at the port faster than they can be stored, or by the loss of a character due to a hardware malfunction. This function is specific to the 884.

execute(*args)

Execute the diagnostic request on the given device

Returns:The initialized response message
sub_function_code = 19
class pymodbus.diag_message.ReturnIopOverrunCountResponse(data=0, **kwargs)

Bases: pymodbus.diag_message.DiagnosticStatusSimpleResponse

The response data field returns the quantity of messages addressed to the slave that it could not handle due to an 884 IOP overrun condition, since its last restart, clear counters operation, or power-up.

sub_function_code = 19
class pymodbus.diag_message.ClearOverrunCountRequest(data=0, **kwargs)

Bases: pymodbus.diag_message.DiagnosticStatusSimpleRequest

Clears the overrun error counter and reset the error flag

An error flag should be cleared, but nothing else in the specification mentions is, so it is ignored.

execute(*args)

Execute the diagnostic request on the given device

Returns:The initialized response message
sub_function_code = 20
class pymodbus.diag_message.ClearOverrunCountResponse(data=0, **kwargs)

Bases: pymodbus.diag_message.DiagnosticStatusSimpleResponse

Clears the overrun error counter and reset the error flag

sub_function_code = 20
class pymodbus.diag_message.GetClearModbusPlusRequest(**kwargs)

Bases: pymodbus.diag_message.DiagnosticStatusSimpleRequest

In addition to the Function code (08) and Subfunction code (00 15 hex) in the query, a two-byte Operation field is used to specify either a ‘Get Statistics’ or a ‘Clear Statistics’ operation. The two operations are exclusive - the ‘Get’ operation cannot clear the statistics, and the ‘Clear’ operation does not return statistics prior to clearing them. Statistics are also cleared on power-up of the slave device.

encode()

Base encoder for a diagnostic response we encode the data set in self.message

Returns:The encoded packet
execute(*args)

Execute the diagnostic request on the given device

Returns:The initialized response message
get_response_pdu_size()

Returns a series of 54 16-bit words (108 bytes) in the data field of the response (this function differs from the usual two-byte length of the data field). The data contains the statistics for the Modbus Plus peer processor in the slave device. Func_code (1 byte) + Sub function code (2 byte) + Operation (2 byte) + Data (108 bytes) :return:

sub_function_code = 21
class pymodbus.diag_message.GetClearModbusPlusResponse(data=0, **kwargs)

Bases: pymodbus.diag_message.DiagnosticStatusSimpleResponse

Returns a series of 54 16-bit words (108 bytes) in the data field of the response (this function differs from the usual two-byte length of the data field). The data contains the statistics for the Modbus Plus peer processor in the slave device.

sub_function_code = 21

pymodbus.events module

Modbus Remote Events

An event byte returned by the Get Communications Event Log function can be any one of four types. The type is defined by bit 7 (the high-order bit) in each byte. It may be further defined by bit 6.

class pymodbus.events.CommunicationRestartEvent

Bases: pymodbus.events.ModbusEvent

Remote device Initiated Communication Restart

The remote device stores this type of event byte when its communications port is restarted. The remote device can be restarted by the Diagnostics function (code 08), with sub-function Restart Communications Option (code 00 01).

That function also places the remote device into a ‘Continue on Error’ or ‘Stop on Error’ mode. If the remote device is placed into ‘Continue on Error’ mode, the event byte is added to the existing event log. If the remote device is placed into ‘Stop on Error’ mode, the byte is added to the log and the rest of the log is cleared to zeros.

The event is defined by a content of zero.

decode(event)

Decodes the event message to its status bits

Parameters:event – The event to decode
encode()

Encodes the status bits to an event message

Returns:The encoded event message
value = 0
class pymodbus.events.EnteredListenModeEvent

Bases: pymodbus.events.ModbusEvent

Remote device Entered Listen Only Mode

The remote device stores this type of event byte when it enters the Listen Only Mode. The event is defined by a content of 04 hex.

decode(event)

Decodes the event message to its status bits

Parameters:event – The event to decode
encode()

Encodes the status bits to an event message

Returns:The encoded event message
value = 4
class pymodbus.events.ModbusEvent

Bases: object

decode(event)

Decodes the event message to its status bits

Parameters:event – The event to decode
encode()

Encodes the status bits to an event message

Returns:The encoded event message
class pymodbus.events.RemoteReceiveEvent(**kwargs)

Bases: pymodbus.events.ModbusEvent

Remote device MODBUS Receive Event

The remote device stores this type of event byte when a query message is received. It is stored before the remote device processes the message. This event is defined by bit 7 set to logic ‘1’. The other bits will be set to a logic ‘1’ if the corresponding condition is TRUE. The bit layout is:

Bit Contents
----------------------------------
0   Not Used
2   Not Used
3   Not Used
4   Character Overrun
5   Currently in Listen Only Mode
6   Broadcast Receive
7   1
decode(event)

Decodes the event message to its status bits

Parameters:event – The event to decode
encode()

Encodes the status bits to an event message

Returns:The encoded event message
class pymodbus.events.RemoteSendEvent(**kwargs)

Bases: pymodbus.events.ModbusEvent

Remote device MODBUS Send Event

The remote device stores this type of event byte when it finishes processing a request message. It is stored if the remote device returned a normal or exception response, or no response.

This event is defined by bit 7 set to a logic ‘0’, with bit 6 set to a ‘1’. The other bits will be set to a logic ‘1’ if the corresponding condition is TRUE. The bit layout is:

Bit Contents
-----------------------------------------------------------
0   Read Exception Sent (Exception Codes 1-3)
1   Slave Abort Exception Sent (Exception Code 4)
2   Slave Busy Exception Sent (Exception Codes 5-6)
3   Slave Program NAK Exception Sent (Exception Code 7)
4   Write Timeout Error Occurred
5   Currently in Listen Only Mode
6   1
7   0
decode(event)

Decodes the event message to its status bits

Parameters:event – The event to decode
encode()

Encodes the status bits to an event message

Returns:The encoded event message

pymodbus.exceptions module

Pymodbus Exceptions

Custom exceptions to be used in the Modbus code.

exception pymodbus.exceptions.ModbusException(string)

Bases: exceptions.Exception

Base modbus exception

isError()

Error

exception pymodbus.exceptions.ModbusIOException(string='')

Bases: pymodbus.exceptions.ModbusException

Error resulting from data i/o

exception pymodbus.exceptions.ParameterException(string='')

Bases: pymodbus.exceptions.ModbusException

Error resulting from invalid parameter

exception pymodbus.exceptions.NotImplementedException(string='')

Bases: pymodbus.exceptions.ModbusException

Error resulting from not implemented function

exception pymodbus.exceptions.ConnectionException(string='')

Bases: pymodbus.exceptions.ModbusException

Error resulting from a bad connection

exception pymodbus.exceptions.NoSuchSlaveException(string='')

Bases: pymodbus.exceptions.ModbusException

Error resulting from making a request to a slave that does not exist

pymodbus.factory module

Modbus Request/Response Decoder Factories

The following factories make it easy to decode request/response messages. To add a new request/response pair to be decodeable by the library, simply add them to the respective function lookup table (order doesn’t matter, but it does help keep things organized).

Regardless of how many functions are added to the lookup, O(1) behavior is kept as a result of a pre-computed lookup dictionary.

class pymodbus.factory.ServerDecoder

Bases: pymodbus.interfaces.IModbusDecoder

Request Message Factory (Server)

To add more implemented functions, simply add them to the list

decode(message)

Wrapper to decode a request packet

Parameters:message – The raw modbus request packet
Returns:The decoded modbus message or None if error
lookupPduClass(function_code)

Use function_code to determine the class of the PDU.

Parameters:function_code – The function code specified in a frame.
Returns:The class of the PDU that has a matching function_code.
class pymodbus.factory.ClientDecoder

Bases: pymodbus.interfaces.IModbusDecoder

Response Message Factory (Client)

To add more implemented functions, simply add them to the list

decode(message)

Wrapper to decode a response packet

Parameters:message – The raw packet to decode
Returns:The decoded modbus message or None if error
lookupPduClass(function_code)

Use function_code to determine the class of the PDU.

Parameters:function_code – The function code specified in a frame.
Returns:The class of the PDU that has a matching function_code.

pymodbus.file_message module

File Record Read/Write Messages

Currently none of these messages are implemented

class pymodbus.file_message.FileRecord(**kwargs)

Bases: object

Represents a file record and its relevant data.

class pymodbus.file_message.ReadFileRecordRequest(records=None, **kwargs)

Bases: pymodbus.pdu.ModbusRequest

This function code is used to perform a file record read. All request data lengths are provided in terms of number of bytes and all record lengths are provided in terms of registers.

A file is an organization of records. Each file contains 10000 records, addressed 0000 to 9999 decimal or 0x0000 to 0x270f. For example, record 12 is addressed as 12. The function can read multiple groups of references. The groups can be separating (non-contiguous), but the references within each group must be sequential. Each group is defined in a seperate ‘sub-request’ field that contains seven bytes:

The reference type: 1 byte (must be 0x06)
The file number: 2 bytes
The starting record number within the file: 2 bytes
The length of the record to be read: 2 bytes

The quantity of registers to be read, combined with all other fields in the expected response, must not exceed the allowable length of the MODBUS PDU: 235 bytes.

decode(data)

Decodes the incoming request

Parameters:data – The data to decode into the address
encode()

Encodes the request packet

Returns:The byte encoded packet
execute(context)

Run a read exeception status request against the store

Parameters:context – The datastore to request from
Returns:The populated response
function_code = 20
class pymodbus.file_message.ReadFileRecordResponse(records=None, **kwargs)

Bases: pymodbus.pdu.ModbusResponse

The normal response is a series of ‘sub-responses,’ one for each ‘sub-request.’ The byte count field is the total combined count of bytes in all ‘sub-responses.’ In addition, each ‘sub-response’ contains a field that shows its own byte count.

decode(data)

Decodes a the response

Parameters:data – The packet data to decode
encode()

Encodes the response

Returns:The byte encoded message
function_code = 20
class pymodbus.file_message.WriteFileRecordRequest(records=None, **kwargs)

Bases: pymodbus.pdu.ModbusRequest

This function code is used to perform a file record write. All request data lengths are provided in terms of number of bytes and all record lengths are provided in terms of the number of 16 bit words.

decode(data)

Decodes the incoming request

Parameters:data – The data to decode into the address
encode()

Encodes the request packet

Returns:The byte encoded packet
execute(context)

Run the write file record request against the context

Parameters:context – The datastore to request from
Returns:The populated response
function_code = 21
class pymodbus.file_message.WriteFileRecordResponse(records=None, **kwargs)

Bases: pymodbus.pdu.ModbusResponse

The normal response is an echo of the request.

decode(data)

Decodes the incoming request

Parameters:data – The data to decode into the address
encode()

Encodes the response

Returns:The byte encoded message
function_code = 21
class pymodbus.file_message.ReadFifoQueueRequest(address=0, **kwargs)

Bases: pymodbus.pdu.ModbusRequest

This function code allows to read the contents of a First-In-First-Out (FIFO) queue of register in a remote device. The function returns a count of the registers in the queue, followed by the queued data. Up to 32 registers can be read: the count, plus up to 31 queued data registers.

The queue count register is returned first, followed by the queued data registers. The function reads the queue contents, but does not clear them.

decode(data)

Decodes the incoming request

Parameters:data – The data to decode into the address
encode()

Encodes the request packet

Returns:The byte encoded packet
execute(context)

Run a read exeception status request against the store

Parameters:context – The datastore to request from
Returns:The populated response
function_code = 24
class pymodbus.file_message.ReadFifoQueueResponse(values=None, **kwargs)

Bases: pymodbus.pdu.ModbusResponse

In a normal response, the byte count shows the quantity of bytes to follow, including the queue count bytes and value register bytes (but not including the error check field). The queue count is the quantity of data registers in the queue (not including the count register).

If the queue count exceeds 31, an exception response is returned with an error code of 03 (Illegal Data Value).

classmethod calculateRtuFrameSize(buffer)

Calculates the size of the message

Parameters:buffer – A buffer containing the data that have been received.
Returns:The number of bytes in the response.
decode(data)

Decodes a the response

Parameters:data – The packet data to decode
encode()

Encodes the response

Returns:The byte encoded message
function_code = 24

pymodbus.interfaces module

Pymodbus Interfaces

A collection of base classes that are used throughout the pymodbus library.

class pymodbus.interfaces.Singleton

Bases: object

Singleton base class http://mail.python.org/pipermail/python-list/2007-July/450681.html

class pymodbus.interfaces.IModbusDecoder

Bases: object

Modbus Decoder Base Class

This interface must be implemented by a modbus message decoder factory. These factories are responsible for abstracting away converting a raw packet into a request / response message object.

decode(message)

Wrapper to decode a given packet

Parameters:message – The raw modbus request packet
Returns:The decoded modbus message or None if error
lookupPduClass(function_code)

Use function_code to determine the class of the PDU.

Parameters:function_code – The function code specified in a frame.
Returns:The class of the PDU that has a matching function_code.
class pymodbus.interfaces.IModbusFramer

Bases: object

A framer strategy interface. The idea is that we abstract away all the detail about how to detect if a current message frame exists, decoding it, sending it, etc so that we can plug in a new Framer object (tcp, rtu, ascii).

addToFrame(message)

Add the next message to the frame buffer

This should be used before the decoding while loop to add the received data to the buffer handle.

Parameters:message – The most recent packet
advanceFrame()

Skip over the current framed message This allows us to skip over the current message after we have processed it or determined that it contains an error. It also has to reset the current frame header handle

buildPacket(message)

Creates a ready to send modbus packet

The raw packet is built off of a fully populated modbus request / response message.

Parameters:message – The request/response to send
Returns:The built packet
checkFrame()

Check and decode the next frame

Returns:True if we successful, False otherwise
getFrame()

Get the next frame from the buffer

Returns:The frame data or ‘’
isFrameReady()

Check if we should continue decode logic

This is meant to be used in a while loop in the decoding phase to let the decoder know that there is still data in the buffer.

Returns:True if ready, False otherwise
populateResult(result)

Populates the modbus result with current frame header

We basically copy the data back over from the current header to the result header. This may not be needed for serial messages.

Parameters:result – The response packet
processIncomingPacket(data, callback)

The new packet processing 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.

Parameters:
  • data – The new packet data
  • callback – The function to send results to
class pymodbus.interfaces.IModbusSlaveContext

Bases: object

Interface for a modbus slave data context

Derived classes must implemented the following methods:
reset(self) validate(self, fx, address, count=1) getValues(self, fx, address, count=1) setValues(self, fx, address, values)
decode(fx)

Converts the function code to the datastore to

Parameters:fx – The function we are working with
Returns:one of [d(iscretes),i(inputs),h(oliding),c(oils)
getValues(fx, address, count=1)

Validates the request to make sure it is in range

Parameters:
  • fx – The function we are working with
  • address – The starting address
  • count – The number of values to retrieve
Returns:

The requested values from a:a+c

i = 15
reset()

Resets all the datastores to their default values

setValues(fx, address, values)

Sets the datastore with the supplied values

Parameters:
  • fx – The function we are working with
  • address – The starting address
  • values – The new values to be set
validate(fx, address, count=1)

Validates the request to make sure it is in range

Parameters:
  • fx – The function we are working with
  • address – The starting address
  • count – The number of values to test
Returns:

True if the request in within range, False otherwise

class pymodbus.interfaces.IPayloadBuilder

Bases: object

This is an interface to a class that can build a payload for a modbus register write command. It should abstract the codec for encoding data to the required format (bcd, binary, char, etc).

build()

Return the payload buffer as a list

This list is two bytes per element and can thus be treated as a list of registers.

Returns:The payload buffer as a list

pymodbus.mei_message module

Encapsulated Interface (MEI) Transport Messages

class pymodbus.mei_message.ReadDeviceInformationRequest(read_code=None, object_id=0, **kwargs)

Bases: pymodbus.pdu.ModbusRequest

This function code allows reading the identification and additional information relative to the physical and functional description of a remote device, only.

The Read Device Identification interface is modeled as an address space composed of a set of addressable data elements. The data elements are called objects and an object Id identifies them.

decode(data)

Decodes data part of the message.

Parameters:data – The incoming data
encode()

Encodes the request packet

Returns:The byte encoded packet
execute(context)

Run a read exeception status request against the store

Parameters:context – The datastore to request from
Returns:The populated response
function_code = 43
sub_function_code = 14
class pymodbus.mei_message.ReadDeviceInformationResponse(read_code=None, information=None, **kwargs)

Bases: pymodbus.pdu.ModbusResponse

classmethod calculateRtuFrameSize(buffer)

Calculates the size of the message

Parameters:buffer – A buffer containing the data that have been received.
Returns:The number of bytes in the response.
decode(data)

Decodes a the response

Parameters:data – The packet data to decode
encode()

Encodes the response

Returns:The byte encoded message
function_code = 43
sub_function_code = 14

pymodbus.other_message module

Diagnostic record read/write

Currently not all implemented

class pymodbus.other_message.ReadExceptionStatusRequest(**kwargs)

Bases: pymodbus.pdu.ModbusRequest

This function code is used to read the contents of eight Exception Status outputs in a remote device. The function provides a simple method for accessing this information, because the Exception Output references are known (no output reference is needed in the function).

decode(data)

Decodes data part of the message.

Parameters:data – The incoming data
encode()

Encodes the message

execute(context=None)

Run a read exeception status request against the store

Returns:The populated response
function_code = 7
class pymodbus.other_message.ReadExceptionStatusResponse(status=0, **kwargs)

Bases: pymodbus.pdu.ModbusResponse

The normal response contains the status of the eight Exception Status outputs. The outputs are packed into one data byte, with one bit per output. The status of the lowest output reference is contained in the least significant bit of the byte. The contents of the eight Exception Status outputs are device specific.

decode(data)

Decodes a the response

Parameters:data – The packet data to decode
encode()

Encodes the response

Returns:The byte encoded message
function_code = 7
class pymodbus.other_message.GetCommEventCounterRequest(**kwargs)

Bases: pymodbus.pdu.ModbusRequest

This function code is used to get a status word and an event count from the remote device’s communication event counter.

By fetching the current count before and after a series of messages, a client can determine whether the messages were handled normally by the remote device.

The device’s event counter is incremented once for each successful message completion. It is not incremented for exception responses, poll commands, or fetch event counter commands.

The event counter can be reset by means of the Diagnostics function (code 08), with a subfunction of Restart Communications Option (code 00 01) or Clear Counters and Diagnostic Register (code 00 0A).

decode(data)

Decodes data part of the message.

Parameters:data – The incoming data
encode()

Encodes the message

execute(context=None)

Run a read exeception status request against the store

Returns:The populated response
function_code = 11
class pymodbus.other_message.GetCommEventCounterResponse(count=0, **kwargs)

Bases: pymodbus.pdu.ModbusResponse

The normal response contains a two-byte status word, and a two-byte event count. The status word will be all ones (FF FF hex) if a previously-issued program command is still being processed by the remote device (a busy condition exists). Otherwise, the status word will be all zeros.

decode(data)

Decodes a the response

Parameters:data – The packet data to decode
encode()

Encodes the response

Returns:The byte encoded message
function_code = 11
class pymodbus.other_message.GetCommEventLogRequest(**kwargs)

Bases: pymodbus.pdu.ModbusRequest

This function code is used to get a status word, event count, message count, and a field of event bytes from the remote device.

The status word and event counts are identical to that returned by the Get Communications Event Counter function (11, 0B hex).

The message counter contains the quantity of messages processed by the remote device since its last restart, clear counters operation, or power-up. This count is identical to that returned by the Diagnostic function (code 08), sub-function Return Bus Message Count (code 11, 0B hex).

The event bytes field contains 0-64 bytes, with each byte corresponding to the status of one MODBUS send or receive operation for the remote device. The remote device enters the events into the field in chronological order. Byte 0 is the most recent event. Each new byte flushes the oldest byte from the field.

decode(data)

Decodes data part of the message.

Parameters:data – The incoming data
encode()

Encodes the message

execute(context=None)

Run a read exeception status request against the store

Returns:The populated response
function_code = 12
class pymodbus.other_message.GetCommEventLogResponse(**kwargs)

Bases: pymodbus.pdu.ModbusResponse

The normal response contains a two-byte status word field, a two-byte event count field, a two-byte message count field, and a field containing 0-64 bytes of events. A byte count field defines the total length of the data in these four field

decode(data)

Decodes a the response

Parameters:data – The packet data to decode
encode()

Encodes the response

Returns:The byte encoded message
function_code = 12
class pymodbus.other_message.ReportSlaveIdRequest(**kwargs)

Bases: pymodbus.pdu.ModbusRequest

This function code is used to read the description of the type, the current status, and other information specific to a remote device.

decode(data)

Decodes data part of the message.

Parameters:data – The incoming data
encode()

Encodes the message

execute(context=None)

Run a read exeception status request against the store

Returns:The populated response
function_code = 17
class pymodbus.other_message.ReportSlaveIdResponse(identifier='x00', status=True, **kwargs)

Bases: pymodbus.pdu.ModbusResponse

The format of a normal response is shown in the following example. The data contents are specific to each type of device.

decode(data)

Decodes a the response

Since the identifier is device dependent, we just return the raw value that a user can decode to whatever it should be.

Parameters:data – The packet data to decode
encode()

Encodes the response

Returns:The byte encoded message
function_code = 17

pymodbus.payload module

Modbus Payload Builders

A collection of utilities for building and decoding modbus messages payloads.

class pymodbus.payload.BinaryPayloadBuilder(payload=None, byteorder='<', wordorder='>', repack=False)

Bases: pymodbus.interfaces.IPayloadBuilder

A utility that helps build payload messages to be written with the various modbus messages. It really is just a simple wrapper around the struct module, however it saves time looking up the format strings. What follows is a simple example:

builder = BinaryPayloadBuilder(byteorder=Endian.Little)
builder.add_8bit_uint(1)
builder.add_16bit_uint(2)
payload = builder.build()
add_16bit_int(value)

Adds a 16 bit signed int to the buffer

Parameters:value – The value to add to the buffer
add_16bit_uint(value)

Adds a 16 bit unsigned int to the buffer

Parameters:value – The value to add to the buffer
add_32bit_float(value)

Adds a 32 bit float to the buffer

Parameters:value – The value to add to the buffer
add_32bit_int(value)

Adds a 32 bit signed int to the buffer

Parameters:value – The value to add to the buffer
add_32bit_uint(value)

Adds a 32 bit unsigned int to the buffer

Parameters:value – The value to add to the buffer
add_64bit_float(value)

Adds a 64 bit float(double) to the buffer

Parameters:value – The value to add to the buffer
add_64bit_int(value)

Adds a 64 bit signed int to the buffer

Parameters:value – The value to add to the buffer
add_64bit_uint(value)

Adds a 64 bit unsigned int to the buffer

Parameters:value – The value to add to the buffer
add_8bit_int(value)

Adds a 8 bit signed int to the buffer

Parameters:value – The value to add to the buffer
add_8bit_uint(value)

Adds a 8 bit unsigned int to the buffer

Parameters:value – The value to add to the buffer
add_bits(values)

Adds a collection of bits to be encoded

If these are less than a multiple of eight, they will be left padded with 0 bits to make it so.

Parameters:value – The value to add to the buffer
add_string(value)

Adds a string to the buffer

Parameters:value – The value to add to the buffer
build()

Return the payload buffer as a list

This list is two bytes per element and can thus be treated as a list of registers.

Returns:The payload buffer as a list
reset()

Reset the payload buffer

to_registers()

Convert the payload buffer into a register layout that can be used as a context block.

Returns:The register layout to use as a block
to_string()

Return the payload buffer as a string

Returns:The payload buffer as a string
class pymodbus.payload.BinaryPayloadDecoder(payload, byteorder='<', wordorder='>')

Bases: object

A utility that helps decode payload messages from a modbus reponse message. It really is just a simple wrapper around the struct module, however it saves time looking up the format strings. What follows is a simple example:

decoder = BinaryPayloadDecoder(payload)
first   = decoder.decode_8bit_uint()
second  = decoder.decode_16bit_uint()
decode_16bit_int()

Decodes a 16 bit signed int from the buffer

decode_16bit_uint()

Decodes a 16 bit unsigned int from the buffer

decode_32bit_float()

Decodes a 32 bit float from the buffer

decode_32bit_int()

Decodes a 32 bit signed int from the buffer

decode_32bit_uint()

Decodes a 32 bit unsigned int from the buffer

decode_64bit_float()

Decodes a 64 bit float(double) from the buffer

decode_64bit_int()

Decodes a 64 bit signed int from the buffer

decode_64bit_uint()

Decodes a 64 bit unsigned int from the buffer

decode_8bit_int()

Decodes a 8 bit signed int from the buffer

decode_8bit_uint()

Decodes a 8 bit unsigned int from the buffer

decode_bits()

Decodes a byte worth of bits from the buffer

decode_string(size=1)

Decodes a string from the buffer

Parameters:size – The size of the string to decode
classmethod fromCoils(klass, coils, byteorder='<')

Initialize a payload decoder with the result of reading a collection of coils from a modbus device.

The coils are treated as a list of bit(boolean) values.

Parameters:
  • coils – The coil results to initialize with
  • byteorder – The endianess of the payload
Returns:

An initialized PayloadDecoder

classmethod fromRegisters(klass, registers, byteorder='<', wordorder='>')

Initialize a payload decoder with the result of reading a collection of registers from a modbus device.

The registers are treated as a list of 2 byte values. We have to do this because of how the data has already been decoded by the rest of the library.

Parameters:
  • registers – The register results to initialize with
  • byteorder – The Byte order of each word
  • wordorder – The endianess of the word (when wordcount is >= 2)
Returns:

An initialized PayloadDecoder

reset()

Reset the decoder pointer back to the start

skip_bytes(nbytes)

Skip n bytes in the buffer

Parameters:nbytes – The number of bytes to skip

pymodbus.pdu module

Contains base classes for modbus request/response/error packets

class pymodbus.pdu.ModbusRequest(**kwargs)

Bases: pymodbus.pdu.ModbusPDU

Base class for a modbus request PDU

doException(exception)

Builds an error response based on the function

Parameters:exception – The exception to return
Raises:An exception response
class pymodbus.pdu.ModbusResponse(**kwargs)

Bases: pymodbus.pdu.ModbusPDU

Base class for a modbus response PDU

should_respond

A flag that indicates if this response returns a result back to the client issuing the request

_rtu_frame_size

Indicates the size of the modbus rtu response used for calculating how much to read.

isError()

Checks if the error is a success or failure

should_respond = True
class pymodbus.pdu.ModbusExceptions

Bases: pymodbus.interfaces.Singleton

An enumeration of the valid modbus exceptions

Acknowledge = 5
GatewayNoResponse = 11
GatewayPathUnavailable = 10
IllegalAddress = 2
IllegalFunction = 1
IllegalValue = 3
MemoryParityError = 8
SlaveBusy = 6
SlaveFailure = 4
classmethod decode(code)

Given an error code, translate it to a string error name.

Parameters:code – The code number to translate
class pymodbus.pdu.ExceptionResponse(function_code, exception_code=None, **kwargs)

Bases: pymodbus.pdu.ModbusResponse

Base class for a modbus exception PDU

ExceptionOffset = 128
decode(data)

Decodes a modbus exception response

Parameters:data – The packet data to decode
encode()

Encodes a modbus exception response

Returns:The encoded exception packet
class pymodbus.pdu.IllegalFunctionRequest(function_code, **kwargs)

Bases: pymodbus.pdu.ModbusRequest

Defines the Modbus slave exception type ‘Illegal Function’ This exception code is returned if the slave:

- does not implement the function code **or**
- is not in a state that allows it to process the function
ErrorCode = 1
decode(data)

This is here so this failure will run correctly

Parameters:data – Not used
execute(context)

Builds an illegal function request error response

Parameters:context – The current context for the message
Returns:The error response packet

pymodbus.register_read_message module

Register Reading Request/Response

class pymodbus.register_read_message.ReadHoldingRegistersRequest(address=None, count=None, **kwargs)

Bases: pymodbus.register_read_message.ReadRegistersRequestBase

This function code is used to read the contents of a contiguous block of holding registers in a remote device. The Request PDU specifies the starting register address and the number of registers. In the PDU Registers are addressed starting at zero. Therefore registers numbered 1-16 are addressed as 0-15.

execute(context)

Run a read holding request against a datastore

Parameters:context – The datastore to request from
Returns:An initialized response, exception message otherwise
function_code = 3
class pymodbus.register_read_message.ReadHoldingRegistersResponse(values=None, **kwargs)

Bases: pymodbus.register_read_message.ReadRegistersResponseBase

This function code is used to read the contents of a contiguous block of holding registers in a remote device. The Request PDU specifies the starting register address and the number of registers. In the PDU Registers are addressed starting at zero. Therefore registers numbered 1-16 are addressed as 0-15.

function_code = 3
class pymodbus.register_read_message.ReadInputRegistersRequest(address=None, count=None, **kwargs)

Bases: pymodbus.register_read_message.ReadRegistersRequestBase

This function code is used to read from 1 to approx. 125 contiguous input registers in a remote device. The Request PDU specifies the starting register address and the number of registers. In the PDU Registers are addressed starting at zero. Therefore input registers numbered 1-16 are addressed as 0-15.

execute(context)

Run a read input request against a datastore

Parameters:context – The datastore to request from
Returns:An initialized response, exception message otherwise
function_code = 4
class pymodbus.register_read_message.ReadInputRegistersResponse(values=None, **kwargs)

Bases: pymodbus.register_read_message.ReadRegistersResponseBase

This function code is used to read from 1 to approx. 125 contiguous input registers in a remote device. The Request PDU specifies the starting register address and the number of registers. In the PDU Registers are addressed starting at zero. Therefore input registers numbered 1-16 are addressed as 0-15.

function_code = 4
class pymodbus.register_read_message.ReadWriteMultipleRegistersRequest(**kwargs)

Bases: pymodbus.pdu.ModbusRequest

This function code performs a combination of one read operation and one write operation in a single MODBUS transaction. The write operation is performed before the read.

Holding registers are addressed starting at zero. Therefore holding registers 1-16 are addressed in the PDU as 0-15.

The request specifies the starting address and number of holding registers to be read as well as the starting address, number of holding registers, and the data to be written. The byte count specifies the number of bytes to follow in the write data field.”

decode(data)

Decode the register request packet

Parameters:data – The request to decode
encode()

Encodes the request packet

Returns:The encoded packet
execute(context)

Run a write single register request against a datastore

Parameters:context – The datastore to request from
Returns:An initialized response, exception message otherwise
function_code = 23
get_response_pdu_size()

Func_code (1 byte) + Byte Count(1 byte) + 2 * Quantity of Coils (n Bytes) :return:

class pymodbus.register_read_message.ReadWriteMultipleRegistersResponse(values=None, **kwargs)

Bases: pymodbus.pdu.ModbusResponse

The normal response contains the data from the group of registers that were read. The byte count field specifies the quantity of bytes to follow in the read data field.

decode(data)

Decode the register response packet

Parameters:data – The response to decode
encode()

Encodes the response packet

Returns:The encoded packet
function_code = 23

pymodbus.register_write_message module

Register Writing Request/Response Messages

class pymodbus.register_write_message.WriteSingleRegisterRequest(address=None, value=None, **kwargs)

Bases: pymodbus.pdu.ModbusRequest

This function code is used to write a single holding register in a remote device.

The Request PDU specifies the address of the register to be written. Registers are addressed starting at zero. Therefore register numbered 1 is addressed as 0.

decode(data)

Decode a write single register packet packet request

Parameters:data – The request to decode
encode()

Encode a write single register packet packet request

Returns:The encoded packet
execute(context)

Run a write single register request against a datastore

Parameters:context – The datastore to request from
Returns:An initialized response, exception message otherwise
function_code = 6
get_response_pdu_size()

Func_code (1 byte) + Register Address(2 byte) + Register Value (2 bytes) :return:

class pymodbus.register_write_message.WriteSingleRegisterResponse(address=None, value=None, **kwargs)

Bases: pymodbus.pdu.ModbusResponse

The normal response is an echo of the request, returned after the register contents have been written.

decode(data)

Decode a write single register packet packet request

Parameters:data – The request to decode
encode()

Encode a write single register packet packet request

Returns:The encoded packet
function_code = 6
class pymodbus.register_write_message.WriteMultipleRegistersRequest(address=None, values=None, **kwargs)

Bases: pymodbus.pdu.ModbusRequest

This function code is used to write a block of contiguous registers (1 to approx. 120 registers) in a remote device.

The requested written values are specified in the request data field. Data is packed as two bytes per register.

decode(data)

Decode a write single register packet packet request

Parameters:data – The request to decode
encode()

Encode a write single register packet packet request

Returns:The encoded packet
execute(context)

Run a write single register request against a datastore

Parameters:context – The datastore to request from
Returns:An initialized response, exception message otherwise
function_code = 16
get_response_pdu_size()

Func_code (1 byte) + Starting Address (2 byte) + Quantity of Reggisters (2 Bytes) :return:

class pymodbus.register_write_message.WriteMultipleRegistersResponse(address=None, count=None, **kwargs)

Bases: pymodbus.pdu.ModbusResponse

“The normal response returns the function code, starting address, and quantity of registers written.

decode(data)

Decode a write single register packet packet request

Parameters:data – The request to decode
encode()

Encode a write single register packet packet request

Returns:The encoded packet
function_code = 16
class pymodbus.register_write_message.MaskWriteRegisterRequest(address=0, and_mask=65535, or_mask=0, **kwargs)

Bases: pymodbus.pdu.ModbusRequest

This function code is used to modify the contents of a specified holding register using a combination of an AND mask, an OR mask, and the register’s current contents. The function can be used to set or clear individual bits in the register.

decode(data)

Decodes the incoming request

Parameters:data – The data to decode into the address
encode()

Encodes the request packet

Returns:The byte encoded packet
execute(context)

Run a mask write register request against the store

Parameters:context – The datastore to request from
Returns:The populated response
function_code = 22
class pymodbus.register_write_message.MaskWriteRegisterResponse(address=0, and_mask=65535, or_mask=0, **kwargs)

Bases: pymodbus.pdu.ModbusResponse

The normal response is an echo of the request. The response is returned after the register has been written.

decode(data)

Decodes a the response

Parameters:data – The packet data to decode
encode()

Encodes the response

Returns:The byte encoded message
function_code = 22

pymodbus.transaction module

Collection of transaction based abstractions

class pymodbus.transaction.FifoTransactionManager(client, **kwargs)

Bases: pymodbus.transaction.ModbusTransactionManager

Impelements a transaction for a manager where the results are returned in a FIFO manner.

addTransaction(request, tid=None)

Adds a transaction to the handler

This holds the requets in case it needs to be resent. After being sent, the request is removed.

Parameters:
  • request – The request to hold on to
  • tid – The overloaded transaction id to use
delTransaction(tid)

Removes a transaction matching the referenced tid

Parameters:tid – The transaction to remove
getTransaction(tid)

Returns a transaction matching the referenced tid

If the transaction does not exist, None is returned

Parameters:tid – The transaction to retrieve
class pymodbus.transaction.DictTransactionManager(client, **kwargs)

Bases: pymodbus.transaction.ModbusTransactionManager

Impelements a transaction for a manager where the results are keyed based on the supplied transaction id.

addTransaction(request, tid=None)

Adds a transaction to the handler

This holds the requets in case it needs to be resent. After being sent, the request is removed.

Parameters:
  • request – The request to hold on to
  • tid – The overloaded transaction id to use
delTransaction(tid)

Removes a transaction matching the referenced tid

Parameters:tid – The transaction to remove
getTransaction(tid)

Returns a transaction matching the referenced tid

If the transaction does not exist, None is returned

Parameters:tid – The transaction to retrieve
class pymodbus.transaction.ModbusSocketFramer(decoder, client=None)

Bases: pymodbus.framer.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
addToFrame(message)

Adds new packet data to the current frame buffer

Parameters:message – The most recent packet
advanceFrame()

Skip over the current framed message This allows us to skip over the current message after we have processed it or determined that it contains an error. It also has to reset the current frame header handle

buildPacket(message)

Creates a ready to send modbus packet

Parameters:message – The populated request/response to send
checkFrame()

Check and decode the next frame Return true if we were successful

decode_data(data)
getFrame()

Return the next frame from the buffered data

Returns:The next full frame buffer
getRawFrame()

Returns the complete buffer

isFrameReady()

Check if we should continue decode logic This is meant to be used in a while loop in the decoding phase to let the decoder factory know that there is still data in the buffer.

Returns:True if ready, False otherwise
populateResult(result)

Populates the modbus result with the transport specific header information (pid, tid, uid, checksum, etc)

Parameters:result – The response packet
processIncomingPacket(data, callback, unit, **kwargs)

The new packet processing 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.

Parameters:
  • data – The new packet data
  • callback – The function to send results to
  • unit – Process if unit id matches, ignore otherwise (could be a

list of unit ids (server) or single unit id(client/server) :param single: True or False (If True, ignore unit address validation)

resetFrame()

Reset the entire message frame. This allows us to skip ovver errors that may be in the stream. It is hard to know if we are simply out of sync or if there is an error in the stream as we have no way to check the start or end of the message (python just doesn’t have the resolution to check for millisecond delays).

class pymodbus.transaction.ModbusRtuFramer(decoder, client)

Bases: pymodbus.framer.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
addToFrame(message)

This should be used before the decoding while loop to add the received data to the buffer handle.

Parameters:message – The most recent packet
advanceFrame()

Skip over the current framed message This allows us to skip over the current message after we have processed it or determined that it contains an error. It also has to reset the current frame header handle

buildPacket(message)

Creates a ready to send modbus packet

Parameters:message – The populated request/response to send
checkFrame()

Check if the next frame is available. Return True if we were successful.

  1. Populate header
  2. Discard frame if UID does not match
decode_data(data)
getFrame()

Get the next frame from the buffer

Returns:The frame data or ‘’
getRawFrame()

Returns the complete buffer

isFrameReady()

Check if we should continue decode logic This is meant to be used in a while loop in the decoding phase to let the decoder know that there is still data in the buffer.

Returns:True if ready, False otherwise
populateHeader(data=None)

Try to set the headers uid, len and crc.

This method examines self._buffer and writes meta information into self._header. It calculates only the values for headers that are not already in the dictionary.

Beware that this method will raise an IndexError if self._buffer is not yet long enough.

populateResult(result)

Populates the modbus result header

The serial packets do not have any header information that is copied.

Parameters:result – The response packet
processIncomingPacket(data, callback, unit, **kwargs)

The new packet processing 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.

Parameters:
  • data – The new packet data
  • callback – The function to send results to
  • unit – Process if unit id matches, ignore otherwise (could be a

list of unit ids (server) or single unit id(client/server) :param single: True or False (If True, ignore unit address validation)

recvPacket(size)

Receives packet from the bus with specified len :param size: Number of bytes to read :return:

resetFrame()

Reset the entire message frame. This allows us to skip over errors that may be in the stream. It is hard to know if we are simply out of sync or if there is an error in the stream as we have no way to check the start or end of the message (python just doesn’t have the resolution to check for millisecond delays).

sendPacket(message)

Sends packets on the bus with 3.5char delay between frames :param message: Message to be sent over the bus :return:

class pymodbus.transaction.ModbusAsciiFramer(decoder, client=None)

Bases: pymodbus.framer.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.

addToFrame(message)

Add the next message to the frame buffer This should be used before the decoding while loop to add the received data to the buffer handle.

Parameters:message – The most recent packet
advanceFrame()

Skip over the current framed message This allows us to skip over the current message after we have processed it or determined that it contains an error. It also has to reset the current frame header handle

buildPacket(message)

Creates a ready to send modbus packet Built off of a modbus request/response

Parameters:message – The request/response to send
Returns:The encoded packet
checkFrame()

Check and decode the next frame

Returns:True if we successful, False otherwise
decode_data(data)
getFrame()

Get the next frame from the buffer

Returns:The frame data or ‘’
isFrameReady()

Check if we should continue decode logic This is meant to be used in a while loop in the decoding phase to let the decoder know that there is still data in the buffer.

Returns:True if ready, False otherwise
populateResult(result)

Populates the modbus result header

The serial packets do not have any header information that is copied.

Parameters:result – The response packet
processIncomingPacket(data, callback, unit, **kwargs)

The new packet processing 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.

Parameters:
  • data – The new packet data
  • callback – The function to send results to
  • unit – Process if unit id matches, ignore otherwise (could be a

list of unit ids (server) or single unit id(client/server)) :param single: True or False (If True, ignore unit address validation)

resetFrame()

Reset the entire message frame. This allows us to skip ovver errors that may be in the stream. It is hard to know if we are simply out of sync or if there is an error in the stream as we have no way to check the start or end of the message (python just doesn’t have the resolution to check for millisecond delays).

class pymodbus.transaction.ModbusBinaryFramer(decoder, client=None)

Bases: pymodbus.framer.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.

addToFrame(message)

Add the next message to the frame buffer This should be used before the decoding while loop to add the received data to the buffer handle.

Parameters:message – The most recent packet
advanceFrame()

Skip over the current framed message This allows us to skip over the current message after we have processed it or determined that it contains an error. It also has to reset the current frame header handle

buildPacket(message)

Creates a ready to send modbus packet

Parameters:message – The request/response to send
Returns:The encoded packet
checkFrame()

Check and decode the next frame

Returns:True if we are successful, False otherwise
decode_data(data)
getFrame()

Get the next frame from the buffer

Returns:The frame data or ‘’
isFrameReady()

Check if we should continue decode logic This is meant to be used in a while loop in the decoding phase to let the decoder know that there is still data in the buffer.

Returns:True if ready, False otherwise
populateResult(result)

Populates the modbus result header

The serial packets do not have any header information that is copied.

Parameters:result – The response packet
processIncomingPacket(data, callback, unit, **kwargs)

The new packet processing 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.

Parameters:
  • data – The new packet data
  • callback – The function to send results to
  • unit – Process if unit id matches, ignore otherwise (could be a

list of unit ids (server) or single unit id(client/server) :param single: True or False (If True, ignore unit address validation)

resetFrame()

Reset the entire message frame. This allows us to skip ovver errors that may be in the stream. It is hard to know if we are simply out of sync or if there is an error in the stream as we have no way to check the start or end of the message (python just doesn’t have the resolution to check for millisecond delays).

pymodbus.utilities module

Modbus Utilities

A collection of utilities for packing data, unpacking data computing checksums, and decode checksums.

pymodbus.utilities.pack_bitstring(bits)

Creates a string out of an array of bits

Parameters:bits – A bit array

example:

bits   = [False, True, False, True]
result = pack_bitstring(bits)
pymodbus.utilities.unpack_bitstring(string)

Creates bit array out of a string

Parameters:string – The modbus data packet to decode

example:

bytes  = 'bytes to decode'
result = unpack_bitstring(bytes)
pymodbus.utilities.default(value)

Given a python object, return the default value of that object.

Parameters:value – The value to get the default of
Returns:The default value
pymodbus.utilities.computeCRC(data)

Computes a crc16 on the passed in string. For modbus, this is only used on the binary serial protocols (in this case RTU).

The difference between modbus’s crc16 and a normal crc16 is that modbus starts the crc value out at 0xffff.

Parameters:data – The data to create a crc16 of
Returns:The calculated CRC
pymodbus.utilities.checkCRC(data, check)

Checks if the data matches the passed in CRC

Parameters:
  • data – The data to create a crc16 of
  • check – The CRC to validate
Returns:

True if matched, False otherwise

pymodbus.utilities.computeLRC(data)

Used to compute the longitudinal redundancy check against a string. This is only used on the serial ASCII modbus protocol. A full description of this implementation can be found in appendex B of the serial line modbus description.

Parameters:data – The data to apply a lrc to
Returns:The calculated LRC
pymodbus.utilities.checkLRC(data, check)

Checks if the passed in data matches the LRC

Parameters:
  • data – The data to calculate
  • check – The LRC to validate
Returns:

True if matched, False otherwise

pymodbus.utilities.rtuFrameSize(data, byte_count_pos)

Calculates the size of the frame based on the byte count.

Parameters:
  • data – The buffer containing the frame.
  • byte_count_pos – The index of the byte count in the buffer.
Returns:

The size of the frame.

The structure of frames with a byte count field is always the same:

  • first, there are some header fields
  • then the byte count field
  • then as many data bytes as indicated by the byte count,
  • finally the CRC (two bytes).

To calculate the frame size, it is therefore sufficient to extract the contents of the byte count field, add the position of this field, and finally increment the sum by three (one byte for the byte count field, two for the CRC).

pymodbus.version module

Handle the version information here; you should only have to change the version tuple.

Since we are using twisted’s version class, we can also query the svn version as well using the local .entries file.

Module contents

Pymodbus: Modbus Protocol Implementation

TwistedModbus is built on top of the code developed by:

Copyright (c) 2001-2005 S.W.A.C. GmbH, Germany. Copyright (c) 2001-2005 S.W.A.C. Bohemia s.r.o., Czech Republic. Hynek Petrak <hynek@swac.cz>

Released under the the BSD license