P25 Decoder Updates.

-Improved handling of channel grants and call event logging
-Prevent traffic channels from changing to control channel state
-Change text on PDU Alternate Multi-Block to reflect trunking message
type
-Added interface for Adjacent Site messages and improved logging
This commit is contained in:
denny
2015-12-20 11:12:08 -05:00
parent c89a68d9fc
commit 6ab4d55f47
16 changed files with 721 additions and 304 deletions

View File

@@ -271,7 +271,8 @@ public class DecoderFactory
if( channelType == ChannelType.STANDARD )
{
long timeout = p25Config.getCallTimeout() * 1000; //convert to milliseconds
//Set call timeout to 3 seconds for P25 traffic channels
long timeout = 3000;
modules.add( new TrafficChannelManager( resourceManager,
decodeConfig, recordConfig, system, site,

View File

@@ -18,6 +18,7 @@
package module.decode.p25;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlTransient;
import module.decode.DecoderType;
import module.decode.config.DecodeConfiguration;
@@ -27,7 +28,7 @@ public class DecodeConfigP25Phase1 extends DecodeConfiguration
{
private P25_LSMDecoder.Modulation mModulation = Modulation.C4FM;
private int mCallTimeout = DEFAULT_CALL_TIMEOUT_SECONDS;
private int mCallTimeout = 1;
private int mTrafficChannelPoolSize = TRAFFIC_CHANNEL_LIMIT_DEFAULT;
public DecodeConfigP25Phase1()
@@ -52,8 +53,13 @@ public class DecodeConfigP25Phase1 extends DecodeConfiguration
{
mModulation = modulation;
}
@XmlAttribute( name="call_timeout" )
/**
* Note: this field is now deprecated.
* @return
*/
@XmlTransient
@Deprecated
public int getCallTimeout()
{
return mCallTimeout;
@@ -63,16 +69,9 @@ public class DecodeConfigP25Phase1 extends DecodeConfiguration
* Sets the call timeout value in seconds ( 10 - 600 );
* @param timeout
*/
@Deprecated
public void setCallTimeout( int timeout )
{
if( CALL_TIMEOUT_MINIMUM <= timeout && timeout <= CALL_TIMEOUT_MAXIMUM )
{
mCallTimeout = timeout;
}
else
{
mCallTimeout = DEFAULT_CALL_TIMEOUT_SECONDS;
}
}

View File

@@ -75,6 +75,22 @@ public class P25CallEvent extends CallEvent
{
return mFrequency;
}
public String toString()
{
StringBuilder sb = new StringBuilder();
sb.append( "P25 " );
sb.append( getCallEventType().name() );
sb.append( " CHAN[" );
sb.append( getChannel() );
sb.append( "] TO[" );
sb.append( getToID() );
sb.append( "] FROM[" );
sb.append( getFromID() );
return sb.toString();
}
public static class Builder
{

View File

@@ -31,6 +31,7 @@ import module.decode.DecoderType;
import module.decode.event.CallEvent;
import module.decode.event.CallEvent.CallEventType;
import module.decode.p25.P25Decoder.Modulation;
import module.decode.p25.message.IAdjacentSite;
import module.decode.p25.message.IBandIdentifier;
import module.decode.p25.message.P25Message;
import module.decode.p25.message.hdu.HDUMessage;
@@ -67,6 +68,7 @@ import module.decode.p25.message.pdu.osp.voice.UnitToUnitVoiceChannelGrantExtend
import module.decode.p25.message.pdu.osp.voice.UnitToUnitVoiceChannelGrantUpdateExtended;
import module.decode.p25.message.tdu.TDUMessage;
import module.decode.p25.message.tdu.lc.AdjacentSiteStatusBroadcast;
import module.decode.p25.message.tdu.lc.AdjacentSiteStatusBroadcastExplicit;
import module.decode.p25.message.tdu.lc.GroupVoiceChannelUpdate;
import module.decode.p25.message.tdu.lc.GroupVoiceChannelUpdateExplicit;
import module.decode.p25.message.tdu.lc.NetworkStatusBroadcast;
@@ -146,16 +148,14 @@ public class P25DecoderState extends DecoderState
private RFSSStatusBroadcast mRFSSStatusMessage;
private RFSSStatusBroadcastExtended mRFSSStatusMessageExtended;
private SNDCPDataChannelAnnouncementExplicit mSNDCPDataChannel;
private HashMap<String,AdjacentStatusBroadcast> mNeighborMap =
new HashMap<String,AdjacentStatusBroadcast>();
private Set<module.decode.p25.message.tsbk.osp.control.SecondaryControlChannelBroadcast> mSecondaryControlChannels =
new TreeSet<>();
private HashMap<Integer,IdentifierUpdate> mBands =
new HashMap<Integer,IdentifierUpdate>();
private Map<Integer,IdentifierUpdate> mBands = new HashMap<>();
private Map<String,Long> mRegistrations = new HashMap<>();
private Map<String,IAdjacentSite> mNeighborMap = new HashMap<>();
private HashMap<String,Long> mRegistrations = new HashMap<String,Long>();
private String mLastCommandEventID;
private String mLastPageEventID;
private String mLastQueryEventID;
@@ -291,7 +291,7 @@ public class P25DecoderState extends DecoderState
hasEvent = true;
}
}
else if( event.getFromID() == null )
else
{
hasEvent = true;
}
@@ -390,15 +390,10 @@ public class P25DecoderState extends DecoderState
}
/**
* Terminator Data Unit, or default message if the CRC failed for a longer
* message. We process these as continuation events.
* Terminator Data Unit
*/
private void processTDU( TDUMessage tdu )
{
// if( mCurrentCallEvent == null )
// {
// broadcast( new DecoderStateEvent( this, Event.CONTINUATION, State.CONTROL ) );
// }
}
/**
@@ -457,10 +452,11 @@ public class P25DecoderState extends DecoderState
case ADJACENT_SITE_STATUS_BROADCAST:
if( tdulc instanceof AdjacentSiteStatusBroadcast )
{
AdjacentSiteStatusBroadcast assb =
(AdjacentSiteStatusBroadcast)tdulc;
IAdjacentSite ias = (IAdjacentSite)tdulc;
updateSystem( assb.getSystemID() );
mNeighborMap.put( ias.getUniqueID(), ias );
updateSystem( ias.getSystemID() );
}
else
{
@@ -468,7 +464,14 @@ public class P25DecoderState extends DecoderState
}
break;
case ADJACENT_SITE_STATUS_BROADCAST_EXPLICIT:
/* This message doesn't provide anything we need for channel state */
if( tdulc instanceof AdjacentSiteStatusBroadcastExplicit )
{
IAdjacentSite ias = (IAdjacentSite)tdulc;
mNeighborMap.put( ias.getUniqueID(), ias );
updateSystem( ias.getSystemID() );
}
break;
case CALL_ALERT:
if( tdulc instanceof module.decode.p25.message.tdu.lc.CallAlert )
@@ -620,7 +623,8 @@ public class P25DecoderState extends DecoderState
mCurrentCallEvent = new P25CallEvent.Builder( CallEventType.GROUP_CALL )
.aliasList( getAliasList() )
.channel( mCurrentChannel )
.details( ( gvcuser.isEncrypted() ? "ENCRYPTED " : "" ) +
.details( "TDULC GROUP VOICE CHANNEL USER" +
( gvcuser.isEncrypted() ? "ENCRYPTED " : "" ) +
( gvcuser.isEmergency() ? "EMERGENCY " : "") )
.frequency( mCurrentChannelFrequency )
.from( from )
@@ -1006,10 +1010,11 @@ public class P25DecoderState extends DecoderState
case ADJACENT_SITE_STATUS_BROADCAST:
if( ldu instanceof module.decode.p25.message.ldu.lc.AdjacentSiteStatusBroadcast )
{
module.decode.p25.message.ldu.lc.AdjacentSiteStatusBroadcast assb =
(module.decode.p25.message.ldu.lc.AdjacentSiteStatusBroadcast)ldu;
IAdjacentSite ias = (IAdjacentSite)ldu;
updateSystem( assb.getSystemID() );
mNeighborMap.put( ias.getUniqueID(), ias );
updateSystem( ias.getSystemID() );
}
else
{
@@ -1018,7 +1023,18 @@ public class P25DecoderState extends DecoderState
break;
case ADJACENT_SITE_STATUS_BROADCAST_EXPLICIT:
/* This message doesn't provide anything we need for channel state */
if( ldu instanceof module.decode.p25.message.ldu.lc.AdjacentSiteStatusBroadcastExplicit )
{
IAdjacentSite ias = (IAdjacentSite)ldu;
mNeighborMap.put( ias.getUniqueID(), ias );
updateSystem( ias.getSystemID() );
}
else
{
logAlternateVendorMessage( ldu );
}
break;
case CALL_ALERT:
if( ldu instanceof module.decode.p25.message.ldu.lc.CallAlert )
@@ -1509,10 +1525,14 @@ public class P25DecoderState extends DecoderState
switch( tsbk.getOpcode() )
{
case ADJACENT_STATUS_BROADCAST:
AdjacentStatusBroadcast neighborMessage =
(AdjacentStatusBroadcast)tsbk;
mNeighborMap.put( neighborMessage.getUniqueID(), neighborMessage );
if( tsbk instanceof AdjacentStatusBroadcast )
{
IAdjacentSite ias = (IAdjacentSite)tsbk;
mNeighborMap.put( ias.getUniqueID(), ias );
updateSystem( ias.getSystemID() );
}
break;
case ACKNOWLEDGE_RESPONSE:
processTSBKResponse( tsbk );
@@ -1627,24 +1647,10 @@ public class P25DecoderState extends DecoderState
*/
private void processPDU( PDUMessage pdu )
{
broadcast( new DecoderStateEvent( this, Event.CONTINUATION, State.DATA ) );
if( pdu instanceof NetworkStatusBroadcastExtended )
{
mNetworkStatusExtended = (NetworkStatusBroadcastExtended)pdu;
}
else if( pdu instanceof ProtectionParameterBroadcast )
{
mProtectionParameterBroadcast =
(ProtectionParameterBroadcast)pdu;
}
else if( pdu instanceof RFSSStatusBroadcastExtended )
{
mRFSSStatusMessageExtended = (RFSSStatusBroadcastExtended)pdu;
}
if( pdu instanceof PDUConfirmedMessage )
{
broadcast( new DecoderStateEvent( this, Event.CONTINUATION, State.DATA ) );
PDUConfirmedMessage pduc = (PDUConfirmedMessage)pdu;
switch( pduc.getPDUType() )
@@ -1747,13 +1753,27 @@ 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:
case GROUP_VOICE_CHANNEL_GRANT:
case INDIVIDUAL_DATA_CHANNEL_GRANT:
case TELEPHONE_INTERCONNECT_VOICE_CHANNEL_GRANT:
case UNIT_TO_UNIT_VOICE_CHANNEL_GRANT:
case UNIT_TO_UNIT_VOICE_CHANNEL_GRANT_UPDATE:
processPDUChannelGrant( pdu );
break;
case ADJACENT_STATUS_BROADCAST:
AdjacentStatusBroadcastExtended asbe =
(AdjacentStatusBroadcastExtended)pdu;
updateSystem( asbe.getSystemID() );
if( pdu instanceof AdjacentStatusBroadcastExtended )
{
IAdjacentSite ias = (IAdjacentSite)pdu;
mNeighborMap.put( ias.getUniqueID(), ias );
updateSystem( ias.getSystemID() );
}
break;
case CALL_ALERT:
if( pdu instanceof CallAlertExtended )
@@ -1823,77 +1843,6 @@ public class P25DecoderState extends DecoderState
logAlternateVendorMessage( pdu );
}
break;
case GROUP_DATA_CHANNEL_GRANT:
if( pdu instanceof GroupDataChannelGrantExtended )
{
GroupDataChannelGrantExtended gdcge =
(GroupDataChannelGrantExtended)pdu;
CallEvent callEvent = new P25CallEvent.Builder( CallEventType.DATA_CALL )
.aliasList( getAliasList() )
.channel( gdcge.getTransmitChannel() )
.details( ( gdcge.isEncrypted() ? "ENCRYPTED" : "" ) +
( gdcge.isEmergency() ? " EMERGENCY" : "") )
.frequency( gdcge.getDownlinkFrequency() )
.from( gdcge.getSourceAddress() )
.to( gdcge.getGroupAddress() )
.build();
broadcast( new TrafficChannelAllocationEvent( this, callEvent ) );
}
else
{
logAlternateVendorMessage( pdu );
}
break;
case GROUP_VOICE_CHANNEL_GRANT:
if( pdu instanceof GroupVoiceChannelGrantExplicit )
{
GroupVoiceChannelGrantExplicit gvcge =
(GroupVoiceChannelGrantExplicit)pdu;
CallEvent callEvent = new P25CallEvent.Builder( CallEventType.CALL )
.aliasList( getAliasList() )
.channel( gvcge.getTransmitChannel() )
.details( ( gvcge.isEncrypted() ? "ENCRYPTED" : "" ) +
( gvcge.isEmergency() ? " EMERGENCY" : "") )
.frequency( gvcge.getDownlinkFrequency() )
.from( gvcge.getSourceAddress() )
.to( gvcge.getGroupAddress() )
.build();
broadcast( new TrafficChannelAllocationEvent( this, callEvent ) );
}
else
{
logAlternateVendorMessage( pdu );
}
break;
case INDIVIDUAL_DATA_CHANNEL_GRANT:
if( pdu instanceof IndividualDataChannelGrantExtended )
{
IndividualDataChannelGrantExtended idcge =
(IndividualDataChannelGrantExtended)pdu;
CallEvent callEvent = new P25CallEvent.Builder( CallEventType.DATA_CALL )
.aliasList( getAliasList() )
.channel( idcge.getTransmitChannel() )
.details( ( idcge.isEncrypted() ? "ENCRYPTED" : "" ) +
( idcge.isEmergency() ? " EMERGENCY" : "") )
.frequency( idcge.getDownlinkFrequency() )
.from( idcge.getSourceWACN() + "-" +
idcge.getSourceSystemID() + "-" +
idcge.getSourceAddress() )
.to( idcge.getTargetAddress() )
.build();
broadcast( new TrafficChannelAllocationEvent( this, callEvent ) );
}
else
{
logAlternateVendorMessage( pdu );
}
break;
case MESSAGE_UPDATE:
if( pdu instanceof MessageUpdateExtended )
{
@@ -1912,14 +1861,36 @@ public class P25DecoderState extends DecoderState
logAlternateVendorMessage( pdu );
}
break;
case NETWORK_STATUS_BROADCAST:
if( pdu instanceof NetworkStatusBroadcastExtended )
{
mNetworkStatusExtended = (NetworkStatusBroadcastExtended)pdu;
}
else
{
logAlternateVendorMessage( pdu );
}
break;
case PROTECTION_PARAMETER_BROADCAST:
if( pdu instanceof ProtectionParameterBroadcast )
{
mProtectionParameterBroadcast =
(ProtectionParameterBroadcast)pdu;
}
else
{
logAlternateVendorMessage( pdu );
}
break;
case RFSS_STATUS_BROADCAST:
if( pdu instanceof RFSSStatusBroadcastExtended )
{
RFSSStatusBroadcastExtended rsbe = (RFSSStatusBroadcastExtended)pdu;
mRFSSStatusMessageExtended = (RFSSStatusBroadcastExtended)pdu;
updateNAC( rsbe.getNAC() );
updateSystem( rsbe.getSystemID() );
updateSite( rsbe.getRFSubsystemID() + "-" + rsbe.getSiteID() );
updateNAC( mRFSSStatusMessageExtended.getNAC() );
updateSystem( mRFSSStatusMessageExtended.getSystemID() );
updateSite( mRFSSStatusMessageExtended.getRFSubsystemID() +
"-" + mRFSSStatusMessageExtended.getSiteID() );
}
else
{
@@ -2019,22 +1990,6 @@ public class P25DecoderState extends DecoderState
logAlternateVendorMessage( pdu );
}
break;
case TELEPHONE_INTERCONNECT_VOICE_CHANNEL_GRANT:
TelephoneInterconnectChannelGrantExplicit ticge =
(TelephoneInterconnectChannelGrantExplicit)pdu;
CallEvent callEvent = new P25CallEvent.Builder( CallEventType.TELEPHONE_INTERCONNECT )
.aliasList( getAliasList() )
.channel( ticge.getTransmitChannel() )
.details( ( ticge.isEncrypted() ? "ENCRYPTED" : "" ) +
( ticge.isEmergency() ? " EMERGENCY" : "") +
" CALL TIMER:" + ticge.getCallTimer() )
.frequency( ticge.getDownlinkFrequency() )
.from( ticge.getAddress() )
.build();
broadcast( new TrafficChannelAllocationEvent( this, callEvent ) );
break;
case UNIT_REGISTRATION_RESPONSE:
if( pdu instanceof UnitRegistrationResponseExtended )
{
@@ -2095,60 +2050,253 @@ public class P25DecoderState extends DecoderState
logAlternateVendorMessage( pdu );
}
break;
case UNIT_TO_UNIT_VOICE_CHANNEL_GRANT:
if( pdu instanceof UnitToUnitVoiceChannelGrantExtended )
{
UnitToUnitVoiceChannelGrantExtended uuvcge =
(UnitToUnitVoiceChannelGrantExtended)pdu;
CallEvent uuCallEvent = new P25CallEvent.Builder( CallEventType.UNIT_TO_UNIT_CALL )
.aliasList( getAliasList() )
.channel( uuvcge.getTransmitChannel() )
.details( ( uuvcge.isEncrypted() ? "ENCRYPTED" : "" ) +
( uuvcge.isEmergency() ? " EMERGENCY" : "") )
.frequency( uuvcge.getDownlinkFrequency() )
.from( uuvcge.getSourceWACN() + "-" +
uuvcge.getSourceSystemID() + "-" +
uuvcge.getSourceID() )
.to( uuvcge.getTargetAddress() )
.build();
broadcast( new TrafficChannelAllocationEvent( this, uuCallEvent ) );
}
else
{
logAlternateVendorMessage( pdu );
}
break;
case UNIT_TO_UNIT_VOICE_CHANNEL_GRANT_UPDATE:
if( pdu instanceof UnitToUnitVoiceChannelGrantUpdateExtended )
{
UnitToUnitVoiceChannelGrantUpdateExtended uuvcgue =
(UnitToUnitVoiceChannelGrantUpdateExtended)pdu;
broadcast( new P25CallEvent.Builder( CallEventType.UNIT_TO_UNIT_CALL )
.aliasList( getAliasList() )
.channel( uuvcgue.getTransmitChannel() )
.details( ( uuvcgue.isEncrypted() ? "ENCRYPTED" : "" ) +
( uuvcgue.isEmergency() ? " EMERGENCY" : "") )
.frequency( uuvcgue.getDownlinkFrequency() )
.from( uuvcgue.getSourceWACN() + "-" +
uuvcgue.getSourceSystemID() + "-" +
uuvcgue.getSourceID() )
.to( uuvcgue.getTargetAddress() )
.build() );
}
else
{
logAlternateVendorMessage( pdu );
}
break;
default:
break;
}
}
}
private void processPDUChannelGrant( PDUMessage pdu )
{
String channel = null;
String from = null;
String to = null;
switch( pdu.getOpcode() )
{
case GROUP_DATA_CHANNEL_GRANT:
if( pdu instanceof GroupDataChannelGrantExtended )
{
GroupDataChannelGrantExtended gdcge =
(GroupDataChannelGrantExtended)pdu;
channel = gdcge.getTransmitChannel();
from = gdcge.getSourceAddress();
to = gdcge.getGroupAddress();
if( hasCallEvent( channel, from, to ) )
{
updateCallEvent( channel, from, to );
}
else
{
P25CallEvent callEvent = new P25CallEvent.Builder( CallEventType.DATA_CALL )
.aliasList( getAliasList() )
.channel( channel )
.details( ( gdcge.isEncrypted() ? "ENCRYPTED" : "" ) +
( gdcge.isEmergency() ? " EMERGENCY" : "") )
.frequency( gdcge.getDownlinkFrequency() )
.from( from )
.to( to )
.build();
registerCallEvent( callEvent );
broadcast( callEvent );
}
}
else
{
logAlternateVendorMessage( pdu );
}
/* We don't allocate traffic channels for data */
break;
case GROUP_VOICE_CHANNEL_GRANT:
if( pdu instanceof GroupVoiceChannelGrantExplicit )
{
GroupVoiceChannelGrantExplicit gvcge =
(GroupVoiceChannelGrantExplicit)pdu;
channel = gvcge.getTransmitChannel();
from = gvcge.getSourceAddress();
to = gvcge.getGroupAddress();
if( hasCallEvent( channel, from, to ) )
{
updateCallEvent( channel, from, to );
}
else
{
P25CallEvent callEvent = new P25CallEvent.Builder( CallEventType.GROUP_CALL )
.aliasList( getAliasList() )
.channel( channel )
.details( ( gvcge.isEncrypted() ? "ENCRYPTED" : "" ) +
( gvcge.isEmergency() ? " EMERGENCY" : "") )
.frequency( gvcge.getDownlinkFrequency() )
.from( from )
.to( to )
.build();
registerCallEvent( callEvent );
broadcast( callEvent );
}
broadcast( new TrafficChannelAllocationEvent( this,
mChannelCallMap.get( channel ) ) );
}
else
{
logAlternateVendorMessage( pdu );
}
break;
case INDIVIDUAL_DATA_CHANNEL_GRANT:
if( pdu instanceof IndividualDataChannelGrantExtended )
{
IndividualDataChannelGrantExtended idcge =
(IndividualDataChannelGrantExtended)pdu;
channel = idcge.getTransmitChannel();
from = idcge.getSourceWACN() + "-" +
idcge.getSourceSystemID() + "-" +
idcge.getSourceAddress();
to = idcge.getTargetAddress();
if( hasCallEvent( channel, from, to ) )
{
updateCallEvent( channel, from, to );
}
else
{
P25CallEvent callEvent = new P25CallEvent.Builder( CallEventType.DATA_CALL )
.aliasList( getAliasList() )
.channel( channel )
.details( ( idcge.isEncrypted() ? "ENCRYPTED" : "" ) +
( idcge.isEmergency() ? " EMERGENCY" : "") )
.frequency( idcge.getDownlinkFrequency() )
.from( from )
.to( to )
.build();
registerCallEvent( callEvent );
broadcast( callEvent );
}
//We don't allocate traffic channels for data
}
else
{
logAlternateVendorMessage( pdu );
}
break;
case TELEPHONE_INTERCONNECT_VOICE_CHANNEL_GRANT:
TelephoneInterconnectChannelGrantExplicit ticge =
(TelephoneInterconnectChannelGrantExplicit)pdu;
channel = ticge.getTransmitChannel();
//We don't know if the subscriber is calling or being called, so
//we use the same address in both from/to fields
from = ticge.getAddress();
to = ticge.getAddress();
if( hasCallEvent( channel, from, to ) )
{
updateCallEvent( channel, from, to );
}
else
{
P25CallEvent callEvent = new P25CallEvent.Builder( CallEventType.TELEPHONE_INTERCONNECT )
.aliasList( getAliasList() )
.channel( channel )
.details( ( ticge.isEncrypted() ? "ENCRYPTED" : "" ) +
( ticge.isEmergency() ? " EMERGENCY" : "") +
" CALL TIMER:" + ticge.getCallTimer() )
.frequency( ticge.getDownlinkFrequency() )
.from( from )
.to( to )
.build();
registerCallEvent( callEvent );
broadcast( callEvent );
}
broadcast( new TrafficChannelAllocationEvent( this,
mChannelCallMap.get( channel ) ) );
break;
case UNIT_TO_UNIT_VOICE_CHANNEL_GRANT:
if( pdu instanceof UnitToUnitVoiceChannelGrantExtended )
{
UnitToUnitVoiceChannelGrantExtended uuvcge =
(UnitToUnitVoiceChannelGrantExtended)pdu;
channel = uuvcge.getTransmitChannel();
from = uuvcge.getSourceWACN() + "-" +
uuvcge.getSourceSystemID() + "-" +
uuvcge.getSourceID();
to = uuvcge.getTargetAddress();
if( hasCallEvent( channel, from, to ) )
{
updateCallEvent( channel, from, to );
}
else
{
P25CallEvent callEvent = new P25CallEvent.Builder( CallEventType.UNIT_TO_UNIT_CALL )
.aliasList( getAliasList() )
.channel( channel )
.details( ( uuvcge.isEncrypted() ? "ENCRYPTED" : "" ) +
( uuvcge.isEmergency() ? " EMERGENCY" : "") )
.frequency( uuvcge.getDownlinkFrequency() )
.from( from )
.to( to )
.build();
registerCallEvent( callEvent );
broadcast( callEvent );
}
broadcast( new TrafficChannelAllocationEvent( this,
mChannelCallMap.get( channel ) ) );
}
else
{
logAlternateVendorMessage( pdu );
}
break;
case UNIT_TO_UNIT_VOICE_CHANNEL_GRANT_UPDATE:
if( pdu instanceof UnitToUnitVoiceChannelGrantUpdateExtended )
{
UnitToUnitVoiceChannelGrantUpdateExtended uuvcgue =
(UnitToUnitVoiceChannelGrantUpdateExtended)pdu;
channel = uuvcgue.getTransmitChannel();
from = uuvcgue.getSourceWACN() + "-" +
uuvcgue.getSourceSystemID() + "-" +
uuvcgue.getSourceID();
to = uuvcgue.getTargetAddress();
if( hasCallEvent( channel, from, to ) )
{
updateCallEvent( channel, from, to );
}
else
{
P25CallEvent callEvent = new P25CallEvent.Builder( CallEventType.UNIT_TO_UNIT_CALL )
.aliasList( getAliasList() )
.channel( channel )
.details( ( uuvcgue.isEncrypted() ? "ENCRYPTED" : "" ) +
( uuvcgue.isEmergency() ? " EMERGENCY" : "") )
.frequency( uuvcgue.getDownlinkFrequency() )
.from( from )
.to( to )
.build();
registerCallEvent( callEvent );
broadcast( callEvent );
}
broadcast( new TrafficChannelAllocationEvent( this,
mChannelCallMap.get( channel ) ) );
}
else
{
logAlternateVendorMessage( pdu );
}
break;
}
}
private void processTSBKCommand( TSBKMessage message )
{
switch( message.getOpcode() )
@@ -2573,7 +2721,7 @@ public class P25DecoderState extends DecoderState
channel = gdcg.getChannel();
from = gdcg.getSourceAddress();
to = gdcg.getGroupAddress();
if( hasCallEvent( channel, from, to ) )
{
updateCallEvent( channel, from, to );
@@ -3277,11 +3425,11 @@ public class P25DecoderState extends DecoderState
}
else
{
for( AdjacentStatusBroadcast neighbor: mNeighborMap.values() )
for( IAdjacentSite neighbor: mNeighborMap.values() )
{
sb.append( "\nNAC:\t" + neighbor.getNAC() );
sb.append( "\nNAC:\t" + ((P25Message)neighbor).getNAC() );
sb.append( "\nSYSTEM:\t" + neighbor.getSystemID() );
sb.append( "\nLRA:\t" + neighbor.getLocationRegistrationArea() );
sb.append( "\nLRA:\t" + neighbor.getLRA() );
String neighborID = neighbor.getRFSS() + "-" + neighbor.getSiteID();
sb.append( "\nRFSS-SITE:\t" + neighborID );
@@ -3298,10 +3446,11 @@ public class P25DecoderState extends DecoderState
sb.append( "\nPCCH:\tDNLINK " + mFrequencyFormatter.format(
(double)neighbor.getDownlinkFrequency() / 1E6d ) +
" [" + neighbor.getIdentifier() + "-" + neighbor.getChannel() + "]" );
" [" + neighbor.getDownlinkChannel() + "]" );
sb.append( "\n\tUPLINK:" + mFrequencyFormatter.format(
(double)neighbor.getUplinkFrequency() / 1E6d ) + "\n" );
sb.append( "\nSERVICES:\t" + Service.getServices( neighbor.getSystemServiceClass() ) );
(double)neighbor.getUplinkFrequency() / 1E6d ) +
" [" + neighbor.getDownlinkChannel() + "]\n" );
sb.append( "\nSERVICES:\t" + neighbor.getSystemServiceClass() );
sb.append( "\n----------------------------------------------------" );
}
}
@@ -3367,6 +3516,8 @@ public class P25DecoderState extends DecoderState
{
TrafficChannelAllocationEvent allocationEvent =
(TrafficChannelAllocationEvent)event;
mCurrentCallEvent = (P25CallEvent)allocationEvent.getCallEvent();
mCurrentChannel = allocationEvent.getCallEvent().getChannel();
broadcast( ChangedAttribute.CHANNEL_NUMBER );

View File

@@ -43,8 +43,6 @@ public class P25Editor extends DecodeEditor
private static final long serialVersionUID = 1L;
private JComboBox<P25_LSMDecoder.Modulation> mComboModulation;
private JLabel mCallTimeoutLabel;
private JSlider mCallTimeout;
private JLabel mTrafficChannelPoolSizeLabel;
private JSlider mTrafficChannelPoolSize;
@@ -67,32 +65,6 @@ public class P25Editor extends DecodeEditor
add( new JLabel( "Modulation:" ) );
add( mComboModulation, "wrap" );
mCallTimeout = new JSlider( JSlider.HORIZONTAL,
DecodeConfiguration.CALL_TIMEOUT_MINIMUM,
DecodeConfiguration.CALL_TIMEOUT_MAXIMUM,
DecodeConfiguration.DEFAULT_CALL_TIMEOUT_SECONDS );
mCallTimeout.setMajorTickSpacing( 90 );
mCallTimeout.setMinorTickSpacing( 10 );
mCallTimeout.setPaintTicks( true );
mCallTimeout.setLabelTable( mCallTimeout.createStandardLabels( 100, 100 ) );
mCallTimeout.setPaintLabels( true );
mCallTimeoutLabel = new JLabel( "Call Timeout: " + mCallTimeout.getValue() + " " );
mCallTimeout.addChangeListener( new ChangeListener()
{
@Override
public void stateChanged( ChangeEvent e )
{
mCallTimeoutLabel.setText( "Call Timeout: " + mCallTimeout.getValue() );
}
} );
add( mCallTimeoutLabel );
add( mCallTimeout, "wrap,grow" );
mTrafficChannelPoolSize = new JSlider( JSlider.HORIZONTAL,
DecodeConfiguration.TRAFFIC_CHANNEL_LIMIT_MINIMUM,
DecodeConfiguration.TRAFFIC_CHANNEL_LIMIT_MAXIMUM,
@@ -150,8 +122,6 @@ public class P25Editor extends DecodeEditor
config.setModulation( (Modulation)mComboModulation.getSelectedItem() );
config.setCallTimeout( mCallTimeout.getValue() );
config.setTrafficChannelPoolSize( mTrafficChannelPoolSize.getValue() );
}
@@ -162,8 +132,6 @@ public class P25Editor extends DecodeEditor
mComboModulation.setSelectedItem( config.getModulation() );
mCallTimeout.setValue( config.getCallTimeout() );
mTrafficChannelPoolSize.setValue( config.getTrafficChannelPoolSize() );
}
}

View File

@@ -0,0 +1,20 @@
package module.decode.p25.message;
/**
* Interface for adjacent site (ie neighbor) messages
*/
public interface IAdjacentSite
{
public String getUniqueID();
public String getRFSS();
public String getSystemID();
public String getSiteID();
public String getLRA();
public String getSystemServiceClass();
public String getDownlinkChannel();
public long getDownlinkFrequency();
public String getUplinkChannel();
public long getUplinkFrequency();
}

View File

@@ -1,16 +1,17 @@
package module.decode.p25.message.ldu.lc;
import module.decode.p25.message.IAdjacentSite;
import module.decode.p25.message.IBandIdentifier;
import module.decode.p25.message.IdentifierReceiver;
import module.decode.p25.message.ldu.LDU1Message;
import module.decode.p25.message.tsbk.osp.control.SystemService;
import module.decode.p25.reference.LinkControlOpcode;
import module.decode.p25.reference.Service;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class AdjacentSiteStatusBroadcast extends LDU1Message
implements IdentifierReceiver
implements IdentifierReceiver, IAdjacentSite
{
private final static Logger mLog =
LoggerFactory.getLogger( AdjacentSiteStatusBroadcast.class );
@@ -46,20 +47,33 @@ public class AdjacentSiteStatusBroadcast extends LDU1Message
sb.append( getMessageStub() );
sb.append( " LRA:" + getLocationRegistrationArea() );
sb.append( " LRA:" + getLRA() );
sb.append( " SYS:" + getSystemID() );
sb.append( " SITE:" + getRFSubsystemID() + "-" + getSiteID() );
sb.append( " SITE:" + getRFSS() + "-" + getSiteID() );
sb.append( " CHAN:" + getChannel() );
sb.append( " " + Service.getServices( getSystemServiceClass() ).toString() );
sb.append( " " + getSystemServiceClass() );
return sb.toString();
}
public String getLocationRegistrationArea()
public String getUniqueID()
{
StringBuilder sb = new StringBuilder();
sb.append( getSystemID() );
sb.append( ":" );
sb.append( getRFSS() );
sb.append( ":" );
sb.append( getSiteID() );
return sb.toString();
}
public String getLRA()
{
return mMessage.getHex( LRA, 2 );
}
@@ -69,7 +83,7 @@ public class AdjacentSiteStatusBroadcast extends LDU1Message
return mMessage.getHex( SYSTEM_ID, 3 );
}
public String getRFSubsystemID()
public String getRFSS()
{
return mMessage.getHex( RFSS_ID, 2 );
}
@@ -94,9 +108,9 @@ public class AdjacentSiteStatusBroadcast extends LDU1Message
return mMessage.getInt( CHANNEL );
}
public int getSystemServiceClass()
public String getSystemServiceClass()
{
return mMessage.getInt( SYSTEM_SERVICE_CLASS );
return SystemService.toString( mMessage.getInt( SYSTEM_SERVICE_CLASS ) );
}
@Override
@@ -114,13 +128,26 @@ public class AdjacentSiteStatusBroadcast extends LDU1Message
return identifiers;
}
public long getDownlinkFrequency()
@Override
public String getDownlinkChannel()
{
return getChannel();
}
@Override
public String getUplinkChannel()
{
return getChannel();
}
public long getDownlinkFrequency()
{
return calculateDownlink( mIdentifierUpdate, getChannelNumber() );
}
public long getUplinkFrequencyB()
public long getUplinkFrequency()
{
return calculateUplink( mIdentifierUpdate, getChannelNumber() );
}

