P25 work in progress

This commit is contained in:
dennis.sheirer
2014-11-15 21:24:21 +00:00
parent eee28a3449
commit 20c9ae329b
34 changed files with 1511 additions and 59 deletions

View File

@@ -86,7 +86,12 @@ public class P25Message extends Message
@Override
public Alias getFromIDAlias()
{
return null;
if( mAliasList != null )
{
return mAliasList.getTalkgroupAlias( getFromID() );
}
return null;
}
@Override
@@ -98,6 +103,11 @@ public class P25Message extends Message
@Override
public Alias getToIDAlias()
{
if( mAliasList != null )
{
return mAliasList.getTalkgroupAlias( getToID() );
}
return null;
}

View File

@@ -82,31 +82,9 @@ public abstract class GroupMultiChannelGrant extends ChannelGrant
return getGroupAddress1();
}
@Override
public Alias getFromIDAlias()
{
if( mAliasList != null )
{
return mAliasList.getTalkgroupAlias( getFromID() );
}
return null;
}
@Override
public String getToID()
{
return getGroupAddress2();
}
@Override
public Alias getToIDAlias()
{
if( mAliasList != null )
{
return mAliasList.getTalkgroupAlias( getToID() );
}
return null;
}
}

View File

@@ -2,6 +2,30 @@ package decode.p25.message.tsbk;
import alias.AliasList;
import bits.BitSetBuffer;
import decode.p25.message.tsbk.osp.control.AcknowledgeResponse;
import decode.p25.message.tsbk.osp.control.AdjacentStatusBroadcast;
import decode.p25.message.tsbk.osp.control.AuthenticationCommand;
import decode.p25.message.tsbk.osp.control.CallAlert;
import decode.p25.message.tsbk.osp.control.DenyResponse;
import decode.p25.message.tsbk.osp.control.ExtendedFunctionCommand;
import decode.p25.message.tsbk.osp.control.GroupAffiliationQuery;
import decode.p25.message.tsbk.osp.control.GroupAffiliationResponse;
import decode.p25.message.tsbk.osp.control.IdentifierUpdate;
import decode.p25.message.tsbk.osp.control.MessageUpdate;
import decode.p25.message.tsbk.osp.control.NetworkStatusBroadcast;
import decode.p25.message.tsbk.osp.control.ProtectionParameterUpdate;
import decode.p25.message.tsbk.osp.data.GroupDataChannelAnnouncement;
import decode.p25.message.tsbk.osp.data.GroupDataChannelAnnouncementExplicit;
import decode.p25.message.tsbk.osp.data.GroupDataChannelGrant;
import decode.p25.message.tsbk.osp.data.IndividualDataChannelGrant;
import decode.p25.message.tsbk.osp.voice.GroupVoiceChannelGrant;
import decode.p25.message.tsbk.osp.voice.GroupVoiceChannelGrantUpdate;
import decode.p25.message.tsbk.osp.voice.GroupVoiceChannelGrantUpdateExplicit;
import decode.p25.message.tsbk.osp.voice.TelephoneInterconnectAnswerRequest;
import decode.p25.message.tsbk.osp.voice.TelephoneInterconnectVoiceChannelGrant;
import decode.p25.message.tsbk.osp.voice.UnitToUnitAnswerRequest;
import decode.p25.message.tsbk.osp.voice.UnitToUnitVoiceChannelGrant;
import decode.p25.message.tsbk.osp.voice.UnitToUnitVoiceChannelGrantUpdate;
import decode.p25.reference.DataUnitID;
import decode.p25.reference.Opcode;
import decode.p25.reference.Vendor;
@@ -46,9 +70,54 @@ public class TSBKMessageFactory
case UNIT_TO_UNIT_VOICE_CHANNEL_GRANT_UPDATE:
return new UnitToUnitVoiceChannelGrantUpdate( message,
duid, aliasList );
case INDIVIDUAL_DATA_CHANNEL_GRANT:
return new IndividualDataChannelGrant( message, duid,
aliasList );
case GROUP_DATA_CHANNEL_GRANT:
return new GroupDataChannelGrant( message, duid,
aliasList );
case GROUP_DATA_CHANNEL_ANNOUNCEMENT:
return new GroupDataChannelAnnouncement( message, duid,
aliasList );
case GROUP_DATA_CHANNEL_ANNOUNCEMENT_EXPLICIT:
return new GroupDataChannelAnnouncementExplicit(
message, duid, aliasList );
case ACKNOWLEDGE_RESPONSE_FNE:
return new AcknowledgeResponse( message, duid,
aliasList );
case ADJACENT_STATUS_BROADCAST:
return new AdjacentStatusBroadcast( message, duid,
aliasList );
case AUTHENTICATION_COMMAND:
return new AuthenticationCommand( message, duid,
aliasList );
case CALL_ALERT:
return new CallAlert( message, duid, aliasList );
case DENY_RESPONSE:
return new DenyResponse( message, duid, aliasList );
case EXTENDED_FUNCTION_COMMAND:
return new ExtendedFunctionCommand( message, duid,
aliasList );
case GROUP_AFFILIATION_QUERY:
return new GroupAffiliationQuery( message, duid,
aliasList );
case GROUP_AFFILIATION_RESPONSE:
return new GroupAffiliationResponse( message, duid,
aliasList );
case IDENTIFIER_UPDATE:
return new IdentifierUpdate( message, duid, aliasList );
case MESSAGE_UPDATE:
return new MessageUpdate( message, duid, aliasList );
case NETWORK_STATUS_BROADCAST:
return new NetworkStatusBroadcast( message, duid,
aliasList );
case PROTECTION_PARAMETER_UPDATE:
return new ProtectionParameterUpdate( message, duid,
aliasList );
default:
return new TSBKMessage( message, duid, aliasList );
}
case MOTOROLA:
default:
return new TSBKMessage( message, duid, aliasList );

View File

