final_ver

Final version Modbus RTU master-slave on Java
This commit is contained in:
Евгений Малыгин 2023-06-21 18:42:46 +03:00
parent 38f69f291a
commit 1a79a0ff77
5 changed files with 307 additions and 61 deletions

1
.idea/modules.xml generated
View File

@ -4,6 +4,7 @@
<modules> <modules>
<module fileurl="file://$PROJECT_DIR$/mbrtu/mbrtu.iml" filepath="$PROJECT_DIR$/mbrtu/mbrtu.iml" /> <module fileurl="file://$PROJECT_DIR$/mbrtu/mbrtu.iml" filepath="$PROJECT_DIR$/mbrtu/mbrtu.iml" />
<module fileurl="file://$PROJECT_DIR$/modbus_master-slave_rtu.iml" filepath="$PROJECT_DIR$/modbus_master-slave_rtu.iml" /> <module fileurl="file://$PROJECT_DIR$/modbus_master-slave_rtu.iml" filepath="$PROJECT_DIR$/modbus_master-slave_rtu.iml" />
<module fileurl="file://$PROJECT_DIR$/modbus_master_rtu.iml" filepath="$PROJECT_DIR$/modbus_master_rtu.iml" />
</modules> </modules>
</component> </component>
</project> </project>

View File

@ -10,5 +10,4 @@ repositories {
dependencies { dependencies {
testCompile group: 'junit', name: 'junit', version: '4.11' testCompile group: 'junit', name: 'junit', version: '4.11'
compile group: 'com.github.kochedykov', name: 'jlibmodbus', version: '1.2.9.0' compile group: 'com.github.kochedykov', name: 'jlibmodbus', version: '1.2.9.0'
} }

View File

@ -1,64 +1,113 @@
import com.intelligt.modbus.jlibmodbus.Modbus; 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.DataHolder;
import com.intelligt.modbus.jlibmodbus.data.ModbusHoldingRegisters; 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 com.intelligt.modbus.jlibmodbus.serial.*;
import jssc.SerialPortList; import jssc.SerialPortList;
import java.io.Console; import java.net.InetAddress;
import java.util.ArrayList;
import java.util.List;
public class MainSlave { public class MainSlave {
static public void main(String[] arg) { static public void main(String[] argv) {
SerialParameters sp = new SerialParameters();
Modbus.setLogLevel(Modbus.LogLevel.LEVEL_DEBUG);
try { try {
String[] dev_list = SerialPortList.getPortNames();
System.out.println("Доступные порты:");
for (int n = 0; n < dev_list.length; n++) { final ModbusSlave slave;
System.out.println(dev_list[n]);
}
if (dev_list.length > 0) { SerialParameters serialParameters = new SerialParameters();
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.setDevice("COM3");
serialParameters.setBaudRate(SerialPort.BaudRate.BAUD_RATE_9600);
serialParameters.setDataBits(8);
serialParameters.setParity(SerialPort.Parity.NONE);
serialParameters.setStopBits(1);
SerialUtils.setSerialPortFactory(new SerialPortFactoryJSSC()); slave = ModbusSlaveFactory.createModbusSlaveRTU(serialParameters);
ModbusSlave m = ModbusSlaveFactory.createModbusSlaveRTU(sp); 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(); MyOwnDataHolder dh = new MyOwnDataHolder();
ModbusHoldingRegisters registers = new ModbusHoldingRegisters(10); dh.addEventListener(new ModbusEventListener() {
registers.set(0, 101); @Override
registers.set(1, 105); public void onWriteToSingleCoil(int address, boolean value) {
registers.set(2, 660); System.out.print("onWriteToSingleCoil: address " + address + ", value " + value);
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();
} }
@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) { } catch (RuntimeException e) {
throw e; throw e;
@ -66,4 +115,67 @@ public class MainSlave {
e.printStackTrace(); 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<ModbusEventListener> modbusEventListenerList = new ArrayList<ModbusEventListener>();
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);
}
}
} }

View File

@ -5,8 +5,7 @@ import com.intelligt.modbus.jlibmodbus.exception.ModbusIOException;
import com.intelligt.modbus.jlibmodbus.serial.*; import com.intelligt.modbus.jlibmodbus.serial.*;
import jssc.SerialPortList; import jssc.SerialPortList;
import java.util.logging.Logger; import java.util.Scanner;
public class main { public class main {
@ -26,8 +25,8 @@ public class main {
} }
if (dev_list.length > 0) { if (dev_list.length > 0) {
//Настройка //Настройка подключения к порту и передачи данных
sp.setDevice(arg[arg.length - 1]); sp.setDevice("COM6");
sp.setBaudRate(SerialPort.BaudRate.BAUD_RATE_9600); sp.setBaudRate(SerialPort.BaudRate.BAUD_RATE_9600);
sp.setDataBits(8); sp.setDataBits(8);
sp.setParity(SerialPort.Parity.NONE); sp.setParity(SerialPort.Parity.NONE);
@ -39,30 +38,145 @@ public class main {
m.connect(); m.connect();
//Настройка
int slaveId = 1; // id устройства slave int slaveId = 1; // id устройства slave
int offset = 0; // Начальный адресс 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 { try {
int[] registerValues = m.readHoldingRegisters(slaveId, offset, quantity); // Настройка тип регситра(в данном случае установлены регистры хранения)
//Вывод System.out.println("Выберите режим: \n"+"1. Чтение регистра флага(Read Coils)\n"+
for (int value : registerValues) { "2. Запись регистра флага(Write Coils)\n"+"3. Чтение дискретного входа(Read Discrete Inputs)\n"+
System.out.println("Адресс: " + offset + ", Значение: " + value); "4. Чтение регистра входа(Read Input Registers)\n"+"5. Чтение регистра хранения(Read Holding Registers)\n"+
offset++; "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) { } catch (ModbusIOException mioE) {
Modbus.log().throwing("???", "???", mioE); Modbus.log().throwing("???", "???", mioE);
} catch (Exception e) { } catch (Exception e) {
Modbus.log().throwing("???", "???", e); Modbus.log().throwing("???", "???", e);
} finally {
try {
m.disconnect();
} catch (ModbusIOException mioE) {
Modbus.log().throwing("???", "???", mioE);
}
} }
} }
} catch (RuntimeException e) { } catch (RuntimeException e) {
throw e; throw e;
} catch (Exception e) { } catch (Exception e) {

20
modbus_master_rtu.iml Normal file
View File

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<module external.linked.project.id="modbus_master_rtu" external.linked.project.path="$MODULE_DIR$" external.root.project.path="$MODULE_DIR$" external.system.id="GRADLE" external.system.module.group="" external.system.module.version="1.0" type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager" inherit-compiler-output="false">
<output url="file://$MODULE_DIR$/build/classes/main" />
<output-test url="file://$MODULE_DIR$/build/classes/test" />
<exclude-output />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/test/java" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/main/resources" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/test/resources" type="java-test-resource" />
<excludeFolder url="file://$MODULE_DIR$/.gradle" />
<excludeFolder url="file://$MODULE_DIR$/build" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" scope="TEST" name="Gradle: junit:junit:4.11" level="project" />
<orderEntry type="library" scope="TEST" name="Gradle: org.hamcrest:hamcrest-core:1.3" level="project" />
</component>
</module>