mirror of
https://github.com/DSheirer/sdrtrunk.git
synced 2026-11-12 08:37:25 -05:00
Merge pull request #391 from DSheirer/389-add-active-to-channel-states
389 Add ACTIVE Channel State and Update P25 Decoder State processing
This commit is contained in:
@@ -123,6 +123,11 @@ public class AttributeMonitor<T>
|
||||
{
|
||||
mCurrentValue = null;
|
||||
mOccurrenceCounts.clear();
|
||||
|
||||
if(mListener != null)
|
||||
{
|
||||
mListener.receive(new AttributeChangeRequest(mAttribute, null, null));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -25,32 +25,36 @@ import io.github.dsheirer.controller.channel.ChannelProcessingManager;
|
||||
import io.github.dsheirer.controller.channel.ChannelUtils;
|
||||
import io.github.dsheirer.icon.IconManager;
|
||||
import io.github.dsheirer.module.ProcessingChain;
|
||||
import io.github.dsheirer.properties.SystemProperties;
|
||||
import io.github.dsheirer.sample.Broadcaster;
|
||||
import io.github.dsheirer.sample.Listener;
|
||||
import net.miginfocom.swing.MigLayout;
|
||||
import org.apache.commons.lang3.Validate;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JMenuItem;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JPopupMenu;
|
||||
import javax.swing.JScrollPane;
|
||||
import javax.swing.JTable;
|
||||
import javax.swing.SwingConstants;
|
||||
import javax.swing.event.ListSelectionEvent;
|
||||
import javax.swing.event.ListSelectionListener;
|
||||
import javax.swing.table.DefaultTableCellRenderer;
|
||||
import java.awt.*;
|
||||
import java.awt.Color;
|
||||
import java.awt.Component;
|
||||
import java.awt.event.MouseAdapter;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class ChannelMetadataPanel extends JPanel implements ListSelectionListener
|
||||
{
|
||||
private final static Logger mLog = LoggerFactory.getLogger(ChannelMetadataPanel.class);
|
||||
|
||||
private static final String PROPERTY_PREFIX_BACKGROUND = "channel.metadata.panel.state.color.";
|
||||
private static final String PROPERTY_PREFIX_FOREGROUND = "channel.metadata.panel.text.color.";
|
||||
private ChannelProcessingManager mChannelProcessingManager;
|
||||
private IconManager mIconManager;
|
||||
private JTable mTable;
|
||||
private Broadcaster<ProcessingChain> mSelectedProcessingChainBroadcaster = new Broadcaster<>();
|
||||
private Map<State,Color> mBackgroundColors = new HashMap<>();
|
||||
private Map<State,Color> mForegroundColors = new HashMap<>();
|
||||
|
||||
/**
|
||||
* Table view for currently decoding channel metadata
|
||||
@@ -94,7 +98,34 @@ public class ChannelMetadataPanel extends JPanel implements ListSelectionListene
|
||||
|
||||
add(scrollPane);
|
||||
|
||||
// new TableColumnWidthMonitor(mTable, PROPERTY_PREFIX, new int[] {15,15,15,15,25,25,25,25,15,40});
|
||||
setColors();
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup the background and foreground color palette for the various channel states.
|
||||
*/
|
||||
private void setColors()
|
||||
{
|
||||
mBackgroundColors.put(State.ACTIVE, Color.CYAN);
|
||||
mForegroundColors.put(State.ACTIVE, Color.YELLOW);
|
||||
mBackgroundColors.put(State.CALL, Color.BLUE);
|
||||
mForegroundColors.put(State.CALL, Color.YELLOW);
|
||||
mBackgroundColors.put(State.CONTROL, Color.ORANGE);
|
||||
mForegroundColors.put(State.CONTROL, Color.BLUE);
|
||||
mBackgroundColors.put(State.DATA, Color.GREEN);
|
||||
mForegroundColors.put(State.DATA, Color.BLUE);
|
||||
mBackgroundColors.put(State.ENCRYPTED, Color.MAGENTA);
|
||||
mForegroundColors.put(State.ENCRYPTED, Color.WHITE);
|
||||
mBackgroundColors.put(State.FADE, Color.LIGHT_GRAY);
|
||||
mForegroundColors.put(State.FADE, Color.DARK_GRAY);
|
||||
mBackgroundColors.put(State.IDLE, Color.WHITE);
|
||||
mForegroundColors.put(State.IDLE, Color.DARK_GRAY);
|
||||
mBackgroundColors.put(State.OVERFLOW, Color.RED);
|
||||
mForegroundColors.put(State.OVERFLOW, Color.YELLOW);
|
||||
mBackgroundColors.put(State.RESET, Color.PINK);
|
||||
mForegroundColors.put(State.RESET, Color.YELLOW);
|
||||
mBackgroundColors.put(State.TEARDOWN, Color.DARK_GRAY);
|
||||
mForegroundColors.put(State.TEARDOWN, Color.WHITE);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -185,44 +216,14 @@ public class ChannelMetadataPanel extends JPanel implements ListSelectionListene
|
||||
State state = (State)value;
|
||||
label.setText(state.getDisplayValue());
|
||||
|
||||
switch(state)
|
||||
if(mBackgroundColors.containsKey(state))
|
||||
{
|
||||
case CALL:
|
||||
background = SystemProperties.getInstance().get(PROPERTY_PREFIX_BACKGROUND + "call", Color.BLUE);
|
||||
foreground = SystemProperties.getInstance().get(PROPERTY_PREFIX_FOREGROUND + "call", Color.YELLOW);
|
||||
break;
|
||||
case CONTROL:
|
||||
background = SystemProperties.getInstance().get(PROPERTY_PREFIX_BACKGROUND + "control", Color.ORANGE);
|
||||
foreground = SystemProperties.getInstance().get(PROPERTY_PREFIX_FOREGROUND + "control", Color.BLUE);
|
||||
break;
|
||||
case DATA:
|
||||
background = SystemProperties.getInstance().get(PROPERTY_PREFIX_BACKGROUND + "data", Color.GREEN);
|
||||
foreground = SystemProperties.getInstance().get(PROPERTY_PREFIX_FOREGROUND + "data", Color.BLUE);
|
||||
break;
|
||||
case ENCRYPTED:
|
||||
background = SystemProperties.getInstance().get(PROPERTY_PREFIX_BACKGROUND + "encrypted", Color.MAGENTA);
|
||||
foreground = SystemProperties.getInstance().get(PROPERTY_PREFIX_FOREGROUND + "encrypted", Color.WHITE);
|
||||
break;
|
||||
case FADE:
|
||||
background = SystemProperties.getInstance().get(PROPERTY_PREFIX_BACKGROUND + "fade", Color.LIGHT_GRAY.BLUE);
|
||||
foreground = SystemProperties.getInstance().get(PROPERTY_PREFIX_FOREGROUND + "fade", Color.YELLOW);
|
||||
break;
|
||||
case IDLE:
|
||||
background = SystemProperties.getInstance().get(PROPERTY_PREFIX_BACKGROUND + "idle", Color.WHITE);
|
||||
foreground = SystemProperties.getInstance().get(PROPERTY_PREFIX_FOREGROUND + "idle", Color.BLUE);
|
||||
break;
|
||||
case OVERFLOW:
|
||||
background = SystemProperties.getInstance().get(PROPERTY_PREFIX_BACKGROUND + "overflow", Color.RED);
|
||||
foreground = SystemProperties.getInstance().get(PROPERTY_PREFIX_FOREGROUND + "overflow", Color.YELLOW);
|
||||
break;
|
||||
case RESET:
|
||||
background = SystemProperties.getInstance().get(PROPERTY_PREFIX_BACKGROUND + "reset", Color.PINK);
|
||||
foreground = SystemProperties.getInstance().get(PROPERTY_PREFIX_FOREGROUND + "reset", Color.YELLOW);
|
||||
break;
|
||||
case TEARDOWN:
|
||||
background = SystemProperties.getInstance().get(PROPERTY_PREFIX_BACKGROUND + "teardown", Color.DARK_GRAY);
|
||||
foreground = SystemProperties.getInstance().get(PROPERTY_PREFIX_FOREGROUND + "teardown", Color.WHITE);
|
||||
break;
|
||||
background = mBackgroundColors.get(state);
|
||||
}
|
||||
|
||||
if(mForegroundColors.containsKey(state))
|
||||
{
|
||||
foreground = mForegroundColors.get(state);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
@@ -303,6 +303,11 @@ public class ChannelState extends Module implements ICallEventProvider, IDecoder
|
||||
{
|
||||
switch(state)
|
||||
{
|
||||
case ACTIVE:
|
||||
broadcast(SquelchState.SQUELCH);
|
||||
updateFadeTimeout();
|
||||
mState = state;
|
||||
break;
|
||||
case CONTROL:
|
||||
//Don't allow traffic channels to be control channels, otherwise they can't transition to teardown
|
||||
if(isStandardChannel())
|
||||
|
||||
@@ -24,54 +24,114 @@ import java.util.EnumSet;
|
||||
*/
|
||||
public enum State
|
||||
{
|
||||
IDLE("IDLE")
|
||||
/**
|
||||
* Active state indicates that valid messages are being decoded that do not indicate any call or data
|
||||
* activity. For example, this is used for P25 when a channel is actively transmitting Terminator Data
|
||||
* Units in between data packets or at the beginning or end of a call.
|
||||
*/
|
||||
ACTIVE("ACTIVE")
|
||||
{
|
||||
@Override
|
||||
public boolean canChangeTo(State state)
|
||||
{
|
||||
return state != TEARDOWN && state != RESET && state != OVERFLOW;
|
||||
return state == CALL |
|
||||
state == CONTROL ||
|
||||
state == DATA ||
|
||||
state == ENCRYPTED ||
|
||||
state == FADE ||
|
||||
state == TEARDOWN;
|
||||
}
|
||||
},
|
||||
/**
|
||||
* Indicates that call messages are being decoded, or a call is in progress (ie producing audio).
|
||||
*/
|
||||
CALL("CALL")
|
||||
{
|
||||
@Override
|
||||
public boolean canChangeTo(State state)
|
||||
{
|
||||
return state == CONTROL || state == DATA || state == ENCRYPTED || state == FADE || state == TEARDOWN;
|
||||
}
|
||||
},
|
||||
DATA("DATA")
|
||||
{
|
||||
@Override
|
||||
public boolean canChangeTo(State state)
|
||||
{
|
||||
return state == CALL || state == CONTROL || state == ENCRYPTED || state == FADE || state == TEARDOWN;
|
||||
}
|
||||
},
|
||||
ENCRYPTED("ENCRYPTED")
|
||||
{
|
||||
@Override
|
||||
public boolean canChangeTo(State state)
|
||||
{
|
||||
return state == FADE || state == TEARDOWN;
|
||||
return state == ACTIVE ||
|
||||
state == CONTROL ||
|
||||
state == DATA ||
|
||||
state == ENCRYPTED ||
|
||||
state == FADE ||
|
||||
state == TEARDOWN;
|
||||
}
|
||||
},
|
||||
/**
|
||||
* Indicates a trunking control channel is being decoded.
|
||||
*/
|
||||
CONTROL("CONTROL")
|
||||
{
|
||||
@Override
|
||||
public boolean canChangeTo(State state)
|
||||
{
|
||||
return state == IDLE || state == FADE;
|
||||
return state == IDLE ||
|
||||
state == FADE;
|
||||
}
|
||||
},
|
||||
/**
|
||||
* Indicates data packets are being decoded
|
||||
*/
|
||||
DATA("DATA")
|
||||
{
|
||||
@Override
|
||||
public boolean canChangeTo(State state)
|
||||
{
|
||||
return state == ACTIVE ||
|
||||
state == CALL ||
|
||||
state == CONTROL ||
|
||||
state == ENCRYPTED ||
|
||||
state == FADE ||
|
||||
state == TEARDOWN;
|
||||
}
|
||||
},
|
||||
/**
|
||||
* Indicates encrypted audio is detected.
|
||||
*/
|
||||
ENCRYPTED("ENCRYPTED")
|
||||
{
|
||||
@Override
|
||||
public boolean canChangeTo(State state)
|
||||
{
|
||||
return state == FADE ||
|
||||
state == TEARDOWN;
|
||||
}
|
||||
},
|
||||
/**
|
||||
* Fade state occurs when the channel is no longer actively decoding an messages. This is a transitory
|
||||
* state before transition to IDLE or back to an active state.
|
||||
*/
|
||||
FADE("FADE")
|
||||
{
|
||||
@Override
|
||||
public boolean canChangeTo(State state)
|
||||
{
|
||||
return state != FADE && state != RESET && state != OVERFLOW;
|
||||
return state != FADE &&
|
||||
state != RESET &&
|
||||
state != OVERFLOW;
|
||||
}
|
||||
},
|
||||
/**
|
||||
* Indicates the channel is idle and not actively decoding any messages
|
||||
*/
|
||||
IDLE("IDLE")
|
||||
{
|
||||
@Override
|
||||
public boolean canChangeTo(State state)
|
||||
{
|
||||
return state != TEARDOWN &&
|
||||
state != RESET &&
|
||||
state != OVERFLOW;
|
||||
}
|
||||
},
|
||||
/**
|
||||
* Indicates that the channel's sample buffer has overflowed and new buffer samples are no longer being
|
||||
* delivered to the channel. This state persists until the processing catches up and reduces the number
|
||||
* of samples in the input buffer below a threshold value. Transition to and from this state is exclusively
|
||||
* managed by the Channel State and no other channel states can be processed from the channel decoders
|
||||
* until the channel state is taken out of overflow.
|
||||
*/
|
||||
OVERFLOW("OVERFLOW")
|
||||
{
|
||||
@Override
|
||||
@@ -80,6 +140,9 @@ public enum State
|
||||
return false;
|
||||
}
|
||||
},
|
||||
/**
|
||||
* Indicates that the channel has been reset and is ready to use for a new decoding session.
|
||||
*/
|
||||
RESET("RESET")
|
||||
{
|
||||
@Override
|
||||
@@ -88,6 +151,10 @@ public enum State
|
||||
return state == IDLE;
|
||||
}
|
||||
},
|
||||
/**
|
||||
* Call or data teardown. This state is used by traffic channels to indicate that a call or data session
|
||||
* has concluded and the channel is ready for tear down and reuse.
|
||||
*/
|
||||
TEARDOWN("TEARDOWN")
|
||||
{
|
||||
@Override
|
||||
@@ -99,7 +166,7 @@ public enum State
|
||||
|
||||
private String mDisplayValue;
|
||||
|
||||
public static final EnumSet<State> CALL_STATES = EnumSet.of(CALL, CONTROL, DATA, ENCRYPTED);
|
||||
public static final EnumSet<State> CALL_STATES = EnumSet.of(ACTIVE, CALL, CONTROL, DATA, ENCRYPTED);
|
||||
public static final EnumSet<State> IDLE_STATES = EnumSet.of(IDLE, FADE);
|
||||
|
||||
private State(String displayValue)
|
||||
|
||||
@@ -254,6 +254,7 @@ public class P25DecoderState extends DecoderState
|
||||
if(mCurrentCallEvent != null)
|
||||
{
|
||||
mCurrentCallEvent.end();
|
||||
broadcast(mCurrentCallEvent);
|
||||
}
|
||||
|
||||
mCurrentCallEvent = null;
|
||||
@@ -395,6 +396,10 @@ public class P25DecoderState extends DecoderState
|
||||
*/
|
||||
private void processTDU(TDUMessage tdu)
|
||||
{
|
||||
if(mChannelType == ChannelType.STANDARD)
|
||||
{
|
||||
broadcast(new DecoderStateEvent(this, Event.DECODE, State.ACTIVE));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -432,19 +437,21 @@ public class P25DecoderState extends DecoderState
|
||||
*/
|
||||
private void processTDULC(TDULinkControlMessage tdulc)
|
||||
{
|
||||
if(mCurrentCallEvent != null)
|
||||
{
|
||||
mCurrentCallEvent.end();
|
||||
broadcast(mCurrentCallEvent);
|
||||
mCurrentCallEvent = null;
|
||||
}
|
||||
|
||||
if(tdulc.getOpcode() == LinkControlOpcode.CALL_TERMINATION_OR_CANCELLATION)
|
||||
{
|
||||
broadcast(new DecoderStateEvent(this, Event.END, State.FADE));
|
||||
|
||||
if(mCurrentCallEvent != null)
|
||||
{
|
||||
mCurrentCallEvent.end();
|
||||
mCurrentCallEvent = null;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
broadcast(new DecoderStateEvent(this, Event.CONTINUATION, State.CALL));
|
||||
broadcast(new DecoderStateEvent(this, Event.DECODE, State.ACTIVE));
|
||||
}
|
||||
|
||||
switch(tdulc.getOpcode())
|
||||
@@ -495,22 +502,17 @@ public class P25DecoderState extends DecoderState
|
||||
/* This opcode as handled at the beginning of the method */
|
||||
break;
|
||||
case CHANNEL_IDENTIFIER_UPDATE:
|
||||
//TODO: does the activity summary need this message?
|
||||
|
||||
/* This message is handled by the P25MessageProcessor and
|
||||
* inserted into any channels needing frequency band info */
|
||||
break;
|
||||
case CHANNEL_IDENTIFIER_UPDATE_EXPLICIT:
|
||||
//TODO: does the activity summary need this message?
|
||||
|
||||
/* This message is handled by the P25MessageProcessor and
|
||||
* inserted into any channels needing frequency band info */
|
||||
break;
|
||||
case EXTENDED_FUNCTION_COMMAND:
|
||||
if(tdulc instanceof ExtendedFunctionCommand)
|
||||
{
|
||||
ExtendedFunctionCommand efc =
|
||||
(ExtendedFunctionCommand)tdulc;
|
||||
ExtendedFunctionCommand efc = (ExtendedFunctionCommand)tdulc;
|
||||
|
||||
broadcast(new P25CallEvent.Builder(CallEvent.CallEventType.COMMAND)
|
||||
.aliasList(getAliasList())
|
||||
@@ -606,42 +608,25 @@ public class P25DecoderState extends DecoderState
|
||||
}
|
||||
break;
|
||||
case GROUP_VOICE_CHANNEL_USER:
|
||||
/* Used on a traffic channel to reflect current call entities */
|
||||
//Used on a traffic channel to reflect that the channel is currently being used by the
|
||||
//TO talkgroup, but that channel is currently quiet (ie no voice) */
|
||||
if(tdulc instanceof GroupVoiceChannelUser)
|
||||
{
|
||||
GroupVoiceChannelUser gvcuser =
|
||||
(GroupVoiceChannelUser)tdulc;
|
||||
GroupVoiceChannelUser gvcuser = (GroupVoiceChannelUser)tdulc;
|
||||
|
||||
broadcast(new DecoderStateEvent(this, Event.CONTINUATION, State.CALL));
|
||||
broadcast(new DecoderStateEvent(this, Event.CONTINUATION, State.ACTIVE));
|
||||
|
||||
//The from value should always be "000000" indicating that nobody is currently talking
|
||||
mFromTalkgroupMonitor.reset();
|
||||
|
||||
String from = gvcuser.getSourceAddress();
|
||||
String to = gvcuser.getGroupAddress();
|
||||
|
||||
mFromTalkgroupMonitor.process(from);
|
||||
mToTalkgroupMonitor.process(to);
|
||||
|
||||
if(mCurrentCallEvent == null)
|
||||
{
|
||||
mCurrentCallEvent = new P25CallEvent.Builder(CallEvent.CallEventType.GROUP_CALL)
|
||||
.aliasList(getAliasList())
|
||||
.channel(mCurrentChannel)
|
||||
.details("TDULC GROUP VOICE CHANNEL USER" +
|
||||
(gvcuser.isEncrypted() ? "ENCRYPTED " : "") +
|
||||
(gvcuser.isEmergency() ? "EMERGENCY " : ""))
|
||||
.frequency(mCurrentChannelFrequency)
|
||||
.from(from)
|
||||
.to(to)
|
||||
.build();
|
||||
|
||||
broadcast(mCurrentCallEvent);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case MESSAGE_UPDATE:
|
||||
if(tdulc instanceof MessageUpdate)
|
||||
{
|
||||
MessageUpdate mu =
|
||||
(MessageUpdate)tdulc;
|
||||
MessageUpdate mu = (MessageUpdate)tdulc;
|
||||
|
||||
broadcast(new P25CallEvent.Builder(CallEvent.CallEventType.SDM)
|
||||
.aliasList(getAliasList())
|
||||
@@ -748,8 +733,7 @@ public class P25DecoderState extends DecoderState
|
||||
io.github.dsheirer.module.decode.p25.message.tdu.lc.SecondaryControlChannelBroadcast sccb =
|
||||
(io.github.dsheirer.module.decode.p25.message.tdu.lc.SecondaryControlChannelBroadcast)tdulc;
|
||||
|
||||
String site = sccb.getRFSubsystemID() + "-" +
|
||||
sccb.getSiteID();
|
||||
String site = sccb.getRFSubsystemID() + "-" + sccb.getSiteID();
|
||||
|
||||
mSiteAttributeMonitor.process(site);
|
||||
}
|
||||
@@ -761,11 +745,9 @@ public class P25DecoderState extends DecoderState
|
||||
case SECONDARY_CONTROL_CHANNEL_BROADCAST_EXPLICIT:
|
||||
if(tdulc instanceof SecondaryControlChannelBroadcastExplicit)
|
||||
{
|
||||
SecondaryControlChannelBroadcastExplicit sccb =
|
||||
(SecondaryControlChannelBroadcastExplicit)tdulc;
|
||||
SecondaryControlChannelBroadcastExplicit sccb = (SecondaryControlChannelBroadcastExplicit)tdulc;
|
||||
|
||||
String site = sccb.getRFSubsystemID() + "-" +
|
||||
sccb.getSiteID();
|
||||
String site = sccb.getRFSubsystemID() + "-" + sccb.getSiteID();
|
||||
|
||||
mSiteAttributeMonitor.process(site);
|
||||
}
|
||||
@@ -777,8 +759,7 @@ public class P25DecoderState extends DecoderState
|
||||
case STATUS_QUERY:
|
||||
if(tdulc instanceof StatusQuery)
|
||||
{
|
||||
StatusQuery sq =
|
||||
(StatusQuery)tdulc;
|
||||
StatusQuery sq = (StatusQuery)tdulc;
|
||||
|
||||
broadcast(new P25CallEvent.Builder(CallEvent.CallEventType.QUERY)
|
||||
.aliasList(getAliasList())
|
||||
@@ -816,8 +797,7 @@ public class P25DecoderState extends DecoderState
|
||||
case TELEPHONE_INTERCONNECT_ANSWER_REQUEST:
|
||||
if(tdulc instanceof TelephoneInterconnectAnswerRequest)
|
||||
{
|
||||
TelephoneInterconnectAnswerRequest tiar =
|
||||
(TelephoneInterconnectAnswerRequest)tdulc;
|
||||
TelephoneInterconnectAnswerRequest tiar = (TelephoneInterconnectAnswerRequest)tdulc;
|
||||
|
||||
broadcast(new P25CallEvent.Builder(CallEvent.CallEventType.PAGE)
|
||||
.aliasList(getAliasList())
|
||||
@@ -835,8 +815,7 @@ public class P25DecoderState extends DecoderState
|
||||
if(mChannelType == ChannelType.STANDARD &&
|
||||
tdulc instanceof TelephoneInterconnectVoiceChannelUser)
|
||||
{
|
||||
TelephoneInterconnectVoiceChannelUser tivcu =
|
||||
(TelephoneInterconnectVoiceChannelUser)tdulc;
|
||||
TelephoneInterconnectVoiceChannelUser tivcu = (TelephoneInterconnectVoiceChannelUser)tdulc;
|
||||
|
||||
String to = tivcu.getAddress();
|
||||
|
||||
@@ -860,8 +839,7 @@ public class P25DecoderState extends DecoderState
|
||||
case UNIT_AUTHENTICATION_COMMAND:
|
||||
if(tdulc instanceof UnitAuthenticationCommand)
|
||||
{
|
||||
UnitAuthenticationCommand uac =
|
||||
(UnitAuthenticationCommand)tdulc;
|
||||
UnitAuthenticationCommand uac = (UnitAuthenticationCommand)tdulc;
|
||||
|
||||
broadcast(new P25CallEvent.Builder(CallEvent.CallEventType.COMMAND)
|
||||
.aliasList(getAliasList())
|
||||
@@ -877,8 +855,7 @@ public class P25DecoderState extends DecoderState
|
||||
case UNIT_REGISTRATION_COMMAND:
|
||||
if(tdulc instanceof UnitRegistrationCommand)
|
||||
{
|
||||
UnitRegistrationCommand urc =
|
||||
(UnitRegistrationCommand)tdulc;
|
||||
UnitRegistrationCommand urc = (UnitRegistrationCommand)tdulc;
|
||||
|
||||
broadcast(new P25CallEvent.Builder(CallEvent.CallEventType.COMMAND)
|
||||
.aliasList(getAliasList())
|
||||
@@ -894,8 +871,7 @@ public class P25DecoderState extends DecoderState
|
||||
case UNIT_TO_UNIT_ANSWER_REQUEST:
|
||||
if(tdulc instanceof UnitToUnitAnswerRequest)
|
||||
{
|
||||
UnitToUnitAnswerRequest uuar =
|
||||
(UnitToUnitAnswerRequest)tdulc;
|
||||
UnitToUnitAnswerRequest uuar = (UnitToUnitAnswerRequest)tdulc;
|
||||
|
||||
broadcast(new P25CallEvent.Builder(CallEvent.CallEventType.PAGE)
|
||||
.aliasList(getAliasList())
|
||||
@@ -913,27 +889,12 @@ public class P25DecoderState extends DecoderState
|
||||
/* Used on traffic channels to indicate the current call entities */
|
||||
if(tdulc instanceof UnitToUnitVoiceChannelUser)
|
||||
{
|
||||
UnitToUnitVoiceChannelUser uuvcu =
|
||||
(UnitToUnitVoiceChannelUser)tdulc;
|
||||
UnitToUnitVoiceChannelUser uuvcu = (UnitToUnitVoiceChannelUser)tdulc;
|
||||
|
||||
String from = uuvcu.getSourceAddress();
|
||||
mFromTalkgroupMonitor.process(from);
|
||||
mFromTalkgroupMonitor.reset();
|
||||
|
||||
String to = uuvcu.getTargetAddress();
|
||||
mToTalkgroupMonitor.process(to);
|
||||
|
||||
if(mCurrentCallEvent != null)
|
||||
{
|
||||
mCurrentCallEvent = new P25CallEvent.Builder(CallEvent.CallEventType.UNIT_TO_UNIT_CALL)
|
||||
.aliasList(getAliasList())
|
||||
.channel(mCurrentChannel)
|
||||
.details((uuvcu.isEncrypted() ? "ENCRYPTED " : "") +
|
||||
(uuvcu.isEmergency() ? "EMERGENCY " : ""))
|
||||
.frequency(mCurrentChannelFrequency)
|
||||
.from(from)
|
||||
.to(to)
|
||||
.build();
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
@@ -1166,9 +1127,17 @@ public class P25DecoderState extends DecoderState
|
||||
(io.github.dsheirer.module.decode.p25.message.ldu.lc.GroupVoiceChannelUser)ldu;
|
||||
|
||||
mFromTalkgroupMonitor.process(gvcuser.getSourceAddress());
|
||||
mCurrentCallEvent.setFromID(mFromTalkgroupMonitor.getValue());
|
||||
|
||||
mToTalkgroupMonitor.process(gvcuser.getGroupAddress());
|
||||
|
||||
String to = mToTalkgroupMonitor.getValue();
|
||||
|
||||
if(mCurrentCallEvent.getToID() == null || !mCurrentCallEvent.getToID().contentEquals(to))
|
||||
{
|
||||
mCurrentCallEvent.setToID(to);
|
||||
}
|
||||
|
||||
if(mChannelType == ChannelType.STANDARD)
|
||||
{
|
||||
if(mCurrentCallEvent.getCallEventType() != CallEvent.CallEventType.GROUP_CALL)
|
||||
@@ -1631,14 +1600,13 @@ public class P25DecoderState extends DecoderState
|
||||
*/
|
||||
private void processPDU(PDUMessage pdu)
|
||||
{
|
||||
broadcast(new DecoderStateEvent(this, Event.CONTINUATION, State.DATA));
|
||||
|
||||
if(pdu instanceof PacketData || pdu instanceof PDUTypeUnknown)
|
||||
{
|
||||
broadcast(new DecoderStateEvent(this, Event.CONTINUATION, State.DATA));
|
||||
}
|
||||
else if(pdu instanceof PDUConfirmedMessage)
|
||||
{
|
||||
broadcast(new DecoderStateEvent(this, Event.CONTINUATION, State.DATA));
|
||||
|
||||
PDUConfirmedMessage pduc = (PDUConfirmedMessage)pdu;
|
||||
|
||||
switch(pduc.getPDUType())
|
||||
@@ -1723,6 +1691,11 @@ public class P25DecoderState extends DecoderState
|
||||
sbTo.append(sud.getUDPDestinationPort());
|
||||
}
|
||||
|
||||
mFromTalkgroupMonitor.reset();
|
||||
mFromTalkgroupMonitor.process(sbFrom.toString());
|
||||
mToTalkgroupMonitor.reset();
|
||||
mToTalkgroupMonitor.process(pduc.getLogicalLinkID());
|
||||
|
||||
broadcast(new DecoderStateEvent(this, Event.START, State.DATA));
|
||||
|
||||
broadcast(new P25CallEvent.Builder(CallEvent.CallEventType.DATA_CALL)
|
||||
@@ -1750,9 +1723,6 @@ public class P25DecoderState extends DecoderState
|
||||
}
|
||||
else
|
||||
{
|
||||
/* These are alternate trunking control blocks in PDU format */
|
||||
broadcast(new DecoderStateEvent(this, Event.CONTINUATION, State.CONTROL));
|
||||
|
||||
switch(pdu.getOpcode())
|
||||
{
|
||||
case GROUP_DATA_CHANNEL_GRANT:
|
||||
|
||||
Reference in New Issue
Block a user