@@ -72,15 +72,4 @@ public abstract class UnitChannelGrant extends ChannelGrant
{
return getTargetAddress();
}
@Override
public Alias getToIDAlias()
{
if( mAliasList != null )
{
return mAliasList.getTalkgroupAlias( getToID() );
}
return null;
}
}

View File

@@ -0,0 +1,121 @@
package decode.p25.message.tsbk.osp.control;
import alias.AliasList;
import bits.BitSetBuffer;
import decode.p25.message.tsbk.TSBKMessage;
import decode.p25.reference.DataUnitID;
import decode.p25.reference.Opcode;
public class AcknowledgeResponse extends TSBKMessage
{
public static final int ADDITIONAL_INFORMATION_FLAG = 80;
public static final int EXTENDED_ADDRESS_FLAG = 81;
public static final int[] SERVICE_TYPE = { 82,83,84,85,86,87 };
public static final int[] WACN = { 88,89,90,91,92,93,94,95,96,97,98,99,100,
101,102,103,104,105,106,107 };
public static final int[] SYSTEM_ID = { 108,109,110,111,112,113,114,115,116,
117,118,119 };
public static final int[] SOURCE_ADDRESS = { 96,97,98,99,100,101,102,103,
104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119 };
public static final int[] TARGET_ADDRESS = { 120,121,122,123,124,125,126,
127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143 };
public AcknowledgeResponse( BitSetBuffer message,
DataUnitID duid,
AliasList aliasList )
{
super( message, duid, aliasList );
}
@Override
public String getEventType()
{
return Opcode.ACKNOWLEDGE_RESPONSE_FNE.getDescription();
}
public String getMessage()
{
StringBuilder sb = new StringBuilder();
sb.append( super.getMessage() );
sb.append( " SVC TYPE: " + getServiceType() );
if( hasAdditionalInformation() )
{
if( hasExtendedAddress() )
{
sb.append( " WACN: " + getWACN() );
sb.append( " SYS ID: " + getSystemID() );
}
else
{
sb.append( " SRC: " + getSourceAddress() );
}
}
return sb.toString();
}
public boolean hasAdditionalInformation()
{
return mMessage.get( ADDITIONAL_INFORMATION_FLAG );
}
public boolean hasExtendedAddress()
{
return mMessage.get( EXTENDED_ADDRESS_FLAG );
}
public String getServiceType()
{
return mMessage.getHex( SERVICE_TYPE, 2 );
}
public String getWACN()
{
if( hasAdditionalInformation() && !hasExtendedAddress() )
{
return mMessage.getHex( WACN, 5 );
}
return null;
}
public String getSystemID()
{
if( hasAdditionalInformation() && !hasExtendedAddress() )
{
return mMessage.getHex( SYSTEM_ID, 3 );
}
return null;
}
public String getSourceAddress()
{
if( hasAdditionalInformation() && !hasExtendedAddress() )
{
return mMessage.getHex( SOURCE_ADDRESS, 6 );
}
return null;
}
@Override
public String getFromID()
{
return getSourceAddress();
}
public String getTargetAddress()
{
return mMessage.getHex( TARGET_ADDRESS, 6 );
}
@Override
public String getToID()
{
return getTargetAddress();
}
}

View File

@@ -0,0 +1,156 @@
package decode.p25.message.tsbk.osp.control;
import alias.AliasList;
import bits.BitSetBuffer;
import decode.p25.message.tsbk.TSBKMessage;
import decode.p25.reference.DataUnitID;
import decode.p25.reference.Opcode;
public class AdjacentStatusBroadcast extends TSBKMessage
{
public static final int[] LOCATION_REGISTRATION_AREA = { 80,81,82,83,84,85,
86,87 };
public static final int CONVENTIONAL_CHANNEL_FLAG = 88;
public static final int SITE_FAILURE_CONDITION_FLAG = 89;
public static final int VALID_FLAG = 90;
public static final int ACTIVE_NETWORK_CONNECTION_FLAG = 91;
public static final int[] SYSTEM_ID = { 92,93,94,95,96,97,98,99,100,101,
102,103 };
public static final int[] RFSS_ID = { 104,105,106,107,108,109,110,111 };
public static final int[] SITE_ID = { 112,113,114,115,116,117,118,119 };
public static final int[] CHANNEL = { 120,121,122,123,124,125,126,127,
128,129,130,131,132,133,134,135 };
public static final int[] SYSTEM_SERVICE_CLASS = { 136,137,138,139,140,141,
142,143 };
public AdjacentStatusBroadcast( BitSetBuffer message,
DataUnitID duid,
AliasList aliasList )
{
super( message, duid, aliasList );
}
@Override
public String getEventType()
{
return Opcode.ADJACENT_STATUS_BROADCAST.getDescription();
}
public String getMessage()
{
StringBuilder sb = new StringBuilder();
sb.append( super.getMessage() );
sb.append( " LRA:" + getLocationRegistrationArea() );
sb.append( " SYSID:" + getSystemID() );
sb.append( " RFSS:" + getRFSS() );
sb.append( " SITE:" + getSiteID() );
sb.append( " CHAN:" + getChannel() );
if( isConventionalChannel() )
{
sb.append( " CONVENTIONAL" );
}
if( isSiteFailureCondition() )
{
sb.append( " FAILURE-CONDITION" );
}
if( isValid() )
{
sb.append( " VALID-INFO" );
}
if( hasActiveNetworkConnection() )
{
sb.append( " ACTIVE-NETWORK-CONN" );
}
sb.append( SystemService.toString( getSystemServiceClass() ) );
return sb.toString();
}
public String getLocationRegistrationArea()
{
return mMessage.getHex( LOCATION_REGISTRATION_AREA, 2 );
}
public boolean isConventionalChannel()
{
return mMessage.get( CONVENTIONAL_CHANNEL_FLAG );
}
public boolean isSiteFailureCondition()
{
return mMessage.get( SITE_FAILURE_CONDITION_FLAG );
}
public boolean isValidSiteInformation()
{
return mMessage.get( VALID_FLAG );
}
public boolean hasActiveNetworkConnection()
{
return mMessage.get( ACTIVE_NETWORK_CONNECTION_FLAG );
}
public String getSystemID()
{
return mMessage.getHex( SYSTEM_ID, 3 );
}
public String getRFSS()
{
return mMessage.getHex( RFSS_ID, 2 );
}
public String getSiteID()
{
return mMessage.getHex( SITE_ID, 2 );
}
public int getChannel()
{
return mMessage.getInt( CHANNEL );
}
public int getSystemServiceClass()
{
return mMessage.getInt( SYSTEM_SERVICE_CLASS );
}
public String getSourceAddress()
{
if( hasAdditionalInformation() && !hasExtendedAddress() )
{
return mMessage.getHex( SOURCE_ADDRESS, 6 );
}
return null;
}
@Override
public String getFromID()
{
return getSourceAddress();
}
public String getTargetAddress()
{
return mMessage.getHex( TARGET_ADDRESS, 6 );
}
@Override
public String getToID()
{
return getTargetAddress();
}
}

