Skip to content

Latest commit

 

History

History
221 lines (159 loc) · 10.5 KB

index.rst

File metadata and controls

221 lines (159 loc) · 10.5 KB

Quick start guide

Overview of the package

pyModbusTCP give access to modbus/TCP server through the ModbusClient object. This class is define in the client module.

Since version 0.1.0, a server is available as ModbusServer class. This server is currently in test (API can change at any time).

To deal with frequent need of modbus data mangling (for example convert 32 bits IEEE float to 2x16 bits words) a special module named utils provide some helpful functions.

Package map:

image

Package setup

from PyPi:

# install the last available version (stable)
sudo pip3 install pyModbusTCP
# or upgrade from an older version
sudo pip3 install pyModbusTCP --upgrade

# you can also install a specific version (here v0.1.10)
sudo pip3 install pyModbusTCP==v0.1.10

from GitHub:

git clone https://github.com/sourceperl/pyModbusTCP.git
cd pyModbusTCP
# here change "python" by your python target(s) version(s) (like python3.9)
sudo python setup.py install

ModbusClient: init

Init module from constructor (raise ValueError if host/port error):

from pyModbusTCP.client import ModbusClient

try:
    c = ModbusClient(host='localhost', port=502)
except ValueError:
    print("Error with host or port params")

Or with properties:

from pyModbusTCP.client import ModbusClient

c = ModbusClient()
c.host = 'localhost'
c.port = 502

Since version 0.2.0, "auto open" mode is the default behaviour to deal with TCP open/close.

The "auto open" mode keep the TCP connection always open, so the default constructor is:

c = ModbusClient(host="localhost", auto_open=True, auto_close=False)

It's also possible to open/close TCP socket before and after each request:

c = ModbusClient(host="localhost", auto_open=True, auto_close=True)

Another way to deal with connection is to manually set it. Like this:

c = ModbusClient(host="localhost", auto_open=False, auto_close=False)

# open the socket for 2 reads then close it.
if c.open():
    regs_list_1 = c.read_holding_registers(0, 10)
    regs_list_2 = c.read_holding_registers(55, 10)
    c.close()

ModbusClient: available modbus requests functions

See http://en.wikipedia.org/wiki/Modbus for full table.

Domain Function name Function code ModbusClient function
Bit

Read Discrete Inputs

------------------------------+

Read Coils

------------------------------+

Write Single Coil

------------------------------+

Write Multiple Coils

2

---------------+

1

---------------+

5

---------------+

15

:py~pyModbusTCP.client.ModbusClient.read_discrete_inputs

--------------------------------------------------------------------------+

:py~pyModbusTCP.client.ModbusClient.read_coils

--------------------------------------------------------------------------+

:py~pyModbusTCP.client.ModbusClient.write_single_coil

--------------------------------------------------------------------------+

:py~pyModbusTCP.client.ModbusClient.write_multiple_coils

Register

Read Input Registers

------------------------------+

Read Holding Registers

------------------------------+

Write Single Register

------------------------------+

Write Multiple Registers

------------------------------+

Read/Write Multiple Registers

------------------------------+

Mask Write Register

4

---------------+

3

---------------+

6

---------------+

16

---------------+

23

---------------+

22

:py~pyModbusTCP.client.ModbusClient.read_input_registers

--------------------------------------------------------------------------+

:py~pyModbusTCP.client.ModbusClient.read_holding_registers

--------------------------------------------------------------------------+

:py~pyModbusTCP.client.ModbusClient.write_single_register

--------------------------------------------------------------------------+

:py~pyModbusTCP.client.ModbusClient.write_multiple_registers

--------------------------------------------------------------------------+

:py~pyModbusTCP.client.ModbusClient.write_read_multiple_registers

--------------------------------------------------------------------------+

n/a

File

Read FIFO Queue

------------------------------+

Read File Record

------------------------------+

Write File Record

------------------------------+

Read Exception Status

24

---------------+

20

---------------+

21

---------------+

7

n/a

--------------------------------------------------------------------------+

n/a

--------------------------------------------------------------------------+

n/a

--------------------------------------------------------------------------+

n/a

Diagnostic

Diagnostic

------------------------------+

Get Com Event Counter

------------------------------+

Get Com Event Log

------------------------------+

Report Slave ID

------------------------------+

Read Device Identification

8

---------------+

11

---------------+

12

---------------+

17

---------------+

43

n/a

--------------------------------------------------------------------------+

n/a

--------------------------------------------------------------------------+

n/a

--------------------------------------------------------------------------+

n/a

--------------------------------------------------------------------------+

:py~pyModbusTCP.client.ModbusClient.read_device_identification

ModbusClient: debug mode

If need, you can enable a debug mode for ModbusClient like this:

from pyModbusTCP.client import ModbusClient
c = ModbusClient(host="localhost", port=502, debug=True)

or:

c.debug = True

when debug is enable all debug message is print on console and you can see modbus frame:

c.read_holding_registers(0, 4)

print:

Tx
[E7 53 00 00 00 06 01] 03 00 00 00 04
Rx
[E7 53 00 00 00 0B 01] 03 08 00 00 00 6F 00 00 00 00
[0, 111, 0, 0]

utils module: Modbus data mangling

When we have to deal with the variety types of registers of PLC device, we often need some data mangling. Utils part of pyModbusTCP can help you in this task. Now, let's see some use cases.

  • deal with negative numbers (two's complement):

    from pyModbusTCP import utils
    
    list_16_bits = [0x0000, 0xFFFF, 0x00FF, 0x8001]
    
    # show "[0, -1, 255, -32767]"
    print(utils.get_list_2comp(list_16_bits, 16))
    
    # show "-1"
    print(utils.get_2comp(list_16_bits[1], 16))

More at http://en.wikipedia.org/wiki/Two%27s_complement

  • convert integer of val_size bits (default is 16) to an array of boolean:

    from pyModbusTCP import utils
    
    # show "[True, False, True, False, False, False, False, False]"
    print(utils.get_bits_from_int(0x05, val_size=8))
  • read of 32 bits registers (also know as long format):

    from pyModbusTCP import utils
    
    list_16_bits = [0x0123, 0x4567, 0xdead, 0xbeef]
    
    # big endian sample (default)
    list_32_bits = utils.word_list_to_long(list_16_bits)
    # show "['0x1234567', '0xdeadbeef']"
    print([hex(i) for i in list_32_bits])
    
    # little endian sample
    list_32_bits = utils.word_list_to_long(list_16_bits, big_endian=False)
    # show "['0x45670123', '0xbeefdead']"
    print([hex(i) for i in list_32_bits])
  • IEEE single/double precision floating-point:

    from pyModbusTCP import utils
    
    # 32 bits IEEE single precision
    # encode : python float 0.3 -> int 0x3e99999a
    # display "0x3e99999a"
    print(hex(utils.encode_ieee(0.3)))
    # decode: python int 0x3e99999a -> float 0.3
    # show "0.300000011921" (it's not 0.3, precision leak with float...)
    print(utils.decode_ieee(0x3e99999a))
    
    # 64 bits IEEE double precision
    # encode: python float 6.62606957e-34 -> int 0x390b860bb596a559
    # display "0x390b860bb596a559"
    print(hex(utils.encode_ieee(6.62606957e-34, double=True)))
    # decode: python int 0x390b860bb596a559 -> float 6.62606957e-34
    # display "6.62606957e-34"
    print(utils.decode_ieee(0x390b860bb596a559, double=True))