I need to write Modbus RTU master app in Java that support 03 - Read Holding Registers and 16 - Write Multiple Registers.
I found three java libraries: jamod, j2mod, modbus4j. I try all of these libraries (I spend about 4 hours) and it still doesn't work.
Do you know any step-by-step tutorial or example code?
I'm using USB->RS-485 converter. If I testing in QModBus, it works good.
Thank you.
import java.io.File;
import com.serotonin.io.serial.SerialParameters;
import com.serotonin.modbus4j.ModbusFactory;
import com.serotonin.modbus4j.ModbusMaster;
import com.serotonin.modbus4j.code.DataType;
import com.serotonin.modbus4j.code.RegisterRange;
import com.serotonin.modbus4j.exception.ModbusInitException;
public class Modbus4JTest {
public static void main(String[] args) throws Exception {
ModbusFactory factory = new ModbusFactory();
SerialParameters params = new SerialParameters();
params.setCommPortId("/dev/ttyUSB1");
params.setBaudRate(9600);
params.setDataBits(8);
params.setStopBits(1);
params.setParity(0);
ModbusMaster master = factory.createRtuMaster(params);
master.setTimeout(2000);
master.setRetries(0);
long start = System.currentTimeMillis();
// Don't start if the RTU master can't be initialized.
try {
master.init();
} catch (ModbusInitException e) {
System.out.println( "Modbus Master Init Error: " + e.getMessage());
return;
}
try {
System.out.println("Reg. 1001 Value:" + master.getValue(7, RegisterRange.HOLDING_REGISTER, 1000, DataType.FOUR_BYTE_FLOAT_SWAPPED));
// more like the above until all required register values are read.
// ..
}
finally {
master.destroy();
}
System.out.println("Time elapsed: " + (System.currentTimeMillis() - start) + "ms");
}
}
.
import java.io.File;
import com.ghgande.j2mod.modbus.ModbusCoupler;
import com.ghgande.j2mod.modbus.io.ModbusSerialTransaction;
import com.ghgande.j2mod.modbus.msg.ModbusRequest;
import com.ghgande.j2mod.modbus.msg.ReadInputRegistersRequest;
import com.ghgande.j2mod.modbus.msg.ReadInputRegistersResponse;
import com.ghgande.j2mod.modbus.net.SerialConnection;
import com.ghgande.j2mod.modbus.util.SerialParameters;
import com.serotonin.modbus4j.msg.ReadHoldingRegistersRequest;
import com.serotonin.modbus4j.msg.ReadHoldingRegistersResponse;
// -Djava.library.path="/usr/lib/jni/"
public class J2mod {
public static void main(String[] args) throws Exception {
File lock = new File("/var/lock/LCK..ttyUSB0");
lock.delete();
File lock1 = new File("/var/lock/LCK..ttyUSB1");
lock1.delete();
SerialConnection con = null; // the connection
ModbusSerialTransaction trans = null; // the transaction
//ReadInputRegistersRequest req = null; // the request
ReadHoldingRegistersRequest req = null;
ReadHoldingRegistersResponse res = null;
//ReadInputRegistersResponse res = null; // the response
String portname = null; // the name of the serial port to be used
int unitid = 0; // the unit identifier we will be talking to
int ref = 0; // the reference, where to start reading from
int count = 0; // the count of IR's to read
int repeat = 1; // a loop for repeating the transaction
try {
portname = "/dev/ttyUSB1";
//System.setProperty("gnu.io.rxtx.SerialPorts", portname);
unitid = 2;
ref = 0;
count = 4;
} catch (Exception ex) {
ex.printStackTrace();
System.exit(1);
}
// 2. Set master identifier
// ModbusCoupler.createModbusCoupler(null);
ModbusCoupler.getReference().setUnitID(1);
// 3. Setup serial parameters
SerialParameters params = new SerialParameters();
params.setPortName(portname);
params.setBaudRate(9600);
params.setDatabits(8);
params.setParity("None");
params.setStopbits(1);
params.setEncoding("rtu");
params.setEcho(false);
// 4. Open the connection
con = new SerialConnection(params);
con.open();
// 5. Prepare a request
req = new ReadHoldingRegistersRequest(unitid, ref, count);
//req = new ReadInputRegistersRequest(ref, count);
//req.setUnitID(unitid);
//req.setHeadless();
// 6. Prepare a transaction
trans = new ModbusSerialTransaction(con);
trans.setRequest(req);
int k = 0;
do {
trans.execute();
res = (ReadInputRegistersResponse) trans.getResponse();
//res = (ReadHoldingRegistersResponse) trans.getResponse();
for (int n = 0; n < res.getWordCount(); n++) {
System.out.println("Word " + n + "=" + res.getRegisterValue(n));
}
k++;
} while (k < repeat);
// 8. Close the connection
con.close();
}
}
Related
I am trying to run below code. I have a MODBUS transmitter connected at COM1 with Baud rate of 9600, transmitting data via USB cable. I want to collect that data.
public static void main(String[] args) {
SerialConnection con = null;
ModbusSerialTransaction trans = null;
ReadInputRegistersRequest req = null;
ReadInputRegistersResponse res = null;
String portname = null;
int unitid = 0;
int ref = 0;
int count = 0;
int repeat = 1;
try {
portname = "COM1";
unitid = 2;
ref = 0;
count = 8;
}
catch (Exception ex) {
ex.printStackTrace();
System.exit(1);
}
ModbusCoupler.getReference().setUnitID(1);
SerialParameters params = new SerialParameters();
params.setPortName(portname);
params.setBaudRate(9600);
params.setDatabits(8);
params.setParity("None");
params.setStopbits(2);
params.setEncoding("rtu");
params.setEcho(false);
con = new SerialConnection(params);
con.open();
req = new ReadInputRegistersRequest(ref, count);
req.setUnitID(unitid);
req.setHeadless();
trans = new ModbusSerialTransaction(con);
trans.setRequest(req);
int k = 0;
do {
trans.execute();
res = (ReadInputRegistersResponse) trans.getResponse();
for (int n = 0; n < res.getWordCount(); n++) {
System.out.println("Word " + n + "=" + res.getRegisterValue(n));
}
k++;
}
while (k < repeat);
con.close();
}
While running the code, I am getting below error.
java.lang.Exception
at net.wimpi.modbus.net.SerialConnection.open(SerialConnection.java:91)
at Main.main(Main.java:50)
Exception in thread "main" java.lang.NullPointerException
at net.wimpi.modbus.io.ModbusSerialTransaction.execute(ModbusSerialTransaction.java:168)
at Main.main(Main.java:66)
While running,
Please help me out in this, as i am not able to figure out the error.
need help with writing to and receiving from the text files
it seems to go almost all the way but then it says that no file exists, at that point it should create one and then start writing to it. it says that it failed to find one and then it just ends itself. I don't know why
package sorting;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Random;
public class Sorting {
private static int[] oneToFiftyThou = new int[50000];
private static int[] fiftyThouToOne = new int[50000];
private static int[] randomFiftyThou = new int[50000];
public static void main(String[] args) {
if(args.length>0) {
if(args[0].equalsIgnoreCase("init")) {
// initialize the 3 files
// 1-50000 file1
// 50000-1 file2
// random 50000 file3
initializeFiles();
writeFiles();
}
} else {
readFilestoArray();
System.out.println(""+oneToFiftyThou[0] + " - " +
oneToFiftyThou[oneToFiftyThou.length-1]);
System.out.println(""+fiftyThouToOne[0] + " - " +
fiftyThouToOne[fiftyThouToOne.length-1]);
System.out.println(""+randomFiftyThou[0] + " - " +
randomFiftyThou[randomFiftyThou.length-1]);
intInsertionSort(oneToFiftyThou);
intInsertionSort(fiftyThouToOne);
intInsertionSort(randomFiftyThou);
}
}
private static void initializeFiles() {
//Array one
for(int i=1; i<oneToFiftyThou.length+1; i++) {
oneToFiftyThou[i-1] = i;
}
//Array two
for(int i=50000; i>0; i--) {
fiftyThouToOne[fiftyThouToOne.length-(i)] = i;
}
//Array Three Random. Copy Array one into a new Array and shuffle.
System.arraycopy(oneToFiftyThou, 0, randomFiftyThou, 0,
randomFiftyThou.length);
Random random = new Random();
for(int i=randomFiftyThou.length-1; i>0; i--) {
int index = random.nextInt(i+1);
//Swap the values
int value = randomFiftyThou[index];
randomFiftyThou[index] = randomFiftyThou[i];
randomFiftyThou[i] = value;
}
}
public static void writeFiles() {
ArrayList<int[]> arrayList = new ArrayList<int[]>();
arrayList.add(oneToFiftyThou);
arrayList.add(fiftyThouToOne);
arrayList.add(randomFiftyThou);
int fileIter = 1;
for(Iterator<int[]> iter = arrayList.iterator();
iter.hasNext(); ) {
int[] array = iter.next();
try {
File file = new File("file"+fileIter+".txt");
//check for file, create it if it doesn't exist
if(!file.exists()) {
file.createNewFile();
}
FileWriter fileWriter = new FileWriter(file);
BufferedWriter bufferWriter = new BufferedWriter
(fileWriter);
for(int i = 0; i<array.length; i++) {
bufferWriter.write(""+array[i]);
if(i!=array.length-1) {
bufferWriter.newLine();
}
}
bufferWriter.close();
fileIter++;
}catch(IOException ioe) {
ioe.printStackTrace();
System.exit(-1);
}
}
}
public static void readFilestoArray() {
ArrayList<int[]> arrayList = new ArrayList<int[]>();
arrayList.add(oneToFiftyThou);
arrayList.add(fiftyThouToOne);
arrayList.add(randomFiftyThou);
int fileIter = 1;
for(Iterator<int[]> iter = arrayList.iterator();
iter.hasNext(); ) {
int[] array = iter.next();
try {
File file = new File("file"+fileIter+".txt");
//check for file, exit with error if file doesn't exist
if(!file.exists()) {
System.out.println("file doesn't exist "
+ file.getName());
System.exit(-1);
}
FileReader fileReader = new FileReader(file);
BufferedReader bufferReader = new BufferedReader
(fileReader);
for(int i = 0; i<array.length; i++) {
array[i] = Integer.parseInt
(bufferReader.readLine());
}
bufferReader.close();
fileIter++;
}catch(IOException ioe) {
ioe.printStackTrace();
System.exit(-1);
}
}
}
private static void intInsertionSort(int[] intArray) {
int comparisonCount = 0;
long startTime = System.currentTimeMillis();
for(int i=1; i<intArray.length;i++) {
int tempValue = intArray[i];
int j = 0;
for(j=i-1; j>=0 && tempValue<intArray[j];j--){
comparisonCount++;
intArray[j+1] = intArray[j];
}
intArray[j+1] = tempValue;
}
long endTime=System.currentTimeMillis();
System.out.println("Comparison Count = " + comparisonCount
+ " running time (in millis) = " +
(endTime-startTime) );
}
}
Well, works for me. Execute it in console like that:
java Sorting init
Then execute it another time:
java Sorting
Works perfectly. If you are in Eclipse go to run configuration > arguments and put init there.
Point is in your main method you are checking if someone invoked the program with init parameter, if yes then you create those files and write to them, if not - you are reading from them. You are probably invoking without init and the files are not there yet, that's why it doesn't work.
I am developing a speed test app like OKLA app (http://www.speedtest.net/).
I've been trying to get bandwidth rate with the most common approach:
Get the time before downloading.
Download some file for some time X.
Get the time after downloading and the total size downloaded.
Calculate speed from TIME and BYTES RECEIVED.
Also, I execute this in two different threads at the same time because is required to saturate de connection to achieve good results.
This approach works very well on PC environment with this JAVA code:
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.FutureTask;
public class TestVelocidad {
static long totalBytesReceived = 0; //
static long startSample;
static long endSample ;
private static final long TIME_FOR_DOWNLOAD_MILISECONDS = (long) 10000.0;
private static final long MILI_TO_NANO = 1000000;
public static void main(String[] args) throws InterruptedException, ExecutionException {
try{
final ExecutorService service;
String downloadFileUrl100MB = "http://cachefly.cachefly.net/100mb.test";
startSample = System.nanoTime();
service = Executors.newFixedThreadPool(6);
FutureTask futureTask_1 = new FutureTask(new SpeedTestThread(downloadFileUrl100MB));
service.execute(futureTask_1);
FutureTask futureTask_2 = new FutureTask(new SpeedTestThread(downloadFileUrl100MB));
service.execute(futureTask_2);
service.shutdownNow();
long result1 = (Long) futureTask_1.get();
long result2 = (Long) futureTask_2.get();
endSample = System.nanoTime();
long timeSpent = (long) endSample-startSample;
long totalBytesReceived = result1 + result2;
System.out.println("Time of threads: " + timeSpent/1000000000.0 + " seconds " + "\nbytes received: " + (totalBytesReceived) );
double calculatedSpeed;
// long finalTimeSpent ;
// finalTimeSpent = (long) ((TIME_FOR_DOWNLOAD_MILISECONDS * MILI_TO_NANO - diff));
calculatedSpeed = SpeedInfo.calculate(timeSpent, totalBytesReceived).megabits;
System.out.println("Velocidad calculada: " + calculatedSpeed + " mbps" );
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
}
class SpeedTestThread implements Callable<Long> {
private String url = new String("");
private static final long TIME_FOR_DOWNLOAD_NANOSECONDS = (long) 10000000000.0;
private static final long MILI_TO_NANO = 1000000;
private long bytesThread;
public SpeedTestThread(String urlToDownload){
url = urlToDownload;
}
public void run() {
}
#Override
public Long call() throws Exception {
System.out.println("FileDownload " + " File to download: " + url );
InputStream stream = null;
long startCon = System.nanoTime();
URL urlToDownload = null;
try {
urlToDownload = new URL(url);
} catch (MalformedURLException e) {
e.printStackTrace();
}
URLConnection con = null;
try {
con = urlToDownload.openConnection();
} catch (IOException e) {
e.printStackTrace();
}
con.setUseCaches(false);
//Tiempo de acceso al archivo.
long connectionLatency = (System.nanoTime() - startCon)/MILI_TO_NANO;
System.out.println("Connection latency = " + connectionLatency + "");
con.setConnectTimeout(5000);
try {
stream = con.getInputStream();
} catch (IOException e) {
e.printStackTrace();
}
long startNano = System.nanoTime();
int currentByte = 0;
try {
while ((currentByte = stream.read()) != -1 ) {
bytesThread++;
if ((System.nanoTime() - startNano) > TIME_FOR_DOWNLOAD_NANOSECONDS){
System.out.println("Time");
break;
}
}
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("Thread bytes received: " + bytesThread);
return bytesThread;
}
}
class SpeedInfo {
public double kilobits = 0;
public double megabits = 0;
public double downspeed = 0;
private static final double BYTE_TO_KILOBIT = 0.008;
private static final double KILOBIT_TO_MEGABIT = 0.001;
/**
* 1 byte = 0.0078125 kilobits
* 1 kilobits = 0.0009765625 megabit
*
* #param downloadTime in miliseconds
* #param bytesIn number of bytes downloaded
* #return SpeedInfo containing current testVelocidadThread
*/
public static SpeedInfo calculate(final long downloadTime, final long bytesIn) {
SpeedInfo info = new SpeedInfo();
//from mil to sec
System.out.println("Bytes transferidos: " + bytesIn + "Tiempo de descarga: " + downloadTime/1000000000);
double time = downloadTime;
double byteIn1 = bytesIn;
double division = (double)(byteIn1 / time);
double bytespersecond = ((division) * 1000000000);
double kilobits = bytespersecond * BYTE_TO_KILOBIT;
double megabits = kilobits * KILOBIT_TO_MEGABIT;
info.downspeed = bytespersecond;
info.kilobits = kilobits;
info.megabits = megabits;
return info;
}
}
The problem is when I run this on a Android application, I had good results on phones with more processing and memory capacity, but poor results on phones with lower capacity.
Any good ideas to achieve good results on most android's phones?.
try to download the file with java nio rather than java io
java io transfer the file first to memory which make the performance poor on low end devices
while java nio using channels you can transfer the file to storage which will make the performance same on all devices approximately
use this code :
len = out.getChannel().transferFrom(readableByteChannel , seekPos , Long.MAX_VALUE);
I want to take real-time data using modbus tcp/ip simulator for filling of a tank that uses port no 502.
How can I write a code in java to get the holding register value from the simulator and also I want to control the values of it?
If you use a Modbus library like this one most of the work is already done for you.
ModbusTcpMasterConfig config = new ModbusTcpMasterConfig.Builder("localhost").build();
ModbusTcpMaster master = new ModbusTcpMaster(config);
CompletableFuture<ReadHoldingRegistersResponse> future =
master.sendRequest(new ReadHoldingRegistersRequest(0, 10), 0);
future.thenAccept(response -> {
System.out.println("Response: " + ByteBufUtil.hexDump(response.getRegisters()));
ReferenceCountUtil.release(response);
});
import java.io.* ;
import java.net.* ;
import java.util.*;
public class Modcli {
public static void main(String argv[]) {
if (argv.length < 4) {
System.out.println("usage: java test3 dns_name unit reg_no num_regs");
System.out.println("eg java test3 aswales8.modicon.com 5 0 10");
return;
}
try {
String ip_adrs = argv[0];
int unit = Integer.parseInt(argv[1]);
int reg_no = Integer.parseInt(argv[2]);
int num_regs = Integer.parseInt(argv[3]);
System.out.println("ip_adrs = "+ip_adrs+" unit = "+unit+" reg_no = "+
reg_no+" num_regs = "+num_regs);
// set up socket
Socket es = new Socket(ip_adrs,502);
OutputStream os= es.getOutputStream();
FilterInputStream is = new BufferedInputStream(es.getInputStream());
byte obuf[] = new byte[261];
byte ibuf[] = new byte[261];
int c = 0;
int i;
// build request of form 0 0 0 0 0 6 ui 3 rr rr nn nn
for (i=0;i<5;i++) obuf[i] = 0;
obuf[5] = 6;
obuf[6] = (byte)unit;
obuf[7] = 3;
obuf[8] = (byte)(reg_no >> 8);
obuf[9] = (byte)(reg_no & 0xff);
obuf[10] = (byte)(num_regs >> 8);
obuf[11] = (byte)(num_regs & 0xff);
// send request
os.write(obuf, 0, 12);
// read response
i = is.read(ibuf, 0, 261);
if (i<9) {
if (i==0) {
System.out.println("unexpected close of connection at remote end");
} else {
System.out.println("response was too short - "+i+" chars");
}
} else if (0 != (ibuf[7] & 0x80)) {
System.out.println("MODBUS exception response - type "+ibuf[8]);
} else if (i != (9+2*num_regs)) {
System.out.println("incorrect response size is "+i+
" expected"+(9+2*num_regs));
} else {
for (i=0;i<=2;i++) {
int w = (ibuf[0+i+i]<<8) + ibuf[1+i+i];
System.out.println("word "+i+" = "+w);
}
for (i=3;i<=5;i++) {
int w = (ibuf[i+3]) ;
System.out.println("word "+i+" = "+w);
}
for (i=0;i<num_regs;i++) {
int w = (ibuf[9+i+i]<<8) + ibuf[10+i+i];
System.out.println("word "+i+" = "+w);
}
}
// close down
es.close();
} catch (Exception e) {
System.out.println("exception :"+e);
}
}
}
I am creating a delimited text string from a data source that contain non-delimited document metadata. All of the data is sorted by index, then subindex, and one of the first things I want to do is create a serial number for each record. The first characters of each line dictate if this is an index or subindex record, and I use these in increment the data as noted in the logic below, which works as expected.
import java.util.*;
import java.io.*;
import java.nio.file.*;
import java.util.regex.*;
import java.lang.StringBuilder;
//
public class mdata
{
public static void main(String[] args)
{
double indexNo = 0;
double subIndexNo = 0;
double recNo = 0 ;
try
{
FileInputStream inputStream = new FileInputStream("whidata0.htm");
BufferedReader br = new BufferedReader(new InputStreamReader(inputStream));
String inputLine = null;
while((inputLine=br.readLine())!=null)
{
String recordNumber = "";
if (inputLine.trim().startsWith("aIE(2")) {
indexNo = indexNo + 1;
subIndexNo = .00;
} else
if (inputLine.trim().startsWith("aIE(3")) {
subIndexNo = subIndexNo + .01;
}
recNo = indexNo + subIndexNo;
System.out.println(recNo);
}
}
//
catch (Exception e)
{
System.err.println("Error: " + e.getMessage());
}
}
}
I have other applications that require me to serialize data, and want to create a standalone method that assigns the serial number. I'm having some issues which may be scope-related, and I need an few extra set of eyes to help me understand what's happening.
Here's where I am so far with creating a serialization method:
import java.util.*;
import java.io.*;
import java.nio.file.*;
import java.util.regex.*;
import java.lang.StringBuilder;
//
public class mdata2
{
public static void main(String[] args)
{
try
{
FileInputStream inputStream = new FileInputStream("whidata0.htm");
BufferedReader br = new BufferedReader(new InputStreamReader(inputStream));
String inputLine = null;
while((inputLine=br.readLine())!=null)
{
recNo = generateSerial(inputLine.trim());
System.out.println(recNo);
}
}
//
catch (Exception e)
{
System.err.println("Error: " + e.getMessage());
}
}
//
public static double generateSerial(String inputLine)
{
double indexNo = 0; // where do
double subIndexNo = 0; // these have
double recNo = 0 ; // to go?
String recordNumber = "";
if (inputLine.trim().startsWith("aIE(2")) {
indexNo = indexNo + 1;
subIndexNo = .00;
} else
if (inputLine.trim().startsWith("aIE(3")) {
subIndexNo = subIndexNo + .01;
}
recNo = indexNo + subIndexNo;
System.out.println(recNo);
return recNo;
}
}
In the first block of code, my recNo prints as a sequence 1.00,2.00,2.01,2.02,2.03,3.00 etc. In the second, that same sequence returns as 1.00,1.00,1.01,1.01,1.01,1.00 etc. Looking at it, that makes sense; the first thing I'm doing in the method is resetting the variables to 0. Initializing the variables in main gives me scope issues--generateSerial doesn't recognize the variable.
I played around with using combinations of this.[variableName] but that didn't seem to ave any effect. What's the best way to handle this?