View File

@@ -0,0 +1,64 @@
package decode.p25.message.tsbk.osp.control;
import alias.AliasList;
import bits.BitSetBuffer;
import decode.p25.message.tsbk.TSBKMessage;
import decode.p25.reference.DataUnitID;
import decode.p25.reference.Opcode;
public class AuthenticationCommand extends TSBKMessage
{
public static final int[] WACN = { 88,89,90,91,92,93,94,95,96,97,98,99,100,
101,102,103,104,105,106,107 };
public static final int[] SYSTEM_ID = { 108,109,110,111,112,113,114,115,116,
117,118,119 };
public static final int[] TARGET_ID = { 120,121,122,123,124,125,126,
127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143 };
public AuthenticationCommand( BitSetBuffer message,
DataUnitID duid,
AliasList aliasList )
{
super( message, duid, aliasList );
}
@Override
public String getEventType()
{
return Opcode.AUTHENTICATION_COMMAND.getDescription();
}
public String getMessage()
{
StringBuilder sb = new StringBuilder();
sb.append( super.getMessage() );
sb.append( " WACN: " + getWACN() );
sb.append( " SYS ID: " + getSystemID() );
sb.append( " TGT ID: " + getTargetID() );
return sb.toString();
}
public String getWACN()
{
return mMessage.getHex( WACN, 5 );
}
public String getSystemID()
{
return mMessage.getHex( SYSTEM_ID, 3 );
}
public String getTargetID()
{
return mMessage.getHex( TARGET_ID, 6 );
}
@Override
public String getToID()
{
return getTargetID();
}
}

View File

@@ -0,0 +1,62 @@
package decode.p25.message.tsbk.osp.control;
import alias.AliasList;
import bits.BitSetBuffer;
import decode.p25.message.tsbk.TSBKMessage;
import decode.p25.reference.DataUnitID;
import decode.p25.reference.Opcode;
public class CallAlert extends TSBKMessage
{
public static final int[] TARGET_ADDRESS = { 96,97,98,99,100,101,102,103,
104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119 };
public static final int[] SOURCE_ID = { 120,121,122,123,124,125,126,
127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143 };
public CallAlert( BitSetBuffer message,
DataUnitID duid,
AliasList aliasList )
{
super( message, duid, aliasList );
}
@Override
public String getEventType()
{
return Opcode.CALL_ALERT.getDescription();
}
public String getMessage()
{
StringBuilder sb = new StringBuilder();
sb.append( super.getMessage() );
sb.append( " SRC ID: " + getSourceID() );
sb.append( " TGT ADDR: " + getTargetAddress() );
return sb.toString();
}
public String getSourceID()
{
return mMessage.getHex( SOURCE_ID, 6 );
}
@Override
public String getFromID()
{
return getSourceID();
}
public String getTargetAddress()
{
return mMessage.getHex( TARGET_ADDRESS, 6 );
}
@Override
public String getToID()
{
return getTargetAddress();
}
}

View File

@@ -0,0 +1,74 @@
package decode.p25.message.tsbk.osp.control;
import alias.AliasList;
import bits.BitSetBuffer;
import decode.p25.message.tsbk.TSBKMessage;
import decode.p25.reference.DataUnitID;
import decode.p25.reference.DenyReason;
import decode.p25.reference.Opcode;
public class DenyResponse extends TSBKMessage
{
public static final int ADDITIONAL_INFORMATION_FLAG = 80;
public static final int[] SERVICE_TYPE = { 82,83,84,85,86,87 };
public static final int[] REASON_CODE = { 88,89,90,91,92,93,94,95 };
/* Additional Info block not yet parsed */
public static final int[] TARGET_ADDRESS = { 120,121,122,123,124,125,126,
127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143 };
public DenyResponse( BitSetBuffer message,
DataUnitID duid,
AliasList aliasList )
{
super( message, duid, aliasList );
}
@Override
public String getEventType()
{
return Opcode.DENY_RESPONSE.getDescription();
}
public String getMessage()
{
StringBuilder sb = new StringBuilder();
sb.append( super.getMessage() );
sb.append( " TGT ADDR: " + getTargetAddress() );
sb.append( " REASON:" + getReason().name() );
return sb.toString();
}
public DenyReason getReason()
{
int code = mMessage.getInt( REASON_CODE );
return DenyReason.fromCode( code );
}
public boolean hasAdditionalInformation()
{
return mMessage.get( ADDITIONAL_INFORMATION_FLAG );
}
public String getServiceType()
{
return mMessage.getHex( SERVICE_TYPE, 2 );
}
public String getTargetAddress()
{
return mMessage.getHex( TARGET_ADDRESS, 6 );
}
@Override
public String getToID()
{
return getTargetAddress();
}
}

View File

