
package simpleserver;
import java.net.*;
import java.io.*;
import java.lang.Object;

/*

A SIMPLE MODBUS ON TCP/IP EXAMPLE

This is a very easy example of a Java Modbus on TCP/IP server, this server implements the reading holding register feature 0x04
Available register are from 1 to 2500, the "modbus_data" array is the data source.

by Ugo Cirmignani
 */
 
 public class ModbusServer  implements Runnable {

 public static byte [] modbus_data = new byte[5000];
 public static int opc = 0;
 private int port;
 private ServerSocket server;
 private Socket client;

 public ModbusServer (int port)
 {
  this.port = port;
  for (int i = 0; i< this.modbus_data.length; i++ )
  this.modbus_data[i] = 0;
  
 }

   public static int unsignedByteToInt(byte b) {
    return (int) b & 0xFF;
    }


  public void run()
 {
  this.port = port;
  for (int i = 0; i< this.modbus_data.length; i++ )
  this.modbus_data[i] = 0;

  if(!startServer())
  System.err.println("Error while creating the server");
 }

 
 private boolean startServer()
 {
  try
  {
  server = new ServerSocket(port);
  server.setReuseAddress(true);
  runServer();
  }
  catch (Exception ex)
  {
  ex.printStackTrace();
  return false;
  }
  System.out.println("Server created with success!");
  return true;
 }



 public void runServer()
 {
  while (true)
  {
   try
   {
   System.out.println("The server is waiting for clients");
   client = server.accept();
   server.setReuseAddress(true);
   client.setReuseAddress(true);
   InetAddress infoclient = client.getInetAddress();
   String clientS = infoclient.getHostAddress();
   int portclient = server.getLocalPort();
   System.out.println("The client " + clientS + " " + portclient +  " is now connected");
   ParallelServer pServer = new ParallelServer(client);
   Thread t = new Thread (pServer);
   t.start();
   }
   catch (Exception ex)
   {
   ex.printStackTrace();
   }
  }
 }


 public class ParallelServer implements Runnable
 {
  private Socket client;
  public ParallelServer (Socket client)
  {
  this.client = client;
  }

  public void run()
  {
   try
   {
   this.client.setReuseAddress(true);
   client.setReuseAddress(true);
   InputStream s1in = client.getInputStream();
   OutputStream s1out = client.getOutputStream();

   byte []  readen = new byte[1024];
   int readen_chars = 0;
   while ( (readen_chars = (s1in.read(readen, 0, 1024))) != -1 )
   {
   int iRx = readen_chars;
   InetAddress infoclient = client.getInetAddress();
   String clientS = infoclient.getHostAddress();
   int portclient = server.getLocalPort();
   System.out.println("Data request from " + clientS + " " + portclient +  "..");

   
         
      if (iRx == 12)
      { 
	  
	  // Check command lenght

       byte[] reply;

       int Starting =  ( unsignedByteToInt(readen[8]) * 256) + unsignedByteToInt(readen[9]);
       int NumberOfRegisters =  (unsignedByteToInt(readen[10]) * 256) + unsignedByteToInt(readen[11]);
       int Ending = Starting + NumberOfRegisters;

    System.out.println("Starting: " + Starting +  " Ending: " + Ending);
                    
      if (NumberOfRegisters > 125)
          Ending = Starting + 127;


      if (NumberOfRegisters <= 125)
      reply = new byte[9 + (NumberOfRegisters * 2)];
      else
      reply = new byte[9 + 254];



                    reply[0] = readen[0]; //Transaction identifier recopied by the server
                    reply[1] = readen[1]; //Transaction identifier recopied by the server
                    reply[2] = readen[2]; //Protocol identifier recopied by the server
                    reply[3] = readen[3]; //Protocol identifier recopied by the server

                    int NumberOfFollowingBytes = 3 + (NumberOfRegisters * 2);
                    reply[4] = (byte)(NumberOfFollowingBytes / 256); //Len upper
                    reply[5] = (byte)(NumberOfFollowingBytes % 256); //Len Lower
                    reply[6] = readen[6]; //Unit identifier recopied by the server
                    reply[7] = 4;  //Function code 04 'ReadInputRegisters'
                    NumberOfFollowingBytes = (NumberOfRegisters * 2);

                    if ((NumberOfFollowingBytes) > 250)
                        reply[8] = (byte)(0);
                    else
                        reply[8] = (byte)(NumberOfFollowingBytes);    //Len upper
                    int ReplyCounter = 9;



                

                    //check for the function code!
                    for (int cc = (Starting * 2); cc < (Ending * 2); cc++)
                    {
                        if ( unsignedByteToInt(readen[7]) == 4)
                        {


                            if (cc + 1 < modbus_data.length)
                            {
                                reply[ReplyCounter + 1] = modbus_data[cc + 1];
                                reply[ReplyCounter] = modbus_data[cc];
                            }
                            else
                            {
                                reply[ReplyCounter] = (byte)(255);
                                reply[ReplyCounter + 1] =  (byte)(255);
                            }


                        }
                        else
                        {
                            reply[ReplyCounter] =  (byte)(255);
                            reply[ReplyCounter + 1] =  (byte)(255);

                        }

                        ReplyCounter += 2;
                        cc++;
                    }


 s1out.write(reply, 0, reply.length);
   
   }
       }
   System.out.println("Client disconnected");

   s1in.close();
   s1out.close();

   client.close();
   this.client.close();


   System.out.println("A client connection was close");
   }
   catch (IOException ex)
   {
    ex.printStackTrace();
   }
   catch (Exception e)
   {
    e.printStackTrace();
   }

  }

 }
}
