/*******************************************************************************
* Copyright (c) 2012 Marine Electric.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the GNU Public License v3.0
* which accompanies this distribution, and is available at
* http://www.gnu.org/licenses/gpl.html
*
* Contributors:
* Marine Electric - initial API and implementation
******************************************************************************/
package serial;
import java.io.IOException;
import java.util.*;
import java.util.logging.FileHandler;
import java.util.logging.Handler;
import java.util.logging.Level;
import java.util.logging.Logger;
import ui.ControlPanel;
import ui.TextOutputPanel;
import util.Configuration;
import util.StackTraceUtil;
import net.wimpi.modbus.ModbusCoupler;
import net.wimpi.modbus.io.ModbusSerialTransaction;
import net.wimpi.modbus.msg.ModbusRequest;
import net.wimpi.modbus.msg.ModbusResponse;
import net.wimpi.modbus.msg.ReadMultipleRegistersRequest;
import net.wimpi.modbus.msg.ReadMultipleRegistersResponse;
import net.wimpi.modbus.msg.WriteMultipleRegistersRequest;
import net.wimpi.modbus.msg.WriteMultipleRegistersResponse;
import net.wimpi.modbus.net.SerialConnection;
import net.wimpi.modbus.procimg.DefaultProcessImageFactory;
import net.wimpi.modbus.procimg.Register;
import net.wimpi.modbus.procimg.SimpleRegister;
import net.wimpi.modbus.util.*;
/**
* TEST_ModCon class - CentralNexus impl
* @extends Thread
*
* @author <a href="mailto:cory@corytodd.us">Cory Todd</a>
*/
public class ModConnector extends Thread {
protected static ModConnector R;
private static final Logger log = Logger.getLogger(ModConnector.class.getPackage().getName());
private static SerialConnection con = null;
private static SerialParameters params;
private int address;
private byte[] data;
private int action;
private int word_count;
private int menu;
private Queue<String> read_resp = new LinkedList<String>();
private String respons_str = null ;
private ModbusCoupler modbusCoupler = null;
boolean comOpen_flag = false , res_flag = true , flag = false ;
Vector<String> v_response =new Vector<String>();
ModbusSerialTransaction trans = null;
ModbusRequest mreq = null;
Register reges = null;
Register[] registers = null;
DefaultProcessImageFactory dpif = null;
WriteMultipleRegistersRequest write_mreq = null;
WriteMultipleRegistersResponse write_mres = null;
private ReadMultipleRegistersRequest read_req;
private ReadMultipleRegistersResponse read_res;
private String actionStr = "";
public static synchronized ModConnector getInstance() {
if( R == null)
R = new ModConnector();
return R;
}
private ModConnector() {
Handler fh;
try {
fh = new FileHandler("%t/MarineElectric.log");
log.addHandler(fh);
} catch (SecurityException e1) {
e1.printStackTrace();
} catch (IOException e1) {
e1.printStackTrace();
}
}
private synchronized boolean createSerial(String portN,int baudRate,int dataBits,String parity,int stopBits,
String encoding,boolean echo,int recTimeout) {
try
{
modbusCoupler = ModbusCoupler.getReference();
modbusCoupler.setUnitID(Configuration.MASTER_ID);
modbusCoupler.setMaster(true);
params = new SerialParameters();
params.setPortName(portN);
params.setBaudRate(baudRate);
params.setDatabits(dataBits);
params.setParity(parity);
params.setStopbits(stopBits);
params.setEncoding(encoding);
params.setEcho(echo);
if(!comOpen_flag) {
updateTop("Opening Port");
conOpen();
}
}
catch(Exception e1)
{
log.log(Level.SEVERE, StackTraceUtil.getStackTrace(e1), e1);
res_flag = false;
}
return flag;
}
private boolean conOpen() {
try
{
// Summary
updateTop("Port: " + params.getPortName());
updateTop("Baud: " + params.getBaudRate());
updateTop("Data bits: " + params.getDatabitsString());
updateTop("Parity: " + params.getParityString());
updateTop("Stop bits: " + params.getStopbitsString());
updateTop("Encoding: " + params.getEncoding());
updateTop("Flow control in: " + params.getFlowControlInString());
updateTop("Flow control out: " + params.getFlowControlOutString());
con = new SerialConnection(params);
con.open();
comOpen_flag= true;
updateTop("Serial Port Created");
}
catch(Exception e)
{
log.log(Level.SEVERE, "Error in connection open: " + StackTraceUtil.getStackTrace(e), e);
updateTop("Error in connection open : " + e.getMessage() );
res_flag = false;
e.printStackTrace();
}
return flag;
}
/**
* conClose
* Close the connection associated with this object
* @return boolean success
*
* @author <a href="mailto:cory@corytodd.us">Cory Todd</a>
*/
@SuppressWarnings("unused")
public synchronized boolean conClose() {
try
{
con.close();
flag=false;
updateTop("Connection Closed");
}
catch(Exception e)
{
log.log(Level.SEVERE, "Error in connection close: " + StackTraceUtil.getStackTrace(e), e);
updateTop("Error in connection close : " + e.getMessage() );
res_flag = false;
}
return flag;
}
/**
* readData
* Read data from using the connection associated with this object
* @param int startAddress
* @param word_count
* @param int menu
* @return String response
*
* @author <a href="mailto:cory@corytodd.us">Cory Todd</a>
*/
private synchronized boolean readData(int startAddress,int word_count,int menu)
{
respons_str=null;
try
{
read_req = new ReadMultipleRegistersRequest();
read_res = new ReadMultipleRegistersResponse();
read_req.setUnitID(Configuration.MASTER_ID);
read_req.setHeadless();
read_req.setReference(startAddress);
read_req.setWordCount( word_count );
if(menu!=1){read_res.setDataLength(11);}
trans = new ModbusSerialTransaction(con);
trans.setRequest(read_req);
trans.setRetries(1);
trans.setTransDelayMS(Configuration.TIMEOUT_MS_SCI);
trans.setCheckingValidity(false);
int k = 0;
do
{
trans.execute();
ModbusResponse mr = trans.getResponse();
read_res = ( ReadMultipleRegistersResponse ) mr ;
k++;
} while ( k < Configuration.REPEAT );
respons_str = read_res.getHexMessage();
res_flag = true;
log.log(Level.INFO, "Response: " + read_res.getHexMessage() );
if( read_res.getFunctionCode() == 3 && read_res.getUnitID() == read_req.getUnitID() )
{
res_flag = true;
v_response.clear();
v_response.removeAllElements();
for( int i=0 ; i < read_res.getWordCount() ; i++ )
{
v_response.add( Integer.toHexString( read_res.getRegisterValue(i) ) );
}
log.log(Level.INFO, "Raw : " + v_response + " Count: " + v_response.size() );
}
}
catch(Exception e)
{
log.log(Level.SEVERE, "Error in read operation: " + StackTraceUtil.getStackTrace(e), e);
updateTop("Error in read Operation : " + e.getMessage() );
res_flag = false;
respons_str = "error" ;
}
// Add data to read-queue
read_resp.add(respons_str);
return res_flag;
}
private synchronized boolean writeMultipleDatas(int startAddress)
{
try
{
//********* Write Multiple Data ************
int bytecount = data.length / 2;
registers = new Register[ bytecount ];
for( int i=0,j=0 ; i<data.length ; i=i+2,j++ )
{
// Compensate for difference in ROV endianess
registers[ j ] = new SimpleRegister( data[ i+1 ] , data[ i ] );
}
try
{
ModConnector.sleep(2);
}
catch(Exception ee)
{ }
write_mreq = new WriteMultipleRegistersRequest();
write_mreq.setDataLength(data.length);
write_mreq.setReference(startAddress);
write_mreq.setRegisters(registers);
write_mreq.setUnitID(Configuration.MASTER_ID);
write_mreq.setHeadless();
trans = new ModbusSerialTransaction( con );
trans.setRequest( write_mreq );
trans.setRetries( 1 );
trans.execute();
write_mres = ( WriteMultipleRegistersResponse ) trans.getResponse();
if( write_mres.getFunctionCode() == 16 )
res_flag = true;
else
res_flag = false;
}
catch( Exception e )
{
log.log(Level.SEVERE, "Error in write operation: " + StackTraceUtil.getStackTrace(e), e);
updateTop("Error in Multiple Write Operation : " + e.getMessage() );
res_flag = false;
respons_str = "error" ;
}
return res_flag;
}
/**
* setAction Helper method
* @return String read response
*
* @author <a href="mailto:cory@corytodd.us">Cory Todd</a>
*/
public String getReadResponse() {
return read_resp.poll();
}
/**
* setAction Helper method
* Set action to read
* TODO Enumerate
* @param int address
* @param int word_count
* @param int menu
*
* @author <a href="mailto:cory@corytodd.us">Cory Todd</a>
*/
public void setAction(int address, int word_count, int menu) {
if(!comOpen_flag)
this.createSerial(Configuration.PORT_NAME, Configuration.BAUD_RATE,
Configuration.DATA_BITS, Configuration.PARITY,1,
Configuration.ENCODING, true, Configuration.TIMEOUT_MS_SCI);
this.action = 1;
this.address = address;
this.word_count = word_count;
this.menu = menu;
actionStr = "Action: Read";
log.log(Level.INFO, actionStr);
actionStr = "";
}
public void setAction(String action, int address, byte[] send) {
if(!comOpen_flag)
this.createSerial(Configuration.PORT_NAME, Configuration.BAUD_RATE,
Configuration.DATA_BITS, Configuration.PARITY,1,
Configuration.ENCODING, true, Configuration.TIMEOUT_MS_SCI);
if(action.equalsIgnoreCase("read")) {
this.action = 1;
this.address = address;
actionStr = "Action: Read";
}
if(action.equalsIgnoreCase("write")) {
this.action = 2;
this.address = address;
this.data = send;
System.out.print("ACtion: Write ");
for(int x=0; x<data.length; x++)
actionStr.concat(data[x] + " ");
}
if(action.equalsIgnoreCase("writeall")){
this.action =3;
data = new byte[send.length];
this.address = address;
this.data = send;
System.out.print("Action: WriteMultiple: ");
for(int x=0; x<data.length; x++)
actionStr.concat(data[x] + " ");
}
log.log(Level.INFO, actionStr);
actionStr = "";
}
@Override
public void run() {
log.log(Level.INFO, "Starting modbus transaction");
switch(action) {
case 1:
readData(this.address, this.word_count, this.menu);
break;
case 2:
break;
case 3:
writeMultipleDatas(this.address);
break;
default:
System.out.println("No Action Specified!");
}
log.log(Level.INFO, "Transaction complete");
}
private void updateTop(String string) {
log.log(Level.INFO, string);
TextOutputPanel.getInstance().updateGUI(string);
}
}