Updates the Passport decoder to the new architecture and implements

per-call recording.
This commit is contained in:
denny
2015-09-26 09:35:05 -04:00
parent 507ae5255e
commit 550f5c5d27
5 changed files with 343 additions and 289 deletions

View File

@@ -238,8 +238,10 @@ public class DecoderFactory
modules.add( getFMDemodulator( decodeConfig, pass, stop, REMOVE_DC ) ); modules.add( getFMDemodulator( decodeConfig, pass, stop, REMOVE_DC ) );
break; break;
case PASSPORT: case PASSPORT:
modules.add( new AudioModule( recordAudio, REMOVE_DC ) );
modules.add( new PassportDecoder( decodeConfig, aliasList ) ); modules.add( new PassportDecoder( decodeConfig, aliasList ) );
modules.add( new PassportDecoderState( aliasList ) ); modules.add( new PassportDecoderState( aliasList ) );
modules.add( getFMDemodulator( decodeConfig, pass, stop, NO_REMOVE_DC ) );
break; break;
case P25_PHASE1: case P25_PHASE1:
DecodeConfigP25Phase1 p25Config = (DecodeConfigP25Phase1)decodeConfig; DecodeConfigP25Phase1 p25Config = (DecodeConfigP25Phase1)decodeConfig;

View File