View File

@@ -1,5 +1,8 @@
package module.decode.p25.message.ldu.lc;
import module.decode.p25.message.IAdjacentSite;
import module.decode.p25.message.IBandIdentifier;
import module.decode.p25.message.IdentifierReceiver;
import module.decode.p25.message.ldu.LDU1Message;
import module.decode.p25.reference.LinkControlOpcode;
@@ -7,6 +10,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class AdjacentSiteStatusBroadcastExplicit extends LDU1Message
implements IdentifierReceiver, IAdjacentSite
{
private final static Logger mLog =
LoggerFactory.getLogger( AdjacentSiteStatusBroadcastExplicit.class );
@@ -22,6 +26,9 @@ public class AdjacentSiteStatusBroadcastExplicit extends LDU1Message
public static final int[] RECEIVE_CHANNEL = { 724,725,730,731,732,733,734,
735,740,741,742,743 };
private IBandIdentifier mTransmitBand;
private IBandIdentifier mReceiveBand;
public AdjacentSiteStatusBroadcastExplicit( LDU1Message message )
{
super( message );
@@ -40,27 +47,45 @@ public class AdjacentSiteStatusBroadcastExplicit extends LDU1Message
sb.append( getMessageStub() );
sb.append( " LRA:" + getLocationRegistrationArea() );
sb.append( " LRA:" + getLRA() );
sb.append( " SITE:" + getRFSubsystemID() + "-" + getSiteID() );
sb.append( " SITE:" + getRFSS() + "-" + getSiteID() );
sb.append( " DNLINK:" + getTransmitChannelNumber() );
sb.append( " DNLINK:" + getDownlinkChannel() );
sb.append( " UPLINK:" + getReceiveChannelNumber() );
sb.append( " UPLINK:" + getUplinkChannel() );
return sb.toString();
}
public String getLocationRegistrationArea()
public String getUniqueID()
{
StringBuilder sb = new StringBuilder();
sb.append( getSystemID() );
sb.append( ":" );
sb.append( getRFSS() );
sb.append( ":" );
sb.append( getSiteID() );
return sb.toString();
}
public String getLRA()
{
return mMessage.getHex( LRA, 2 );
}
public String getRFSubsystemID()
public String getRFSS()
{
return mMessage.getHex( RFSS_ID, 2 );
}
public String getSystemID()
{
return "***";
}
public String getSiteID()
{
return mMessage.getHex( SITE_ID, 2 );
@@ -76,7 +101,7 @@ public class AdjacentSiteStatusBroadcastExplicit extends LDU1Message
return mMessage.getInt( TRANSMIT_CHANNEL );
}
public String getTransmitChannelNumber()
public String getDownlinkChannel()
{
return getTransmitIdentifier() + "-" + getTransmitChannel();
}
@@ -91,8 +116,50 @@ public class AdjacentSiteStatusBroadcastExplicit extends LDU1Message
return mMessage.getInt( RECEIVE_CHANNEL );
}
public String getReceiveChannelNumber()
public String getUplinkChannel()
{
return getReceiveIdentifier() + "-" + getReceiveChannel();
}
@Override
public String getSystemServiceClass()
{
return "[]";
}
public long getDownlinkFrequency()
{
return calculateDownlink( mTransmitBand, getTransmitChannel() );
}
public long getUplinkFrequency()
{
return calculateUplink( mReceiveBand, getReceiveChannel() );
}
@Override
public void setIdentifierMessage( int identifier, IBandIdentifier message )
{
if( identifier == getTransmitIdentifier() )
{
mTransmitBand = message;
}
if( identifier == getReceiveIdentifier() )
{
mReceiveBand = message;
}
}
@Override
public int[] getIdentifiers()
{
int[] identifiers = new int[ 2 ];
identifiers[ 0 ] = getTransmitIdentifier();
identifiers[ 1 ] = getReceiveIdentifier();
return identifiers;
}
}