@@ -0,0 +1,58 @@
package decode.p25.message.tsbk.osp.control;
import alias.AliasList;
import bits.BitSetBuffer;
import decode.p25.message.tsbk.TSBKMessage;
import decode.p25.reference.DataUnitID;
import decode.p25.reference.Opcode;
public class ExtendedFunctionCommand extends TSBKMessage
{
public static final int[] EXTENDED_FUNCTION = { 80,81,82,83,84,85,86,87,
88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,
108,109,110,111,112,113,114,115,116,117,118,119 };
public static final int[] TARGET_ADDRESS = { 120,121,122,123,124,125,126,
127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143 };
public ExtendedFunctionCommand( BitSetBuffer message,
DataUnitID duid,
AliasList aliasList )
{
super( message, duid, aliasList );
}
@Override
public String getEventType()
{
return Opcode.EXTENDED_FUNCTION_COMMAND.getDescription();
}
public String getMessage()
{
StringBuilder sb = new StringBuilder();
sb.append( super.getMessage() );
sb.append( " EXTENDED FUNCTION:" + getExtendedFunction() );
sb.append( " TGT ADDR: " + getTargetAddress() );
return sb.toString();
}
public String getExtendedFunction()
{
return mMessage.getHex( EXTENDED_FUNCTION, 10 );
}
public String getTargetAddress()
{
return mMessage.getHex( TARGET_ADDRESS, 6 );
}
@Override
public String getToID()
{
return getTargetAddress();
}
}

View File

@@ -0,0 +1,63 @@
package decode.p25.message.tsbk.osp.control;
import alias.AliasList;
import bits.BitSetBuffer;
import decode.p25.message.tsbk.TSBKMessage;
import decode.p25.reference.DataUnitID;
import decode.p25.reference.Opcode;
public class GroupAffiliationQuery extends TSBKMessage
{
public static final int[] SOURCE_ADDRESS = { 96,97,98,99,100,101,102,103,
104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119 };
public static final int[] TARGET_ADDRESS = { 120,121,122,123,124,125,126,
127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143 };
public GroupAffiliationQuery( BitSetBuffer message,
DataUnitID duid,
AliasList aliasList )
{
super( message, duid, aliasList );
}
@Override
public String getEventType()
{
return Opcode.GROUP_AFFILIATION_QUERY.getDescription();
}
public String getMessage()
{
StringBuilder sb = new StringBuilder();
sb.append( super.getMessage() );
sb.append( " SRC ADDR: " + getSourceAddress() );
sb.append( " TGT ADDR: " + getTargetAddress() );
return sb.toString();
}
public String getSourceAddress()
{
return mMessage.getHex( SOURCE_ADDRESS, 6 );
}
@Override
public String getFromID()
{
return getSourceAddress();
}
public String getTargetAddress()
{
return mMessage.getHex( TARGET_ADDRESS, 6 );
}
@Override
public String getToID()
{
return getTargetAddress();
}
}

View File

@@ -0,0 +1,87 @@
package decode.p25.message.tsbk.osp.control;
import alias.AliasList;
import bits.BitSetBuffer;
import decode.p25.message.tsbk.TSBKMessage;
import decode.p25.reference.DataUnitID;
import decode.p25.reference.Opcode;
public class GroupAffiliationResponse extends TSBKMessage
{
public enum AffiliationStatus { ACCEPT, FAIL, DENY, REFUSED };
public static final int LOCAL_GLOBAL_AFFILIATION_FLAG = 80;
public static final int[] GROUP_AFFILIATION_VALUE = { 86,87 };
public static final int[] ANNOUNCEMENT_GROUP_ADDRESS = { 88,89,90,91,
92,93,94,95,96,97,98,99,100,101,102,103 };
public static final int[] GROUP_ADDRESS = { 104,105,106,107,108,109,110,111,
112,113,114,115,116,117,118,119 };
public static final int[] TARGET_ADDRESS = { 120,121,122,123,124,125,126,
127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143 };
public GroupAffiliationResponse( BitSetBuffer message,
DataUnitID duid,
AliasList aliasList )
{
super( message, duid, aliasList );
}
@Override
public String getEventType()
{
return Opcode.GROUP_AFFILIATION_RESPONSE.getDescription();
}
public String getMessage()
{
StringBuilder sb = new StringBuilder();
sb.append( super.getMessage() );
sb.append( " STATUS:" + getStatus().name() );
sb.append( " ANNOUNCE GROUP:" + getAnnouncementGroupAddress() );
sb.append( " GRP ADDR:" + getGroupAddress() );
sb.append( " TGT ADDR: " + getTargetAddress() );
return sb.toString();
}
public String getAffiliation()
{
return mMessage.get( LOCAL_GLOBAL_AFFILIATION_FLAG) ? " GLOBAL" : " LOCAL";
}
public AffiliationStatus getStatus()
{
int status = mMessage.getInt( GROUP_AFFILIATION_VALUE );
return AffiliationStatus.values()[ status ];
}
public String getAnnouncementGroupAddress()
{
return mMessage.getHex( ANNOUNCEMENT_GROUP_ADDRESS, 4 );
}
public String getGroupAddress()
{
return mMessage.getHex( GROUP_ADDRESS, 4 );
}
@Override
public String getFromID()
{
return getGroupAddress();
}
public String getTargetAddress()
{
return mMessage.getHex( TARGET_ADDRESS, 6 );
}
@Override
public String getToID()
{
return getTargetAddress();
}
}

View File

