I'm working on a modbus UDP implementation [ J2Mod(2.3.4) ] in Java. I have found almost no useful documentation. I have a boolean array like flags.
Slave will read it via SimpleProcessImage->DigitalIn
Slave will use that flags and change them
Then write it to SimpleProcessImage->DigitalOut in every 10 secs.
I need help on 1st step. When I use master.readCoils(i, 1) and master.writeCoils(i, true). It only use DigitalOut. It write to DigitalOut and read from DigitalOut.
for (int i = 0; i < interSize ; i++) {
SimpleDigitalOut dout = (SimpleDigitalOut) image.getDigitalOut(i);
dout.set(i%5==0);
image.setDigitalOut(i, dout);
}
If I change DigitalOut on slave side as shown above, I can get changed values through DigitalOut. But I need to use them both; DigitalOut and DigitalIn.
Here's my code for slave.
public class Slave {
private SimpleProcessImage image;
private ModbusSlave slave;
private int interSize = 62000;
int step;
public Slave(){
image = new SimpleProcessImage();
step=0;
for (int i = 0; i < interSize; i++) {
image.addDigitalOut(i, new SimpleDigitalOut(false));
image.addDigitalIn(i, new SimpleDigitalIn(false));
}
(new Timer()).scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
read();
write();
}
}, 0, 10000);
startServer();
}
private void read() {
System.out.print("Read In : ");
for (int i = 0; i < interSize; i++) {
System.out.print((image.getDigitalIn(i).isSet() ? 1 : 0) + " ");
}
System.out.print("Read Out: ");
for (int i = 0; i < interSize; i++) {
System.out.print((image.getDigitalOut(i).isSet() ? 1 : 0) + " ");
}
}
public void startServer() {
try {
slave = ModbusSlaveFactory.createUDPSlave(502);
slave.addProcessImage(0, image);
slave.open();
} catch (ModbusException e) {
e.printStackTrace();
}
}
}
Also here my client
public class Client {
private ModbusUDPMaster master;
int interSize = 62000 ;
Client() {
master = new ModbusUDPMaster("127.0.0.1", 502);
try {
master.connect();
} catch (Exception e) {
e.printStackTrace();
}
write();
while(true){
read();
}
}
public static void main(String... args) {
new Client();
}
private void write() {
for (int i = 0; i < interSize; i++) {
try {
master.writeCoil(i, i%3==0);
} catch (ModbusException e) {
e.printStackTrace();
}
}
}
private void read() {
try {
for (int i = 0; i < interSize; i++) {
System.out.print(master.readCoils(i, 1).toString());
}
} catch (ModbusException e) {
e.printStackTrace();
}
}
}
If anybody still looking for answer, as shown here, you can read DigitalIn via readInputDiscretes function.
Read Discretes
// master.readInputDiscretes(<discrete ref>, <count>); // Uses a UNIT ID of 1
master.readInputDiscretes(<unit id>, <discrete ref>, <count>);
Related
I have kinda figured out how sockets work but I seem to have run into another wall. I'm supposed to somehow use the socket to transfer the data, but how? when I try it gives me a SocketException bind, saying it's already in use. I used it originally to connect it to a Directory, where I will gather other nodes and then if one doesn't have the data, it will ask for it from the other nodes.
class Download extends Thread {
CloudByte[] list = new CloudByte[1000000];
#Override
public void run() {
try {
var nodes = ConnectingDirectory.getNodes();
for (Nodes node : nodes) {
if ((node.getHostPort() == ConnectingDirectory.getHostIP())) {
downloadFile(node.getHostPort());
}
}
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
}
try {
fileWriting(getFile().getName(), list);
} catch (IOException e) {
e.printStackTrace();
}
}
public synchronized void downloadFile(int port) throws IOException, ClassNotFoundException {
while (true) {
ServerSocket ss = ConnectingDirectory.getServerSocket();
Socket socket = ss.accept();
ObjectInputStream ois = new ObjectInputStream(socket.getInputStream());
for (int j = 0; j <= 9999; j += 1) {
byte[] bit = (byte[]) ois.readObject();
for (int i = 0; i < bit.length; i++) {
list[i + j * 100] = new CloudByte(bit[i]);
}
}
System.out.println("Download Completed");
}
}
This is the function, I'm using to Download the date from the InputStream, the problem I'm having is that it's not downloading unless I restart the other Node. Is there a way to avoid having to do that? I really am at a loss.
Note; the for is because I need to transfer 1000000 bytes, in packets of 100 bytes.
The sending the data is:
class Upload extends Thread {
#Override
public void run() {
if (getFile().exists()) {
var nodes = ConnectingDirectory.getNodes();
for (Nodes node : nodes) {
if (node.getHostPort() == ConnectingDirectory.getHostIP()) {
try {
uploadFile(node.getHostPort());
} catch (IOException e) {
e.printStackTrace();
}
}
}
} else {
new Download().start();
}
}
public static void uploadFile(int hostPort) throws IOException {
Socket socket = new Socket("localhost", hostPort);
ObjectOutputStream objectOutputStream = new ObjectOutputStream(socket.getOutputStream());
ByteBlockRequest bbr = new ByteBlockRequest(getStoredData());
for (int j = 0; j <= 9999; j += 1) {
objectOutputStream.writeObject(bbr.blocksToSend(j));
}
objectOutputStream.flush();
System.out.println("Uploaded all the Data!");
}
Creating the server socket:
public ConnectingDirectory(String hostName, int hostIP, int directoryIP) throws IOException {
this.hostName = hostName;
this.directoryIP = directoryIP;
ConnectingDirectory.hostIP = hostIP;
this.address = InetAddress.getByName(hostName);
socket = new Socket(address, directoryIP);
serverSocket = new ServerSocket(hostIP);
signUp();
askConnectedNodes();
}
The problem I am having is acquiring all reachable clients on a network.The below method returns some clients when called. In most cases other android clients.However for the PC it fails when firewall is on.Is there a more effective way to get all clients in Java/android purely or will I need to use android NDK?Any help from experts in this domain will be appreciated.Thanks in advance.
/***
* ping_JavaStyle(final int j)
* uses multi threads to enhance performance
* while pinging from 0>j<=255
* #param j
*/
private void ping_JavaStyle(final int j)
{
new Thread(new Runnable() { // new thread for parallel execution
public void run() {
try {
String testIp = prefix + String.valueOf(j);
InetAddress address = InetAddress.getByName(testIp);
String output = address.toString().substring(1);
if (address.isReachable(3000)) {
System.out.println(output + " is on the network");
ipList.add(testIp);
} else {
if (retest(testIp, 139)) {
ipList.add(testIp);
} else {
System.out.println("Not Reachable: " + output);
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();
}
After Researching some more, got this working.With help of this repo:https://github.com/stealthcopter/AndroidNetworkTools
Below code solves the problem:
** RunnableTask.Java
* Created by Kirk on 10/29/2017.
*/
public class RunnableTask implements Callable<Boolean> {
private String testIp = "";
private Boolean is_Reachable = false;
public RunnableTask(String testIp) {
this.testIp = testIp;
}
#Override
public Boolean call() throws Exception {
try {
PingResult pingResult = Ping.onAddress(this.testIp).setTimes(1).setTimeOutMillis(1500).doPing();
if (pingResult.isReachable) {
is_Reachable = true;
}
} catch (UnknownHostException e) {
e.printStackTrace();
}
return is_Reachable;
}
}
And use in the caller method:
private static final int NTHREDS = 255;
//.......
ExecutorService executor = Executors.newFixedThreadPool(NTHREDS);
List<Future<Boolean>> thread_Values_list = new ArrayList<>();
for (int i = 1; i <= 255; i++) {
final int j = i;
try {
try {
String testIp = prefix + String.valueOf(j);
RunnableTask worker = new RunnableTask(testIp);
Future<Boolean> submit = executor.submit(worker);
thread_Values_list.add(submit);
} catch (Exception e) {
e.printStackTrace();
}
} catch (Exception e) {
}
}
for (Future<Boolean> finishedThread : thread_Values_list) {
String reachable_Ip = "";
try {
if (finishedThread.get()) {
reachable_Ip = prefix + String.valueOf(finishThread_counter);
ipList.add(reachable_Ip);
}
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
finishThread_counter++;
}
executor.shutdown();
}
I'm having trouble getting my PrintStream to work correctly. I built a basic chatroom with commands (excuse my code if its messy, I just kind of threw it together) But the enter your name print statement only runs AFTER the name is inputted. So it hangs with a cursor until text is submitted then prints
Test (This is the input)
Enter your name:
Welcome to the channel Test. Current members: Test,
The first line is the input and the second and third is the resulting print statement. Is there a solution I'm missing? (All appropriate classes have been imported)
public class FinalProjectClientThread extends Thread
{
public DataInputStream is = null;
public PrintStream os = null;
public Socket clientSocket = null;
public final FinalProjectClientThread[] threads;
public int clientCount;
public String ClientName;
private boolean isModerator;
private boolean isMuted;
public FinalProjectClientThread(Socket clientSocket, FinalProjectClientThread[] threads)
{
this.clientSocket = clientSocket;
this.threads = threads;
clientCount = threads.length;
isModerator = false;
}
public String getClientName()
{
return ClientName;
}
private void setClientName(String n)
{
ClientName = n;
}
public void stopServer()
{
System.exit(0);
}
public void kickUser()
{
try
{
clientSocket.close();
}
catch(IOException e)
{
}
}
public void muteUser()
{
isMuted = true;
}
public void run()
{
int maxClients = this.clientCount;
FinalProjectClientThread[] threads = this.threads;
try
{
is = new DataInputStream(clientSocket.getInputStream());
os = new PrintStream(clientSocket.getOutputStream());
os.flush();
os.print("");
os.flush();
os.print("Enter your name: ");
os.flush();
String name = is.readLine();
this.setClientName(name);
os.print("\nWelcome to the channel " + name+". ");
os.flush();
//Count number of users in channel
int count = 0;
for(int i = 0; i < maxClients; i++)
{
if(threads[i]!=null&&threads[i].getClientName() != null)
{
count++;
}
}
//Print text based on number
if(count == 0)
{
os.println("There are no other members.");
os.flush();
}
else
{
os.print("Current members: ");
os.flush();
}
//Print member's names
for(int i = 0; i < maxClients; i++)
{
if(threads[i]!=null&&threads[i].getClientName() != null)
{
os.print(threads[i].getClientName()+ ", ");
os.flush();
}
}
os.println();
os.flush();
for(int i = 0; i < maxClients; i++)
{
if (threads[i] != null && threads[i] != this)
{
threads[i].os.println(name + " has joined the channel");
}
}
while (true)
{
String line = is.readLine();
if (line.equals("/leave"))
{
break;
}
else if(line.equals("/mod"))
{
os.println("Enter the moderator code: ");
String line2 = is.readLine();
if(line2.equals("hurricanemod"))
{
isModerator = true;
for (int i = 0; i < maxClients; i++)
{
if (threads[i] != null)
{
threads[i].os.println(name+" is now a moderator");
}
}
}
else
{
os.println("That code is incorrect");
}
}
else if(line.equals("/help"))
{
os.print("The following commands are valid: leave, help, mod, kick, mute, unmute");
}
else if(line.indexOf("/kick") == 0)
{
if(isModerator)
{
for(int i = 0; i < maxClients; i++)
{
if(threads[i] != null && threads[i].getClientName().equals(line.substring(6, line.length())))
{
threads[i].kickUser();
}
}
os.println("User kicked");
}
else
{
os.println("You must be a moderator to kick people. Use /mod and the code provided by the server hoster");
}
}
else if(line.equals("/stop"))
{
if(isModerator)
{
this.stopServer();
}
else
{
os.println("You must be a moderator to stop the server. Use /mod and the code provided by the server hoster");
}
}
else if(line.indexOf("/mute") == 0)
{
if(isModerator)
{
for(int i = 0; i < maxClients; i++)
{
if(threads[i] != null && threads[i].getClientName().equals(line.substring(6, line.length())))
{
threads[i].muteUser();
}
}
os.println(line.substring(6, line.length())+ " was muted.");
}
else
{
os.println("You must be a moderator to kick people. Use /mod and the code provided by the server hoster");
}
}
else
{
if(!isMuted)
{
for (int i = 0; i < maxClients; i++)
{
if (threads[i] != null)
{
threads[i].os.println(name+": " + line);
}
}
}
else
{
os.println("You are muted");
}
}
}
for (int i = 0; i < maxClients; i++)
{
if (threads[i] != null && threads[i] != this)
{
threads[i].os.println(name + " left the channel");
}
}
os.println("You have left the channel");
for (int i = 0; i < maxClients; i++)
{
if (threads[i] == this)
{
threads[i] = null;
}
}
is.close();
os.close();
clientSocket.close();
}
catch (IOException e)
{
System.err.println("IOExcepetion(Thread)");
}
}
}
Server
public class FinalProjectServer
{
private static Scanner kb = new Scanner (System.in);
private static ServerSocket serverSocket = null;
private static Socket clientSocket = null;
private static int clientCount = 10;
private static FinalProjectClientThread[] clientList = new FinalProjectClientThread[clientCount];
public static void main(String[] args)
{
/*System.out.print("Enter port for server to run on: ");
int port = kb.nextInt();*/
int port = 25565;
try
{
serverSocket = new ServerSocket(port);
}
catch(IOException e)
{
System.err.println("IOException");
}
while(true)
{
try
{
clientSocket = serverSocket.accept();
int i = 0;
for(i = 0; i < clientCount; i++)
{
if(clientList[i] == null)
{
clientList[i] = new FinalProjectClientThread(clientSocket,clientList);
clientList[i].start();
break;
}
}
if(i == clientCount)
{
PrintStream os = new PrintStream(clientSocket.getOutputStream());
os.println("Max number of client reached. Please contact server host.");
os.close();
clientSocket.close();
}
}
catch(IOException e)
{
System.err.println(e);
}
}
}
}
Client
public class FinalProjectClient implements Runnable
{
private static Scanner kb = new Scanner(System.in);
// The client socket
private static Socket clientSocket = null;
// The output stream
private static PrintStream os = null;
// The input stream
private static DataInputStream is = null;
private static BufferedReader inputLine = null;
private static boolean closed = false;
public static void main(String[] args)
{
System.out.print("Enter the IP of the host computer: ");
String IP = kb.nextLine();
System.out.print("Enter the port number: ");
int port = kb.nextInt();
try
{
clientSocket = new Socket(IP, port);
inputLine = new BufferedReader(new InputStreamReader(System.in));
os = new PrintStream(clientSocket.getOutputStream());
is = new DataInputStream(clientSocket.getInputStream());
}
catch(UnknownHostException e)
{
System.err.println("Can not find host, Unknown");
}
catch(IOException e)
{
System.err.println("IOException");
}
try
{
new Thread(new FinalProjectClient()).start();
while(!closed)
{
os.println(inputLine.readLine());
}
os.close();
is.close();
clientSocket.close();
}
catch(IOException e)
{
System.out.println(e);
}
}
public void run()
{
String reply;
try
{
while((reply = is.readLine()) != null)
{
System.out.println(reply);
if(reply.indexOf("/leave") != -1)
break;
}
closed = true;
}
catch(IOException e)
{
System.err.println(e);
}
}
}
I was writing code which first adds mouse position to arraylist (with dealys) and after that, it will repeat by moveMouse (robot). I think that I'm doing all well. But it's not working. Can anyone help me? Thanks!
Code:
CoursorMove
public class CoursorMove {
private ArrayList<Point> coordinates = new ArrayList<>();
public void addNewObjectWithCoordinates() {
coordinates.add(MouseInfo.getPointerInfo().getLocation());
}
public Point getCoordinate(int index) {
return coordinates.get(index);
}
public void play() {
for (int i = 0; i < 5; i++) {
CoursorMove bang = new CoursorMove();
bang.addNewObjectWithCoordinates();
System.out.println(bang.getCoordinate(0).getX());
try {
Thread.sleep(1500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
int howmany = coordinates.size();
int index = 0;
public int getHowmany() {
return howmany;
}
public void setHowmany(int howmany) {
this.howmany = howmany;
}
public void moveCoursor() {
while (index < howmany) {
try {
Robot robot = new Robot();
robot.mouseMove(coordinates.get(index).x, coordinates.get(index).y);
robot.delay(1500);
} catch (AWTException e) {
System.err.println("Error CM 68L"); // error CoursorMove class
// Line 68
e.printStackTrace();
}
index++;
}
}
}
Main.
public class Main {
public static void main(String[] args) {
CoursorMove triup = new CoursorMove();
triup.play();
triup.moveCoursor();
}
}
Here are a few modifications that should help.
First, you don't need to store separate variables for how many coordinates you have
public int getHowmany() {
return coordinates.size();
}
Second, you are never adding to the same coordinates list because you use a new instance of your class. You don't need to make one at all, you can call those methods directly on the current instance.
public void play() {
for (int i = 0; i < 5; i++) {
addNewObjectWithCoordinates();
System.out.println(getCoordinate(0).getX());
// sleep thread
}
}
Then same problem below, you probably only want one robot, not one for every loop
public void moveCoursor() {
Robot robot = new Robot();
while (index < getHowmany()) {
try {
robot.mouseMove...
Did you verify that you jump into the
while (index < howmany) {}
loop?
from what I see here is you put:
int howmany = coordinates.size();
int index = 0;
into your class directly. But you never update "howmany" after you added items to it.
As a result is howmany = 0 at initialization, because coordinates.size() is 0 in the beginning.
I guess you have to set "howmany"'s value after you added your coordinates.
e.g.
public void play() {
for (int i = 0; i < 5; i++) {
addNewObjectWithCoordinates();
System.out.println(getCoordinate(0).getX());
try {
Thread.sleep(1500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
howmany = coordinates.size();
}
EDIT:
Additionally you have to stop creating a new CoursorMove object every time. I updated the play method for that
I am still a java newbie and trying to play around learning threads. My question is that it does not loop 5 times. It runs one time and exits. I am using a.class to lock on the class object, such that both the threads are locking on the same object monitor.
class a implements Runnable {
Thread thr;
int count;
String time;
a(String s) {
thr = new Thread(this, s);
thr.start();
}
public void run() {
count++;
if (Thread.currentThread().getName().compareTo("one") == 0) {
synchronized (a.class) {
try {
for (int i = 0; i < 5; i++) {
System.out.println("Now running thread " + Thread.currentThread().getName() + " with count " + count);
time = "Tick";
System.out.println(time);
notify();
while (time == "Tock") {
wait();
}
}
} catch (Exception e) {
}
}
} else if (Thread.currentThread().getName().compareTo("two") == 0) {
synchronized (a.class) {
try {
for (int j = 0; j < 5; j++) {
System.out.println("Now running thread " + Thread.currentThread().getName() + " with count " + count);
time = "Tock";
System.out.println(time);
notify();
while (time == "Tick") {
wait();
}
}
} catch (Exception e) {
}
}
}
}
}
public class b {
public static void main(String args[]) {
a obj1 = new a("one");
a obj2 = new a("two");
}
}
Here you go, with the original code:
class a implements Runnable {
Thread thr;
int count;
static String time = "Tock";
a(String s) {
thr = new Thread(this, s);
thr.start();
}
public void run() {
count++;
if (Thread.currentThread().getName().compareTo("one") == 0) {
synchronized (a.class) {
try {
for (int i = 0; i < 5; i++) {
while (time.equals("Tock")) {
a.class.wait();
}
System.out.println("Now running thread "
+ Thread.currentThread().getName()
+ " with count " + count);
time = "Tock";
System.out.println(time);
a.class.notify();
}
} catch (Exception e) {
e.printStackTrace();
}
}
} else if (Thread.currentThread().getName().compareTo("two") == 0) {
synchronized (a.class) {
try {
for (int j = 0; j < 5; j++) {
while (time.equals("Tick")) {
a.class.wait();
}
System.out.println("Now running thread "
+ Thread.currentThread().getName()
+ " with count " + count);
time = "Tick";
System.out.println(time);
a.class.notify();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}
public class Test {
public static void main(String args[]) {
a obj1 = new a("one");
a obj2 = new a("two");
}
}
The problem was that you were calling wait and notify on the implicit this object, when the lock was being held on the a.class object, hence you must call wait/notify on a.class. That was it.
I also did a small restructuring, since I assume you wanted them to print Tick and Tock in an alternating sequence, right?
The answer to why you only loop once is that you call notify() on an object that is not locked and thus an IllegalMonitorStateException is thrown and caught by the empty catch statement.
This is one way to do it. Not saying that it is the best. I tried to keep it close to your code:
public class TickTock {
static final int N = 4;
Object lock = new Object();
int token;
class Worker extends Thread {
int id;
Worker(int id) {
this.id = id;
}
#Override
public void run() {
try {
synchronized (lock) {
for (int i = 0; i < 5; i++) {
while (id != token%N) lock.wait();
System.out.println(id + " " + i);
token++;
lock.notifyAll();
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
void start() {
for (int i = 0; i < N; i++) {
new Worker(i).start();
}
}
public static void main(String[] args) {
new TickTock().start();
}
}
When comparing strings (and objects in general), you should use equals as opposed to == (which is generally reserved for primitives): while(time.equals("Tock")). == on strings will often times result in false when you want it to (and think it should) return true, and hence your loop will exit before expected.