View File

@@ -45,7 +45,19 @@ public class PDUMessage extends P25Message
sb.append( "NAC:" );
sb.append( getNAC() );
sb.append( " " );
sb.append( getDUID().getLabel() );
switch( getFormat() )
{
case ALTERNATE_MULTI_BLOCK_TRUNKING_CONTROL:
sb.append( "ATSBK" );
break;
case UNCONFIRMED_MULTI_BLOCK_TRUNKING_CONTROL:
sb.append( "**** UNCONFIRMED MULTI-BLOCK TRUNKING CONTROL" );
break;
default:
sb.append( getDUID().getLabel() );
break;
}
if( vendor == Vendor.STANDARD )
{

View File

@@ -66,6 +66,7 @@ public class PDUMessageFactory
return new GroupDataChannelGrantExtended(
message, duid, aliasList );
case GROUP_VOICE_CHANNEL_GRANT:
return new GroupVoiceChannelGrantExplicit(
message, duid, aliasList );
case INDIVIDUAL_DATA_CHANNEL_GRANT:
@@ -123,7 +124,6 @@ public class PDUMessageFactory
case UNCONFIRMED_MULTI_BLOCK_TRUNKING_CONTROL:
return new PDUMessage( message, duid, aliasList );
default:
return new PDUMessage( message, duid, aliasList );
}