@@ -0,0 +1,153 @@
package decode.p25.message.tsbk.osp.control;
import alias.AliasList;
import bits.BitSetBuffer;
import decode.p25.message.tsbk.TSBKMessage;
import decode.p25.reference.DataUnitID;
import decode.p25.reference.Opcode;
public class IdentifierUpdate extends TSBKMessage
{
public static final int[] CHANNEL_IDENTIFIER = { 80,81,82,83 };
public static final int[] CHANNEL_SPACING = { 102,103,104,105,106,107,108,
109,110,111 };
public static final int[] BANDWIDTH = { 84,85,86,87,88,89,90,91,92 };
public static final int[] BANDWIDTH_VHF_UHF = { 84,85,86,87 };
public static final int[] TRANSMIT_OFFSET = { 93,94,95,96,97,98,99,100,101 };
public static final int TRANSMIT_OFFSET_VHF_UHF_SIGN = 88;
public static final int[] TRANSMIT_OFFSET_VHF_UHF = { 89,90,91,92,93,94,
95,96,97,98,99,100,101 };
public static final int[] BASE_FREQUENCY = { 112,113,114,115,116,117,118,
119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,
137,138,139,140,141,142,143 };
public IdentifierUpdate( BitSetBuffer message,
DataUnitID duid,
AliasList aliasList )
{
super( message, duid, aliasList );
}
@Override
public String getEventType()
{
return Opcode.IDENTIFIER_UPDATE.getDescription();
}
public String getMessage()
{
StringBuilder sb = new StringBuilder();
sb.append( super.getMessage() );
sb.append( " CHAN:" + getIdentifier() );
sb.append( " DOWNLINK:" + getDownlinkFrequency() );
sb.append( " UPLINK:" + ( getUplinkFrequency() ) );
sb.append( " BW:" + getBandwidth() );
sb.append( " SPACING:" + getChannelSpacing() );
return sb.toString();
}
public int getIdentifier()
{
return mMessage.getInt( CHANNEL_IDENTIFIER );
}
/**
* Channel spacing in hertz
*/
public int getChannelSpacing()
{
return mMessage.getInt( CHANNEL_SPACING ) * 125; //Hertz
}
/**
* Base frequency in hertz
*/
public long getBaseFrequency()
{
return mMessage.getLong( BASE_FREQUENCY ) * 5l; //Hertz
}
public boolean isVHF_UHF()
{
long base = getBaseFrequency();
return ( ( 136000000 <= base && base <= 172000000 ) ||
( 380000000 <= base && base <= 512000000 ) );
}
/**
* Channel bandwidth in hertz
*/
public int getBandwidth()
{
int bandwidth = mMessage.getInt( BANDWIDTH );
if( isVHF_UHF() )
{
switch( bandwidth )
{
case 4:
return 6250;
case 5:
return 12500;
default:
return 0;
}
}
else
{
return bandwidth * 125;
}
}
/**
* Transmit offset in hertz
*/
public long getOffset()
{
if( isVHF_UHF() )
{
long offset = mMessage.getLong( TRANSMIT_OFFSET_VHF_UHF );
if( mMessage.get( TRANSMIT_OFFSET_VHF_UHF_SIGN ) )
{
return offset;
}
else
{
return -offset;
}
}
else
{
return mMessage.getLong( TRANSMIT_OFFSET ) * 250l;
}
}
/**
* Uplink ( radio to tower) frequency in hertz
*/
public long getUplinkFrequency()
{
return getBaseFrequency() - getOffset();
}
/**
* Downlink ( tower to radio ) frequency in hertz
*/
public long getDownlinkFrequency()
{
return getBaseFrequency();
}
}

View File

@@ -0,0 +1,70 @@
package decode.p25.message.tsbk.osp.control;
import alias.AliasList;
import bits.BitSetBuffer;
import decode.p25.message.tsbk.TSBKMessage;
import decode.p25.reference.DataUnitID;
import decode.p25.reference.Opcode;
public class MessageUpdate extends TSBKMessage
{
public static final int[] SHORT_DATA_MESSAGE = { 80,81,82,83,84,85,86,87,88,89,90,91,
92,93,94,95 };
public static final int[] TARGET_ADDRESS = { 96,97,98,99,100,101,102,103,
104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119 };
public static final int[] SOURCE_ADDRESS = { 120,121,122,123,124,125,126,
127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143 };
public MessageUpdate( BitSetBuffer message,
DataUnitID duid,
AliasList aliasList )
{
super( message, duid, aliasList );
}
@Override
public String getEventType()
{
return Opcode.MESSAGE_UPDATE.getDescription();
}
public String getMessage()
{
StringBuilder sb = new StringBuilder();
sb.append( super.getMessage() );
sb.append( " MSG:" + getShortDataMessage() );
sb.append( " SRC ADDR: " + getSourceAddress() );
sb.append( " TGT ADDR: " + getTargetAddress() );
return sb.toString();
}
public String getShortDataMessage()
{
return mMessage.getHex( SHORT_DATA_MESSAGE, 4 );
}
public String getSourceAddress()
{
return mMessage.getHex( SOURCE_ADDRESS, 6 );
}
@Override
public String getFromID()
{
return getSourceAddress();
}
public String getTargetAddress()
{
return mMessage.getHex( TARGET_ADDRESS, 6 );
}
@Override
public String getToID()
{
return getTargetAddress();
}
}

View File

@@ -0,0 +1,79 @@
package decode.p25.message.tsbk.osp.control;
import alias.AliasList;
import bits.BitSetBuffer;
import decode.p25.message.tsbk.TSBKMessage;
import decode.p25.reference.DataUnitID;
import decode.p25.reference.Opcode;
public class NetworkStatusBroadcast extends TSBKMessage
{
public static final int[] LOCATION_REGISTRATION_AREA = { 80,81,82,83,84,85,
86,87 };
public static final int[] WACN = { 88,89,90,91,92,93,94,95,96,97,98,99,100,
101,102,103,104,105,106,107 };
public static final int[] SYSTEM_ID = { 108,109,110,111,112,113,114,115,116,
117,118,119 };
public static final int[] CHANNEL = { 120,121,122,123,124,125,126,127,128,
129,130,131,132,133,134,135 };
public static final int[] SYSTEM_SERVICE_CLASS = { 136,137,138,139,140,141,
142,143 };
public NetworkStatusBroadcast( BitSetBuffer message,
DataUnitID duid,
AliasList aliasList )
{
super( message, duid, aliasList );
}
@Override
public String getEventType()
{
return Opcode.NETWORK_STATUS_BROADCAST.getDescription();
}
public String getMessage()
{
StringBuilder sb = new StringBuilder();
sb.append( super.getMessage() );
sb.append( " LRA:" + getLocationRegistrationArea() );
sb.append( " WACN:" + getWACN() );
sb.append( " SYS:" + getSystemID() );
sb.append( " CNTRL CHAN:" + getChannel() );
sb.append( " SYS SVC CLASS:" +
SystemService.toString( getSystemServiceClass() ) );
return sb.toString();
}
public String getLocationRegistrationArea()
{
return mMessage.getHex( LOCATION_REGISTRATION_AREA, 2 );
}
public String getWACN()
{
return mMessage.getHex( WACN, 5 );
}
public String getSystemID()
{
return mMessage.getHex( SYSTEM_ID, 3 );
}
public int getChannel()
{
return mMessage.getInt( CHANNEL );
}
public int getSystemServiceClass()
{
return mMessage.getInt( SYSTEM_SERVICE_CLASS );
}
}

