Updated Call Event handling/display for all decoders and updated channel display values for all decoders.

- Call events now show start-stop timestamps.  (or START-In Progress if call is ongoing )
 - Call start/stop events are now on the same event line.
 - Channel panels now display site and/or channel info
 - LTR call events are limited to CALLs on the current LCN, in order to cut down on false call events resulting from noise.
 - Passport display channels now show site/channel.
 - Changed default window used by the DFTProcessor to Cosine, which doesn't have as much FFT bin leakage.
This commit is contained in:
dennis.sheirer
2014-09-15 00:42:20 +00:00
parent 0f43c7ed22
commit ad456d81a3
18 changed files with 949 additions and 412 deletions

View File

@@ -17,6 +17,7 @@
******************************************************************************/
package decode.fleetsync2;
import log.Log;
import message.Message;
import alias.Alias;
import controller.state.AuxChannelState;

View File

@@ -21,11 +21,13 @@ import alias.Alias;
import alias.AliasList;
import controller.activity.CallEvent;
import decode.DecoderType;
import decode.ltrstandard.LTRStandardMessage;
public class LTRCallEvent extends CallEvent
{
private int mChannel;
private long mFrequency;
private int mValidCallMessages = 1;
public LTRCallEvent( CallEventType callEventType,
AliasList aliasList,
@@ -41,6 +43,50 @@ public class LTRCallEvent extends CallEvent
mChannel = channel;
mFrequency = frequency;
}
/**
* LTR sends multiple CALL messages during a call. In order to detect noise
* bursts from valid calls, send every valid call message to this method
* and the event will keep a tally of valid call messages in order to
* determine if the call was a valid (and loggable) call event.
*/
public boolean addMessage( LTRStandardMessage message )
{
String talkgroup = message.getTalkgroupID();
if( talkgroup.contentEquals( getToID() ) )
{
mValidCallMessages++;
return true;
}
return false;
}
public boolean addMessage( LTRNetMessage message )
{
String talkgroup = message.getTalkgroupID();
if( talkgroup.contentEquals( getToID() ) )
{
mValidCallMessages++;
return true;
}
return false;
}
public boolean isValid()
{
if( getCallEventType() == CallEventType.CALL )
{
return mValidCallMessages > 1;
}
return true;
}
private Alias getAlias( String talkgroup )
{
@@ -55,7 +101,7 @@ public class LTRCallEvent extends CallEvent
@Override
public Alias getFromIDAlias()
{
if( mCallEventType == CallEventType.CALL_START ||
if( mCallEventType == CallEventType.CALL ||
mCallEventType == CallEventType.REGISTER ||
mCallEventType == CallEventType.ID_UNIQUE )
{

View File

@@ -17,23 +17,27 @@
******************************************************************************/
package decode.ltrnet;
import java.awt.EventQueue;
import java.util.HashMap;
import message.Message;
import alias.Alias;
import alias.AliasList;
import controller.activity.CallEvent;
import controller.activity.CallEvent.CallEventType;
import controller.activity.CallEventModel;
import controller.channel.ProcessingChain;
import controller.state.AuxChannelState;
import controller.state.ChannelState;
import controller.state.ChannelState.State;
public class LTRNetChannelState extends ChannelState
{
private String mToTalkgroup;
private Alias mToTalkgroupAlias;
private String mFromTalkgroup;
private Alias mFromTalkgroupAlias;
private String mFromTalkgroupType;
private String mTalkgroup;
private Alias mTalkgroupAlias;
private String mDescription;
private int mChannelNumber;
private LTRCallEvent mCurrentCallEvent;
private HashMap<Integer,String> mActiveCalls = new HashMap<Integer,String>();
private LTRNetActivitySummary mActivitySummary;
public LTRNetChannelState( ProcessingChain channel, AliasList aliasList )
@@ -50,27 +54,47 @@ public class LTRNetChannelState extends ChannelState
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
* We can receive multiple call tear-down messages -- only respond to
* the message that can change the state to fade
*/
if( getState().canChangeTo( State.FADE ) )
{
mCallEventModel.add(
new LTRCallEvent.Builder( type )
.aliasList( getAliasList() )
.channel( mChannelNumber )
.frequency( mProcessingChain.getChannel()
.getTunerChannel().getFrequency() )
.to( mToTalkgroup )
.build() );
LTRCallEvent current = getCurrentLTRCallEvent();
if( current != null )
{
/* Close out the call event. If we only received 1 call
* message, then flag it as noise and remove the call event */
if( current.isValid() )
{
mCallEventModel.setEnd( current );
}
else
{
mCallEventModel.remove( current );
}
}
}
mCurrentCallEvent = null;
setCurrentCallEvent( null );
mActiveCalls.clear();
super.fade( type );
}
public LTRCallEvent getCurrentLTRCallEvent()
{
CallEvent current = getCurrentCallEvent();
if( current != null )
{
return (LTRCallEvent)current;
}
return null;
}
@Override
public String getActivitySummary()
{
@@ -103,64 +127,106 @@ public class LTRNetChannelState extends ChannelState
switch( ltr.getMessageType() )
{
case CA_STRT:
mToTalkgroup = ltr.getTalkgroupID();
broadcastChange( ChangedAttribute.TO_TALKGROUP );
if( talkgroupAlias != null )
if( mChannelNumber == 0 )
{
mToTalkgroupAlias = talkgroupAlias;
broadcastChange( ChangedAttribute.TO_TALKGROUP_ALIAS );
mChannelNumber = ltr.getChannel();
}
mChannelNumber = ltr.getChannel();
broadcastChange( ChangedAttribute.CHANNEL_NUMBER );
if( getState() != ChannelState.State.CALL )
if( ltr.getChannel() == mChannelNumber )
{
mCallEventModel.add(
new LTRCallEvent.Builder( CallEventType.CALL_START )
processCallMessage( ltr );
if( ltr.getGroup() == 253 )
{
mDescription = "REGISTER";
broadcastChange( ChangedAttribute.DESCRIPTION );
}
else
{
mTalkgroup = ltr.getTalkgroupID();
broadcastChange( ChangedAttribute.TO_TALKGROUP );
if( talkgroupAlias != null )
{
mTalkgroupAlias = talkgroupAlias;
broadcastChange( ChangedAttribute.TO_TALKGROUP_ALIAS );
}
}
}
else
{
//Call Detect
if( !mActiveCalls.containsKey( ltr.getChannel() ) ||
!mActiveCalls.get( ltr.getChannel() )
.contentEquals( ltr.getTalkgroupID() ) )
{
mActiveCalls.put( ltr.getChannel(),
ltr.getTalkgroupID() );
mCallEventModel.add(
new LTRCallEvent.Builder( CallEventType.CALL_DETECT )
.aliasList( mAliasList )
.channel( ltr.getChannel() )
.frequency( mProcessingChain.getChannel()
.getTunerChannel().getFrequency() )
.to( mToTalkgroup )
.to( ltr.getTalkgroupID() )
.build() );
}
}
setState( State.CALL );
break;
case CA_ENDD:
mToTalkgroup = ltr.getTalkgroupID();
broadcastChange( ChangedAttribute.TO_TALKGROUP );
if( talkgroupAlias != null )
if( ltr.getGroup() != 253 )
{
mToTalkgroupAlias = talkgroupAlias;
broadcastChange( ChangedAttribute.TO_TALKGROUP_ALIAS );
mTalkgroup = ltr.getTalkgroupID();
broadcastChange( ChangedAttribute.TO_TALKGROUP );
if( talkgroupAlias != null )
{
mTalkgroupAlias = talkgroupAlias;
broadcastChange( ChangedAttribute.TO_TALKGROUP_ALIAS );
}
}
fade( CallEventType.CALL_END );
break;
case ID_UNIQ:
mFromTalkgroupType = "UID";
broadcastChange( ChangedAttribute.FROM_TALKGROUP_TYPE );
mDescription = "REGISTER UID";
broadcastChange( ChangedAttribute.DESCRIPTION );
mFromTalkgroup = String.valueOf( ltr.getRadioUniqueID() );
broadcastChange( ChangedAttribute.FROM_TALKGROUP );
mTalkgroup = String.valueOf( ltr.getRadioUniqueID() );
broadcastChange( ChangedAttribute.TO_TALKGROUP );
mFromTalkgroupAlias = ltr.getRadioUniqueIDAlias();
broadcastChange( ChangedAttribute.FROM_TALKGROUP_ALIAS );
mTalkgroupAlias = ltr.getRadioUniqueIDAlias();
broadcastChange( ChangedAttribute.TO_TALKGROUP_ALIAS );
mCallEventModel.add(
final LTRCallEvent currentEvent = getCurrentLTRCallEvent();
if( currentEvent != null &&
currentEvent.getCallEventType() == CallEventType.REGISTER )
{
final String uid = String.valueOf( ltr.getRadioUniqueID() );
if( uid != null )
{
mCallEventModel.setFromID( currentEvent, uid );
}
}
else
{
mCallEventModel.add(
new LTRCallEvent.Builder( CallEventType.REGISTER )
.aliasList( mAliasList )
.details( "Radio Unique ID" )
.frequency( mProcessingChain.getChannel()
.getTunerChannel().getFrequency() )
.from( String.valueOf( ltr.getRadioUniqueID() ) )
.build() );
.aliasList( mAliasList )
.details( "Radio Unique ID" )
.frequency( mProcessingChain.getChannel()
.getTunerChannel().getFrequency() )
.from( String.valueOf( ltr.getRadioUniqueID() ) )
.build() );
}
setState( State.CALL );
break;
case SY_IDLE:
mChannelNumber = ltr.getChannel();
broadcastChange( ChangedAttribute.CHANNEL_NUMBER );
break;
default:
break;
}
@@ -177,85 +243,83 @@ public class LTRNetChannelState extends ChannelState
switch( ltr.getMessageType() )
{
case CA_STRT:
mToTalkgroup = ltr.getTalkgroupID();
broadcastChange( ChangedAttribute.TO_TALKGROUP );
if( talkgroupAlias != null )
{
mToTalkgroupAlias = talkgroupAlias;
broadcastChange( ChangedAttribute.TO_TALKGROUP_ALIAS );
}
processCallMessage( ltr );
if( getState() != State.CALL )
if( ltr.getGroup() == 253 )
{
mCurrentCallEvent =
new LTRCallEvent.Builder( CallEventType.CALL_START )
.aliasList( mAliasList )
.channel( ltr.getChannel() )
.frequency( mProcessingChain.getChannel()
.getTunerChannel().getFrequency() )
.to( mToTalkgroup )
.build();
mCallEventModel.add( mCurrentCallEvent );
mDescription = "REGISTER";
broadcastChange( ChangedAttribute.DESCRIPTION );
}
else
{
mTalkgroup = ltr.getTalkgroupID();
broadcastChange( ChangedAttribute.TO_TALKGROUP );
if( talkgroupAlias != null )
{
mTalkgroupAlias = talkgroupAlias;
broadcastChange( ChangedAttribute.TO_TALKGROUP_ALIAS );
}
}
setState( State.CALL );
break;
case CA_ENDD:
mToTalkgroup = ltr.getTalkgroupID();
mTalkgroup = ltr.getTalkgroupID();
broadcastChange( ChangedAttribute.TO_TALKGROUP );
if( talkgroupAlias != null )
{
mToTalkgroupAlias = talkgroupAlias;
mTalkgroupAlias = talkgroupAlias;
broadcastChange( ChangedAttribute.TO_TALKGROUP_ALIAS );
}
fade( CallEventType.CALL_END );
break;
case ID_UNIQ:
mFromTalkgroupType = "UID";
broadcastChange( ChangedAttribute.FROM_TALKGROUP_TYPE );
mDescription = "REGISTER UID";
broadcastChange( ChangedAttribute.DESCRIPTION );
mFromTalkgroup = String.valueOf( ltr.getRadioUniqueID() );
broadcastChange( ChangedAttribute.FROM_TALKGROUP );
mTalkgroup = String.valueOf( ltr.getRadioUniqueID() );
broadcastChange( ChangedAttribute.TO_TALKGROUP );
mFromTalkgroupAlias = ltr.getRadioUniqueIDAlias();
broadcastChange( ChangedAttribute.FROM_TALKGROUP_ALIAS );
mTalkgroupAlias = ltr.getRadioUniqueIDAlias();
broadcastChange( ChangedAttribute.TO_TALKGROUP_ALIAS );
if( getState() != State.CALL )
if( getState() != State.DATA )
{
mCallEventModel.add( new LTRCallEvent.Builder(
CallEventType.ID_UNIQUE )
.aliasList( mAliasList )
.details( "Unique ID" )
.frequency( mProcessingChain.getChannel()
.getTunerChannel().getFrequency() )
.from( String.valueOf( ltr.getRadioUniqueID() ) )
.build() );
LTRCallEvent event =
new LTRCallEvent.Builder( CallEventType.REGISTER )
.aliasList( mAliasList )
.channel( ltr.getChannel() )
.frequency( mProcessingChain.getChannel()
.getTunerChannel().getFrequency() )
.to( ltr.getTalkgroupID() )
.build();
mCallEventModel.add( event );
setCurrentCallEvent( event );
setState( State.DATA );
}
else
if( mCurrentCallEvent != null )
{
if( mCurrentCallEvent != null )
{
mCurrentCallEvent.setFromID(
String.valueOf( ltr.getRadioUniqueID() ) );
mCurrentCallEvent.setDetails( "Unique ID" );
}
mCurrentCallEvent.setFromID(
String.valueOf( ltr.getRadioUniqueID() ) );
mCurrentCallEvent.setDetails( "Unique ID" );
}
setState( State.CALL );
break;
case ID_ESNH:
case ID_ESNL:
mFromTalkgroupType = "ESN";
broadcastChange( ChangedAttribute.FROM_TALKGROUP_TYPE );
mDescription = "ESN";
broadcastChange( ChangedAttribute.DESCRIPTION );
mFromTalkgroup = ltr.getESN();
broadcastChange( ChangedAttribute.FROM_TALKGROUP );
mTalkgroup = ltr.getESN();
broadcastChange( ChangedAttribute.TO_TALKGROUP );
mFromTalkgroupAlias = ltr.getESNAlias();
broadcastChange( ChangedAttribute.FROM_TALKGROUP_ALIAS );
mTalkgroupAlias = ltr.getESNAlias();
broadcastChange( ChangedAttribute.TO_TALKGROUP_ALIAS );
setState( State.CALL );
setState( State.DATA );
mCallEventModel.add(
new LTRCallEvent.Builder( CallEventType.REGISTER_ESN )
@@ -273,49 +337,88 @@ public class LTRNetChannelState extends ChannelState
}
}
private void processCallMessage( LTRNetMessage message )
{
LTRCallEvent current = getCurrentLTRCallEvent();
if( current == null || !current.addMessage( message ) )
{
if( current != null )
{
mCallEventModel.remove( current );
}
LTRCallEvent event;
if( message.getGroup() == 253 )
{
event = new LTRCallEvent.Builder( CallEventType.REGISTER )
.aliasList( mAliasList )
.channel( message.getChannel() )
.frequency( mProcessingChain.getChannel()
.getTunerChannel().getFrequency() )
.to( message.getTalkgroupID() )
.build();
setState( State.DATA );
}
else
{
event = new LTRCallEvent.Builder( CallEventType.CALL )
.aliasList( mAliasList )
.channel( message.getChannel() )
.frequency( mProcessingChain.getChannel()
.getTunerChannel().getFrequency() )
.to( message.getTalkgroupID() )
.build();
setState( State.CALL );
}
mCallEventModel.add( event );
setCurrentCallEvent( event );
}
else
{
if( getState() == State.CALL )
{
setState( State.CALL );
}
else if( getState() == State.DATA )
{
setState( State.DATA );
}
}
}
public void reset()
{
mToTalkgroup = null;
mTalkgroup = null;
broadcastChange( ChangedAttribute.TO_TALKGROUP );
mToTalkgroupAlias = null;
mTalkgroupAlias = null;
broadcastChange( ChangedAttribute.TO_TALKGROUP_ALIAS );
mFromTalkgroup = null;
broadcastChange( ChangedAttribute.FROM_TALKGROUP );
mFromTalkgroupAlias = null;
broadcastChange( ChangedAttribute.FROM_TALKGROUP_ALIAS );
mFromTalkgroupType = " ";
broadcastChange( ChangedAttribute.FROM_TALKGROUP_TYPE );
mDescription = null;
broadcastChange( ChangedAttribute.DESCRIPTION );
super.reset();
}
public String getToTalkgroup()
{
return mToTalkgroup;
return mTalkgroup;
}
public Alias getToTalkgroupAlias()
{
return mToTalkgroupAlias;
return mTalkgroupAlias;
}
public String getFromTalkgroup()
public String getDescription()
{
return mFromTalkgroup;
}
public Alias getFromTalkgroupAlias()
{
return mFromTalkgroupAlias;
}
public String getFromTalkgroupType()
{
return mFromTalkgroupType;
return mDescription;
}
public boolean hasChannelNumber()

View File

@@ -37,12 +37,11 @@ public class LTRNetPanel extends ChannelStatePanel
private JLabel mChannelLabel;
private JLabel mProtocol = new JLabel( "LTR-Net" );
private JLabel mToTalkgroup = new JLabel();
private JLabel mToTalkgroupAlias = new JLabel();
private JLabel mTalkgroup = new JLabel();
private JLabel mTalkgroupAlias = new JLabel();
private JLabel mFromType = new JLabel( " " );
private JLabel mFromTalkgroup = new JLabel();
private JLabel mFromTalkgroupAlias = new JLabel();
private JLabel mLCN = new JLabel( "LCN:" );
private JLabel mDescription = new JLabel();
public LTRNetPanel( Channel channel )
{
@@ -69,32 +68,28 @@ public class LTRNetPanel extends ChannelStatePanel
mProtocol.setFont( mFontDecoder );
mProtocol.setForeground( mColorLabelDecoder );
mToTalkgroup.setFont( mFontDecoder );
mToTalkgroup.setForeground( mColorLabelDecoder );
mTalkgroup.setFont( mFontDecoder );
mTalkgroup.setForeground( mColorLabelDecoder );
mToTalkgroupAlias.setFont( mFontDecoder );
mToTalkgroupAlias.setForeground( mColorLabelDecoder );
mTalkgroupAlias.setFont( mFontDecoder );
mTalkgroupAlias.setForeground( mColorLabelDecoder );
mFromType.setFont( mFontDecoder );
mFromType.setForeground( mColorLabelDecoder );
mLCN.setFont( mFontDecoder );
mLCN.setForeground( mColorLabelDecoder );
mFromTalkgroup.setFont( mFontDecoder );
mFromTalkgroup.setForeground( mColorLabelDecoder );
mFromTalkgroupAlias.setFont( mFontDecoder );
mFromTalkgroupAlias.setForeground( mColorLabelDecoder );
mDescription.setFont( mFontDecoder );
mDescription.setForeground( mColorLabelDecoder );
add( mStateLabel );
add( mSourceLabel );
add( mChannelLabel, "wrap" );
add( mProtocol );
add( mToTalkgroup );
add( mToTalkgroupAlias, "wrap" );
add( mTalkgroup );
add( mTalkgroupAlias, "wrap" );
add( mFromType );
add( mFromTalkgroup );
add( mFromTalkgroupAlias, "wrap" );
add( mLCN );
add( mDescription, "span,wrap" );
}
@Override
@@ -122,47 +117,31 @@ public class LTRNetPanel extends ChannelStatePanel
case SYSTEM_NAME:
mChannelLabel.setText( mChannel.getChannelDisplayName() );
break;
case FROM_TALKGROUP:
mFromTalkgroup.setText( state.getFromTalkgroup() );
break;
case FROM_TALKGROUP_ALIAS:
Alias fromAlias = state.getFromTalkgroupAlias();
if( fromAlias != null )
{
mFromTalkgroupAlias.setText( fromAlias.getName() );
String iconNameString = fromAlias.getIconName();
mFromTalkgroupAlias.setIcon( getSettingsManager()
.getImageIcon( iconNameString, 12 ) );
}
else
{
mFromTalkgroupAlias.setText( null );
mFromTalkgroupAlias.setIcon( null );
}
break;
case FROM_TALKGROUP_TYPE:
mFromType.setText( state.getFromTalkgroupType() );
break;
case TO_TALKGROUP:
mToTalkgroup.setText( state.getToTalkgroup() );
mTalkgroup.setText( state.getToTalkgroup() );
break;
case TO_TALKGROUP_ALIAS:
Alias tgAlias = state.getToTalkgroupAlias();
if( tgAlias != null )
{
mToTalkgroupAlias.setText( tgAlias.getName() );
mTalkgroupAlias.setText( tgAlias.getName() );
String iconNameString = tgAlias.getIconName();
mToTalkgroupAlias.setIcon( getSettingsManager()
mTalkgroupAlias.setIcon( getSettingsManager()
.getImageIcon( iconNameString, 12 ) );
}
else
{
mToTalkgroupAlias.setText( null );
mToTalkgroupAlias.setIcon( null );
mTalkgroupAlias.setText( null );
mTalkgroupAlias.setIcon( null );
}
break;
case DESCRIPTION:
mDescription.setText( state.getDescription() );
break;
case CHANNEL_NUMBER:
mLCN.setText( "LCN: " + state.getChannelNumber() );
break;
default:
break;
}
@@ -192,25 +171,21 @@ public class LTRNetPanel extends ChannelStatePanel
{
mProtocol.setForeground( mColorLabelDecoder );
}
if( mToTalkgroup != null )
if( mTalkgroup != null )
{
mToTalkgroup.setForeground( mColorLabelDecoder );
mTalkgroup.setForeground( mColorLabelDecoder );
}
if( mToTalkgroupAlias != null )
if( mTalkgroupAlias != null )
{
mToTalkgroupAlias.setForeground( mColorLabelDecoder );
mTalkgroupAlias.setForeground( mColorLabelDecoder );
}
if( mFromType != null )
if( mLCN != null )
{
mFromType.setForeground( mColorLabelDecoder );
mLCN.setForeground( mColorLabelDecoder );
}
if( mFromTalkgroup != null )
if( mDescription != null )
{
mFromTalkgroup.setForeground( mColorLabelDecoder );
}
if( mFromTalkgroupAlias != null )
{
mFromTalkgroupAlias.setForeground( mColorLabelDecoder );
mDescription.setForeground( mColorLabelDecoder );
}
break;
case CHANNEL_STATE_LABEL_DETAILS:

View File

@@ -22,7 +22,9 @@ import java.util.HashMap;
import message.Message;
import alias.Alias;
import alias.AliasList;
import controller.activity.CallEvent;
import controller.activity.CallEvent.CallEventType;
import controller.activity.CallEventModel;
import controller.channel.ProcessingChain;
import controller.state.AuxChannelState;
import controller.state.ChannelState;
@@ -72,19 +74,24 @@ public class LTRChannelState extends ChannelState
switch( ltr.getMessageType() )
{
/**
* Process Call Message
*
* States:
* 1) Call message with invalid LCN
* 2) State=IDLE/FADE, new CA_STRT
* 3) State=CALL, new CA_STRT, same talkgroup
* 4) State=CALL, new CA_STRT, different talkgroup
*/
case CA_STRT:
if( 0 < ltr.getChannel() && ltr.getChannel() <=20 )
{
/* If this channel is the same as the talkgroup's home
* repeater, then the channel number refers to the
* currently tuned frequency and we capture the channel
* number ... otherwise, it might be reflecting a call
* on another LCN */
if( ltr.getChannel() == ltr.getHomeRepeater() )
{
/* If we haven't captured the LCN yet ... */
if( mChannelNumber == 0 )
{
mChannelNumber = ltr.getChannel();
broadcastChange( ChangedAttribute.CHANNEL_NUMBER );
}
}
/* If this call event is for this channel, then update
* talkgroup and alias */
@@ -95,32 +102,47 @@ public class LTRChannelState extends ChannelState
mTalkgroupAlias = ltr.getTalkgroupIDAlias();
broadcastChange( ChangedAttribute.FROM_TALKGROUP_ALIAS );
LTRCallEvent current = getCurrentLTRCallEvent();
/* If we have an ongoing call, then add this message
* to the current event - if addMessage returns
* false, then we have a different talkgroup and a
* new call event, so close out the old one. */
if( current != null && !current.addMessage( ltr ) )
{
if( current.isValid() )
{
mCallEventModel.setEnd( current );
}
else
{
mCallEventModel.remove( current );
}
setCallEventModel( null );
current = null;
}
if( current == null )
{
LTRCallEvent event =
new LTRCallEvent.Builder( CallEventType.CALL )
.to( ltr.getTalkgroupID() )
.aliasList( getAliasList() )
.channel( ltr.getChannel() )
.frequency( ( ltr.getChannel() == mChannelNumber ) ?
mProcessingChain.getChannel()
.getTunerChannel().getFrequency() : 0 )
.build();
mCallEventModel.add( event );
setCurrentCallEvent( event );
}
setState( State.CALL );
}
/* If this is a new call, log a call event */
if( !mActiveCalls.containsKey( ltr.getChannel() ) ||
!mActiveCalls.get( ltr.getChannel() )
.contentEquals( ltr.getTalkgroupID() ) )
{
mActiveCalls.put( ltr.getChannel(), ltr.getTalkgroupID() );
CallEventType callEventType =
( ltr.getChannel() == mChannelNumber ) ?
CallEventType.CALL_START :
CallEventType.CALL_DETECT;
mCallEventModel.add(
new LTRCallEvent.Builder( callEventType )
.to( ltr.getTalkgroupID() )
.aliasList( getAliasList() )
.channel( ltr.getChannel() )
.frequency( ( ltr.getChannel() == mChannelNumber ) ?
mProcessingChain.getChannel()
.getTunerChannel().getFrequency() : 0 )
.build() );
}
setState( State.CALL );
}
break;
case CA_ENDD:
@@ -149,27 +171,47 @@ public class LTRChannelState extends ChannelState
}
}
public LTRCallEvent getCurrentLTRCallEvent()
{
CallEvent current = getCurrentCallEvent();
if( current != null )
{
return (LTRCallEvent)current;
}
return null;
}
/**
* 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
*/
/* We can receive multiple call tear-down messages -- only respond to
* the message that can change the state to fade */
if( getState().canChangeTo( State.FADE ) )
{
mActiveCalls.clear();
mCallEventModel.add(
new LTRCallEvent.Builder( type )
.aliasList( getAliasList() )
.channel( mChannelNumber )
.frequency( mProcessingChain.getChannel().getTunerChannel().getFrequency() )
.to( mTalkgroup )
.build() );
LTRCallEvent current = getCurrentLTRCallEvent();
if( current != null )
{
/* Close out the call event. If we only received 1 call
* message, then flag it as noise and remove the call event */
if( current.isValid() )
{
mCallEventModel.setEnd( current );
}
else
{
mCallEventModel.remove( current );
}
}
setCurrentCallEvent( null );
}
super.fade( type );

View File

@@ -41,8 +41,7 @@ public class LTRPanel extends ChannelStatePanel
private JLabel mTalkgroup = new JLabel();
private JLabel mTalkgroupAlias = new JLabel();
private JLabel mLCNLabel = new JLabel( "LCN" );
private JLabel mLCN = new JLabel();
private JLabel mLCN = new JLabel( "LCN:" );
private SettingsManager mSettingsManager;
@@ -86,9 +85,6 @@ public class LTRPanel extends ChannelStatePanel
mTalkgroupAlias.setFont( mFontDecoder );
mTalkgroupAlias.setForeground( mColorLabelDecoder );
mLCNLabel.setFont( mFontDecoder );
mLCNLabel.setForeground( mColorLabelDetails );
mLCN.setFont( mFontDecoder );
mLCN.setForeground( mColorLabelDecoder );
@@ -100,7 +96,6 @@ public class LTRPanel extends ChannelStatePanel
add( mTalkgroup );
add( mTalkgroupAlias, "wrap" );
add( mLCNLabel );
add( mLCN, "wrap" );
}
@@ -120,12 +115,7 @@ public class LTRPanel extends ChannelStatePanel
case CHANNEL_NUMBER:
if( state.getChannelNumber() != 0 )
{
mLCN.setText(
String.valueOf( state.getChannelNumber() ) );
}
else
{
mLCN.setText( "" );
mLCN.setText( "LCN: " + state.getChannelNumber() );
}
break;
case FROM_TALKGROUP:
@@ -208,10 +198,6 @@ public class LTRPanel extends ChannelStatePanel
{
mChannelLabel.setForeground( mColorLabelDetails );
}
if( mLCNLabel != null )
{
mLCNLabel.setForeground( mColorLabelDetails );
}
break;
}
}

View File

@@ -23,6 +23,7 @@ import source.config.SourceConfigTuner;
import alias.AliasList;
import audio.SquelchListener;
import audio.SquelchListener.SquelchState;
import controller.activity.CallEvent;
import controller.activity.CallEvent.CallEventType;
import controller.channel.Channel;
import controller.channel.Channel.ChannelType;
@@ -43,7 +44,6 @@ public class MPT1327ChannelState extends ChannelState
private ChannelMap mChannelMap;
private MPT1327ActivitySummary mActivitySummary;
public MPT1327ChannelState( ProcessingChain processingChain,
AliasList aliasList,
ChannelMap channelMap )
@@ -63,6 +63,12 @@ public class MPT1327ChannelState extends ChannelState
mActivitySummary.dispose();
mActivitySummary = null;
mCurrentCallEvent = null;
}
public void setCurrentCall( MPT1327CallEvent event )
{
mCurrentCallEvent = event;
}
@Override
@@ -203,8 +209,8 @@ public class MPT1327ChannelState extends ChannelState
traffic.addListener( (Listener<Message>)this );
CallEventType type = traffic.isProcessing() ?
CallEventType.CALL_START :
CallEventType.CALL_START_NO_TUNER;
CallEventType.CALL :
CallEventType.CALL_NO_TUNER;
/*
* Set the traffic channel's call event model to
@@ -212,15 +218,20 @@ public class MPT1327ChannelState extends ChannelState
*/
traffic.getProcessingChain().getChannelState()
.setCallEventModel( mCallEventModel );
MPT1327CallEvent callStartEvent =
new MPT1327CallEvent.Builder( type )
.aliasList( traffic.getProcessingChain().getAliasList() )
.channel( channelNumber )
.frequency( mChannelMap.getFrequency( channelNumber ) )
.from( mpt.getFromID() )
.to( mpt.getToID() )
.build();
mCallEventModel.add(
new MPT1327CallEvent.Builder( type )
.aliasList( traffic.getProcessingChain().getAliasList() )
.channel( channelNumber )
.frequency( mChannelMap.getFrequency( channelNumber ) )
.from( mpt.getFromID() )
.to( mpt.getToID() )
.build() );
traffic.getProcessingChain().getChannelState()
.setCurrentCallEvent( callStartEvent );
mCallEventModel.add( callStartEvent );
}
}
break;
@@ -260,14 +271,25 @@ public class MPT1327ChannelState extends ChannelState
*/
if( getState().canChangeTo( State.FADE ) )
{
mCallEventModel.add(
new MPT1327CallEvent.Builder( type )
.aliasList( getAliasList() )
.channel( mChannelNumber )
.frequency( mChannelMap.getFrequency( mChannelNumber ) )
.from( mFromTalkgroup )
.to( mToTalkgroup )
.build() );
CallEvent current = getCurrentCallEvent();
if( current != null )
{
mCallEventModel.setEnd( current );
}
else
{
mCallEventModel.add(
new MPT1327CallEvent.Builder( type )
.aliasList( getAliasList() )
.channel( mChannelNumber )
.frequency( mChannelMap.getFrequency( mChannelNumber ) )
.from( mFromTalkgroup )
.to( mToTalkgroup )
.build() );
}
setCurrentCall( null );
}
super.fade( type );