View File

@@ -1,5 +1,6 @@
package module.decode.p25.message.pdu.osp.control;
import module.decode.p25.message.IAdjacentSite;
import module.decode.p25.message.IBandIdentifier;
import module.decode.p25.message.IdentifierReceiver;
import module.decode.p25.message.pdu.PDUMessage;
@@ -11,7 +12,7 @@ import bits.BinaryMessage;
import edac.CRCP25;
public class AdjacentStatusBroadcastExtended extends PDUMessage
implements IdentifierReceiver
implements IdentifierReceiver, IAdjacentSite
{
public static final int[] LRA = { 88,89,90,91,92,93,94,95 };
public static final int[] SYSTEM_ID = { 100,101,102,103,104,105,106,107,108,
@@ -57,11 +58,11 @@ public class AdjacentStatusBroadcastExtended extends PDUMessage
sb.append( getMessageStub() );
sb.append( " LRA:" + getLocationRegistrationArea() );
sb.append( " LRA:" + getLRA() );
sb.append( " SYS:" + getSystemID() );
sb.append( " RFSS:" + getRFSubsystemID() );
sb.append( " RFSS:" + getRFSS() );
sb.append( " SITE:" + getSiteID() );
@@ -73,28 +74,29 @@ public class AdjacentStatusBroadcastExtended extends PDUMessage
sb.append( " UP:" + getUplinkFrequency() );
sb.append( " SYS SVC CLASS:" +
SystemService.toString( getSystemServiceClass() ) );
sb.append( " SYS SVC CLASS:" + getSystemServiceClass() );
return sb.toString();
}
public String getLocationRegistrationArea()
{
return mMessage.getHex( LRA, 2 );
}
public String getUniqueID()
{
StringBuilder sb = new StringBuilder();
sb.append( getSystemID() );
sb.append( ":" );
sb.append( getRFSS() );
sb.append( ":" );
sb.append( getSiteID() );
return sb.toString();
}
public String getSystemID()
{
return mMessage.getHex( SYSTEM_ID, 3 );
}
public String getRFSubsystemID()
{
return mMessage.getHex( RF_SUBSYSTEM_ID, 2 );
}
public String getSiteID()
{
return mMessage.getHex( SITE_ID, 2 );
@@ -120,11 +122,6 @@ public class AdjacentStatusBroadcastExtended extends PDUMessage
return mMessage.getInt( RECEIVE_CHANNEL );
}
public int getSystemServiceClass()
{
return mMessage.getInt( SYSTEM_SERVICE_CLASS );
}
public long getDownlinkFrequency()
{
return calculateDownlink( mTransmitIdentifierProvider, getTransmitChannel() );
@@ -158,4 +155,34 @@ public class AdjacentStatusBroadcastExtended extends PDUMessage
return idens;
}
@Override
public String getRFSS()
{
return mMessage.getHex( RF_SUBSYSTEM_ID, 2 );
}
@Override
public String getLRA()
{
return mMessage.getHex( LRA, 2 );
}
@Override
public String getSystemServiceClass()
{
return SystemService.toString( mMessage.getInt( SYSTEM_SERVICE_CLASS ) );
}
@Override
public String getDownlinkChannel()
{
return getTransmitIdentifier() + "-" + getTransmitChannel();
}
@Override
public String getUplinkChannel()
{
return getReceiveIdentifier() + "-" + getReceiveChannel();
}
}

