From 1a79a0ff773f55ba0c81c0c5f97251185b4bdff9 Mon Sep 17 00:00:00 2001 From: evg3 Date: Wed, 21 Jun 2023 18:42:46 +0300 Subject: [PATCH] final_ver Final version Modbus RTU master-slave on Java --- .idea/modules.xml | 1 + mbrtu/build.gradle | 1 - mbrtu/src/main/java/MainSlave.java | 200 ++++++++++++++++++++++------- mbrtu/src/main/java/main.java | 146 ++++++++++++++++++--- modbus_master_rtu.iml | 20 +++ 5 files changed, 307 insertions(+), 61 deletions(-) create mode 100644 modbus_master_rtu.iml diff --git a/.idea/modules.xml b/.idea/modules.xml index 75ee111..1995461 100644 --- a/.idea/modules.xml +++ b/.idea/modules.xml @@ -4,6 +4,7 @@ + \ No newline at end of file diff --git a/mbrtu/build.gradle b/mbrtu/build.gradle index 12be60b..144c635 100644 --- a/mbrtu/build.gradle +++ b/mbrtu/build.gradle @@ -10,5 +10,4 @@ repositories { dependencies { testCompile group: 'junit', name: 'junit', version: '4.11' compile group: 'com.github.kochedykov', name: 'jlibmodbus', version: '1.2.9.0' - } \ No newline at end of file diff --git a/mbrtu/src/main/java/MainSlave.java b/mbrtu/src/main/java/MainSlave.java index 88c8ff0..bce154f 100644 --- a/mbrtu/src/main/java/MainSlave.java +++ b/mbrtu/src/main/java/MainSlave.java @@ -1,64 +1,113 @@ import com.intelligt.modbus.jlibmodbus.Modbus; -import com.intelligt.modbus.jlibmodbus.ModbusSlave; -import com.intelligt.modbus.jlibmodbus.ModbusSlaveFactory; import com.intelligt.modbus.jlibmodbus.data.DataHolder; import com.intelligt.modbus.jlibmodbus.data.ModbusHoldingRegisters; -import com.intelligt.modbus.jlibmodbus.exception.ModbusIOException; +import com.intelligt.modbus.jlibmodbus.data.ModbusCoils; +import com.intelligt.modbus.jlibmodbus.exception.IllegalDataAddressException; +import com.intelligt.modbus.jlibmodbus.exception.IllegalDataValueException; +import com.intelligt.modbus.jlibmodbus.ModbusSlave; +import com.intelligt.modbus.jlibmodbus.ModbusSlaveFactory; +import com.intelligt.modbus.jlibmodbus.tcp.TcpParameters; import com.intelligt.modbus.jlibmodbus.serial.*; import jssc.SerialPortList; -import java.io.Console; +import java.net.InetAddress; +import java.util.ArrayList; +import java.util.List; public class MainSlave { - static public void main(String[] arg) { - SerialParameters sp = new SerialParameters(); - Modbus.setLogLevel(Modbus.LogLevel.LEVEL_DEBUG); + static public void main(String[] argv) { try { - String[] dev_list = SerialPortList.getPortNames(); - System.out.println("Доступные порты:"); - for (int n = 0; n < dev_list.length; n++) { - System.out.println(dev_list[n]); - } + final ModbusSlave slave; - if (dev_list.length > 0) { - sp.setDevice(arg[arg.length - 1]); - sp.setBaudRate(SerialPort.BaudRate.BAUD_RATE_9600); - sp.setDataBits(8); - sp.setParity(SerialPort.Parity.NONE); - sp.setStopBits(1); + SerialParameters serialParameters = new SerialParameters(); + serialParameters.setDevice("COM3"); + serialParameters.setBaudRate(SerialPort.BaudRate.BAUD_RATE_9600); + serialParameters.setDataBits(8); + serialParameters.setParity(SerialPort.Parity.NONE); + serialParameters.setStopBits(1); - SerialUtils.setSerialPortFactory(new SerialPortFactoryJSSC()); - ModbusSlave m = ModbusSlaveFactory.createModbusSlaveRTU(sp); + slave = ModbusSlaveFactory.createModbusSlaveRTU(serialParameters); + slave.setReadTimeout(0); // if not set default timeout is 1000ms, I think this must be set to 0 (infinitive timeout) + Modbus.setLogLevel(Modbus.LogLevel.LEVEL_DEBUG); - DataHolder dataHolder = new DataHolder(); - ModbusHoldingRegisters registers = new ModbusHoldingRegisters(10); - registers.set(0, 101); - registers.set(1, 105); - registers.set(2, 660); - - dataHolder.setHoldingRegisters(registers); - m.setDataHolder(dataHolder); - - try { - m.listen(); - int symbol = 0; - while (symbol >= 0) { - symbol = System.in.read(); - if (symbol != 10) - registers.set(0, symbol); - } - - } catch (ModbusIOException e) { - e.printStackTrace(); - } catch (RuntimeException e) { - throw e; - } catch (Exception e) { - e.printStackTrace(); + MyOwnDataHolder dh = new MyOwnDataHolder(); + dh.addEventListener(new ModbusEventListener() { + @Override + public void onWriteToSingleCoil(int address, boolean value) { + System.out.print("onWriteToSingleCoil: address " + address + ", value " + value); } + + @Override + public void onWriteToMultipleCoils(int address, int quantity, boolean[] values) { + System.out.print("onWriteToMultipleCoils: address " + address + ", quantity " + quantity); + } + + @Override + public void onWriteToSingleHoldingRegister(int address, int value) { + System.out.print("onWriteToSingleHoldingRegister: address " + address + ", value " + value); + } + + @Override + public void onWriteToMultipleHoldingRegisters(int address, int quantity, int[] values) { + System.out.print("onWriteToMultipleHoldingRegisters: address " + address + ", quantity " + quantity); + } + }); + + slave.setDataHolder(dh); + ModbusHoldingRegisters hr = new ModbusHoldingRegisters(10); + hr.set(0, 12345); + hr.set(1, 1234); + slave.getDataHolder().setHoldingRegisters(hr); + ModbusCoils cl = new ModbusCoils(10); + cl.set(0,true); + cl.set(1,false); + cl.set(2,false); + cl.set(3,true); + cl.set(4,true); + cl.set(5,false); + cl.set(6,true); + cl.set(7,false); + slave.getDataHolder().setCoils(cl); + ModbusCoils ds = dh.getDiscreteInputs(); + ds.set(0,true); + ds.set(1,true); + ds.set(2,false); + slave.getDataHolder().setDiscreteInputs(ds); + ModbusHoldingRegisters ir = dh.getInputRegisters(); + ir.set(0,432); + ir.set(1,234); + slave.getDataHolder().setInputRegisters(ir); + slave.setServerAddress(1); + /* + * using master-branch it should be #slave.open(); + */ + slave.listen(); + + /* + * since 1.2.8 + */ + if (slave.isListening()) { + Runtime.getRuntime().addShutdownHook(new Thread() { + @Override + public void run() { + synchronized (slave) { + slave.notifyAll(); + } + } + }); + + synchronized (slave) { + slave.wait(); + } + + /* + * using master-branch it should be #slave.close(); + */ + slave.shutdown(); } } catch (RuntimeException e) { throw e; @@ -66,4 +115,67 @@ public class MainSlave { e.printStackTrace(); } } + + public interface ModbusEventListener { + void onWriteToSingleCoil(int address, boolean value); + + void onWriteToMultipleCoils(int address, int quantity, boolean[] values); + + void onWriteToSingleHoldingRegister(int address, int value); + + void onWriteToMultipleHoldingRegisters(int address, int quantity, int[] values); + } + + public static class MyOwnDataHolder extends DataHolder { + + final List modbusEventListenerList = new ArrayList(); + + public MyOwnDataHolder() { + + setHoldingRegisters(new ModbusHoldingRegisters(10)); + setCoils(new ModbusCoils(128)); + setDiscreteInputs(new ModbusCoils(128)); + setInputRegisters(new ModbusHoldingRegisters(10)); + } + + public void addEventListener(ModbusEventListener listener) { + modbusEventListenerList.add(listener); + } + + public boolean removeEventListener(ModbusEventListener listener) { + return modbusEventListenerList.remove(listener); + } + + @Override + public void writeHoldingRegister(int offset, int value) throws IllegalDataAddressException, IllegalDataValueException { + for (ModbusEventListener l : modbusEventListenerList) { + l.onWriteToSingleHoldingRegister(offset, value); + } + super.writeHoldingRegister(offset, value); + } + + @Override + public void writeHoldingRegisterRange(int offset, int[] range) throws IllegalDataAddressException, IllegalDataValueException { + for (ModbusEventListener l : modbusEventListenerList) { + l.onWriteToMultipleHoldingRegisters(offset, range.length, range); + } + super.writeHoldingRegisterRange(offset, range); + } + + @Override + public void writeCoil(int offset, boolean value) throws IllegalDataAddressException, IllegalDataValueException { + for (ModbusEventListener l : modbusEventListenerList) { + l.onWriteToSingleCoil(offset, value); + } + super.writeCoil(offset, value); + } + + @Override + public void writeCoilRange(int offset, boolean[] range) throws IllegalDataAddressException, IllegalDataValueException { + for (ModbusEventListener l : modbusEventListenerList) { + l.onWriteToMultipleCoils(offset, range.length, range); + } + super.writeCoilRange(offset, range); + } + } } \ No newline at end of file diff --git a/mbrtu/src/main/java/main.java b/mbrtu/src/main/java/main.java index b6dd12f..dfc8a97 100644 --- a/mbrtu/src/main/java/main.java +++ b/mbrtu/src/main/java/main.java @@ -5,8 +5,7 @@ import com.intelligt.modbus.jlibmodbus.exception.ModbusIOException; import com.intelligt.modbus.jlibmodbus.serial.*; import jssc.SerialPortList; -import java.util.logging.Logger; - +import java.util.Scanner; public class main { @@ -26,8 +25,8 @@ public class main { } if (dev_list.length > 0) { - //Настройка - sp.setDevice(arg[arg.length - 1]); + //Настройка подключения к порту и передачи данных + sp.setDevice("COM6"); sp.setBaudRate(SerialPort.BaudRate.BAUD_RATE_9600); sp.setDataBits(8); sp.setParity(SerialPort.Parity.NONE); @@ -39,30 +38,145 @@ public class main { m.connect(); + //Настройка int slaveId = 1; // id устройства slave int offset = 0; // Начальный адресс - int quantity = 3; //Количество условных портов + int quantity1 = 8; //Количество условных портов + int quantity2 = 3; + int quantity3 = 2; + int quantity4 = 2; + + Scanner sc = new Scanner(System.in); try { - int[] registerValues = m.readHoldingRegisters(slaveId, offset, quantity); // Настройка тип регситра(в данном случае установлены регистры хранения) - //Вывод - for (int value : registerValues) { - System.out.println("Адресс: " + offset + ", Значение: " + value); - offset++; + System.out.println("Выберите режим: \n"+"1. Чтение регистра флага(Read Coils)\n"+ + "2. Запись регистра флага(Write Coils)\n"+"3. Чтение дискретного входа(Read Discrete Inputs)\n"+ + "4. Чтение регистра входа(Read Input Registers)\n"+"5. Чтение регистра хранения(Read Holding Registers)\n"+ + "6. Запись регистра хранения(Write Holding Registers)\n"); + + int swc = sc.nextInt(); + + switch (swc){ + case 1: + boolean[] regCoils = m.readCoils(slaveId, offset, quantity1); + for(boolean val1 : regCoils){ + System.out.println("Адресс флага: "+offset+", Значения флага: "+ val1); + offset++; + if(offset == quantity1){ + break; + } + } + break; + + case 2: + System.out.println("Выберите Single или Multiple coils запись: \n" + "1. Запись Single Coil\n"+ + "2. Запись Multiple Coils\n"); + + Scanner sc2 = new Scanner(System.in); + int coilsc = sc2.nextInt(); + switch (coilsc){ + case 1: + m.writeSingleCoil(slaveId, 0, true); + boolean[] wregCoils = m.readCoils(slaveId, offset, quantity1); + for(boolean val2 : wregCoils){ + System.out.println("Адресс флага: "+offset+", Значения флага: "+ val2); + offset++; + if(offset == quantity1){ + break; + } + } + break; + case 2: + m.writeMultipleCoils(1,0,new boolean[]{true,true,true,true,true,true,true,true}); + boolean[] wregMulCoils = m.readCoils(slaveId, offset, quantity1); + for(boolean val2 : wregMulCoils){ + System.out.println("Адресс флага: "+offset+", Значения флага: "+ val2); + offset++; + if(offset == quantity1){ + break; + } + } + break; + default: + System.out.println("Введите верное число!\n"); + break; + } + break; + + case 3: + boolean[] readDisc = m.readDiscreteInputs(slaveId, offset, quantity2); + for (boolean val3 : readDisc){ + System.out.println("Адрес: "+offset + ", Значение: "+ val3); + offset++; + if(offset == quantity2){ + break; + } + } + break; + + case 4: + int[] readInp = m.readInputRegisters(slaveId, offset, quantity3); + for (int val4 : readInp){ + System.out.println("Адрес: "+offset + ", Значение: "+ val4); + offset++; + if(offset == quantity3){ + break; + } + } + break; + + case 5: + int[] regVal = m.readHoldingRegisters(slaveId, offset, quantity4); + for (int val5 : regVal){ + System.out.println("Адрес: "+offset + ", Значение: "+ val5); + offset++; + if(offset == quantity4){ + break; + } + } + break; + case 6: + System.out.println("Выберите Single или Multiple Holding Registers запись: \n" + "1. Запись Single Holding Register\n"+ + "2. Запись Multiple Holding Registers\n"); + Scanner sc3 = new Scanner(System.in); + int hregsc = sc3.nextInt(); + switch (hregsc){ + case 1: + m.writeSingleRegister(1, 0, 15); + int[] wSinregVal = m.readHoldingRegisters(slaveId, offset, quantity4); + for (int val6 : wSinregVal){ + System.out.println("Адрес: "+offset + ", Значение: "+ val6); + offset++; + if(offset == quantity4){ + break; + } + } + break; + case 2: + m.writeMultipleRegisters(1, 0, new int[]{37, 73}); + int[] wMulregVal = m.readHoldingRegisters(slaveId, offset, quantity4); + for (int val6 : wMulregVal){ + System.out.println("Адрес: "+offset + ", Значение: "+ val6); + offset++; + if(offset == quantity4){ + break; + } + } + break; + } + break; + default: + System.out.println("Введите цифру из списка!\n"); } + } catch (ModbusIOException mioE) { Modbus.log().throwing("???", "???", mioE); } catch (Exception e) { Modbus.log().throwing("???", "???", e); - } finally { - try { - m.disconnect(); - } catch (ModbusIOException mioE) { - Modbus.log().throwing("???", "???", mioE); - } } } + } catch (RuntimeException e) { throw e; } catch (Exception e) { diff --git a/modbus_master_rtu.iml b/modbus_master_rtu.iml new file mode 100644 index 0000000..90d34da --- /dev/null +++ b/modbus_master_rtu.iml @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file