mirror of
https://github.com/DSheirer/sdrtrunk.git
synced 2026-11-12 16:47:31 -05:00
Resolves #609 P25 Phase 2 call events are not chaining together and are causing streaming events in the event panel. (#614)
This commit is contained in:
@@ -98,7 +98,9 @@ public class P25TrafficChannelManager extends Module implements IDecodeEventProv
|
||||
private List<Channel> mManagedPhase2TrafficChannels;
|
||||
|
||||
private Map<APCO25Channel,Channel> mAllocatedTrafficChannelMap = new ConcurrentHashMap<>();
|
||||
private Map<APCO25Channel,P25ChannelGrantEvent> mChannelGrantEventMap = new ConcurrentHashMap<>();
|
||||
private Map<APCO25Channel,P25ChannelGrantEvent> mPhase1ChannelGrantEventMap = new ConcurrentHashMap<>();
|
||||
private Map<APCO25Channel,P25ChannelGrantEvent> mPhase2TS0ChannelGrantEventMap = new ConcurrentHashMap<>();
|
||||
private Map<APCO25Channel,P25ChannelGrantEvent> mPhase2TS1ChannelGrantEventMap = new ConcurrentHashMap<>();
|
||||
|
||||
private Listener<ChannelEvent> mChannelEventListener;
|
||||
private Listener<IDecodeEvent> mDecodeEventListener;
|
||||
@@ -271,7 +273,7 @@ public class P25TrafficChannelManager extends Module implements IDecodeEventProv
|
||||
IdentifierCollection identifierCollection, Opcode opcode, long timestamp)
|
||||
{
|
||||
|
||||
P25ChannelGrantEvent event = mChannelGrantEventMap.get(apco25Channel);
|
||||
P25ChannelGrantEvent event = mPhase1ChannelGrantEventMap.get(apco25Channel);
|
||||
|
||||
if(event != null && isSameCall(identifierCollection, event.getIdentifierCollection()))
|
||||
{
|
||||
@@ -287,11 +289,11 @@ public class P25TrafficChannelManager extends Module implements IDecodeEventProv
|
||||
P25ChannelGrantEvent continuationGrantEvent = P25ChannelGrantEvent.builder(timestamp, serviceOptions)
|
||||
.channel(apco25Channel)
|
||||
.eventDescription(getEventType(opcode, serviceOptions).toString() + " - Continue")
|
||||
.details("CHANNEL GRANT " + (serviceOptions != null ? serviceOptions : "UNKNOWN SERVICE OPTIONS"))
|
||||
.details("PHASE 1 CHANNEL GRANT " + (serviceOptions != null ? serviceOptions : ""))
|
||||
.identifiers(identifierCollection)
|
||||
.build();
|
||||
|
||||
mChannelGrantEventMap.put(apco25Channel, continuationGrantEvent);
|
||||
mPhase1ChannelGrantEventMap.put(apco25Channel, continuationGrantEvent);
|
||||
broadcast(continuationGrantEvent);
|
||||
}
|
||||
}
|
||||
@@ -309,7 +311,7 @@ public class P25TrafficChannelManager extends Module implements IDecodeEventProv
|
||||
if(trafficChannel != null)
|
||||
{
|
||||
event.setEventDescription(getEventType(opcode, serviceOptions).toString());
|
||||
event.setDetails("CHANNEL GRANT " + (serviceOptions != null ? serviceOptions : "UNKNOWN SERVICE OPTIONS"));
|
||||
event.setDetails("PHASE 1 CHANNEL GRANT " + (serviceOptions != null ? serviceOptions : ""));
|
||||
event.setChannelDescriptor(apco25Channel);
|
||||
broadcast(event);
|
||||
SourceConfigTuner sourceConfig = new SourceConfigTuner();
|
||||
@@ -328,11 +330,11 @@ public class P25TrafficChannelManager extends Module implements IDecodeEventProv
|
||||
P25ChannelGrantEvent channelGrantEvent = P25ChannelGrantEvent.builder(timestamp, serviceOptions)
|
||||
.channel(apco25Channel)
|
||||
.eventDescription(getEventType(opcode, serviceOptions).toString() + " - Ignored")
|
||||
.details("DATA CALL IGNORED: " + (serviceOptions != null ? serviceOptions : "UNKNOWN SERVICE OPTIONS"))
|
||||
.details("DATA CALL IGNORED: " + (serviceOptions != null ? serviceOptions : ""))
|
||||
.identifiers(identifierCollection)
|
||||
.build();
|
||||
|
||||
mChannelGrantEventMap.put(apco25Channel, channelGrantEvent);
|
||||
mPhase1ChannelGrantEventMap.put(apco25Channel, channelGrantEvent);
|
||||
|
||||
broadcast(channelGrantEvent);
|
||||
return;
|
||||
@@ -341,11 +343,11 @@ public class P25TrafficChannelManager extends Module implements IDecodeEventProv
|
||||
P25ChannelGrantEvent channelGrantEvent = P25ChannelGrantEvent.builder(timestamp, serviceOptions)
|
||||
.channel(apco25Channel)
|
||||
.eventDescription(getEventType(opcode, serviceOptions).toString())
|
||||
.details("CHANNEL GRANT " + (serviceOptions != null ? serviceOptions : "UNKNOWN SERVICE OPTIONS"))
|
||||
.details("PHASE 1 CHANNEL GRANT " + (serviceOptions != null ? serviceOptions : ""))
|
||||
.identifiers(identifierCollection)
|
||||
.build();
|
||||
|
||||
mChannelGrantEventMap.put(apco25Channel, channelGrantEvent);
|
||||
mPhase1ChannelGrantEventMap.put(apco25Channel, channelGrantEvent);
|
||||
|
||||
//Allocate a traffic channel for the downlink frequency if one isn't already allocated
|
||||
//NOTE: we could also allocate a traffic channel for the uplink frequency here, in the future
|
||||
@@ -388,9 +390,25 @@ public class P25TrafficChannelManager extends Module implements IDecodeEventProv
|
||||
((MutableIdentifierCollection)identifierCollection).silentUpdate(ScrambleParameterIdentifier.create(mPhase2ScrambleParameters));
|
||||
}
|
||||
|
||||
P25ChannelGrantEvent event = mChannelGrantEventMap.get(apco25Channel);
|
||||
int timeslot = apco25Channel.getTimeslot();
|
||||
|
||||
identifierCollection.setTimeslot(apco25Channel.getTimeslot());
|
||||
P25ChannelGrantEvent event = null;
|
||||
|
||||
if(timeslot == 0)
|
||||
{
|
||||
event = mPhase2TS0ChannelGrantEventMap.get(apco25Channel);
|
||||
}
|
||||
else if(timeslot == 1)
|
||||
{
|
||||
event = mPhase2TS1ChannelGrantEventMap.get(apco25Channel);
|
||||
}
|
||||
else
|
||||
{
|
||||
mLog.error("Ignoring: Invalid timeslot [" + timeslot + "] detected for P25 Phase 2 Channel Grant.");
|
||||
return;
|
||||
}
|
||||
|
||||
identifierCollection.setTimeslot(timeslot);
|
||||
|
||||
if(event != null && isSameCall(identifierCollection, event.getIdentifierCollection()))
|
||||
{
|
||||
@@ -406,11 +424,19 @@ public class P25TrafficChannelManager extends Module implements IDecodeEventProv
|
||||
P25ChannelGrantEvent continuationGrantEvent = P25ChannelGrantEvent.builder(timestamp, serviceOptions)
|
||||
.channel(apco25Channel)
|
||||
.eventDescription(getEventType(opcode, serviceOptions).toString() + " - Continue")
|
||||
.details("CHANNEL GRANT " + (serviceOptions != null ? serviceOptions : "UNKNOWN SERVICE OPTIONS"))
|
||||
.details("PHASE 2 CHANNEL GRANT " + (serviceOptions != null ? serviceOptions : ""))
|
||||
.identifiers(identifierCollection)
|
||||
.build();
|
||||
|
||||
mChannelGrantEventMap.put(apco25Channel, continuationGrantEvent);
|
||||
if(timeslot == 0)
|
||||
{
|
||||
mPhase2TS0ChannelGrantEventMap.put(apco25Channel, continuationGrantEvent);
|
||||
}
|
||||
else
|
||||
{
|
||||
mPhase2TS1ChannelGrantEventMap.put(apco25Channel, continuationGrantEvent);
|
||||
}
|
||||
|
||||
broadcast(continuationGrantEvent);
|
||||
}
|
||||
}
|
||||
@@ -429,7 +455,7 @@ public class P25TrafficChannelManager extends Module implements IDecodeEventProv
|
||||
if(trafficChannel != null)
|
||||
{
|
||||
event.setEventDescription(getEventType(opcode, serviceOptions).toString());
|
||||
event.setDetails("CHANNEL GRANT " + (serviceOptions != null ? serviceOptions : "UNKNOWN SERVICE OPTIONS"));
|
||||
event.setDetails("PHASE 2 CHANNEL GRANT " + (serviceOptions != null ? serviceOptions : ""));
|
||||
event.setChannelDescriptor(apco25Channel);
|
||||
broadcast(event);
|
||||
SourceConfigTuner sourceConfig = new SourceConfigTuner();
|
||||
@@ -456,11 +482,11 @@ public class P25TrafficChannelManager extends Module implements IDecodeEventProv
|
||||
P25ChannelGrantEvent channelGrantEvent = P25ChannelGrantEvent.builder(timestamp, serviceOptions)
|
||||
.channel(apco25Channel)
|
||||
.eventDescription(getEventType(opcode, serviceOptions).toString() + " - Ignored")
|
||||
.details("DATA CALL IGNORED: " + (serviceOptions != null ? serviceOptions : "UNKNOWN SERVICE OPTIONS"))
|
||||
.details("PHASE 2 DATA CALL IGNORED: " + (serviceOptions != null ? serviceOptions : ""))
|
||||
.identifiers(identifierCollection)
|
||||
.build();
|
||||
|
||||
mChannelGrantEventMap.put(apco25Channel, channelGrantEvent);
|
||||
mPhase1ChannelGrantEventMap.put(apco25Channel, channelGrantEvent);
|
||||
|
||||
broadcast(channelGrantEvent);
|
||||
return;
|
||||
@@ -469,11 +495,18 @@ public class P25TrafficChannelManager extends Module implements IDecodeEventProv
|
||||
P25ChannelGrantEvent channelGrantEvent = P25ChannelGrantEvent.builder(timestamp, serviceOptions)
|
||||
.channel(apco25Channel)
|
||||
.eventDescription(getEventType(opcode, serviceOptions).toString())
|
||||
.details("CHANNEL GRANT " + (serviceOptions != null ? serviceOptions : "UNKNOWN SERVICE OPTIONS"))
|
||||
.details("PHASE 2 CHANNEL GRANT " + (serviceOptions != null ? serviceOptions : ""))
|
||||
.identifiers(identifierCollection)
|
||||
.build();
|
||||
|
||||
mChannelGrantEventMap.put(apco25Channel, channelGrantEvent);
|
||||
if(timeslot == 0)
|
||||
{
|
||||
mPhase2TS0ChannelGrantEventMap.put(apco25Channel, channelGrantEvent);
|
||||
}
|
||||
else
|
||||
{
|
||||
mPhase2TS1ChannelGrantEventMap.put(apco25Channel, channelGrantEvent);
|
||||
}
|
||||
|
||||
//Allocate a traffic channel for the downlink frequency if one isn't already allocated
|
||||
//NOTE: we could also allocate a traffic channel for the uplink frequency here, in the future
|
||||
@@ -735,6 +768,53 @@ public class P25TrafficChannelManager extends Module implements IDecodeEventProv
|
||||
*/
|
||||
public class TrafficChannelTeardownMonitor implements Listener<ChannelEvent>
|
||||
{
|
||||
/**
|
||||
* Removes any call events that are associated with the specified channel.
|
||||
* @param channel that was removed
|
||||
*/
|
||||
private void cleanupCallEvents(Channel channel)
|
||||
{
|
||||
if(channel.getSourceConfiguration() instanceof SourceConfigTuner)
|
||||
{
|
||||
long frequency = ((SourceConfigTuner)channel.getSourceConfiguration()).getFrequency();
|
||||
|
||||
if(channel.getDecodeConfiguration().getDecoderType() == DecoderType.P25_PHASE1)
|
||||
{
|
||||
List<APCO25Channel> channels = new ArrayList<>(mPhase1ChannelGrantEventMap.keySet());
|
||||
|
||||
for(APCO25Channel p25Channel: channels)
|
||||
{
|
||||
if(p25Channel.getDownlinkFrequency() == frequency)
|
||||
{
|
||||
mPhase1ChannelGrantEventMap.remove(p25Channel);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
List<APCO25Channel> channels = new ArrayList<>(mPhase2TS0ChannelGrantEventMap.keySet());
|
||||
|
||||
for(APCO25Channel p25Channel: channels)
|
||||
{
|
||||
if(p25Channel.getDownlinkFrequency() == frequency)
|
||||
{
|
||||
mPhase2TS0ChannelGrantEventMap.remove(p25Channel);
|
||||
}
|
||||
}
|
||||
|
||||
channels = new ArrayList<>(mPhase2TS1ChannelGrantEventMap.keySet());
|
||||
|
||||
for(APCO25Channel p25Channel: channels)
|
||||
{
|
||||
if(p25Channel.getDownlinkFrequency() == frequency)
|
||||
{
|
||||
mPhase2TS1ChannelGrantEventMap.remove(p25Channel);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void receive(ChannelEvent channelEvent)
|
||||
{
|
||||
@@ -773,15 +853,9 @@ public class P25TrafficChannelManager extends Module implements IDecodeEventProv
|
||||
{
|
||||
mAvailablePhase2TrafficChannelQueue.add(channel);
|
||||
}
|
||||
|
||||
P25ChannelGrantEvent event = mChannelGrantEventMap.remove(toRemove);
|
||||
|
||||
if(event != null)
|
||||
{
|
||||
event.end(System.currentTimeMillis());
|
||||
broadcast(event);
|
||||
}
|
||||
}
|
||||
|
||||
cleanupCallEvents(channel);
|
||||
break;
|
||||
case NOTIFICATION_PROCESSING_START_REJECTED:
|
||||
APCO25Channel rejected = null;
|
||||
@@ -808,7 +882,7 @@ public class P25TrafficChannelManager extends Module implements IDecodeEventProv
|
||||
mAvailablePhase2TrafficChannelQueue.add(channel);
|
||||
}
|
||||
|
||||
P25ChannelGrantEvent event = mChannelGrantEventMap.get(rejected);
|
||||
P25ChannelGrantEvent event = mPhase1ChannelGrantEventMap.get(rejected);
|
||||
|
||||
if(event != null)
|
||||
{
|
||||
@@ -826,6 +900,8 @@ public class P25TrafficChannelManager extends Module implements IDecodeEventProv
|
||||
broadcast(event);
|
||||
}
|
||||
}
|
||||
|
||||
cleanupCallEvents(channel);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -184,19 +184,37 @@ public class P25Channel implements IChannelDescriptor
|
||||
*/
|
||||
public String toString()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
if(getDownlinkBandIdentifier() == getUplinkBandIdentifier() && getDownlinkChannelNumber() == getUplinkChannelNumber())
|
||||
{
|
||||
return getDownlinkBandIdentifier() + "-" + (getDownlinkLogicalChannelNumber());
|
||||
sb.append(getDownlinkBandIdentifier()).append("-").append(getDownlinkLogicalChannelNumber());
|
||||
}
|
||||
else if(hasUplinkChannel())
|
||||
{
|
||||
return getDownlinkBandIdentifier() + "-" + (getDownlinkLogicalChannelNumber()) + "/" +
|
||||
getUplinkBandIdentifier() + "-" + (getUplinkLogicalChannelNumber());
|
||||
sb.append(getDownlinkBandIdentifier())
|
||||
.append("-")
|
||||
.append(getDownlinkLogicalChannelNumber())
|
||||
.append("/")
|
||||
.append(getUplinkBandIdentifier())
|
||||
.append("-")
|
||||
.append(getUplinkLogicalChannelNumber());
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.append(getDownlinkBandIdentifier())
|
||||
.append("-")
|
||||
.append(getDownlinkLogicalChannelNumber())
|
||||
.append("/-----");
|
||||
return getDownlinkBandIdentifier() + "-" + (getDownlinkLogicalChannelNumber()) + "/-----";
|
||||
}
|
||||
|
||||
if(isTDMAChannel())
|
||||
{
|
||||
sb.append(" TS").append(getTimeslot());
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -28,8 +28,6 @@ import io.github.dsheirer.channel.state.State;
|
||||
import io.github.dsheirer.channel.state.TimeslotDecoderState;
|
||||
import io.github.dsheirer.controller.channel.Channel;
|
||||
import io.github.dsheirer.controller.channel.Channel.ChannelType;
|
||||
import io.github.dsheirer.controller.channel.ChannelEvent;
|
||||
import io.github.dsheirer.controller.channel.IChannelEventListener;
|
||||
import io.github.dsheirer.identifier.Form;
|
||||
import io.github.dsheirer.identifier.Identifier;
|
||||
import io.github.dsheirer.identifier.IdentifierClass;
|
||||
@@ -87,7 +85,6 @@ import io.github.dsheirer.module.decode.p25.phase2.message.mac.structure.UnitToU
|
||||
import io.github.dsheirer.module.decode.p25.phase2.message.mac.structure.UnitToUnitVoiceChannelUserAbbreviated;
|
||||
import io.github.dsheirer.module.decode.p25.phase2.message.mac.structure.UnitToUnitVoiceChannelUserExtended;
|
||||
import io.github.dsheirer.module.decode.p25.phase2.timeslot.AbstractVoiceTimeslot;
|
||||
import io.github.dsheirer.sample.Listener;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@@ -96,14 +93,13 @@ import org.slf4j.LoggerFactory;
|
||||
* by monitoring the decoded message stream.
|
||||
*
|
||||
*/
|
||||
public class P25P2DecoderState extends TimeslotDecoderState implements IChannelEventListener, IdentifierUpdateListener
|
||||
public class P25P2DecoderState extends TimeslotDecoderState implements IdentifierUpdateListener
|
||||
{
|
||||
private final static Logger mLog = LoggerFactory.getLogger(P25P2DecoderState.class);
|
||||
|
||||
private ChannelType mChannelType;
|
||||
private PatchGroupManager mPatchGroupManager = new PatchGroupManager();
|
||||
private P25P2NetworkConfigurationMonitor mNetworkConfigurationMonitor = new P25P2NetworkConfigurationMonitor();
|
||||
private Listener<ChannelEvent> mChannelEventListener;
|
||||
private DecodeEvent mCurrentCallEvent;
|
||||
|
||||
/**
|
||||
@@ -125,16 +121,6 @@ public class P25P2DecoderState extends TimeslotDecoderState implements IChannelE
|
||||
return DecoderType.P25_PHASE2;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements the IChannelEventListener interface to receive traffic channel teardown notifications so that the
|
||||
* traffic channel manager can manage traffic channel allocations.
|
||||
*/
|
||||
@Override
|
||||
public Listener<ChannelEvent> getChannelEventListener()
|
||||
{
|
||||
return mChannelEventListener;
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs a full reset to prepare this object for reuse on a new channel
|
||||
*/
|
||||
@@ -145,7 +131,7 @@ public class P25P2DecoderState extends TimeslotDecoderState implements IChannelE
|
||||
resetState();
|
||||
}
|
||||
|
||||
/**
|
||||
/**
|
||||
* Resets any temporal state details
|
||||
*/
|
||||
protected void resetState()
|
||||
|
||||
@@ -1,21 +1,23 @@
|
||||
/*
|
||||
* ******************************************************************************
|
||||
* sdrtrunk
|
||||
* Copyright (C) 2014-2019 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
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
* * ******************************************************************************
|
||||
* * Copyright (C) 2014-2019 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
|
||||
* * the Free Software Foundation, either version 3 of the License, or
|
||||
* * (at your option) any later version.
|
||||
* *
|
||||
* * This program is distributed in the hope that it will be useful,
|
||||
* * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* * GNU General Public License for more details.
|
||||
* *
|
||||
* * You should have received a copy of the GNU General Public License
|
||||
* * along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* * *****************************************************************************
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* *****************************************************************************
|
||||
*/
|
||||
package io.github.dsheirer.source.config;
|
||||
|
||||
@@ -89,7 +91,8 @@ public class SourceConfigTuner extends SourceConfiguration
|
||||
@Override
|
||||
public String getDescription()
|
||||
{
|
||||
return FREQUENCY_FORMAT.format((double)mFrequency / 1000000.0d) + " MHz";
|
||||
return FREQUENCY_FORMAT.format((double)mFrequency / 1000000.0d) +
|
||||
(mPreferredTuner != null ? "MHz PREFERRED TUNER:" + mPreferredTuner : "MHz");
|
||||
}
|
||||
|
||||
@JsonIgnore
|
||||
@@ -97,4 +100,10 @@ public class SourceConfigTuner extends SourceConfiguration
|
||||
{
|
||||
return new TunerChannel(mFrequency, bandwidth);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return getDescription();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user