View File

@@ -77,6 +77,9 @@ public class GroupVoiceChannelGrantExplicit extends PDUMessage
sb.append( " CHAN UP:" + getReceiveChannelIdentifier() + "-" + getReceiveChannelNumber() );
sb.append( " " + getUplinkFrequency() );
sb.append( " " );
sb.append( mMessage.toString() );
return sb.toString();
}

View File

@@ -1,7 +1,9 @@
package module.decode.p25.message.tdu.lc;
import module.decode.p25.message.IAdjacentSite;
import module.decode.p25.message.IBandIdentifier;
import module.decode.p25.message.IdentifierReceiver;
import module.decode.p25.message.tsbk.osp.control.SystemService;
import module.decode.p25.reference.LinkControlOpcode;
import module.decode.p25.reference.Service;
@@ -9,7 +11,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class AdjacentSiteStatusBroadcast extends TDULinkControlMessage
implements IdentifierReceiver
implements IdentifierReceiver, IAdjacentSite
{
private final static Logger mLog =
LoggerFactory.getLogger( AdjacentSiteStatusBroadcast.class );
@@ -45,20 +47,33 @@ public class AdjacentSiteStatusBroadcast extends TDULinkControlMessage
sb.append( getMessageStub() );
sb.append( " LRA:" + getLocationRegistrationArea() );
sb.append( " LRA:" + getLRA() );
sb.append( " SYS:" + getSystemID() );
sb.append( " SITE:" + getRFSubsystemID() + "-" + getSiteID() );
sb.append( " SITE:" + getRFSS() + "-" + getSiteID() );
sb.append( " CHAN:" + getChannel() );
sb.append( " " + Service.getServices( getSystemServiceClass() ).toString() );
sb.append( " " + getSystemServiceClass() );
return sb.toString();
}
public String getLocationRegistrationArea()
public String getUniqueID()
{
StringBuilder sb = new StringBuilder();
sb.append( getSystemID() );
sb.append( ":" );
sb.append( getRFSS() );
sb.append( ":" );
sb.append( getSiteID() );
return sb.toString();
}
public String getLRA()
{
return mMessage.getHex( LRA, 2 );
}
@@ -68,7 +83,7 @@ public class AdjacentSiteStatusBroadcast extends TDULinkControlMessage
return mMessage.getHex( SYSTEM_ID, 3 );
}
public String getRFSubsystemID()
public String getRFSS()
{
return mMessage.getHex( RFSS_ID, 2 );
}
@@ -88,14 +103,26 @@ public class AdjacentSiteStatusBroadcast extends TDULinkControlMessage
return getIdentifier() + "-" + getChannelNumber();
}
@Override
public String getDownlinkChannel()
{
return getChannel();
}
@Override
public String getUplinkChannel()
{
return getChannel();
}
public int getChannelNumber()
{
return mMessage.getInt( CHANNEL );
}
public int getSystemServiceClass()
public String getSystemServiceClass()
{
return mMessage.getInt( SYSTEM_SERVICE_CLASS );
return SystemService.toString( mMessage.getInt( SYSTEM_SERVICE_CLASS ) );
}
@Override
@@ -119,7 +146,7 @@ public class AdjacentSiteStatusBroadcast extends TDULinkControlMessage
return calculateDownlink( mIdentifierUpdate, getChannelNumber() );
}
public long getUplinkFrequencyB()
public long getUplinkFrequency()
{
return calculateUplink( mIdentifierUpdate, getChannelNumber() );
}

