modbus_master 1.0.0  modbus_master: ^1.0.0 copied to clipboard
modbus_master: ^1.0.0 copied to clipboard
An easy to use package using which a dart program can work as a Modbus/TCP master device.
'modbus_master' is an easy to use package using which a dart program can work as a Modbus/TCP master device.
- Currently users can use only these features of Modbus/TCP:
- Discrete input
- Read single discrete input
 
- Coil
- Read single coil
- Write single coil
 
- Input Register
- Read single input register
 
- Holding Register
- Read single holding register
- Write single holding register
 
 
- Discrete input
- Currently only TCP ipv4 is implemented.
- A single stream object is used for response received from all slave devices.
- This package handles socket networking part in a separate isolate so that main isolate is free to handle other tasks like UI part of flutter.
- This package can be used on all platforms which supports dart:io & dart:isolate i.e. WINDOWS, LINUX, MACOS, ANDROID, IOS.
Important information to know about this package #
For each request, a response is always generated #
- If response is not received from slave device within timeout, an error response is generated by library and is put to "responses()" stream
- When first request is sent to a slave device, connection is established and connection is kept alive.
- Whenever a request is sent to a slave device, first it checks whether connection is already established.
- If connection is already established, then sends request.
- If connection is found to be broken, then tries to establish connection.
 
- If there are already 247 active connections, and request to a new address is sent. Then, earliest connection is broken, and this new connection is established.
- If close method is executed, then first responses for all pending requests are generated. After that, all active connections are closed.
Timeout #
An error response is produced by package, if slave response is not received within timeout. Duration of timeout differs in two different scenarios:
- Scenario 1: When connection is already established
- if response is not produced within timeout(default 1000ms),
- master produces error response
 
 Timeout = request timeout (default 1000ms) 
- if response is not produced within timeout(default 1000ms),
- Scenario 2: When connection is not established
- master tries for connection
- if connection is not established within socketConnectionTimeout(default 2000 ms)
- master produces error response
 
- if connection is established
- if response is not produced within timeout (default 1000ms)
- master produces error response
 
 
- if response is not produced within timeout (default 1000ms)
 Timeout (maximum) = socket connection timeout(default 2000ms) + request timeout(default 1000ms) 
Limitations #
- works with only ipv4, ipv6 is not supported
- only 247 slaves can be connected at one time,
- when more than 247 slave is connected, oldest slave connection is broken
 
- Only single element can be read at once, reading multiple coils or multiple registers is not implemented, although reading multiple elements is specified in modbus/tcp implementation
- Only single element can be written to at once, writing to multiple coils or to multiple registers is not implemented, although writing to multiple elements is specified in modbus/tcp implementation
- works with dart 3.0 and above because it uses dart records
Steps to use this library #
- 
make function async where this object needs to be created 
- 
make an instance of ModbusMaster class like this only. final modbusMaster = await ModbusMaster.start();
- 
listen to stream of response using stream modbusMaster.responses().listen( (response) { print(response); } );
- 
Send request to slave using these commands - 
read single coil of a slave modbusMaster.readCoil( ipv4: '192.168.29.163', portNo: 502, elementNumberOneTo65536: 11, );
- 
read single discrete input of a slave modbusMaster.readDiscreteInput( ipv4: '192.168.1.5', elementNumberOneTo65536: 11, );
- 
read single holding register of a slave modbusMaster.readHoldingRegister( ipv4: '192.168.1.5', elementNumberOneTo65536: 11, );
- 
read single input register of a slave modbusMaster.readInputRegister( ipv4: '192.168.1.5', elementNumberOneTo65536: 11, );
- 
write single coil of a slave modbusMaster.writeCoil( ipv4: '192.168.1.5', elementNumberOneTo65536: 11, valueToBeWritten: true, );
- 
write single holding register of a slave modbusMaster.writeHoldingRegister( ipv4: '192.168.1.5', elementNumberOneTo65536: 11, valueToBeWritten: 15525, );
 
- 
- 
close must be called at end to close all tcp connections and stop modbus master modbusMaster.close();
Example Code #
1. First start Modbus/TCP server i.e. slave device using pyModbusTCP library #
from pyModbusTCP.server import ModbusServer
import time
import socket
# get ipv4 address
host_ip = socket.gethostbyname(socket.gethostname())
modbusServer = ModbusServer(host = host_ip, port =502, no_block =True)
try:
    print('Trying to start MODBUS/TCP SLAVE SERVER')
    modbusServer.start()
    print(f'MODBUS/TCP SLAVE SERVER is online at {host_ip}')
    
    set_coil = True
    while True:
        if set_coil:
            # coil address is coil number - 1, therefore 11-1 is written
            modbusServer.data_bank.set_coils(11-1,bit_list=[True])
            print('COIL-11 = SET')
        else:
            modbusServer.data_bank.set_coils(11-1,bit_list=[False])
            print('COIL-11 = RESET')
        print('WAITING FOR 5 SECONDS')
        time.sleep(5)
        set_coil = not set_coil
except Exception as error:
    print(error)
    print(f'Trying to stop MODBUS/TCP SLAVE SERVER at {host_ip}')
    modbusServer.stop()
    print('MODBUS/TCP SLAVE SERVER is offline')
2. Check whether Modbus/TCP server (slave) is online or not #
- Check whether socket for Server is open or not using windows powershell command
# use ip address of your device, which is printed by python script netstat -na | Select-String "192.168.29.163:502"- When socket is listening, netstat command shows this
TCP 192.168.29.163:502 0.0.0.0:0 LISTENING
- When socket is closed, netstat command shows nothing
 
- When socket is listening, netstat command shows this
3. Use dart code & ModbusMaster library to read value of coil of slave (pyModbusTCP server) #
import 'modbus_master_isolate.dart';
void main() {
  testReadingCoil();
}
void testReadingCoil() async {
  final modbusMaster = await ModbusMaster.start();
  int countResponseReceived = 0;
  modbusMaster.responses().listen(
    (response) {
      ++countResponseReceived;
      print(response);
      if (countResponseReceived >= 3) {
        // close modbusMaster when 3 responses are received
        modbusMaster.close();
      }
    },
  );
  for (int i = 1; i <= 5; ++i) {
    print('-> Request $i');
    try {
      modbusMaster.readCoil(
        ipv4: '192.168.29.163',
        portNo: 502,
        elementNumberOneTo65536: 11,
      );
    } catch (e) {
      // When read request is executed after close command, exception is raised.
      print('EXCEPTION THROWN WHILE READING $e');
    }
    await Future.delayed(Duration(seconds: 5));
  }
}
4. Close python script by repeatedly pressing Ctrl+C in python interpreter #
- Check whether socket is open or not using 'netstat' command given above.
- If python script has finished but socket is open, use python statement to close modbusServer
modbusServer.stop()
- Recheck status of socket using 'netstat'.