mirror of
https://github.com/DSheirer/sdrtrunk.git
synced 2026-11-12 16:47:31 -05:00
Updated LTR Standard decoder state to new architecture to support
per-call recording and accurate state tracking. Resolved issue with ThreadPoolManager limiting total number of scheduled tasks (removed limiter - original intent is now OBE) Updated ChannelState to better handle auxiliary decoder decode events, so that when a fleetsync ident is at the end of the transmission, the decode doesn't kick the channel back into a call state after it has faded, causing static bursts and additional empty recordings. Updated recording file name to include millisecond level precision, to further avoid duplicate recording names
This commit is contained in:
@@ -66,8 +66,6 @@ public class CallEventModel extends AbstractTableModel implements Listener<CallE
|
||||
|
||||
private SimpleDateFormat mSDFTime = new SimpleDateFormat( "HH:mm:ss" );
|
||||
|
||||
private boolean mNewMessagesFirst = true;
|
||||
|
||||
public CallEventModel()
|
||||
{
|
||||
}
|
||||
@@ -102,10 +100,6 @@ public class CallEventModel extends AbstractTableModel implements Listener<CallE
|
||||
*/
|
||||
public void receive( final CallEvent event )
|
||||
{
|
||||
//TODO: reverse this so that the new events go to the end and the oldest
|
||||
//events are at the beginning ... use the getObjectAt() to control
|
||||
//correct access to the ordering imposed.
|
||||
|
||||
if( event.isValid() )
|
||||
{
|
||||
if( !mEvents.contains( event ) )
|
||||
|
||||
@@ -43,6 +43,8 @@ public class Fleetsync2DecoderState extends DecoderState
|
||||
|
||||
private String mMessage;
|
||||
private String mMessageType;
|
||||
|
||||
private long mFrequency;
|
||||
|
||||
public Fleetsync2DecoderState( AliasList aliasList )
|
||||
{
|
||||
@@ -158,14 +160,14 @@ public class Fleetsync2DecoderState extends DecoderState
|
||||
}
|
||||
|
||||
FleetsyncCallEvent fsCallEvent =
|
||||
FleetsyncCallEvent.getFleetsync2Event( fleetsync );
|
||||
FleetsyncCallEvent.getFleetsync2Event( fleetsync, mFrequency );
|
||||
|
||||
fsCallEvent.setAliasList( getAliasList() );
|
||||
|
||||
broadcast( fsCallEvent );
|
||||
|
||||
/* Broadcast decode event so that the channel state will
|
||||
* kick in and reset everything */
|
||||
* kick in and reset everything after a short delay */
|
||||
broadcast( new DecoderStateEvent( this, Event.DECODE, state ) );
|
||||
}
|
||||
}
|
||||
@@ -248,6 +250,9 @@ public class Fleetsync2DecoderState extends DecoderState
|
||||
case RESET:
|
||||
resetState();
|
||||
break;
|
||||
case SOURCE_FREQUENCY:
|
||||
mFrequency = event.getFrequency();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -24,14 +24,19 @@ import alias.AliasList;
|
||||
|
||||
public class FleetsyncCallEvent extends CallEvent
|
||||
{
|
||||
private long mFrequency = 0;
|
||||
|
||||
public FleetsyncCallEvent( CallEventType callEventType,
|
||||
AliasList aliasList,
|
||||
String fromID,
|
||||
String toID,
|
||||
String details )
|
||||
String details,
|
||||
long frequency )
|
||||
{
|
||||
super( DecoderType.FLEETSYNC2, callEventType,
|
||||
aliasList, fromID, toID, details );
|
||||
|
||||
mFrequency = frequency;
|
||||
}
|
||||
|
||||
private Alias getAlias( String ident )
|
||||
@@ -65,7 +70,7 @@ public class FleetsyncCallEvent extends CallEvent
|
||||
@Override
|
||||
public long getFrequency()
|
||||
{
|
||||
return 0;
|
||||
return mFrequency;
|
||||
}
|
||||
|
||||
public static class Builder
|
||||
@@ -78,6 +83,7 @@ public class FleetsyncCallEvent extends CallEvent
|
||||
private String mFromID;
|
||||
private String mToID;
|
||||
private String mDetails;
|
||||
private long mFrequency;
|
||||
|
||||
public Builder( CallEventType callEventType )
|
||||
{
|
||||
@@ -89,6 +95,12 @@ public class FleetsyncCallEvent extends CallEvent
|
||||
mAliasList = aliasList;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder frequency( long frequency )
|
||||
{
|
||||
mFrequency = frequency;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder from( String val )
|
||||
{
|
||||
@@ -123,11 +135,12 @@ public class FleetsyncCallEvent extends CallEvent
|
||||
builder.mAliasList,
|
||||
builder.mFromID,
|
||||
builder.mToID,
|
||||
builder.mDetails );
|
||||
builder.mDetails,
|
||||
builder.mFrequency );
|
||||
}
|
||||
|
||||
public static FleetsyncCallEvent
|
||||
getFleetsync2Event( FleetsyncMessage message )
|
||||
public static FleetsyncCallEvent getFleetsync2Event(
|
||||
FleetsyncMessage message, long frequency )
|
||||
{
|
||||
CallEventType type = CallEventType.UNKNOWN;
|
||||
StringBuilder sbDetails = new StringBuilder();
|
||||
@@ -176,6 +189,7 @@ public class FleetsyncCallEvent extends CallEvent
|
||||
{
|
||||
return new FleetsyncCallEvent.Builder( type )
|
||||
.details( sbDetails.toString() )
|
||||
.frequency( frequency )
|
||||
.from( message.getFromID() )
|
||||
.build();
|
||||
}
|
||||
@@ -183,6 +197,7 @@ public class FleetsyncCallEvent extends CallEvent
|
||||
{
|
||||
return new FleetsyncCallEvent.Builder( type )
|
||||
.details( sbDetails.toString() )
|
||||
.frequency( frequency )
|
||||
.from( message.getFromID() )
|
||||
.to( message.getToID() )
|
||||
.build();
|
||||
|
||||
@@ -27,7 +27,6 @@ public class LTRCallEvent extends CallEvent
|
||||
{
|
||||
private String mChannel;
|
||||
private long mFrequency;
|
||||
private int mValidCallMessages = 1;
|
||||
|
||||
public LTRCallEvent( DecoderType type,
|
||||
CallEventType callEventType,
|
||||
@@ -44,26 +43,6 @@ public class LTRCallEvent extends CallEvent
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the message's talkgroup matches this call event. Counts the
|
||||
* number of messages that match this call event to use in determining if
|
||||
@@ -78,24 +57,12 @@ public class LTRCallEvent extends CallEvent
|
||||
if( talkgroup != null && getToID() != null &&
|
||||
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 )
|
||||
{
|
||||
if( hasAliasList() )
|
||||
|
||||
@@ -675,7 +675,7 @@ public class LTRNetDecoderState extends DecoderState
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the decoder state for re-use on another channel
|
||||
* Performs a full reset
|
||||
*/
|
||||
public void reset()
|
||||
{
|
||||
@@ -694,7 +694,7 @@ public class LTRNetDecoderState extends DecoderState
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the decoder state after a call event
|
||||
* Resets the decoder state after a call or other decode event
|
||||
*/
|
||||
private void resetState()
|
||||
{
|
||||
|
||||
@@ -21,6 +21,7 @@ import java.awt.EventQueue;
|
||||
|
||||
import javax.swing.JLabel;
|
||||
|
||||
import net.miginfocom.swing.MigLayout;
|
||||
import module.decode.state.ChangedAttribute;
|
||||
import module.decode.state.DecoderPanel;
|
||||
import settings.ColorSetting;
|
||||
@@ -53,7 +54,11 @@ public class LTRStandardDecoderPanel extends DecoderPanel
|
||||
|
||||
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 );
|
||||
|
||||
mTalkgroup.setFont( mFontDecoder );
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*******************************************************************************
|
||||
* SDR Trunk
|
||||
* Copyright (C) 2014 Dennis Sheirer
|
||||
* Copyright (C) 2014,2015 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -17,7 +17,6 @@
|
||||
******************************************************************************/
|
||||
package module.decode.ltrstandard;
|
||||
|
||||
import java.text.DecimalFormat;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
@@ -35,22 +34,19 @@ import module.decode.state.DecoderStateEvent.Event;
|
||||
import module.decode.state.State;
|
||||
import alias.Alias;
|
||||
import alias.AliasList;
|
||||
import audio.metadata.Metadata;
|
||||
import audio.metadata.MetadataType;
|
||||
|
||||
public class LTRStandardDecoderState extends DecoderState
|
||||
{
|
||||
private static final int sINT_NULL_VALUE = -1;
|
||||
private DecimalFormat mDecimalFormatter = new DecimalFormat("0.00000");
|
||||
|
||||
private HashMap<Integer,String> mActiveCalls = new HashMap<Integer,String>();
|
||||
private HashSet<String> mTalkgroupsFirstHeard = new HashSet<String>();
|
||||
private TreeSet<String> mTalkgroups = new TreeSet<String>();
|
||||
private TreeSet<Integer> mActiveLCNs = new TreeSet<Integer>();
|
||||
private int mMonitoredLCN;
|
||||
|
||||
private String mTalkgroup;
|
||||
private Alias mTalkgroupAlias;
|
||||
private int mChannelNumber;
|
||||
|
||||
private long mFrequency;
|
||||
|
||||
public LTRStandardDecoderState( AliasList aliasList )
|
||||
@@ -111,14 +107,13 @@ public class LTRStandardDecoderState extends DecoderState
|
||||
broadcast( ChangedAttribute.TO_TALKGROUP_ALIAS );
|
||||
|
||||
LTRCallEvent current = getCurrentCallEvent();
|
||||
|
||||
/* 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 ) )
|
||||
|
||||
/* Detect when we haven't reset from the previous
|
||||
* call and now have a new call coming in with
|
||||
* a different talkgroup */
|
||||
if( current != null && isDifferentTalkgroup( mTalkgroup ) )
|
||||
{
|
||||
mCurrentCallEvent.setEnd( System.currentTimeMillis() );
|
||||
mCurrentCallEvent.end();
|
||||
broadcast( mCurrentCallEvent );
|
||||
mCurrentCallEvent = null;
|
||||
}
|
||||
@@ -136,30 +131,35 @@ public class LTRStandardDecoderState extends DecoderState
|
||||
|
||||
broadcast( mCurrentCallEvent );
|
||||
|
||||
broadcast( new DecoderStateEvent( this, Event.START, State.CALL ) );
|
||||
broadcast( new Metadata( MetadataType.TO,
|
||||
mTalkgroup, mTalkgroupAlias, true ) );
|
||||
|
||||
broadcast( new DecoderStateEvent( this,
|
||||
Event.START, State.CALL ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
broadcast( new DecoderStateEvent( this, Event.CONTINUATION, State.CALL ) );
|
||||
broadcast( new DecoderStateEvent( this,
|
||||
Event.CONTINUATION, State.CALL ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case CA_ENDD:
|
||||
mTalkgroup = ltr.getTalkgroupID();
|
||||
broadcast( ChangedAttribute.FROM_TALKGROUP );
|
||||
broadcast( ChangedAttribute.TO_TALKGROUP );
|
||||
|
||||
mTalkgroupAlias = ltr.getTalkgroupIDAlias();
|
||||
broadcast( ChangedAttribute.FROM_TALKGROUP_ALIAS );
|
||||
broadcast( ChangedAttribute.TO_TALKGROUP_ALIAS );
|
||||
|
||||
if( mCurrentCallEvent != null )
|
||||
{
|
||||
mCurrentCallEvent.setEnd( System.currentTimeMillis() );
|
||||
mCurrentCallEvent.end();
|
||||
broadcast( mCurrentCallEvent );
|
||||
broadcast( new DecoderStateEvent( this, Event.END, State.FADE ) );
|
||||
mCurrentCallEvent = null;
|
||||
}
|
||||
|
||||
|
||||
int home = ltr.getHomeRepeater();
|
||||
|
||||
if( 0 < home && home <= 20 )
|
||||
@@ -182,9 +182,9 @@ public class LTRStandardDecoderState extends DecoderState
|
||||
{
|
||||
if( channel == home )
|
||||
{
|
||||
if( mMonitoredLCN != channel )
|
||||
if( mChannelNumber != channel )
|
||||
{
|
||||
mMonitoredLCN = channel;
|
||||
mChannelNumber = channel;
|
||||
broadcast( ChangedAttribute.CHANNEL_NUMBER );
|
||||
}
|
||||
|
||||
@@ -206,15 +206,16 @@ public class LTRStandardDecoderState extends DecoderState
|
||||
if( idleChannel == ltr.getHomeRepeater() &&
|
||||
idleChannel == ltr.getFree() )
|
||||
{
|
||||
if( mMonitoredLCN != idleChannel )
|
||||
if( mChannelNumber != idleChannel )
|
||||
{
|
||||
mMonitoredLCN = idleChannel;
|
||||
mChannelNumber = idleChannel;
|
||||
broadcast( ChangedAttribute.CHANNEL_NUMBER );
|
||||
}
|
||||
|
||||
mActiveLCNs.add( idleChannel );
|
||||
}
|
||||
broadcast( new DecoderStateEvent( this, Event.CONTINUATION, State.IDLE ) );
|
||||
broadcast( new DecoderStateEvent( this,
|
||||
Event.CONTINUATION, State.IDLE ) );
|
||||
break;
|
||||
case UN_KNWN:
|
||||
default:
|
||||
@@ -224,60 +225,49 @@ public class LTRStandardDecoderState extends DecoderState
|
||||
}
|
||||
}
|
||||
|
||||
// /**
|
||||
// * 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 respond to
|
||||
// * the message that can change the state to fade */
|
||||
// if( getState().canChangeTo( State.FADE ) )
|
||||
// {
|
||||
// mActiveCalls.clear();
|
||||
//
|
||||
// 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 );
|
||||
// }
|
||||
|
||||
/**
|
||||
* 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 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs a full reset
|
||||
*/
|
||||
public void reset()
|
||||
{
|
||||
mActiveCalls.clear();
|
||||
mTalkgroupsFirstHeard.clear();
|
||||
mTalkgroups.clear();
|
||||
mActiveLCNs.clear();
|
||||
mChannelNumber = 0;
|
||||
|
||||
resetState();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs a temporal reset following a call or other decode event
|
||||
*/
|
||||
private void resetState()
|
||||
{
|
||||
if( mCurrentCallEvent != null )
|
||||
{
|
||||
mCurrentCallEvent.setEnd( System.currentTimeMillis() );
|
||||
broadcast( mCurrentCallEvent );
|
||||
mCurrentCallEvent = null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void resetState()
|
||||
{
|
||||
|
||||
mTalkgroup = null;
|
||||
broadcast( ChangedAttribute.FROM_TALKGROUP );
|
||||
broadcast( ChangedAttribute.TO_TALKGROUP );
|
||||
|
||||
mTalkgroupAlias = null;
|
||||
broadcast( ChangedAttribute.FROM_TALKGROUP_ALIAS );
|
||||
broadcast( ChangedAttribute.TO_TALKGROUP_ALIAS );
|
||||
}
|
||||
|
||||
public String getTalkgroup()
|
||||
@@ -303,7 +293,6 @@ public class LTRStandardDecoderState extends DecoderState
|
||||
@Override
|
||||
public void init()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -333,9 +322,9 @@ public class LTRStandardDecoderState extends DecoderState
|
||||
|
||||
sb.append( "Monitored LCN: " );
|
||||
|
||||
if( mMonitoredLCN > 0 )
|
||||
if( mChannelNumber > 0 )
|
||||
{
|
||||
sb.append( mMonitoredLCN );
|
||||
sb.append( mChannelNumber );
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -568,7 +568,6 @@ public class ChannelState extends Module implements ICallEventProvider,
|
||||
mSquelchLocked = true;
|
||||
break;
|
||||
case CONTINUATION:
|
||||
case DECODE:
|
||||
if( isEndingState() )
|
||||
{
|
||||
setState( event.getState() );
|
||||
@@ -578,6 +577,12 @@ public class ChannelState extends Module implements ICallEventProvider,
|
||||
updateFadeTimeout();
|
||||
}
|
||||
break;
|
||||
case DECODE:
|
||||
if( getState() == State.IDLE )
|
||||
{
|
||||
setState( event.getState() );
|
||||
}
|
||||
break;
|
||||
case END:
|
||||
setState( State.FADE );
|
||||
break;
|
||||
|
||||
Reference in New Issue
Block a user