View File

@@ -1,11 +1,15 @@
package module.decode.p25.message.tdu.lc;
import module.decode.p25.message.IAdjacentSite;
import module.decode.p25.message.IBandIdentifier;
import module.decode.p25.message.IdentifierReceiver;
import module.decode.p25.reference.LinkControlOpcode;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class AdjacentSiteStatusBroadcastExplicit extends TDULinkControlMessage
implements IdentifierReceiver, IAdjacentSite
{
private final static Logger mLog =
LoggerFactory.getLogger( AdjacentSiteStatusBroadcastExplicit.class );
@@ -21,6 +25,9 @@ public class AdjacentSiteStatusBroadcastExplicit extends TDULinkControlMessage
public static final int[] RECEIVE_CHANNEL = { 164,165,166,167,168,169,170,
171,184,185,186,187 };
private IBandIdentifier mTransmitBand;
private IBandIdentifier mReceiveBand;
public AdjacentSiteStatusBroadcastExplicit( TDULinkControlMessage source )
{
super( source );
@@ -39,32 +46,56 @@ public class AdjacentSiteStatusBroadcastExplicit extends TDULinkControlMessage
sb.append( getMessageStub() );
sb.append( " LRA:" + getLocationRegistrationArea() );
sb.append( " LRA:" + getLRA() );
sb.append( " SITE:" + getRFSubsystemID() + "-" + getSiteID() );
sb.append( " SITE:" + getRFSS() + "-" + getSiteID() );
sb.append( " DNLINK:" + getTransmitChannelNumber() );
sb.append( " DNLINK:" + getDownlinkChannel() );
sb.append( " UPLINK:" + getReceiveChannelNumber() );
sb.append( " UPLINK:" + getUplinkChannel() );
return sb.toString();
}
public String getLocationRegistrationArea()
public String getUniqueID()
{
StringBuilder sb = new StringBuilder();
sb.append( getSystemID() );
sb.append( ":" );
sb.append( getRFSS() );
sb.append( ":" );
sb.append( getSiteID() );
return sb.toString();
}
public String getLRA()
{
return mMessage.getHex( LRA, 2 );
}
public String getRFSubsystemID()
public String getRFSS()
{
return mMessage.getHex( RFSS_ID, 2 );
}
public String getSystemID()
{
return "***";
}
public String getSiteID()
{
return mMessage.getHex( SITE_ID, 2 );
}
@Override
public String getSystemServiceClass()
{
return "[]";
}
public int getTransmitIdentifier()
{
return mMessage.getInt( TRANSMIT_IDENTIFIER );
@@ -75,7 +106,7 @@ public class AdjacentSiteStatusBroadcastExplicit extends TDULinkControlMessage
return mMessage.getInt( TRANSMIT_CHANNEL );
}
public String getTransmitChannelNumber()
public String getDownlinkChannel()
{
return getTransmitIdentifier() + "-" + getTransmitChannel();
}
@@ -90,8 +121,43 @@ public class AdjacentSiteStatusBroadcastExplicit extends TDULinkControlMessage
return mMessage.getInt( RECEIVE_CHANNEL );
}
public String getReceiveChannelNumber()
public String getUplinkChannel()
{
return getReceiveIdentifier() + "-" + getReceiveChannel();
}
public long getDownlinkFrequency()
{
return calculateDownlink( mTransmitBand, getTransmitChannel() );
}
public long getUplinkFrequency()
{
return calculateUplink( mReceiveBand, getReceiveChannel() );
}
@Override
public void setIdentifierMessage( int identifier, IBandIdentifier message )
{
if( identifier == getTransmitIdentifier() )
{
mTransmitBand = message;
}
if( identifier == getReceiveIdentifier() )
{
mReceiveBand = message;
}
}
@Override
public int[] getIdentifiers()
{
int[] identifiers = new int[ 2 ];
identifiers[ 0 ] = getTransmitIdentifier();
identifiers[ 1 ] = getReceiveIdentifier();
return identifiers;
}
}