View File

@@ -0,0 +1,65 @@
package decode.p25.message.tsbk.osp.control;
import alias.AliasList;
import bits.BitSetBuffer;
import decode.p25.message.tsbk.TSBKMessage;
import decode.p25.reference.DataUnitID;
import decode.p25.reference.Opcode;
public class ProtectionParameterUpdate extends TSBKMessage
{
public static final int[] ALGORITHM_ID = { 96,97,98,99,100,101,102,103 };
public static final int[] KEY_ID = { 104,105,106,107,108,109,110,111,112,
113,114,115,116,117,118,119 };
public static final int[] TARGET_ADDRESS = { 120,121,122,123,124,125,126,
127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143 };
public ProtectionParameterUpdate( BitSetBuffer message,
DataUnitID duid,
AliasList aliasList )
{
super( message, duid, aliasList );
}
@Override
public String getEventType()
{
return Opcode.PROTECTION_PARAMETER_UPDATE.getDescription();
}
public String getMessage()
{
StringBuilder sb = new StringBuilder();
sb.append( super.getMessage() );
sb.append( " TGT ADDR: " + getTargetAddress() );
sb.append( " ALGORITHM:" + getAlgorithmID() );
sb.append( " KEY:" + getKeyID() );
return sb.toString();
}
public String getAlgorithmID()
{
return mMessage.getHex( ALGORITHM_ID, 2 );
}
public String getKeyID()
{
return mMessage.getHex( KEY_ID, 4 );
}
public String getTargetAddress()
{
return mMessage.getHex( TARGET_ADDRESS, 6 );
}
@Override
public String getToID()
{
return getTargetAddress();
}
}

View File

@@ -0,0 +1,74 @@
package decode.p25.message.tsbk.osp.control;
import alias.AliasList;
import bits.BitSetBuffer;
import decode.p25.message.tsbk.TSBKMessage;
import decode.p25.reference.DataUnitID;
import decode.p25.reference.Opcode;
import decode.p25.reference.QueuedResponseReason;
public class QueuedResponse extends TSBKMessage
{
public static final int ADDITIONAL_INFORMATION_FLAG = 80;
public static final int[] SERVICE_TYPE = { 82,83,84,85,86,87 };
public static final int[] REASON_CODE = { 88,89,90,91,92,93,94,95 };
/* Additional Info block not yet parsed */
public static final int[] TARGET_ADDRESS = { 120,121,122,123,124,125,126,
127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143 };
public QueuedResponse( BitSetBuffer message,
DataUnitID duid,
AliasList aliasList )
{
super( message, duid, aliasList );
}
@Override
public String getEventType()
{
return Opcode.QUEUED_RESPONSE.getDescription();
}
public String getMessage()
{
StringBuilder sb = new StringBuilder();
sb.append( super.getMessage() );
sb.append( " TGT ADDR: " + getTargetAddress() );
sb.append( " REASON:" + getReason().name() );
return sb.toString();
}
public QueuedResponseReason getReason()
{
int code = mMessage.getInt( REASON_CODE );
return QueuedResponseReason.fromCode( code );
}
public boolean hasAdditionalInformation()
{
return mMessage.get( ADDITIONAL_INFORMATION_FLAG );
}
public String getServiceType()
{
return mMessage.getHex( SERVICE_TYPE, 2 );
}
public String getTargetAddress()
{
return mMessage.getHex( TARGET_ADDRESS, 6 );
}
@Override
public String getToID()
{
return getTargetAddress();
}
}

View File

@@ -0,0 +1,85 @@
package decode.p25.message.tsbk.osp.control;
public class SystemService
{
public static boolean isCompositeControlChannel( int service )
{
return ( service & 0x01 ) == 0x01;
}
public static boolean isUpdateControlChannelOnly( int service )
{
return ( service & 0x02 ) == 0x02;
}
public static boolean isBackupControlChannelOnly( int service )
{
return ( service & 0x04 ) == 0x04;
}
public static boolean providesDataServiceRequests( int service )
{
return ( service & 0x10 ) == 0x10;
}
public static boolean providesVoiceServiceRequests( int service )
{
return ( service & 0x20 ) == 0x20;
}
public static boolean providesRegistrationServices( int service )
{
return ( service & 0x40 ) == 0x40;
}
public static boolean providesAuthenticationServices( int service )
{
return ( service & 0x80 ) == 0x80;
}
public static String toString( int service )
{
StringBuilder sb = new StringBuilder();
sb.append( "CONTROL CHAN:" );
if( isCompositeControlChannel( service ) )
{
sb.append( " COMPOSITE" );
}
if( isUpdateControlChannelOnly( service ) )
{
sb.append( " UPDATE" );
}
if( isBackupControlChannelOnly( service ) )
{
sb.append( " BACKUP" );
}
sb.append( " SERVICES:" );
if( providesAuthenticationServices( service ) )
{
sb.append( " AUTHENTICATION" );
}
if( providesDataServiceRequests( service ) )
{
sb.append( " DATA" );
}
if( providesRegistrationServices( service ) )
{
sb.append( " REGISTRATION" );
}
if( providesVoiceServiceRequests( service ) )
{
sb.append( " VOICE" );
}
return sb.toString();
}
}

View File

