mirror of
https://github.com/DSheirer/sdrtrunk.git
synced 2026-11-13 00:57:31 -05:00
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:
@@ -26,7 +26,8 @@ import decode.DecoderType;
|
||||
|
||||
public abstract class CallEvent
|
||||
{
|
||||
protected long mEventTime = System.currentTimeMillis();
|
||||
protected long mEventStart = System.currentTimeMillis();
|
||||
protected long mEventEnd;
|
||||
|
||||
private SimpleDateFormat mSDF = new SimpleDateFormat( "yyyyMMdd','HHmmss" );
|
||||
|
||||
@@ -52,6 +53,11 @@ public abstract class CallEvent
|
||||
mDetails = details;
|
||||
}
|
||||
|
||||
public void setEnd( long end )
|
||||
{
|
||||
mEventEnd = end;
|
||||
}
|
||||
|
||||
public DecoderType getDecoderType()
|
||||
{
|
||||
return mDecoderType;
|
||||
@@ -77,9 +83,14 @@ public abstract class CallEvent
|
||||
return mAliasList != null;
|
||||
}
|
||||
|
||||
public long getEventTime()
|
||||
public long getEventStartTime()
|
||||
{
|
||||
return mEventTime;
|
||||
return mEventStart;
|
||||
}
|
||||
|
||||
public long getEventEndTime()
|
||||
{
|
||||
return mEventEnd;
|
||||
}
|
||||
|
||||
public String getFromID()
|
||||
@@ -122,7 +133,8 @@ public abstract class CallEvent
|
||||
|
||||
public static String getCSVHeader()
|
||||
{
|
||||
return "DATE,TIME,DECODER,EVENT,FROM,FROM_ALIAS,TO,TO_ALIAS,"
|
||||
return "START_DATE,START_TIME,END_DATE,END_TIME,"
|
||||
+ "DECODER,EVENT,FROM,FROM_ALIAS,TO,TO_ALIAS,"
|
||||
+ "CHANNEL,FREQUENCY,DETAILS";
|
||||
}
|
||||
|
||||
@@ -131,7 +143,16 @@ public abstract class CallEvent
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append( "'" );
|
||||
sb.append( mSDF.format( new Date( getEventTime() ) ) );
|
||||
sb.append( mSDF.format( new Date( getEventStartTime() ) ) );
|
||||
sb.append( "','" );
|
||||
if( mEventEnd != 0 )
|
||||
{
|
||||
sb.append( mSDF.format( new Date( getEventEndTime() ) ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.append( "','" );
|
||||
}
|
||||
sb.append( "','" );
|
||||
sb.append( getDecoderType().toString() );
|
||||
sb.append( "','" );
|
||||
@@ -189,11 +210,11 @@ public abstract class CallEvent
|
||||
public enum CallEventType
|
||||
{
|
||||
ACKNOWLEDGE( "Acknowledge" ),
|
||||
CALL_DETECT( "Call Detect" ),
|
||||
CALL_START( "Call Start" ),
|
||||
CALL_START_UNIQUE_ID( "Call Start" ),
|
||||
CALL_START_NO_TUNER( "Call - No Tuner" ),
|
||||
CALL( "Call" ),
|
||||
CALL_END( "Call End" ),
|
||||
CALL_DETECT( "Call Detect" ),
|
||||
CALL_UNIQUE_ID( "UID Call" ),
|
||||
CALL_NO_TUNER( "Call - No Tuner" ),
|
||||
CALL_TIMEOUT( "Call Timeout" ),
|
||||
EMERGENCY( "EMERGENCY" ),
|
||||
GPS( "GPS" ),
|
||||
@@ -205,7 +226,8 @@ public abstract class CallEvent
|
||||
REQUEST( "Request" ),
|
||||
SDM( "SDM" ),
|
||||
STATUS( "Status" ),
|
||||
UNKNOWN( "Unknown" );
|
||||
UNKNOWN( "Unknown" ),
|
||||
INVALID( "Invalid" );
|
||||
|
||||
private String mLabel;
|
||||
|
||||
|
||||
@@ -18,29 +18,36 @@
|
||||
package controller.activity;
|
||||
|
||||
import java.awt.EventQueue;
|
||||
import java.text.DecimalFormat;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedList;
|
||||
|
||||
import javax.swing.table.AbstractTableModel;
|
||||
|
||||
import log.Log;
|
||||
import sample.Broadcaster;
|
||||
import sample.Listener;
|
||||
import controller.activity.CallEvent.CallEventType;
|
||||
|
||||
public class CallEventModel extends AbstractTableModel
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private static DecimalFormat mFrequencyFormatter =
|
||||
new DecimalFormat( "0.000000" );
|
||||
|
||||
private static final int DEFAULT_ICON_HEIGHT = 14;
|
||||
|
||||
private static final int sTIME = 0;
|
||||
private static final int sEVENT = 1;
|
||||
private static final int sFROM_ID = 2;
|
||||
private static final int sFROM_ALIAS = 3;
|
||||
private static final int sTO_ID = 4;
|
||||
private static final int sTO_ALIAS =5;
|
||||
private static final int sCHANNEL = 6;
|
||||
private static final int sFREQUENCY = 7;
|
||||
private static final int sDETAILS = 8;
|
||||
public static final int TIME = 0;
|
||||
public static final int EVENT = 1;
|
||||
public static final int FROM_ID = 2;
|
||||
public static final int FROM_ALIAS = 3;
|
||||
public static final int TO_ID = 4;
|
||||
public static final int TO_ALIAS = 5;
|
||||
public static final int CHANNEL = 6;
|
||||
public static final int FREQUENCY = 7;
|
||||
public static final int DETAILS = 8;
|
||||
|
||||
protected int mMaxMessages = 500;
|
||||
|
||||
@@ -49,9 +56,9 @@ public class CallEventModel extends AbstractTableModel
|
||||
protected String[] mHeaders = new String[] { "Time",
|
||||
"Event",
|
||||
"From",
|
||||
"From Alias",
|
||||
"Alias",
|
||||
"To",
|
||||
"To Alias",
|
||||
"Alias",
|
||||
"Channel",
|
||||
"Frequency",
|
||||
"Details" };
|
||||
@@ -67,16 +74,23 @@ public class CallEventModel extends AbstractTableModel
|
||||
|
||||
public void dispose()
|
||||
{
|
||||
mEvents.clear();
|
||||
synchronized( mEvents )
|
||||
{
|
||||
mEvents.clear();
|
||||
}
|
||||
|
||||
mBroadcaster.dispose();
|
||||
}
|
||||
|
||||
public void flush()
|
||||
{
|
||||
/* Flush all events to listeners ( normally the call event logger ) */
|
||||
for( CallEvent event: mEvents )
|
||||
synchronized( mEvents )
|
||||
{
|
||||
mBroadcaster.receive( event );
|
||||
for( CallEvent event: mEvents )
|
||||
{
|
||||
mBroadcaster.receive( event );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -91,30 +105,137 @@ public class CallEventModel extends AbstractTableModel
|
||||
}
|
||||
|
||||
public void add( final CallEvent event )
|
||||
{
|
||||
try
|
||||
{
|
||||
synchronized ( mEvents )
|
||||
{
|
||||
mEvents.addFirst( event );
|
||||
}
|
||||
|
||||
fireTableRowsInserted( 0, 0 );
|
||||
|
||||
prune();
|
||||
}
|
||||
catch( Exception e )
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public void remove( final CallEvent event )
|
||||
{
|
||||
EventQueue.invokeLater( new Runnable()
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
mEvents.addFirst( event );
|
||||
|
||||
CallEventModel.this.fireTableRowsInserted( 0, 0 );
|
||||
|
||||
prune();
|
||||
synchronized ( mEvents )
|
||||
{
|
||||
final int row = mEvents.indexOf( event );
|
||||
|
||||
mEvents.remove( event );
|
||||
|
||||
if( row != -1 )
|
||||
{
|
||||
fireTableRowsDeleted( row, row );
|
||||
}
|
||||
}
|
||||
}
|
||||
} );
|
||||
}
|
||||
|
||||
public int indexOf( CallEvent event )
|
||||
{
|
||||
return mEvents.indexOf( event );
|
||||
}
|
||||
|
||||
public void setEnd( final CallEvent event )
|
||||
{
|
||||
try
|
||||
{
|
||||
EventQueue.invokeAndWait( new Runnable()
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
if( event != null )
|
||||
{
|
||||
event.setEnd( System.currentTimeMillis() );
|
||||
|
||||
synchronized ( mEvents )
|
||||
{
|
||||
int row = indexOf( event );
|
||||
|
||||
if( row != -1 )
|
||||
{
|
||||
fireTableCellUpdated( row, TIME );
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.error( "CallEventModel - couldn't log end time - event was null" );
|
||||
}
|
||||
}
|
||||
} );
|
||||
}
|
||||
catch( Exception e )
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public void setFromID( final CallEvent event, final String from )
|
||||
{
|
||||
EventQueue.invokeLater( new Runnable()
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
try
|
||||
{
|
||||
if( event != null )
|
||||
{
|
||||
event.setFromID( from );
|
||||
|
||||
synchronized ( mEvents )
|
||||
{
|
||||
int row = indexOf( event );
|
||||
|
||||
if( row != -1 )
|
||||
{
|
||||
fireTableCellUpdated( row, FROM_ID );
|
||||
fireTableCellUpdated( row, FROM_ALIAS );
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.error( "CallEventModel - tried to set from ID on "
|
||||
+ "call event - couldn't find index of event" );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch( Exception e )
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
} );
|
||||
}
|
||||
|
||||
private void prune()
|
||||
{
|
||||
while( mEvents.size() > mMaxMessages )
|
||||
synchronized( mEvents )
|
||||
{
|
||||
CallEvent event = mEvents.removeLast();
|
||||
|
||||
mBroadcaster.receive( event );
|
||||
|
||||
super.fireTableRowsDeleted( mEvents.size(), mEvents.size() );
|
||||
while( mEvents.size() > mMaxMessages )
|
||||
{
|
||||
CallEvent event = mEvents.removeLast();
|
||||
|
||||
mBroadcaster.receive( event );
|
||||
|
||||
fireTableRowsDeleted( mEvents.size(), mEvents.size() );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -138,26 +259,64 @@ public class CallEventModel extends AbstractTableModel
|
||||
@Override
|
||||
public Object getValueAt( int rowIndex, int columnIndex )
|
||||
{
|
||||
switch( columnIndex )
|
||||
synchronized( mEvents )
|
||||
{
|
||||
case sTIME:
|
||||
return mSDFTime.format( mEvents.get( rowIndex ).getEventTime() );
|
||||
case sEVENT:
|
||||
return mEvents.get( rowIndex ).getCallEventType();
|
||||
case sFROM_ID:
|
||||
return mEvents.get( rowIndex ).getFromID();
|
||||
case sFROM_ALIAS:
|
||||
return mEvents.get( rowIndex ).getFromIDAlias();
|
||||
case sTO_ID:
|
||||
return mEvents.get( rowIndex ).getToID();
|
||||
case sTO_ALIAS:
|
||||
return mEvents.get( rowIndex ).getToIDAlias();
|
||||
case sCHANNEL:
|
||||
return mEvents.get( rowIndex ).getChannel();
|
||||
case sFREQUENCY:
|
||||
return mEvents.get( rowIndex ).getFrequency();
|
||||
case sDETAILS:
|
||||
return mEvents.get( rowIndex ).getDetails();
|
||||
switch( columnIndex )
|
||||
{
|
||||
case TIME:
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append( mSDFTime.format(
|
||||
mEvents.get( rowIndex ).getEventStartTime() ) );
|
||||
|
||||
if( mEvents.get( rowIndex ).getEventEndTime() != 0 )
|
||||
{
|
||||
sb.append( " - " );
|
||||
sb.append( mSDFTime.format(
|
||||
mEvents.get( rowIndex ).getEventEndTime() ) );
|
||||
}
|
||||
else if( mEvents.get( rowIndex )
|
||||
.getCallEventType() == CallEventType.CALL )
|
||||
{
|
||||
sb.append( " - In Progress" );
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
case EVENT:
|
||||
return mEvents.get( rowIndex ).getCallEventType();
|
||||
case FROM_ID:
|
||||
return mEvents.get( rowIndex ).getFromID();
|
||||
case FROM_ALIAS:
|
||||
return mEvents.get( rowIndex ).getFromIDAlias();
|
||||
case TO_ID:
|
||||
return mEvents.get( rowIndex ).getToID();
|
||||
case TO_ALIAS:
|
||||
return mEvents.get( rowIndex ).getToIDAlias();
|
||||
case CHANNEL:
|
||||
int channel = mEvents.get( rowIndex ).getChannel();
|
||||
|
||||
if( channel != 0 )
|
||||
{
|
||||
return channel;
|
||||
}
|
||||
else
|
||||
{
|
||||
return null;
|
||||
}
|
||||
case FREQUENCY:
|
||||
long frequency = mEvents.get( rowIndex ).getFrequency();
|
||||
|
||||
if( frequency != 0 )
|
||||
{
|
||||
return mFrequencyFormatter.format( (double)frequency / 1E6d );
|
||||
}
|
||||
else
|
||||
{
|
||||
return null;
|
||||
}
|
||||
case DETAILS:
|
||||
return mEvents.get( rowIndex ).getDetails();
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
******************************************************************************/
|
||||
package controller.state;
|
||||
|
||||
import java.awt.EventQueue;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
@@ -42,6 +43,7 @@ import controller.activity.CallEventModel;
|
||||
import controller.activity.MessageActivityModel;
|
||||
import controller.channel.Channel.ChannelType;
|
||||
import controller.channel.ProcessingChain;
|
||||
import decode.mpt1327.MPT1327CallEvent;
|
||||
|
||||
/**
|
||||
* ChannelState provides a state machine for tracking a voice or data call
|
||||
@@ -98,7 +100,6 @@ public abstract class ChannelState implements Listener<Message>
|
||||
protected AudioTypeListener mAudioTypeListener;
|
||||
protected AudioType mAudioType = AudioType.NORMAL;
|
||||
|
||||
|
||||
protected CallEventModel mCallEventModel = new CallEventModel();
|
||||
|
||||
protected JTable mCallEventTable;
|
||||
@@ -111,6 +112,8 @@ public abstract class ChannelState implements Listener<Message>
|
||||
|
||||
protected AliasList mAliasList;
|
||||
|
||||
protected CallEvent mCurrentCallEvent;
|
||||
|
||||
public ChannelState( ProcessingChain processingChain, AliasList aliasList )
|
||||
{
|
||||
mProcessingChain = processingChain;
|
||||
@@ -125,6 +128,16 @@ public abstract class ChannelState implements Listener<Message>
|
||||
mCallResetTimeout = props.get( "call.reset.timeout", 4000 );
|
||||
}
|
||||
|
||||
public void setCurrentCallEvent( CallEvent callEvent )
|
||||
{
|
||||
mCurrentCallEvent = callEvent;
|
||||
}
|
||||
|
||||
public CallEvent getCurrentCallEvent()
|
||||
{
|
||||
return mCurrentCallEvent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows setting the call event model to use for traffic channels, so that
|
||||
* all traffic channels can share the parent control channel call event
|
||||
@@ -190,12 +203,9 @@ public abstract class ChannelState implements Listener<Message>
|
||||
return mAliasList != null;
|
||||
}
|
||||
|
||||
public void broadcastChange( ChangedAttribute attribute )
|
||||
public void broadcastChange( final ChangedAttribute attribute )
|
||||
{
|
||||
if( mChangeBroadcaster != null )
|
||||
{
|
||||
mChangeBroadcaster.broadcast( attribute );
|
||||
}
|
||||
mChangeBroadcaster.broadcast( attribute );
|
||||
}
|
||||
|
||||
public void setCallFadeTimeout( long milliseconds )
|
||||
@@ -648,6 +658,7 @@ public abstract class ChannelState implements Listener<Message>
|
||||
CHANNEL_SITE_NUMBER,
|
||||
CHANNEL_SITE_NUMBER_ALIAS,
|
||||
CHANNEL_STATE,
|
||||
DESCRIPTION,
|
||||
FROM_TALKGROUP,
|
||||
FROM_TALKGROUP_ALIAS,
|
||||
FROM_TALKGROUP_TYPE,
|
||||
|
||||
Reference in New Issue
Block a user