View File

@@ -1,5 +1,6 @@
package module.decode.p25.message.tsbk.osp.control;
import module.decode.p25.message.IAdjacentSite;
import module.decode.p25.message.IBandIdentifier;
import module.decode.p25.message.IdentifierReceiver;
import module.decode.p25.message.tsbk.TSBKMessage;
@@ -8,7 +9,8 @@ import module.decode.p25.reference.Opcode;
import alias.AliasList;
import bits.BinaryMessage;
public class AdjacentStatusBroadcast extends TSBKMessage implements IdentifierReceiver
public class AdjacentStatusBroadcast extends TSBKMessage
implements IdentifierReceiver, IAdjacentSite
{
public static final int[] LOCATION_REGISTRATION_AREA = { 80,81,82,83,84,85,
86,87 };
@@ -47,7 +49,7 @@ public class AdjacentStatusBroadcast extends TSBKMessage implements IdentifierRe
sb.append( getMessageStub() );
sb.append( " LRA:" + getLocationRegistrationArea() );
sb.append( " LRA:" + getLRA() );
sb.append( " SYS:" + getSystemID() );
@@ -79,12 +81,24 @@ public class AdjacentStatusBroadcast extends TSBKMessage implements IdentifierRe
sb.append( " ACTIVE-NETWORK-CONN" );
}
sb.append( SystemService.toString( getSystemServiceClass() ) );
sb.append( getSystemServiceClass() );
return sb.toString();
}
public String getLocationRegistrationArea()
@Override
public String getDownlinkChannel()
{
return getIdentifier() + "-" + getChannel();
}
@Override
public String getUplinkChannel()
{
return getIdentifier() + "-" + getChannel();
}
public String getLRA()
{
return mMessage.getHex( LOCATION_REGISTRATION_AREA, 2 );
}
@@ -147,9 +161,9 @@ public class AdjacentStatusBroadcast extends TSBKMessage implements IdentifierRe
return mMessage.getInt( IDENTIFIER );
}
public int getSystemServiceClass()
public String getSystemServiceClass()
{
return mMessage.getInt( SYSTEM_SERVICE_CLASS );
return SystemService.toString( mMessage.getInt( SYSTEM_SERVICE_CLASS ) );
}
public long getDownlinkFrequency()
@@ -161,6 +175,7 @@ public class AdjacentStatusBroadcast extends TSBKMessage implements IdentifierRe
{
return calculateUplink( mIdentifierUpdate, getChannel() );
}
@Override
public void setIdentifierMessage( int identifier, IBandIdentifier message )