View File

@@ -17,6 +17,8 @@
******************************************************************************/
package decode.passport;
import log.Log;
public enum PassportBand
{
BAND_800( "800", 800000000 ),
@@ -38,6 +40,8 @@ public enum PassportBand
BAND_VHF( "VHF", 0 ),
BAND_UNKNOWN( "UNK", 0 );
public static int CHANNEL_BANDWIDTH = 12500; //Hertz
private String mDescription;
private int mBase;
@@ -59,6 +63,17 @@ public enum PassportBand
}
}
public long getFrequency( int channel )
{
return ( mBase + ( channel * CHANNEL_BANDWIDTH ) );
}
public int getChannel( long frequency )
{
return Math.round( (float)( frequency - mBase ) /
(float)CHANNEL_BANDWIDTH );
}
public String getDescription()
{
return mDescription;

View File

@@ -26,6 +26,7 @@ public class PassportCallEvent extends CallEvent
{
private int mChannel;
private long mFrequency;
private int mValidCallMessages = 1;
public PassportCallEvent( CallEventType callEventType,
AliasList aliasList,
@@ -42,6 +43,29 @@ public class PassportCallEvent extends CallEvent
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 )
{
if( hasAliasList() )

View File

@@ -17,11 +17,15 @@
******************************************************************************/
package decode.passport;
import java.util.HashMap;
import log.Log;
import message.Message;
import alias.Alias;
import alias.AliasList;
import audio.AudioType;
import audio.SquelchListener;
import controller.activity.CallEvent;
import controller.activity.CallEvent.CallEventType;
import controller.channel.ProcessingChain;
import controller.state.AuxChannelState;
@@ -34,9 +38,10 @@ public class PassportChannelState extends ChannelState
private String mMobileID;
private Alias mMobileIDAlias;
private int mChannelNumber;
private long mFrequency;
private PassportCallEvent mCurrentCallEvent;
private int mSiteNumber;
private PassportBand mSiteBand;
private PassportActivitySummary mActivitySummary;
private HashMap<Integer,String> mActiveCalls = new HashMap<Integer,String>();
public PassportChannelState( ProcessingChain channel, AliasList aliasList )
{
@@ -44,7 +49,7 @@ public class PassportChannelState extends ChannelState
mActivitySummary = new PassportActivitySummary( aliasList );
}
@Override
public String getActivitySummary()
{
@@ -66,7 +71,7 @@ public class PassportChannelState extends ChannelState
public void receive( Message message )
{
super.receive( message );
if( message instanceof PassportMessage )
{
mActivitySummary.receive( message );
@@ -78,44 +83,109 @@ public class PassportChannelState extends ChannelState
switch( passport.getMessageType() )
{
case CA_STRT:
setTalkgroup( String.valueOf( passport.getTalkgroupID() ) );
setTalkgroupAlias( passport.getTalkgroupIDAlias() );
if( mTalkgroupAlias != null )
if( mChannelNumber == 0 )
{
try
{
if( mTalkgroupAlias.hasAudioType() )
mChannelNumber = passport.getLCN();
}
if( passport.getLCN() == mChannelNumber )
{
setTalkgroup( String.valueOf( passport.getTalkgroupID() ) );
setTalkgroupAlias( passport.getTalkgroupIDAlias() );
if( mTalkgroupAlias != null )
{
try
{
mAudioTypeListener.setAudioType(
mTalkgroupAlias.getAudioType() );
if( mTalkgroupAlias.hasAudioType() )
{
mAudioTypeListener.setAudioType(
mTalkgroupAlias.getAudioType() );
}
}
}
catch( Exception e )
{
e.printStackTrace();
}
catch( Exception e )
{
Log.error( "Error setting audio for "
+ "passport call", e );
}
}
PassportCallEvent current =
getCurrentPassportCallEvent();
/* If we're already in a call event, add the message
* to the current call event ... if false, then we
* have a different call ... cleanup the old one. */
if( current != null && !current.addMessage( passport ) )
{
Log.info( "Current call event - testing" );
if( current.isValid() )
{
final PassportCallEvent endEvent =
getCurrentPassportCallEvent();
mCallEventModel.setEnd( endEvent );
}
else
{
mCallEventModel.remove( current );
}
current = null;
setCurrentCallEvent( null );
}
if( current == null )
{
mCurrentCallEvent = new PassportCallEvent
.Builder( CallEventType.CALL )
.aliasList( mAliasList )
.channel( mChannelNumber )
.frequency( passport.getLCNFrequency() )
.to( String.valueOf( passport.getTalkgroupID() ) )
.build();
mCallEventModel.add( mCurrentCallEvent );
}
State state = getState();
if( state == State.IDLE || state == State.CALL )
{
setState( State.CALL );
}
else if( state == State.DATA )
{
setState( State.DATA );
}
}
mChannelNumber = passport.getLCN();
mFrequency = passport.getLCNFrequency();
if( getState() != State.CALL )
else
{
mCurrentCallEvent = new PassportCallEvent
.Builder( CallEventType.CALL_START )
.aliasList( mAliasList )
.channel( mChannelNumber )
.frequency( mFrequency )
.to( String.valueOf( passport.getTalkgroupID() ) )
.build();
//Call Detection
int lcn = passport.getLCN();
String tg = String.valueOf( passport.getTalkgroupID() );
mCallEventModel.add( mCurrentCallEvent );
if( !mActiveCalls.containsKey( lcn ) ||
!mActiveCalls.get( lcn ).contentEquals( tg ) )
{
mActiveCalls.put( lcn, tg );
PassportCallEvent event = new PassportCallEvent
.Builder( CallEventType.CALL_DETECT )
.aliasList( mAliasList )
.channel( lcn )
.details( "Site: " + passport.getSite() )
.frequency( passport.getLCNFrequency() )
.to( tg )
.build();
mCallEventModel.add( event );
}
}
setState( State.CALL );
break;
case DA_STRT:
//TODO: add channel number checking and log a call event if on another site
setTalkgroup( String.valueOf( passport.getTalkgroupID() ) );
setTalkgroupAlias( passport.getTalkgroupIDAlias() );
setState( State.DATA );
@@ -129,12 +199,48 @@ public class PassportChannelState extends ChannelState
setMobileID( passport.getMobileID() );
setMobileIDAlias( passport.getMobileIDAlias() );
if( mCurrentCallEvent != null )
final String mid = passport.getMobileID();
final PassportCallEvent event =
getCurrentPassportCallEvent();
if( event != null && mid != null )
{
mCurrentCallEvent.setFromID( mMobileID );
mCallEventModel.setFromID( event, mid );
}
setState( State.CALL );
break;
case RA_REGI:
mCallEventModel.add( new PassportCallEvent
.Builder( CallEventType.REGISTER )
.aliasList( mAliasList )
.channel( passport.getLCN() )
.frequency( passport.getLCNFrequency() )
.to( passport.getToID() )
.build() );
//TODO: add logic to recognize the register event and suppress the subsequent
//call messages, but capture the group assignments.
setState( State.DATA );
break;
case SY_IDLE:
PassportBand band = passport.getSiteBand();
if( mSiteBand == null || mSiteBand != band )
{
mSiteBand = band;
mSiteNumber = passport.getSite();
long frequency = mProcessingChain.getChannel()
.getTunerChannel().getFrequency();
mChannelNumber = mSiteBand.getChannel( frequency );
broadcastChange( ChangedAttribute.CHANNEL_NUMBER );
}
default:
break;
}
}
}
@@ -152,21 +258,33 @@ public class PassportChannelState extends ChannelState
*/
if( getState().canChangeTo( State.FADE ) )
{
mCallEventModel.add(
new PassportCallEvent.Builder( type )
.aliasList( getAliasList() )
.channel( mChannelNumber )
.frequency( mProcessingChain.getChannel()
.getTunerChannel().getFrequency() )
.to( mTalkgroup )
.build() );
final PassportCallEvent current = getCurrentPassportCallEvent();
if( current != null )
{
mCallEventModel.setEnd( current );
}
}
setCurrentCallEvent( null );
mActiveCalls.clear();
super.fade( type );
}
public PassportCallEvent getCurrentPassportCallEvent()
{
CallEvent current = getCurrentCallEvent();
if( current != null )
{
return (PassportCallEvent)current;
}
return null;
}
/**
* Make the ConventionalChannelState always unsquelched
*/
@@ -190,6 +308,16 @@ public class PassportChannelState extends ChannelState
super.reset();
}
public int getChannelNumber()
{
return mChannelNumber;
}
public int getSiteNumber()
{
return mSiteNumber;
}
public String getTalkgroup()
{
return mTalkgroup;

View File

@@ -207,11 +207,6 @@ public class PassportMessage extends Message
return PassportBand.lookup( getInt( sNEIGHBOR_BAND ) );
}
public long getFrequency( int base, int channel )
{
return ( base + ( channel * 12500 ) );
}
public int getFree()
{
return getInt( sFREE );
@@ -233,7 +228,7 @@ public class PassportMessage extends Message
{
PassportBand band = getNeighborBand();
return getFrequency( band.getBase(), getFree() );
return band.getFrequency( getFree() );
}
return 0;
@@ -377,15 +372,13 @@ public class PassportMessage extends Message
@Override
public String getToID()
{
// TODO Auto-generated method stub
return null;
return String.valueOf( getTalkgroupID() );
}
@Override
public Alias getToIDAlias()
{
// TODO Auto-generated method stub
return null;
return getTalkgroupIDAlias();
}
public long getSiteFrequency( int channel )
@@ -396,9 +389,7 @@ public class PassportMessage extends Message
if( band != PassportBand.BAND_UNKNOWN )
{
int base = band.getBase();
return getFrequency( base, channel );
return band.getFrequency( channel );
}
}
@@ -493,7 +484,7 @@ public class PassportMessage extends Message
sb.append( getFreeFrequencyFormatted() );
break;
case CA_ENDD:
sb.append( "END TG:" );
sb.append( "END TG:" );
sb.append( format( getTalkgroupID(), 5 ) );
sb.append( "/" );
Alias endAlias = getTalkgroupIDAlias();

View File

@@ -19,6 +19,7 @@ package decode.passport;
import java.util.HashMap;
import log.Log;
import message.Message;
import message.MessageType;
import sample.Broadcaster;

View File

@@ -41,7 +41,7 @@ public class PassportPanel extends ChannelStatePanel
private JLabel mToTalkgroup = new JLabel();
private JLabel mToTalkgroupAlias = new JLabel();
private JLabel mFromTalkgroupType = new JLabel( " " );
private JLabel mSiteAndChannel = new JLabel( "Site:" );
private JLabel mFromTalkgroup = new JLabel();
private JLabel mFromTalkgroupAlias = new JLabel();
@@ -86,8 +86,8 @@ public class PassportPanel extends ChannelStatePanel
mToTalkgroupAlias.setFont( mFontDecoder );
mToTalkgroupAlias.setForeground( mColorLabelDecoder );
mFromTalkgroupType.setFont( mFontDecoder );
mFromTalkgroupType.setForeground( mColorLabelDecoder );
mSiteAndChannel.setFont( mFontDecoder );
mSiteAndChannel.setForeground( mColorLabelDecoder );
mFromTalkgroup.setFont( mFontDecoder );
mFromTalkgroup.setForeground( mColorLabelDecoder );
@@ -103,7 +103,7 @@ public class PassportPanel extends ChannelStatePanel
add( mToTalkgroup );
add( mToTalkgroupAlias, "wrap" );
add( mFromTalkgroupType );
add( mSiteAndChannel );
add( mFromTalkgroup );
add( mFromTalkgroupAlias, "wrap" );
}
@@ -135,7 +135,16 @@ public class PassportPanel extends ChannelStatePanel
mChannelLabel.setText( mChannel.getChannelDisplayName() );
break;
case TO_TALKGROUP:
mToTalkgroup.setText( state.getTalkgroup() );
String tg = state.getTalkgroup();
if( tg != null )
{
mToTalkgroup.setText( "TG:" + tg );
}
else
{
mToTalkgroup.setText( null );
}
break;
case TO_TALKGROUP_ALIAS:
Alias toAlias = state.getTalkgroupAlias();
@@ -156,16 +165,14 @@ public class PassportPanel extends ChannelStatePanel
case FROM_TALKGROUP:
String mid = state.getMobileID();
mFromTalkgroup.setText( state.getMobileID() );
if( mid != null )
{
mFromTalkgroupType.setText( "Mobile ID" );
}
else
{
mFromTalkgroupType.setText( " " );
}
if( mid != null )
{
mFromTalkgroup.setText( "MIN:" + mid );
}
else
{
mFromTalkgroup.setText( null );
}
break;
case FROM_TALKGROUP_ALIAS:
Alias fromAlias = state.getMobileIDAlias();
@@ -183,6 +190,15 @@ public class PassportPanel extends ChannelStatePanel
mFromTalkgroupAlias.setIcon( null );
}
break;
case CHANNEL_NUMBER:
StringBuilder sb = new StringBuilder();
sb.append( "Site: " );
sb.append( state.getSiteNumber() );
sb.append( "/" );
sb.append( state.getChannelNumber() );
mSiteAndChannel.setText( sb.toString() );
break;
default:
break;
}
@@ -222,9 +238,9 @@ public class PassportPanel extends ChannelStatePanel
{
mToTalkgroupAlias.setForeground( mColorLabelDecoder );
}
if( mFromTalkgroupType != null )
if( mSiteAndChannel != null )
{
mFromTalkgroupType.setForeground( mColorLabelDecoder );
mSiteAndChannel.setForeground( mColorLabelDecoder );
}
if( mFromTalkgroup != null )
{