@@ -1,7 +1,8 @@
package decode.p25.message.tsbk;
package decode.p25.message.tsbk.osp.data;
import alias.AliasList;
import bits.BitSetBuffer;
import decode.p25.message.tsbk.GroupMultiChannelGrant;
import decode.p25.reference.DataUnitID;
import decode.p25.reference.Opcode;

View File

@@ -1,7 +1,8 @@
package decode.p25.message.tsbk;
package decode.p25.message.tsbk.osp.data;
import alias.AliasList;
import bits.BitSetBuffer;
import decode.p25.message.tsbk.GroupChannelGrantExplicit;
import decode.p25.reference.DataUnitID;
import decode.p25.reference.Opcode;

View File

@@ -1,7 +1,8 @@
package decode.p25.message.tsbk;
package decode.p25.message.tsbk.osp.data;
import alias.AliasList;
import bits.BitSetBuffer;
import decode.p25.message.tsbk.GroupChannelGrant;
import decode.p25.reference.DataUnitID;
import decode.p25.reference.Opcode;

View File

@@ -1,7 +1,8 @@
package decode.p25.message.tsbk;
package decode.p25.message.tsbk.osp.data;
import alias.AliasList;
import bits.BitSetBuffer;
import decode.p25.message.tsbk.UnitChannelGrant;
import decode.p25.reference.DataUnitID;
import decode.p25.reference.Opcode;

View File

@@ -1,8 +1,9 @@
package decode.p25.message.tsbk;
package decode.p25.message.tsbk.osp.voice;
import alias.Alias;
import alias.AliasList;
import bits.BitSetBuffer;
import decode.p25.message.tsbk.GroupChannelGrant;
import decode.p25.reference.DataUnitID;
import decode.p25.reference.Opcode;

View File

@@ -1,7 +1,8 @@
package decode.p25.message.tsbk;
package decode.p25.message.tsbk.osp.voice;
import alias.AliasList;
import bits.BitSetBuffer;
import decode.p25.message.tsbk.GroupMultiChannelGrant;
import decode.p25.reference.DataUnitID;
import decode.p25.reference.Opcode;

View File

@@ -1,7 +1,8 @@
package decode.p25.message.tsbk;
package decode.p25.message.tsbk.osp.voice;
import alias.AliasList;
import bits.BitSetBuffer;
import decode.p25.message.tsbk.GroupChannelGrantExplicit;
import decode.p25.reference.DataUnitID;
import decode.p25.reference.Opcode;

View File

@@ -1,4 +1,4 @@
package decode.p25.message.tsbk;
package decode.p25.message.tsbk.osp.voice;
import java.util.ArrayList;
import java.util.List;
@@ -6,6 +6,7 @@ import java.util.List;
import alias.Alias;
import alias.AliasList;
import bits.BitSetBuffer;
import decode.p25.message.tsbk.TSBKMessage;
import decode.p25.reference.DataUnitID;
import decode.p25.reference.Digit;
import decode.p25.reference.Opcode;
@@ -82,15 +83,4 @@ public class TelephoneInterconnectAnswerRequest extends TSBKMessage
{
return getTargetAddress();
}
@Override
public Alias getToIDAlias()
{
if( mAliasList != null )
{
return mAliasList.getTalkgroupAlias( getToID() );
}
return null;
}
}

View File

@@ -1,7 +1,8 @@
package decode.p25.message.tsbk;
package decode.p25.message.tsbk.osp.voice;
import alias.AliasList;
import bits.BitSetBuffer;
import decode.p25.message.tsbk.UnitChannelGrant;
import decode.p25.reference.DataUnitID;
import decode.p25.reference.Opcode;

View File

@@ -1,4 +1,4 @@
package decode.p25.message.tsbk;
package decode.p25.message.tsbk.osp.voice;
import alias.AliasList;
import bits.BitSetBuffer;

View File

@@ -1,7 +1,8 @@
package decode.p25.message.tsbk;
package decode.p25.message.tsbk.osp.voice;
import alias.AliasList;
import bits.BitSetBuffer;
import decode.p25.message.tsbk.UnitChannelGrant;
import decode.p25.reference.DataUnitID;
import decode.p25.reference.Opcode;

View File

@@ -1,7 +1,8 @@
package decode.p25.message.tsbk;
package decode.p25.message.tsbk.osp.voice;
import alias.AliasList;
import bits.BitSetBuffer;
import decode.p25.message.tsbk.UnitChannelGrant;
import decode.p25.reference.DataUnitID;
import decode.p25.reference.Opcode;

View File

@@ -1,7 +1,8 @@
package decode.p25.message.tsbk;
package decode.p25.message.tsbk.osp.voice;
import alias.AliasList;
import bits.BitSetBuffer;
import decode.p25.message.tsbk.UnitChannelGrant;
import decode.p25.reference.DataUnitID;
import decode.p25.reference.Opcode;

View File