View File

@@ -309,26 +309,45 @@ public class ChannelState extends Module implements ICallEventProvider,
switch( state )
{
case CONTROL:
//Don't allow traffic channels to be control channels,
//otherwise they won't get call tear down
if( mChannelType != ChannelType.TRAFFIC )
{
broadcast( SquelchState.SQUELCH );
updateFadeTimeout();
startMonitor();
mState = state;
broadcast( ChangedAttribute.CHANNEL_STATE );
}
break;
case DATA:
case ENCRYPTED:
broadcast( SquelchState.SQUELCH );
updateFadeTimeout();
startMonitor();
mState = state;
broadcast( ChangedAttribute.CHANNEL_STATE );
break;
case CALL:
broadcast( SquelchState.UNSQUELCH );
updateFadeTimeout();
startMonitor();
mState = state;
broadcast( ChangedAttribute.CHANNEL_STATE );
break;
case FADE:
broadcast( SquelchState.SQUELCH );
updateResetTimeout();
startMonitor();
mState = state;
broadcast( ChangedAttribute.CHANNEL_STATE );
break;
case END:
broadcast( SquelchState.SQUELCH );
broadcast( new DecoderStateEvent( this, Event.RESET, State.IDLE ) );
broadcast( new MetadataReset() );
mState = state;
broadcast( ChangedAttribute.CHANNEL_STATE );
break;
case IDLE:
broadcast( SquelchState.SQUELCH );
@@ -350,14 +369,13 @@ public class ChannelState extends Module implements ICallEventProvider,
mTrafficChannelCallEvent = null;
}
}
mState = state;
broadcast( ChangedAttribute.CHANNEL_STATE );
break;
default:
break;
}
mState = state;
broadcast( ChangedAttribute.CHANNEL_STATE );
}
}