@@ -26,7 +26,6 @@ public class PassportCallEvent extends CallEvent
{ {
private String mChannel; private String mChannel;
private long mFrequency; private long mFrequency;
private int mValidCallMessages = 1;
public PassportCallEvent( CallEventType callEventType, public PassportCallEvent( CallEventType callEventType,
AliasList aliasList, AliasList aliasList,
@@ -43,29 +42,6 @@ public class PassportCallEvent extends CallEvent
mFrequency = frequency; mFrequency = frequency;
} }
public boolean addMessage( PassportMessage message )
{
String tg = message.getToID();
if( tg.contentEquals( getToID() ) )
{
mValidCallMessages++;
return true;
}
return false;
}
public boolean isValid()
{
if( getCallEventType() == CallEventType.CALL )
{
return mValidCallMessages > 1;
}
return true;
}
private Alias getAlias( String talkgroup ) private Alias getAlias( String talkgroup )
{ {
if( hasAliasList() ) if( hasAliasList() )

View File

@@ -103,21 +103,15 @@ public class PassportDecoder extends Decoder
@Override @Override
public void reset() public void reset()
{ {
// TODO Auto-generated method stub
} }
@Override @Override
public void start() public void start()
{ {
// TODO Auto-generated method stub
} }
@Override @Override
public void stop() public void stop()
{ {
// TODO Auto-generated method stub
} }
} }

View File

@@ -21,6 +21,7 @@ import java.awt.EventQueue;
import javax.swing.JLabel; import javax.swing.JLabel;
import net.miginfocom.swing.MigLayout;
import module.decode.state.ChangedAttribute; import module.decode.state.ChangedAttribute;
import module.decode.state.DecoderPanel; import module.decode.state.DecoderPanel;
import settings.ColorSetting; import settings.ColorSetting;
@@ -55,7 +56,11 @@ public class PassportDecoderPanel extends DecoderPanel
public void init() public void init()
{ {
mProtocol.setFont( mFontDecoder ); super.init();
setLayout( new MigLayout( "insets 0 0 0 0", "[grow,fill]", "[]0[]0[]") );
mProtocol.setFont( mFontDecoder );
mProtocol.setForeground( mColorLabelDecoder ); mProtocol.setForeground( mColorLabelDecoder );
mToTalkgroup.setFont( mFontDecoder ); mToTalkgroup.setFont( mFontDecoder );

View File

@@ -17,7 +17,6 @@
******************************************************************************/ ******************************************************************************/
package module.decode.passport; package module.decode.passport;
import java.text.DecimalFormat;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
@@ -27,24 +26,27 @@ import java.util.TreeSet;
import message.Message; import message.Message;
import module.decode.DecoderType; import module.decode.DecoderType;
import module.decode.event.CallEvent;
import module.decode.event.CallEvent.CallEventType;
import module.decode.state.ChangedAttribute; import module.decode.state.ChangedAttribute;
import module.decode.state.DecoderState; import module.decode.state.DecoderState;
import module.decode.state.DecoderStateEvent; import module.decode.state.DecoderStateEvent;
import module.decode.state.DecoderStateEvent.Event;
import module.decode.state.State;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import alias.Alias; import alias.Alias;
import alias.AliasList; import alias.AliasList;
import audio.metadata.Metadata;
import audio.metadata.MetadataType;
public class PassportDecoderState extends DecoderState public class PassportDecoderState extends DecoderState
{ {
private final static Logger mLog = private final static Logger mLog =
LoggerFactory.getLogger( PassportDecoderState.class ); LoggerFactory.getLogger( PassportDecoderState.class );
private static final int sINT_NULL_VALUE = -1;
private DecimalFormat mDecimalFormatter = new DecimalFormat("0.00000");
private HashSet<String> mTalkgroupsFirstHeard = new HashSet<String>(); private HashSet<String> mTalkgroupsFirstHeard = new HashSet<String>();
private TreeSet<String> mTalkgroups = new TreeSet<String>(); private TreeSet<String> mTalkgroups = new TreeSet<String>();
private TreeSet<String> mMobileIDs = new TreeSet<String>(); private TreeSet<String> mMobileIDs = new TreeSet<String>();
@@ -59,6 +61,7 @@ public class PassportDecoderState extends DecoderState
private int mSiteNumber; private int mSiteNumber;
private PassportBand mSiteBand; private PassportBand mSiteBand;
private HashMap<Integer,String> mActiveCalls = new HashMap<Integer,String>(); private HashMap<Integer,String> mActiveCalls = new HashMap<Integer,String>();
private long mFrequency;
public PassportDecoderState( AliasList aliasList ) public PassportDecoderState( AliasList aliasList )
{ {
@@ -77,229 +80,323 @@ public class PassportDecoderState extends DecoderState
} }
@Override @Override
public void stop() public void init()
{ {
} }
@Override @Override
@SuppressWarnings( "incomplete-switch" ) public void stop()
{
}
private void logTalkgroup( String talkgroup )
{
if( mTalkgroupsFirstHeard.contains( talkgroup ) )
{
mTalkgroups.add( talkgroup );
}
else
{
mTalkgroupsFirstHeard.add( talkgroup );
}
}
private PassportCallEvent getCurrentCallEvent()
{
return (PassportCallEvent)mCurrentCallEvent;
}
/**
* Indicates if the talkgroup is different than the talkgroup specified in
* the current call event
*/
private boolean isDifferentTalkgroup( String talkgroup )
{
return talkgroup != null &&
mCurrentCallEvent != null &&
mCurrentCallEvent.getToID() != null &&
!mCurrentCallEvent.getToID().contentEquals( talkgroup );
}
@Override
public void receive( Message message ) public void receive( Message message )
{ {
// if( message instanceof PassportMessage ) if( message instanceof PassportMessage )
// { {
// PassportMessage passport = ((PassportMessage)message); PassportMessage passport = (PassportMessage)message;
//
// if( passport.isValid() ) if( passport.isValid() )
// { {
// switch( passport.getMessageType() ) switch( passport.getMessageType() )
// { {
// case CA_STRT: case CA_STRT:
// mSiteLCNs.put( passport.getLCN(), mSiteLCNs.put( passport.getLCN(),
// passport.getLCNFrequencyFormatted() ); passport.getLCNFrequencyFormatted() );
// case CA_ENDD:
// String talkgroup = String talkgroup =
// String.valueOf( passport.getTalkgroupID() ); String.valueOf( passport.getTalkgroupID() );
//
// if( mTalkgroupsFirstHeard.contains( talkgroup ) ) logTalkgroup( talkgroup );
// {
// mTalkgroups.add( talkgroup ); if( mChannelNumber == 0 )
// } {
// else mChannelNumber = passport.getLCN();
// { }
// mTalkgroupsFirstHeard.add( talkgroup );
// } /* Call on this channel */
// break; if( passport.getLCN() == mChannelNumber )
// case ID_RDIO: {
// String min = passport.getMobileID(); setTalkgroup( talkgroup );
//
// if( min != null ) setTalkgroupAlias( passport.getTalkgroupIDAlias() );
// {
// mMobileIDs.add( min ); PassportCallEvent current = getCurrentCallEvent();
// }
// break; /* If we're already in a call event, add the message
// case SY_IDLE: * to the current call event ... if false, then we
// if( passport.getFree() != 0 ) * have a different call ... cleanup the old one. */
// { if( current != null && isDifferentTalkgroup( talkgroup ) )
// mNeighborLCNs.put( passport.getFree(), {
// passport.getFreeFrequencyFormatted() ); mCurrentCallEvent.end();
// } mCurrentCallEvent = null;
// break; }
// default:
// break; if( mCurrentCallEvent == null )
// } {
// } mCurrentCallEvent = new PassportCallEvent
// } .Builder( CallEventType.CALL )
// .aliasList( getAliasList() )
// if( message instanceof PassportMessage ) .channel( String.valueOf( mChannelNumber ) )
// { .frequency( passport.getLCNFrequency() )
// mActivitySummary.receive( message ); .to( String.valueOf( passport.getTalkgroupID() ) )
// .build();
// PassportMessage passport = (PassportMessage)message;
// broadcast( mCurrentCallEvent );
// if( passport.isValid() )
// { broadcast( new Metadata( MetadataType.TO,
// switch( passport.getMessageType() ) mTalkgroup, mTalkgroupAlias, true ) );
// {
// case CA_STRT: broadcast( new DecoderStateEvent( this,
// if( mChannelNumber == 0 ) Event.START, State.CALL ) );
// { }
// mChannelNumber = passport.getLCN(); else
// } {
// broadcast( new DecoderStateEvent( this,
// if( passport.getLCN() == mChannelNumber ) Event.CONTINUATION, State.CALL ) );
// { }
// setTalkgroup( String.valueOf( passport.getTalkgroupID() ) ); }
// setTalkgroupAlias( passport.getTalkgroupIDAlias() ); else
// {
// if( mTalkgroupAlias != null ) //Call Detection
// { int lcn = passport.getLCN();
// try String tg = String.valueOf( passport.getTalkgroupID() );
// {
// if( mTalkgroupAlias.hasAudioType() ) if( !mActiveCalls.containsKey( lcn ) ||
// { !mActiveCalls.get( lcn ).contentEquals( tg ) )
// mAudioTypeListener.setAudioType( {
// mTalkgroupAlias.getAudioType() ); mActiveCalls.put( lcn, tg );
// }
// } broadcast( new PassportCallEvent
// catch( Exception e ) .Builder( CallEventType.CALL_DETECT )
// { .aliasList( getAliasList() )
// mLog.error( "Error setting audio for " .channel( String.valueOf( lcn ) )
// + "passport call", e ); .details( "Site: " + passport.getSite() )
// } .frequency( passport.getLCNFrequency() )
// } .to( tg )
// .build() );
// PassportCallEvent current = }
// getCurrentPassportCallEvent(); }
// break;
// /* If we're already in a call event, add the message case CA_ENDD:
// * to the current call event ... if false, then we String endTalkgroup =
// * have a different call ... cleanup the old one. */ String.valueOf( passport.getTalkgroupID() );
// if( current != null && !current.addMessage( passport ) )
// { logTalkgroup( endTalkgroup );
// if( current.isValid() ) setTalkgroup( endTalkgroup );
// {
// final PassportCallEvent endEvent = setTalkgroupAlias( passport.getTalkgroupIDAlias() );
// getCurrentPassportCallEvent();
// broadcast( new DecoderStateEvent( this,
// mCallEventModel.setEnd( endEvent ); Event.END, State.CALL ) );
// }
// else if( mCurrentCallEvent != null )
// { {
// mCallEventModel.remove( current ); mCurrentCallEvent.end();
// } broadcast( mCurrentCallEvent );
// mCurrentCallEvent = null;
// current = null;
// setCurrentCallEvent( null ); broadcast( new DecoderStateEvent( this, Event.RESET, State.FADE ) );
// } }
// break;
// if( current == null ) case DA_STRT:
// { mSiteLCNs.put( passport.getLCN(),
// mCurrentCallEvent = new PassportCallEvent passport.getLCNFrequencyFormatted() );
// .Builder( CallEventType.CALL )
// .aliasList( mAliasList ) String dataTalkgroup =
// .channel( String.valueOf( mChannelNumber ) ) String.valueOf( passport.getTalkgroupID() );
// .frequency( passport.getLCNFrequency() )
// .to( String.valueOf( passport.getTalkgroupID() ) ) logTalkgroup( dataTalkgroup );
// .build();
// if( mChannelNumber == 0 )
// mCallEventModel.add( mCurrentCallEvent ); {
// } mChannelNumber = passport.getLCN();
// }
// State state = getState();
// /* Data call on this channel */
// if( state == State.IDLE || state == State.CALL ) if( passport.getLCN() == mChannelNumber )
// { {
// setState( State.CALL ); setTalkgroup( dataTalkgroup );
// }
// else if( state == State.DATA ) setTalkgroupAlias( passport.getTalkgroupIDAlias() );
// {
// setState( State.DATA ); PassportCallEvent current = getCurrentCallEvent();
// }
// } /* If we're already in a call event, add the message
// else * to the current call event ... if false, then we
// { * have a different call ... cleanup the old one. */
// //Call Detection if( current != null && isDifferentTalkgroup( dataTalkgroup ) )
// int lcn = passport.getLCN(); {
// String tg = String.valueOf( passport.getTalkgroupID() ); mCurrentCallEvent.end();
// mCurrentCallEvent = null;
// if( !mActiveCalls.containsKey( lcn ) || }
// !mActiveCalls.get( lcn ).contentEquals( tg ) )
// { if( mCurrentCallEvent == null )
// mActiveCalls.put( lcn, tg ); {
// mCurrentCallEvent = new PassportCallEvent
// PassportCallEvent event = new PassportCallEvent .Builder( CallEventType.DATA_CALL )
// .Builder( CallEventType.CALL_DETECT ) .aliasList( getAliasList() )
// .aliasList( mAliasList ) .channel( String.valueOf( mChannelNumber ) )
// .channel( String.valueOf( lcn ) ) .frequency( passport.getLCNFrequency() )
// .details( "Site: " + passport.getSite() ) .to( String.valueOf( passport.getTalkgroupID() ) )
// .frequency( passport.getLCNFrequency() ) .build();
// .to( tg )
// .build(); broadcast( mCurrentCallEvent );
//
// mCallEventModel.add( event ); broadcast( new Metadata( MetadataType.TO,
// } mTalkgroup, mTalkgroupAlias, true ) );
// }
// break; broadcast( new DecoderStateEvent( this,
// case DA_STRT: Event.START, State.DATA ) );
////TODO: add channel number checking and log a call event if on another site }
// setTalkgroup( String.valueOf( passport.getTalkgroupID() ) ); else
// setTalkgroupAlias( passport.getTalkgroupIDAlias() ); {
// setState( State.DATA ); broadcast( new DecoderStateEvent( this,
// break; Event.CONTINUATION, State.DATA ) );
// case CA_ENDD: }
// setTalkgroup( String.valueOf( passport.getTalkgroupID() ) ); }
// setTalkgroupAlias( passport.getTalkgroupIDAlias() ); else
// fade( CallEventType.CALL_END ); {
// break; //Call Detection
// case ID_RDIO: int lcn = passport.getLCN();
// setMobileID( passport.getMobileID() ); String tg = String.valueOf( passport.getTalkgroupID() );
// setMobileIDAlias( passport.getMobileIDAlias() );
// if( !mActiveCalls.containsKey( lcn ) ||
// final String mid = passport.getMobileID(); !mActiveCalls.get( lcn ).contentEquals( tg ) )
// {
// final PassportCallEvent event = mActiveCalls.put( lcn, tg );
// getCurrentPassportCallEvent();
// broadcast( new PassportCallEvent
// if( event != null && mid != null ) .Builder( CallEventType.DATA_CALL )
// { .aliasList( getAliasList() )
// mCallEventModel.setFromID( event, mid ); .channel( String.valueOf( lcn ) )
// } .details( "Site: " + passport.getSite() )
// .frequency( passport.getLCNFrequency() )
// setState( State.CALL ); .to( tg )
// break; .build() );
// case RA_REGI: }
// mCallEventModel.add( new PassportCallEvent }
// .Builder( CallEventType.REGISTER ) break;
// .aliasList( mAliasList ) case DA_ENDD:
// .channel( String.valueOf( passport.getLCN() ) ) String dataEndTalkgroup =
// .frequency( passport.getLCNFrequency() ) String.valueOf( passport.getTalkgroupID() );
// .to( passport.getToID() )
// .build() ); logTalkgroup( dataEndTalkgroup );
////TODO: add logic to recognize the register event and suppress the subsequent setTalkgroup( dataEndTalkgroup );
////call messages, but capture the group assignments.
// setState( State.DATA ); setTalkgroupAlias( passport.getTalkgroupIDAlias() );
// break;
// case SY_IDLE: broadcast( new DecoderStateEvent( this,
// PassportBand band = passport.getSiteBand(); Event.END, State.DATA ) );
//
// if( mSiteBand == null || mSiteBand != band ) if( mCurrentCallEvent != null )
// { {
// mSiteBand = band; mCurrentCallEvent.end();
// broadcast( mCurrentCallEvent );
// mSiteNumber = passport.getSite(); mCurrentCallEvent = null;
//
// long frequency = mProcessingChain.getChannel() broadcast( new DecoderStateEvent( this, Event.RESET, State.FADE ) );
// .getTunerChannel().getFrequency(); }
// break;
// mChannelNumber = mSiteBand.getChannel( frequency ); case ID_RDIO:
// String min = passport.getMobileID();
// broadcast( ChangedAttribute.CHANNEL_NUMBER );
// } if( min != null )
// default: {
// break; mMobileIDs.add( min );
// } }
// }
// } setMobileID( min );
setMobileIDAlias( passport.getMobileIDAlias() );
broadcast( new Metadata( MetadataType.FROM,
mMobileID, mMobileIDAlias, true ) );
final CallEvent current = getCurrentCallEvent();
if( current != null )
{
current.setFromID( min );
broadcast( current );
}
break;
case RA_REGI:
if( mCurrentCallEvent == null ||
mCurrentCallEvent.getCallEventType() != CallEventType.REGISTER )
{
mCurrentCallEvent = new PassportCallEvent
.Builder( CallEventType.REGISTER )
.aliasList( getAliasList() )
.channel( String.valueOf( passport.getLCN() ) )
.frequency( passport.getLCNFrequency() )
.to( passport.getToID() )
.build();
broadcast( mCurrentCallEvent );
broadcast( new DecoderStateEvent( this,
Event.START, State.DATA ) );
}
else
{
broadcast( new DecoderStateEvent( this,
Event.CONTINUATION, State.DATA ) );
}
break;
case SY_IDLE:
if( passport.getFree() != 0 )
{
mNeighborLCNs.put( passport.getFree(),
passport.getFreeFrequencyFormatted() );
}
PassportBand band = passport.getSiteBand();
if( mSiteBand == null || mSiteBand != band )
{
mSiteBand = band;
mSiteNumber = passport.getSite();
mChannelNumber = mSiteBand.getChannel( mFrequency );
broadcast( ChangedAttribute.CHANNEL_NUMBER );
}
break;
default:
break;
}
}
}
} }
public static String formatTalkgroup( String talkgroup ) public static String formatTalkgroup( String talkgroup )
@@ -434,36 +531,14 @@ public class PassportDecoderState extends DecoderState
return sb.toString(); return sb.toString();
} }
// /**
// * Intercept the fade event so that we can generate a call end event
// */
// @Override
// public void fade( final CallEventType type )
// {
// /*
// * We can receive multiple call tear-down messages -- only post a call
// * end event for the one that can change the state to fade
// */
// if( getState().canChangeTo( State.FADE ) )
// {
// final PassportCallEvent current = getCurrentPassportCallEvent();
//
// if( current != null )
// {
// mCallEventModel.setEnd( current );
// }
// }
//
// setCurrentCallEvent( null );
//
// mActiveCalls.clear();
//
// super.fade( type );
// }
public void reset() public void reset()
{ {
//TODO: finish this mTalkgroupsFirstHeard.clear();
mTalkgroups.clear();
mMobileIDs.clear();
mSiteLCNs.clear();
mNeighborLCNs.clear();
resetState(); resetState();
} }
@@ -530,17 +605,19 @@ public class PassportDecoderState extends DecoderState
broadcast( ChangedAttribute.FROM_TALKGROUP_ALIAS ); broadcast( ChangedAttribute.FROM_TALKGROUP_ALIAS );
} }
@Override
public void init()
{
// TODO Auto-generated method stub
}
@Override @Override
public void receiveDecoderStateEvent( DecoderStateEvent event ) public void receiveDecoderStateEvent( DecoderStateEvent event )
{ {
// TODO Auto-generated method stub switch( event.getEvent() )
{
case RESET:
resetState();
break;
case SOURCE_FREQUENCY:
mFrequency = event.getFrequency();
break;
default:
break;
}
} }
} }