@@ -0,0 +1,125 @@
package decode.p25.reference;
public enum DenyReason
{
RESERVED( 0x00 ),
REQUESTING_UNIT_NOT_VALID( 0x10 ),
REQUESTING_UNIT_NOT_AUTHORIZED_FOR_SERVICE( 0x11 ),
TARGET_UNIT_NOT_VALID( 0x20 ),
TARGET_UNIT_NOT_AUTHORIZED_FOR_SERVICE( 0x21 ),
TARGET_UNIT_REFUSED_CALL( 0x2F ),
TARGET_GROUP_NOT_VALID( 0x30 ),
TARGET_GROUP_NOT_AUTHORIZED_FOR_SERVICE( 0x31 ),
INVALID_DIALING( 0x40 ),
TELEPHONE_NUMBER_NOT_AUTHORIZED( 0x41 ),
PSTN_NOT_VALID( 0x42 ),
CALL_TIMEOUT( 0x50 ),
LANDLINE_TERMINATED_CALL( 0x51 ),
SUBSCRIBER_UNIT_TERMINATED_CALL( 0x52 ),
CALL_PREEMPTED( 0x5F ),
SITE_ACCESS_DENIAL( 0x60 ),
USER_OR_SYSTEM_DEFINED( 0x61 ),
CALL_OPTIONS_NOT_VALID_FOR_SERVICE( 0xF0 ),
PROTECTION_SERVICE_OPTION_NOT_VALID( 0xF1 ),
DUPLEX_SERVICE_OPTION_NOT_VALID( 0xF2 ),
CIRCUIT_OR_PACKET_MODE_OPTION_NOT_VALID( 0xF3 ),
SYSTEM_DOES_NOT_SUPPORT_SERVICE( 0xFF ),
UNKNOWN( -1 );
private int mCode;
private DenyReason( int code )
{
mCode = code;
}
public static DenyReason fromCode( int code )
{
if( code == 0x10 )
{
return DenyReason.REQUESTING_UNIT_NOT_VALID;
}
else if( code == 0x11 )
{
return REQUESTING_UNIT_NOT_AUTHORIZED_FOR_SERVICE;
}
else if( code == 0x20 )
{
return DenyReason.TARGET_UNIT_NOT_VALID;
}
else if( code == 0x21 )
{
return TARGET_UNIT_NOT_AUTHORIZED_FOR_SERVICE;
}
else if( code == 0x2F )
{
return DenyReason.TARGET_UNIT_REFUSED_CALL;
}
else if( code == 0x30 )
{
return TARGET_GROUP_NOT_VALID;
}
else if( code == 0x31 )
{
return DenyReason.TARGET_GROUP_NOT_AUTHORIZED_FOR_SERVICE;
}
else if( code == 0x40 )
{
return DenyReason.INVALID_DIALING;
}
else if( code == 0x41 )
{
return DenyReason.TELEPHONE_NUMBER_NOT_AUTHORIZED;
}
else if( code == 0x42 )
{
return DenyReason.PSTN_NOT_VALID;
}
else if( code == 0x50 )
{
return CALL_TIMEOUT;
}
else if( code == 0x51 )
{
return LANDLINE_TERMINATED_CALL;
}
else if( code == 0x52 )
{
return SUBSCRIBER_UNIT_TERMINATED_CALL;
}
else if( code == 0x5F )
{
return DenyReason.CALL_PREEMPTED;
}
else if( code == 0x60 )
{
return SITE_ACCESS_DENIAL;
}
else if( code == 0xF0 )
{
return CALL_OPTIONS_NOT_VALID_FOR_SERVICE;
}
else if( code == 0xF1 )
{
return PROTECTION_SERVICE_OPTION_NOT_VALID;
}
else if( code == 0xF2 )
{
return DenyReason.DUPLEX_SERVICE_OPTION_NOT_VALID;
}
else if( code == 0xF3 )
{
return CIRCUIT_OR_PACKET_MODE_OPTION_NOT_VALID;
}
else if( code <= 0x5E )
{
return DenyReason.RESERVED;
}
else if( code >= 0x61 )
{
return DenyReason.USER_OR_SYSTEM_DEFINED;
}
return UNKNOWN;
}
}

View File

@@ -63,7 +63,7 @@ public enum Opcode
RFSS_STATUS_BROADCAST( "RFSS Status Broadcast", 58 ),
NETWORK_STATUS_BROADCAST( "Network Status Broadcast", 59 ),
ADJACENT_STATUS_BROADCAST( "Adjacent Status Broadcast", 60 ),
IDENTIFIER_UPDATE_NON_VHF_UHF( "Identifier Update for non-VHF/UHF Bands", 61 ),
IDENTIFIER_UPDATE( "Identifier Update", 61 ),
PROTECTION_PARAMETER_BROADCAST( "Protection Parameter Broadcast", 62 ),
PROTECTION_PARAMETER_UPDATE( "Protection Parameter Update", 63 ),
UNKNOWN( "Unknown", -1 );

View File

@@ -0,0 +1,69 @@
package decode.p25.reference;
public enum QueuedResponseReason
{
RESERVED( 0x00 ),
REQUESTING_UNIT_BUSY_OTHER_SERVICE( 0x10 ),
TARGET_UNIT_BUSY_OTHER_SERVICE( 0x20 ),
TARGET_UNIT_QUEUED_THIS_CALL( 0x2F ),
TARGET_GROUP_CURRENTLY_ACTIVE( 0x30 ),
CHANNEL_RESOURCES_UNAVAILABLE( 0x40 ),
TELEPHONE_RESOURCES_UNAVAILABLE( 0x41 ),
DATA_RESOURCES_UNAVAILABLE( 0x42 ),
SUPERSEDING_SERVICE_CURRENTLY_ACTIVE( 0x50 ),
USER_OR_SYSTEM_DEFINED( 0x80 ),
UNKNOWN( -1 );
private int mCode;
private QueuedResponseReason( int code )
{
mCode = code;
}
public static QueuedResponseReason fromCode( int code )
{
if( code == 0x10 )
{
return QueuedResponseReason.REQUESTING_UNIT_BUSY_OTHER_SERVICE;
}
else if( code == 0x20 )
{
return QueuedResponseReason.TARGET_UNIT_BUSY_OTHER_SERVICE;
}
else if( code == 0x2F )
{
return QueuedResponseReason.TARGET_UNIT_QUEUED_THIS_CALL;
}
else if( code == 0x30 )
{
return QueuedResponseReason.TARGET_GROUP_CURRENTLY_ACTIVE;
}
else if( code == 0x40 )
{
return QueuedResponseReason.CHANNEL_RESOURCES_UNAVAILABLE;
}
else if( code == 0x41 )
{
return QueuedResponseReason.TELEPHONE_RESOURCES_UNAVAILABLE;
}
else if( code == 0x42 )
{
return QueuedResponseReason.DATA_RESOURCES_UNAVAILABLE;
}
else if( code == 0x50 )
{
return QueuedResponseReason.SUPERSEDING_SERVICE_CURRENTLY_ACTIVE;
}
else if( code <= 0x7F )
{
return QueuedResponseReason.RESERVED;
}
else if( code >= 0x80 )
{
return QueuedResponseReason.USER_OR_SYSTEM_DEFINED;
}
return UNKNOWN;
}
}