/**
* Copyright 2014 Comcast Cable Communications Management, LLC
*
* This file is part of CATS.
*
* CATS is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* CATS is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with CATS. If not, see <http://www.gnu.org/licenses/>.
*/
package com.comcast.cats.service.ir.redrat;
import static com.comcast.cats.service.ir.redrat.RedRatCommands.IPADDRESS_ARGUMENT;
import static com.comcast.cats.service.ir.redrat.RedRatCommands.IRNETBOX_IR_COMMAND;
import static com.comcast.cats.service.ir.redrat.RedRatCommands.KEYSET_ARGUMENT;
import static com.comcast.cats.service.ir.redrat.RedRatCommands.KEY_ARGUMENT;
import static com.comcast.cats.service.ir.redrat.RedRatCommands.PORT_ARGUMENT;
import java.io.IOException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.comcast.cats.ir.commands.CatsCommand;
import com.comcast.cats.ir.commands.DelayCommand;
import com.comcast.cats.ir.commands.IrCommand;
import com.comcast.cats.ir.commands.PressKeyAndHoldCommand;
import com.comcast.cats.ir.commands.PressKeyCommand;
import com.comcast.cats.service.WebServiceReturn;
import com.comcast.cats.service.WebServiceReturnEnum;
import com.comcast.cats.telnet.TelnetConnection;
/**
* Represents a port of the IrNetBox device.
*
* @author skurup00c
*
*/
public class IrNetBoxProPort extends RedRatDevicePort
{
int portNumber;
/**
* Represents a count value of 35 for for press and hold.
*/
private static final String REPEAT_COUNT_35 = "_repeat35";
/**
* Format for key that has a count value.
*/
String repeatCountFormat = REPEAT_COUNT_35;
private static final Logger logger = LoggerFactory.getLogger( IrNetBoxProPort.class );
private static final String PRESSKEY_EXPECTED_RESULT = "OK";
public static final int WAIT_INTERVAL = 500;
public IrNetBoxProPort( int portNumber, IrNetBoxPro irDevice )
{
super( portNumber, irDevice );
this.portNumber = portNumber;
}
@Override
public synchronized WebServiceReturn sendCommand( CatsCommand catsCommand )
{
WebServiceReturn retVal = new WebServiceReturn();
retVal.setResult( WebServiceReturnEnum.FAILURE );
String commandString = null;
String expectedResult = null;
logger.debug( "sendCommand() CatsCommand " + catsCommand );
if ( catsCommand != null )
{
while ( catsCommand.hasNext() )
{
CatsCommand command = catsCommand.next();
if ( command instanceof DelayCommand )
{
logger.debug( "Its a DelayCommand() " + command );
try
{
Thread.sleep( ( ( DelayCommand ) command ).getDelay() );
}
catch ( InterruptedException e )
{
e.printStackTrace();
}
retVal.setResult( WebServiceReturnEnum.SUCCESS );
retVal.setMessage( "CATS Command slept for " + ( ( DelayCommand ) command ).getDelay() + " ms." );
}
else if ( command instanceof IrCommand )
{
logger.debug( "sendCommand() catsCommand.next() " + command );
commandString = getDeviceUnderstandablePressKeyCommand( command );
expectedResult = getExpectedResult( command );
logger.debug( "commandString " + commandString + " expectedResult " + expectedResult );
if ( commandString != null )
{
retVal = sendCommand( commandString, expectedResult );
if(retVal.getResult().equals( WebServiceReturnEnum.FAILURE )){
logger.warn( "sendCommand() retVal.getMessage() " + retVal.getMessage() );
}
}
else
{
retVal.setMessage( "IrNetBoxPro does not know how to handle this command" );
}
}
else
{
retVal.setMessage( "IrNetBoxPro does not know how to handle this command" );
}
}
}
else
{
retVal.setMessage( "Command is null" );
}
return retVal;
}
/**
* Send a command via the {@link TelnetConnection}
*
* @param commandString
* @param expectedResult
* @return
*/
private WebServiceReturn sendCommand( String commandString, String expectedResult )
{
WebServiceReturn retVal = new WebServiceReturn();
retVal.setResult( WebServiceReturnEnum.FAILURE );
String response = null;
RedRatHubConnection telnetConnection = ( ( IrNetBoxPro ) redratDevice ).getConnection( portNumber );
logger.debug( "sendCommand() telnetConnection " + telnetConnection );
if ( telnetConnection != null )
{
response = sendTelnetCommand( telnetConnection, commandString );
logger.debug( "sendCommand() response " + response );
if ( !expectedResult.equals( response ) )
{
retVal.setMessage( "RedRat did not return an expected Result. Command " + commandString
+ " : Expected Result " + expectedResult + " : returned response " + response );
}
else
{
retVal.setResult( WebServiceReturnEnum.SUCCESS );
retVal.setMessage( response );
}
}else{
logger.warn( "Didnt get a telnetConnection to RedratHub. " + telnetConnection );
retVal.setMessage( "Could not connect to RedRatHub" );
}
return retVal;
}
private String getDeviceUnderstandablePressKeyCommand( CatsCommand command )
{
String commandString = null;
if ( command instanceof PressKeyCommand )
{
PressKeyCommand pressKeyCommand = ( PressKeyCommand ) command;
commandString = IRNETBOX_IR_COMMAND
.replace( IPADDRESS_ARGUMENT, ( ( IrNetBoxPro ) redratDevice ).getIpAddress() )
.replace( KEYSET_ARGUMENT, pressKeyCommand.getIrKeySet() )
.replace( PORT_ARGUMENT, String.valueOf( portNumber ) );
String key = pressKeyCommand.getRemoteCommand().toString();
if ( command instanceof PressKeyAndHoldCommand )
{
key = key.concat( repeatCountFormat );
}
commandString = commandString.replace( KEY_ARGUMENT, key );
}
return commandString;
}
private String getExpectedResult( CatsCommand command )
{
String expectedResult = null;
if ( command instanceof PressKeyCommand )
{
expectedResult = PRESSKEY_EXPECTED_RESULT;
}
return expectedResult;
}
private String sendTelnetCommand( RedRatHubConnection telnetConnection, String command )
{
String retVal = "";
int retries = 0;
boolean tryRetry = false;
do
{
try
{
logger.info( "sendCommand "+command );
long start = System.currentTimeMillis();
retVal = telnetConnection.sendCommand( command );
long end = System.currentTimeMillis();
if(end-start > 1500){
logger.warn( "sendCommand "+command+" response "+retVal+" time taken by hub "+(end-start)+"ms" );
}else{
logger.trace( "sendCommand "+command+" response "+retVal+" time taken by hub "+(end-start)+"ms" );
}
tryRetry = false;
}
catch ( IOException e )
{
logger.warn( "connectTelnet failed " + e.getMessage() );
tryRetry = true;
retries++;
// try reconnecting
try
{
telnetConnection.disconnect();
telnetConnection.connect( true );
}
catch ( IOException e2 )
{
logger.warn( "Could not reconnect. The hub may have crashed. " + e2.getMessage() );
}
if ( retries == 3 )
{
logger.warn( "sendTelnetCommand failed " + e.getMessage() );
retVal += e.getMessage();
telnetConnection.releaseConnection(); //avoid being GC. Return to pool instead.
}
else
{
try
{
Thread.sleep( WAIT_INTERVAL );
}
catch ( InterruptedException e1 )
{
logger.warn( "connectTelnet wait interrupted " + e1.getMessage() );
}
}
}
} while ( tryRetry && retries < 3 );
return retVal;
}
}