Initial commit of redesigned internal processing and audio management.

Note: Several of the decoders are currently non-functioning in this
commit.  If you want the latest functioning codebase, please checkout
the commit prior to this one.  All decoders will eventually be updated
with this new architecture.

Currently broken:
- Logging and recording
- Aux decoders (Fleetsync/MDC/LoJack/Tait)
- LTR/Passport decoders

Changes in this commit:
- Module architecture for decoders and components with central
provisioning by the DecoderFactory
- Transition from Complex sample stream processing to float buffer
processing for improved memory management
- Redesigned filter structures - to support buffers and streams
- Resolved several memory leak issues
- Universal sharing of the thread pool manager
- Added centralized audio management with call/user prioritization and
new gui with mute/volume controls
- Embedded audio metadata for eventual streaming support
- Redesigned ProcessingChain to support independent re-use
- Added new TrafficChannelManager to handle traffic channel allocations
- Traffic Channel pool size and Call timeout available in P25 and
MPT1327 configs
- Redesigned channel and decoder gui components
This commit is contained in:
denny
2015-09-01 07:10:26 -04:00
parent 538a299246
commit f4d8ea281d
570 changed files with 21578 additions and 17012 deletions

View File

@@ -0,0 +1,121 @@
package module.decode.p25.message.tsbk.osp.control;
import module.decode.p25.message.tsbk.TSBKMessage;
import module.decode.p25.reference.DataUnitID;
import module.decode.p25.reference.Opcode;
import alias.AliasList;
import bits.BinaryMessage;
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( BinaryMessage message,
DataUnitID duid,
AliasList aliasList )
{
super( message, duid, aliasList );
}
@Override
public String getEventType()
{
return Opcode.ACKNOWLEDGE_RESPONSE.getDescription();
}
public String getMessage()
{
StringBuilder sb = new StringBuilder();
sb.append( getMessageStub() );
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,180 @@
package module.decode.p25.message.tsbk.osp.control;
import module.decode.p25.message.IBandIdentifier;
import module.decode.p25.message.IdentifierReceiver;
import module.decode.p25.message.tsbk.TSBKMessage;
import module.decode.p25.reference.DataUnitID;
import module.decode.p25.reference.Opcode;
import alias.AliasList;
import bits.BinaryMessage;
public class AdjacentStatusBroadcast extends TSBKMessage implements IdentifierReceiver
{
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[] IDENTIFIER = { 120,121,122,123 };
public static final int[] CHANNEL = { 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 };
private IBandIdentifier mIdentifierUpdate;
public AdjacentStatusBroadcast( BinaryMessage 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( getMessageStub() );
sb.append( " LRA:" + getLocationRegistrationArea() );
sb.append( " SYS:" + getSystemID() );
sb.append( " SITE:" + getRFSS() + "-" + getSiteID() );
sb.append( " CHAN:" + getIdentifier() + "-" + getChannel() );
sb.append( " DN:" + getDownlinkFrequency() );
sb.append( " UP:" + getUplinkFrequency() );
if( isConventionalChannel() )
{
sb.append( " CONVENTIONAL" );
}
if( isSiteFailureCondition() )
{
sb.append( " FAILURE-CONDITION" );
}
if( isValidSiteInformation() )
{
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 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 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 getIdentifier()
{
return mMessage.getInt( IDENTIFIER );
}
public int getSystemServiceClass()
{
return mMessage.getInt( SYSTEM_SERVICE_CLASS );
}
public long getDownlinkFrequency()
{
return calculateDownlink( mIdentifierUpdate, getChannel() );
}
public long getUplinkFrequency()
{
return calculateUplink( mIdentifierUpdate, getChannel() );
}
@Override
public void setIdentifierMessage( int identifier, IBandIdentifier message )
{
/* we're only expecting 1 identifier, so use whatever is received */
mIdentifierUpdate = message;
}
public int[] getIdentifiers()
{
int[] idens = new int[ 1 ];
idens[ 0 ] = getIdentifier();
return idens;
}
}

View File

@@ -0,0 +1,77 @@
package module.decode.p25.message.tsbk.osp.control;
import module.decode.p25.message.tsbk.TSBKMessage;
import module.decode.p25.reference.DataUnitID;
import module.decode.p25.reference.Opcode;
import alias.AliasList;
import bits.BinaryMessage;
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( BinaryMessage 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( getMessageStub() );
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 );
}
public String getFullTargetID()
{
StringBuilder sb = new StringBuilder();
sb.append( getWACN() );
sb.append( "-" );
sb.append( getSystemID() );
sb.append( "-" );
sb.append( getTargetID() );
return sb.toString();
}
@Override
public String getToID()
{
return getTargetID();
}
}

View File

@@ -0,0 +1,62 @@
package module.decode.p25.message.tsbk.osp.control;
import module.decode.p25.message.tsbk.TSBKMessage;
import module.decode.p25.reference.DataUnitID;
import module.decode.p25.reference.Opcode;
import alias.AliasList;
import bits.BinaryMessage;
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( BinaryMessage 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( getMessageStub() );
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,95 @@
package module.decode.p25.message.tsbk.osp.control;
import module.decode.p25.message.tsbk.TSBKMessage;
import module.decode.p25.reference.DataUnitID;
import module.decode.p25.reference.DenyReason;
import module.decode.p25.reference.Opcode;
import alias.AliasList;
import bits.BinaryMessage;
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 };
public static final int[] CALL_OPTIONS = { 96,97,98,99,100,101,102,103 };
public static final int[] SOURCE_GROUP = { 104,105,106,107,108,109,110,111 };
public static final int[] SOURCE_ADDRESS = { 96,97,98,99,100,101,102,103,104,
105,106,107,108,109,110,111 };
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( BinaryMessage 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( getMessageStub() );
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 Opcode getServiceType()
{
return Opcode.fromValue( mMessage.getInt( SERVICE_TYPE ) );
}
public String getSourceAddress()
{
switch( getServiceType() )
{
case GROUP_DATA_CHANNEL_GRANT:
case GROUP_VOICE_CHANNEL_GRANT:
return mMessage.getHex( SOURCE_GROUP, 4 );
case UNIT_TO_UNIT_VOICE_CHANNEL_GRANT:
case INDIVIDUAL_DATA_CHANNEL_GRANT:
case TELEPHONE_INTERCONNECT_VOICE_CHANNEL_GRANT:
return mMessage.getHex( SOURCE_ADDRESS, 6 );
default:
break;
}
return null;
}
public String getTargetAddress()
{
return mMessage.getHex( TARGET_ADDRESS, 6 );
}
@Override
public String getToID()
{
return getTargetAddress();
}
}

View File

@@ -0,0 +1,87 @@
package module.decode.p25.message.tsbk.osp.control;
import module.decode.p25.message.tsbk.TSBKMessage;
import module.decode.p25.reference.DataUnitID;
import module.decode.p25.reference.ExtendedFunction;
import module.decode.p25.reference.Opcode;
import alias.AliasList;
import bits.BinaryMessage;
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 };
public static final int[] ARGUMENT = { 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( BinaryMessage 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( getMessageStub() );
sb.append( " EXTENDED FUNCTION:" + getExtendedFunction().getLabel() );
sb.append( " ARGUMENT: " + getTargetAddress() );
sb.append( " TGT ADDR: " + getTargetAddress() );
return sb.toString();
}
public ExtendedFunction getExtendedFunction()
{
return ExtendedFunction.fromValue( mMessage.getInt( EXTENDED_FUNCTION ) );
}
public String getArgument()
{
return mMessage.getHex( ARGUMENT, 6 );
}
public String getSourceAddress()
{
switch( getExtendedFunction() )
{
case RADIO_CHECK:
case RADIO_CHECK_ACK:
case RADIO_DETACH:
case RADIO_DETACH_ACK:
case RADIO_INHIBIT:
case RADIO_INHIBIT_ACK:
case RADIO_UNINHIBIT:
case RADIO_UNINHIBIT_ACK:
return getArgument();
default:
break;
}
return null;
}
public String getTargetAddress()
{
return mMessage.getHex( TARGET_ADDRESS, 6 );
}
@Override
public String getToID()
{
return getTargetAddress();
}
}

View File

@@ -0,0 +1,63 @@
package module.decode.p25.message.tsbk.osp.control;
import module.decode.p25.message.tsbk.TSBKMessage;
import module.decode.p25.reference.DataUnitID;
import module.decode.p25.reference.Opcode;
import alias.AliasList;
import bits.BinaryMessage;
public class GroupAffiliationQuery 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_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( BinaryMessage 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( getMessageStub() );
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,86 @@
package module.decode.p25.message.tsbk.osp.control;
import module.decode.p25.message.tsbk.TSBKMessage;
import module.decode.p25.reference.DataUnitID;
import module.decode.p25.reference.Opcode;
import module.decode.p25.reference.Response;
import alias.AliasList;
import bits.BinaryMessage;
public class GroupAffiliationResponse extends TSBKMessage
{
public static final int LOCAL_GLOBAL_AFFILIATION_FLAG = 80;
public static final int[] AFFILIATION_RESPONSE = { 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( BinaryMessage 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( getMessageStub() );
sb.append( " AFFILIATION:" + getResponse().name() );
sb.append( " ANNOUNCE GROUP:" + getAnnouncementGroupAddress() );
sb.append( " GRP ADDR:" + getGroupAddress() );
sb.append( " TGT ADDR: " + getTargetAddress() );
return sb.toString();
}
public String getAffiliationScope()
{
return mMessage.get( LOCAL_GLOBAL_AFFILIATION_FLAG) ? " GLOBAL" : " LOCAL";
}
public Response getResponse()
{
int response = mMessage.getInt( AFFILIATION_RESPONSE );
return Response.fromValue( response );
}
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,48 @@
package module.decode.p25.message.tsbk.osp.control;
import module.decode.p25.message.IBandIdentifier;
import module.decode.p25.message.tsbk.TSBKMessage;
import module.decode.p25.reference.DataUnitID;
import alias.AliasList;
import bits.BinaryMessage;
public abstract class IdentifierUpdate extends TSBKMessage
implements IBandIdentifier
{
public static final int[] 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[] 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( BinaryMessage message,
DataUnitID duid,
AliasList aliasList )
{
super( message, duid, aliasList );
}
@Override
public int getIdentifier()
{
return mMessage.getInt( IDENTIFIER );
}
@Override
public long getChannelSpacing()
{
return mMessage.getLong( CHANNEL_SPACING ) * 125l;
}
@Override
public long getBaseFrequency()
{
return mMessage.getLong( BASE_FREQUENCY ) * 5l;
}
@Override
public abstract long getTransmitOffset();
}

View File

@@ -0,0 +1,73 @@
package module.decode.p25.message.tsbk.osp.control;
import module.decode.p25.reference.DataUnitID;
import module.decode.p25.reference.Opcode;
import alias.AliasList;
import bits.BinaryMessage;
public class IdentifierUpdateNonVUHF extends IdentifierUpdate
{
public static final int[] BANDWIDTH = { 84,85,86,87,88,89,90,91,92 };
public static final int TRANSMIT_OFFSET_VHF_UHF_SIGN = 93;
public static final int[] TRANSMIT_OFFSET = { 94,95,96,97,98,99,100,101 };
public IdentifierUpdateNonVUHF( BinaryMessage message,
DataUnitID duid,
AliasList aliasList )
{
super( message, duid, aliasList );
}
@Override
public String getEventType()
{
return Opcode.IDENTIFIER_UPDATE_NON_VUHF.getDescription();
}
public String getMessage()
{
StringBuilder sb = new StringBuilder();
sb.append( getMessageStub() );
sb.append( " IDEN:" + getIdentifier() );
sb.append( " BASE:" + getBaseFrequency() );
sb.append( " BW:" + getBandwidth() );
sb.append( " SPACING:" + getChannelSpacing() );
sb.append( " OFFSET:" + getTransmitOffset() );
return sb.toString();
}
/**
* Channel bandwidth in hertz
*/
public int getBandwidth()
{
return mMessage.getInt( BANDWIDTH ) * 125;
}
/**
* Transmit offset in hertz
*/
@Override
public long getTransmitOffset()
{
long offset = mMessage.getLong( TRANSMIT_OFFSET ) * 250000l;
if( mMessage.get( TRANSMIT_OFFSET_VHF_UHF_SIGN ) )
{
return offset;
}
else
{
return -offset;
}
}
}

View File

@@ -0,0 +1,85 @@
package module.decode.p25.message.tsbk.osp.control;
import module.decode.p25.reference.DataUnitID;
import module.decode.p25.reference.Opcode;
import alias.AliasList;
import bits.BinaryMessage;
public class IdentifierUpdateVUHF extends IdentifierUpdate
{
public static final int[] BANDWIDTH = { 84,85,86,87 };
public static final int TRANSMIT_OFFSET_VHF_UHF_SIGN = 88;
public static final int[] TRANSMIT_OFFSET = { 89,90,91,92,93,94,95,96,97,98,
99,100,101 };
public IdentifierUpdateVUHF( BinaryMessage message,
DataUnitID duid,
AliasList aliasList )
{
super( message, duid, aliasList );
}
@Override
public String getEventType()
{
return Opcode.IDENTIFIER_UPDATE_VHF_UHF_BANDS.getDescription();
}
public String getMessage()
{
StringBuilder sb = new StringBuilder();
sb.append( getMessageStub() );
sb.append( " IDEN:" + getIdentifier() );
sb.append( " BASE:" + getBaseFrequency() );
sb.append( " BW:" + getBandwidth() );
sb.append( " SPACING:" + getChannelSpacing() );
sb.append( " OFFSET:" + getTransmitOffset() );
return sb.toString();
}
/**
* Channel bandwidth in hertz
*/
public int getBandwidth()
{
int bandwidth = mMessage.getInt( BANDWIDTH );
switch( bandwidth )
{
case 4:
return 6250;
case 5:
return 12500;
default:
return 0;
}
}
/**
* Transmit offset in hertz
*/
@Override
public long getTransmitOffset()
{
long offset = mMessage.getLong( TRANSMIT_OFFSET ) *
getChannelSpacing();
if( mMessage.get( TRANSMIT_OFFSET_VHF_UHF_SIGN ) )
{
return offset;
}
else
{
return -offset;
}
}
}

View File

@@ -0,0 +1,78 @@
package module.decode.p25.message.tsbk.osp.control;
import module.decode.p25.message.tsbk.TSBKMessage;
import module.decode.p25.reference.DataUnitID;
import module.decode.p25.reference.Opcode;
import module.decode.p25.reference.Response;
import alias.AliasList;
import bits.BinaryMessage;
public class LocationRegistrationResponse extends TSBKMessage
{
public static final int[] REGISTRATION_RESPONSE = { 86,87 };
public static final int[] GROUP_ADDRESS = { 88,89,90,91,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[] 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 LocationRegistrationResponse( BinaryMessage message,
DataUnitID duid,
AliasList aliasList )
{
super( message, duid, aliasList );
}
@Override
public String getEventType()
{
return Opcode.LOCATION_REGISTRATION_RESPONSE.getDescription();
}
public String getMessage()
{
StringBuilder sb = new StringBuilder();
sb.append( getMessageStub() );
sb.append( " REGISTRATION:" + getResponse().name() );
sb.append( " GROUP:" + getGroupAddress() );
sb.append( " RFSS: " + getRFSSID() );
sb.append( " SITE: " + getSiteID() );
sb.append( " TGT ADDR: " + getTargetAddress() );
return sb.toString();
}
public Response getResponse()
{
return Response.fromValue( mMessage.getInt( REGISTRATION_RESPONSE ) );
}
public String getGroupAddress()
{
return mMessage.getHex( GROUP_ADDRESS, 4 );
}
public String getRFSSID()
{
return mMessage.getHex( RFSS_ID, 2 );
}
public String getSiteID()
{
return mMessage.getHex( SITE_ID, 2 );
}
public String getTargetAddress()
{
return mMessage.getHex( TARGET_ADDRESS, 6 );
}
@Override
public String getToID()
{
return getTargetAddress();
}
}

View File

@@ -0,0 +1,70 @@
package module.decode.p25.message.tsbk.osp.control;
import module.decode.p25.message.tsbk.TSBKMessage;
import module.decode.p25.reference.DataUnitID;
import module.decode.p25.reference.Opcode;
import alias.AliasList;
import bits.BinaryMessage;
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( BinaryMessage 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( getMessageStub() );
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,126 @@
package module.decode.p25.message.tsbk.osp.control;
import module.decode.p25.message.IBandIdentifier;
import module.decode.p25.message.IdentifierReceiver;
import module.decode.p25.message.tsbk.TSBKMessage;
import module.decode.p25.reference.DataUnitID;
import module.decode.p25.reference.Opcode;
import module.decode.p25.reference.P25NetworkCallsign;
import alias.AliasList;
import bits.BinaryMessage;
public class NetworkStatusBroadcast extends TSBKMessage implements IdentifierReceiver
{
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[] IDENTIFIER = { 120,121,122,123 };
public static final int[] CHANNEL = { 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 };
private IBandIdentifier mIdentifierUpdate;
public NetworkStatusBroadcast( BinaryMessage 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( getMessageStub() );
sb.append( " LRA:" + getLocationRegistrationArea() );
sb.append( " WACN:" + getWACN() );
sb.append( " SYS:" + getSystemID() );
sb.append( " CTRL CHAN:" + getIdentifier() + "-" + getChannel() );
sb.append( " DN:" + getDownlinkFrequency() );
sb.append( " UP:" + getUplinkFrequency() );
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 String getNetworkCallsign()
{
return P25NetworkCallsign.getCallsign( mMessage.getInt( WACN ),
mMessage.getInt( SYSTEM_ID ) );
}
public int getIdentifier()
{
return mMessage.getInt( IDENTIFIER );
}
public int getChannel()
{
return mMessage.getInt( CHANNEL );
}
public int getSystemServiceClass()
{
return mMessage.getInt( SYSTEM_SERVICE_CLASS );
}
public long getDownlinkFrequency()
{
return calculateDownlink( mIdentifierUpdate, getChannel() );
}
public long getUplinkFrequency()
{
return calculateUplink( mIdentifierUpdate, getChannel() );
}
@Override
public void setIdentifierMessage( int identifier, IBandIdentifier message )
{
/* we're only expecting 1 identifier, so use whatever is received */
mIdentifierUpdate = message;
}
public int[] getIdentifiers()
{
int[] idens = new int[ 1 ];
idens[ 0 ] = getIdentifier();
return idens;
}
}

View File

@@ -0,0 +1,66 @@
package module.decode.p25.message.tsbk.osp.control;
import module.decode.p25.message.tsbk.TSBKMessage;
import module.decode.p25.reference.DataUnitID;
import module.decode.p25.reference.Encryption;
import module.decode.p25.reference.Opcode;
import alias.AliasList;
import bits.BinaryMessage;
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( BinaryMessage 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( getMessageStub() );
sb.append( " TGT ADDR: " + getTargetAddress() );
sb.append( " ENCRYPTION ALGORITHM:" + getAlgorithm().name() );
sb.append( " KEY:" + getKeyID() );
return sb.toString();
}
public Encryption getAlgorithm()
{
return Encryption.fromValue( mMessage.getInt( ALGORITHM_ID ) );
}
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,96 @@
package module.decode.p25.message.tsbk.osp.control;
import module.decode.p25.message.tsbk.TSBKMessage;
import module.decode.p25.reference.DataUnitID;
import module.decode.p25.reference.Opcode;
import module.decode.p25.reference.QueuedResponseReason;
import alias.AliasList;
import bits.BinaryMessage;
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 };
public static final int[] CALL_OPTIONS = { 96,97,98,99,100,101,102,103 };
public static final int[] SOURCE_GROUP = { 104,105,106,107,108,109,110,111 };
public static final int[] SOURCE_ADDRESS = { 96,97,98,99,100,101,102,103,104,
105,106,107,108,109,110,111 };
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( BinaryMessage 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( getMessageStub() );
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 Opcode getServiceType()
{
return Opcode.fromValue( mMessage.getInt( SERVICE_TYPE ) );
}
public String getSourceAddress()
{
switch( getServiceType() )
{
case GROUP_DATA_CHANNEL_GRANT:
case GROUP_VOICE_CHANNEL_GRANT:
return mMessage.getHex( SOURCE_GROUP, 4 );
case UNIT_TO_UNIT_VOICE_CHANNEL_GRANT:
case INDIVIDUAL_DATA_CHANNEL_GRANT:
return mMessage.getHex( SOURCE_ADDRESS, 6 );
case TELEPHONE_INTERCONNECT_VOICE_CHANNEL_GRANT:
return "DELAY:" + ( mMessage.getInt( SOURCE_ADDRESS ) * 5 ) + "SECS";
default:
break;
}
return null;
}
public String getTargetAddress()
{
return mMessage.getHex( TARGET_ADDRESS, 6 );
}
@Override
public String getToID()
{
return getTargetAddress();
}
}

View File

@@ -0,0 +1,136 @@
package module.decode.p25.message.tsbk.osp.control;
import module.decode.p25.message.IBandIdentifier;
import module.decode.p25.message.IdentifierReceiver;
import module.decode.p25.message.tsbk.TSBKMessage;
import module.decode.p25.reference.DataUnitID;
import module.decode.p25.reference.Opcode;
import alias.AliasList;
import bits.BinaryMessage;
public class RFSSStatusBroadcast extends TSBKMessage implements IdentifierReceiver
{
public static final int[] LOCATION_REGISTRATION_AREA = { 80,81,82,83,84,85,
86,87 };
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[] IDENTIFIER = { 120,121,122,123 };
public static final int[] CHANNEL = { 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 };
private IBandIdentifier mIdentifierUpdate;
public RFSSStatusBroadcast( BinaryMessage message,
DataUnitID duid,
AliasList aliasList )
{
super( message, duid, aliasList );
}
@Override
public String getEventType()
{
return Opcode.RFSS_STATUS_BROADCAST.getDescription();
}
public String getMessage()
{
StringBuilder sb = new StringBuilder();
sb.append( getMessageStub() );
sb.append( " LRA:" + getLocationRegistrationArea() );
sb.append( " SYSID:" + getSystemID() );
sb.append( " RFSS:" + getRFSubsystemID() );
sb.append( " SITE:" + getSiteID() );
sb.append( " CHAN:" + getIdentifier() + "-" + getChannel() );
sb.append( " DN:" + getDownlinkFrequency() );
sb.append( " UP:" + getUplinkFrequency() );
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 hasActiveNetworkConnection()
{
return mMessage.get( ACTIVE_NETWORK_CONNECTION_FLAG );
}
public String getSystemID()
{
return mMessage.getHex( SYSTEM_ID, 3 );
}
public String getRFSubsystemID()
{
return mMessage.getHex( RFSS_ID, 2 );
}
public String getSiteID()
{
return mMessage.getHex( SITE_ID, 2 );
}
public int getIdentifier()
{
return mMessage.getInt( IDENTIFIER );
}
public int getChannel()
{
return mMessage.getInt( CHANNEL );
}
public int getSystemServiceClass()
{
return mMessage.getInt( SYSTEM_SERVICE_CLASS );
}
public long getDownlinkFrequency()
{
return calculateDownlink( mIdentifierUpdate, getChannel() );
}
public long getUplinkFrequency()
{
return calculateUplink( mIdentifierUpdate, getChannel() );
}
@Override
public void setIdentifierMessage( int identifier, IBandIdentifier message )
{
/* we're only expecting 1 identifier, so use whatever is received */
mIdentifierUpdate = message;
}
public int[] getIdentifiers()
{
int[] idens = new int[ 1 ];
idens[ 0 ] = getIdentifier();
return idens;
}
}

View File

@@ -0,0 +1,69 @@
package module.decode.p25.message.tsbk.osp.control;
import module.decode.p25.message.tsbk.TSBKMessage;
import module.decode.p25.reference.DataUnitID;
import module.decode.p25.reference.Opcode;
import alias.AliasList;
import bits.BinaryMessage;
public class RadioUnitMonitorCommand extends TSBKMessage
{
public static final int[] TX_MULTIPLIER = { 94,95 };
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 RadioUnitMonitorCommand( BinaryMessage message,
DataUnitID duid,
AliasList aliasList )
{
super( message, duid, aliasList );
}
@Override
public String getEventType()
{
return Opcode.RADIO_UNIT_MONITOR_COMMAND.getDescription();
}
public String getMessage()
{
StringBuilder sb = new StringBuilder();
sb.append( getMessageStub() );
sb.append( " MULT:" + getTransmitMultiplier() );
sb.append( " SRC ADDR: " + getSourceAddress() );
sb.append( " TGT ADDR: " + getTargetAddress() );
return sb.toString();
}
public int getTransmitMultiplier()
{
return mMessage.getInt( TX_MULTIPLIER );
}
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,73 @@
package module.decode.p25.message.tsbk.osp.control;
import module.decode.p25.message.tsbk.TSBKMessage;
import module.decode.p25.reference.DataUnitID;
import module.decode.p25.reference.Opcode;
import module.decode.p25.reference.Response;
import module.decode.p25.reference.StackOperation;
import alias.AliasList;
import bits.BinaryMessage;
public class RoamingAddressCommand extends TSBKMessage
{
public static final int[] STACK_OPERATION = { 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[] 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 RoamingAddressCommand( BinaryMessage message,
DataUnitID duid,
AliasList aliasList )
{
super( message, duid, aliasList );
}
@Override
public String getEventType()
{
return Opcode.ROAMING_ADDRESS_COMMAND.getDescription();
}
public String getMessage()
{
StringBuilder sb = new StringBuilder();
sb.append( getMessageStub() );
sb.append( getStackOperation().name() );
sb.append( " WACN:" + getWACN() );
sb.append( " SYSTEM: " + getSystemID() );
sb.append( " TGT ID: " + getTargetID() );
return sb.toString();
}
public StackOperation getStackOperation()
{
return StackOperation.fromValue( mMessage.getInt( STACK_OPERATION ) );
}
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,207 @@
package module.decode.p25.message.tsbk.osp.control;
import module.decode.p25.message.IBandIdentifier;
import module.decode.p25.message.IdentifierReceiver;
import module.decode.p25.message.tsbk.TSBKMessage;
import module.decode.p25.reference.DataUnitID;
import module.decode.p25.reference.Opcode;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import alias.AliasList;
import bits.BinaryMessage;
public class SecondaryControlChannelBroadcast extends TSBKMessage
implements IdentifierReceiver, Comparable<SecondaryControlChannelBroadcast>
{
private final static Logger mLog =
LoggerFactory.getLogger( SecondaryControlChannelBroadcast.class );
public static final int[] RFSS_ID = { 80,81,82,83,84,85,86,87 };
public static final int[] SITE_ID = { 88,89,90,91,92,93,94,95 };
public static final int[] IDENTIFIER_1 = { 96,97,98,99 };
public static final int[] CHANNEL_1 = { 100,101,102,103,104,105,106,107,108,
109,110,111 };
public static final int[] SYSTEM_SERVICE_CLASS_1 = { 112,113,114,115,116,
117,118,119 };
public static final int[] IDENTIFIER_2 = { 120,121,122,123 };
public static final int[] CHANNEL_2 = { 124,125,126,127,128,129,130,131,132,
133,134,135 };
public static final int[] SYSTEM_SERVICE_CLASS_2 = { 136,137,138,139,140,
141,142,143 };
private IBandIdentifier mIdentifierUpdate1;
private IBandIdentifier mIdentifierUpdate2;
public SecondaryControlChannelBroadcast( BinaryMessage message,
DataUnitID duid,
AliasList aliasList )
{
super( message, duid, aliasList );
}
@Override
public String getEventType()
{
return Opcode.SECONDARY_CONTROL_CHANNEL_BROADCAST.getDescription();
}
public String getMessage()
{
StringBuilder sb = new StringBuilder();
sb.append( getMessageStub() );
sb.append( " SITE:" + getRFSS() + "-" + getSiteID() );
sb.append( " CHAN1:" + getIdentifier1() + "-" + getChannel1() );
sb.append( " DN1:" + getDownlinkFrequency1() );
sb.append( " UP1:" + getUplinkFrequency1() );
sb.append( " SVC1:" +
SystemService.toString( getSystemServiceClass1() ) );
if( hasChannel2() )
{
sb.append( " CHAN2:" + getIdentifier2() + "-" + getChannel2() );
sb.append( " DN2:" + getDownlinkFrequency2() );
sb.append( " UP2:" + getUplinkFrequency2() );
sb.append( " SVC2:" +
SystemService.toString( getSystemServiceClass2() ) );
}
return sb.toString();
}
public String getRFSS()
{
return mMessage.getHex( RFSS_ID, 2 );
}
public String getSiteID()
{
return mMessage.getHex( SITE_ID, 2 );
}
public int getIdentifier1()
{
return mMessage.getInt( IDENTIFIER_1 );
}
public int getChannel1()
{
return mMessage.getInt( CHANNEL_1 );
}
public int getSystemServiceClass1()
{
return mMessage.getInt( SYSTEM_SERVICE_CLASS_1 );
}
public int getIdentifier2()
{
return mMessage.getInt( IDENTIFIER_2 );
}
public int getChannel2()
{
return mMessage.getInt( CHANNEL_2 );
}
public int getSystemServiceClass2()
{
return mMessage.getInt( SYSTEM_SERVICE_CLASS_2 );
}
public boolean hasChannel2()
{
return getSystemServiceClass2() != 0;
}
public long getDownlinkFrequency1()
{
return calculateDownlink( mIdentifierUpdate1, getChannel1() );
}
public long getUplinkFrequency1()
{
return calculateUplink( mIdentifierUpdate1, getChannel1() );
}
public long getDownlinkFrequency2()
{
return calculateDownlink( mIdentifierUpdate2, getChannel2() );
}
public long getUplinkFrequency2()
{
return calculateUplink( mIdentifierUpdate2, getChannel2() );
}
@Override
public void setIdentifierMessage( int identifier, IBandIdentifier message )
{
if( identifier == getIdentifier1() )
{
mIdentifierUpdate1 = message;
}
if( identifier == getIdentifier2() )
{
mIdentifierUpdate2 = message;
}
}
public int[] getIdentifiers()
{
int[] idens;
if( hasChannel2() )
{
idens = new int[ 2 ];
idens[ 0 ] = getIdentifier1();
idens[ 1 ] = getIdentifier2();
}
else
{
idens = new int[ 1 ];
idens[ 0 ] = getIdentifier1();
}
return idens;
}
@Override
public int compareTo( SecondaryControlChannelBroadcast other )
{
if( other.getSiteID().contentEquals( getSiteID() ) &&
other.getIdentifier1() == getIdentifier1() &&
other.getChannel1() == getChannel1() &&
other.getChannel2() == getChannel2() &&
other.getIdentifier2() == getIdentifier2() &&
other.getDownlinkFrequency1() == getDownlinkFrequency1() &&
other.getUplinkFrequency1() == getUplinkFrequency1() &&
other.getDownlinkFrequency2() == getDownlinkFrequency2() &&
other.getUplinkFrequency2() == getUplinkFrequency2() )
{
return 0;
}
else if( other.getIdentifier1() < getIdentifier1() )
{
return -1;
}
else
{
return 1;
}
}
}

View File

@@ -0,0 +1,59 @@
package module.decode.p25.message.tsbk.osp.control;
import module.decode.p25.reference.DataUnitID;
import module.decode.p25.reference.Opcode;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import alias.AliasList;
import bits.BinaryMessage;
public class SecondaryControlChannelBroadcastExplicit
extends SecondaryControlChannelBroadcast
{
private final static Logger mLog = LoggerFactory.getLogger(
SecondaryControlChannelBroadcastExplicit.class );
public SecondaryControlChannelBroadcastExplicit( BinaryMessage message,
DataUnitID duid, AliasList aliasList )
{
super( message, duid, aliasList );
}
@Override
public String getEventType()
{
return Opcode.SECONDARY_CONTROL_CHANNEL_BROADCAST_EXPLICIT.getDescription();
}
public String getMessage()
{
StringBuilder sb = new StringBuilder();
sb.append( getMessageStub() );
sb.append( " SITE:" + getRFSS() + "-" + getSiteID() );
sb.append( " DOWNLINK:" + getIdentifier1() + "-" + getChannel1() );
sb.append( " " + getDownlinkFrequency1() );
sb.append( " SVC1:" +
SystemService.toString( getSystemServiceClass1() ) );
if( hasChannel2() )
{
sb.append( " UPLINK:" + getIdentifier2() + "-" + getChannel2() );
sb.append( " " + getUplinkFrequency1() );
sb.append( " SVC2:" +
SystemService.toString( getSystemServiceClass2() ) );
}
return sb.toString();
}
}

View File

@@ -0,0 +1,62 @@
package module.decode.p25.message.tsbk.osp.control;
import module.decode.p25.message.tsbk.TSBKMessage;
import module.decode.p25.reference.DataUnitID;
import module.decode.p25.reference.Opcode;
import alias.AliasList;
import bits.BinaryMessage;
public class StatusQuery 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_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 StatusQuery( BinaryMessage message,
DataUnitID duid,
AliasList aliasList )
{
super( message, duid, aliasList );
}
@Override
public String getEventType()
{
return Opcode.STATUS_QUERY.getDescription();
}
public String getMessage()
{
StringBuilder sb = new StringBuilder();
sb.append( getMessageStub() );
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,76 @@
package module.decode.p25.message.tsbk.osp.control;
import module.decode.p25.message.tsbk.TSBKMessage;
import module.decode.p25.reference.DataUnitID;
import module.decode.p25.reference.Opcode;
import alias.AliasList;
import bits.BinaryMessage;
public class StatusUpdate extends TSBKMessage
{
public static final int[] USER_STATUS = { 72,73,74,75,88,89,90,91 };
public static final int[] UNIT_STATUS = { 92,93,94,95,96,97,98,99 };
public static final int[] TARGET_ADDRESS = { 112,113,114,115,116,117,118,
119,120,121,122,123,136,137,138,139,140,141,142,143,144,145,146,147 };
public static final int[] SOURCE_ADDRESS = { 160,161,162,163,164,165,166,
167,168,169,170,171,184,185,186,187,188,189,190,190,192,193,194,195 };
public StatusUpdate( BinaryMessage message,
DataUnitID duid,
AliasList aliasList )
{
super( message, duid, aliasList );
}
@Override
public String getEventType()
{
return Opcode.STATUS_UPDATE.getDescription();
}
public String getMessage()
{
StringBuilder sb = new StringBuilder();
sb.append( getMessageStub() );
sb.append( " STATUS USER:" + getUserStatus() );
sb.append( " UNIT:" + getUnitStatus() );
sb.append( " SRC ADDR: " + getSourceAddress() );
sb.append( " TGT ADDR: " + getTargetAddress() );
return sb.toString();
}
public String getUserStatus()
{
return mMessage.getHex( USER_STATUS, 2 );
}
public String getUnitStatus()
{
return mMessage.getHex( UNIT_STATUS, 2 );
}
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 module.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" );
}
sb.append( " ]" );
return sb.toString();
}
}

View File

@@ -0,0 +1,64 @@
package module.decode.p25.message.tsbk.osp.control;
import java.util.List;
import module.decode.p25.message.tsbk.TSBKMessage;
import module.decode.p25.reference.DataUnitID;
import module.decode.p25.reference.Opcode;
import module.decode.p25.reference.Service;
import alias.AliasList;
import bits.BinaryMessage;
public class SystemServiceBroadcast extends TSBKMessage
{
public static final int[] AVAILABLE_SERVICES = { 88,89,90,91,92,93,94,95,
96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111 };
public static final int[] SUPPORTED_SERVICES = { 112,113,114,115,116,117,
118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135 };
public static final int[] REQUEST_PRIORITY_LEVEL = { 136,137,138,139,140,
141,142,143 };
public SystemServiceBroadcast( BinaryMessage message,
DataUnitID duid,
AliasList aliasList )
{
super( message, duid, aliasList );
}
@Override
public String getEventType()
{
return Opcode.SYSTEM_SERVICE_BROADCAST.getDescription();
}
public String getMessage()
{
StringBuilder sb = new StringBuilder();
sb.append( getMessageStub() );
sb.append( " SERVICES AVAILABLE " );
sb.append( getAvailableServices() );
sb.append( " SUPPORTED " );
sb.append( getSupportedServices() );
return sb.toString();
}
public List<Service> getAvailableServices()
{
long bitmap = mMessage.getLong( AVAILABLE_SERVICES );
return Service.getServices( bitmap );
}
public List<Service> getSupportedServices()
{
long bitmap = mMessage.getLong( SUPPORTED_SERVICES );
return Service.getServices( bitmap );
}
}

View File

@@ -0,0 +1,156 @@
package module.decode.p25.message.tsbk.osp.control;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.TimeZone;
import module.decode.p25.message.tsbk.TSBKMessage;
import module.decode.p25.reference.DataUnitID;
import module.decode.p25.reference.Opcode;
import alias.AliasList;
import bits.BinaryMessage;
public class TimeAndDateAnnouncement extends TSBKMessage
{
public static final int VALID_DATE_INDICATOR = 80;
public static final int VALID_TIME_INDICATOR = 81;
public static final int VALID_LOCAL_TIME_OFFSET_INDICATOR = 82;
public static final int LOCAL_TIME_OFFSET_SIGN = 84;
public static final int[] LOCAL_TIME_OFFSET = { 85,86,87,88,89,90,91,92,
93,94,95 };
public static final int[] MONTH = { 96,97,98,99 };
public static final int[] DAY = { 100,101,102,103 };
public static final int[] YEAR = { 105,106,107,108,109,110,111,112,113,114,
115,116,117 };
public static final int[] HOURS = { 120,121,122,123,124 };
public static final int[] MINUTES = { 125,126,127,128,129,130 };
public static final int[] SECONDS = { 131,132,133,134,135,136 };
private SimpleDateFormat mTimeFormatter =
new SimpleDateFormat( "EEE, d MMM yyyy HH:mm:ss Z" );
public TimeAndDateAnnouncement( BinaryMessage message, DataUnitID duid,
AliasList aliasList )
{
super( message, duid, aliasList );
}
@Override
public String getEventType()
{
return Opcode.TIME_DATE_ANNOUNCEMENT.getDescription();
}
public String getMessage()
{
StringBuilder sb = new StringBuilder();
sb.append( getMessageStub() );
if( hasValidDate() )
{
sb.append( " DATE-TIME:" );
}
sb.append( " " );
sb.append( mTimeFormatter.format( new Date( getDateTimestamp() ) ) );
return sb.toString();
}
public long getDateTimestamp()
{
Calendar cal = new GregorianCalendar( getTimeZone() );
if( hasValidDate() )
{
cal.set( Calendar.YEAR, getYear() );
cal.set( Calendar.MONTH, getMonth() );
cal.set( Calendar.DAY_OF_MONTH, getDay() );
}
if( hasValidTime() )
{
cal.set( Calendar.HOUR, getHour() );
cal.set( Calendar.MINUTE, getMinute() );
cal.set( Calendar.SECOND, getSecond() );
}
return cal.getTimeInMillis();
}
public boolean hasValidDate()
{
return mMessage.get( VALID_DATE_INDICATOR );
}
public boolean hasValidTime()
{
return mMessage.get( VALID_TIME_INDICATOR );
}
public TimeZone getTimeZone()
{
StringBuilder sb = new StringBuilder();
sb.append( "GMT " );
sb.append( mMessage.get( LOCAL_TIME_OFFSET_SIGN ) ? "-" : "+" );
int offsetMinutes = getLocalTimeOffset();
sb.append( (int)( offsetMinutes / 60 ) );
sb.append( " : " );
sb.append( offsetMinutes % 60 );
return TimeZone.getTimeZone( sb.toString() );
}
public boolean hasValidLocalTimeOffset()
{
return mMessage.get( VALID_LOCAL_TIME_OFFSET_INDICATOR );
}
/**
* Local Time Offset in minutes
*/
public int getLocalTimeOffset()
{
return mMessage.getInt( LOCAL_TIME_OFFSET );
}
public int getMonth()
{
return mMessage.getInt( MONTH );
}
public int getDay()
{
return mMessage.getInt( DAY );
}
public int getYear()
{
return mMessage.getInt( YEAR );
}
public int getHour()
{
return mMessage.getInt( HOURS );
}
public int getMinute()
{
return mMessage.getInt( MINUTES );
}
public int getSecond()
{
return mMessage.getInt( SECONDS );
}
}

View File

@@ -0,0 +1,65 @@
package module.decode.p25.message.tsbk.osp.control;
import module.decode.p25.message.tsbk.TSBKMessage;
import module.decode.p25.reference.DataUnitID;
import module.decode.p25.reference.Opcode;
import module.decode.p25.reference.Response;
import alias.AliasList;
import bits.BinaryMessage;
public class UnitDeregistrationAcknowledge 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[] 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 UnitDeregistrationAcknowledge( BinaryMessage message,
DataUnitID duid,
AliasList aliasList )
{
super( message, duid, aliasList );
}
@Override
public String getEventType()
{
return Opcode.UNIT_DEREGISTRATION_ACKNOWLEDGE.getDescription();
}
public String getMessage()
{
StringBuilder sb = new StringBuilder();
sb.append( getMessageStub() );
sb.append( " WACN:" + getWACN() );
sb.append( " SYSTEM:" + getSystemID() );
sb.append( " SRC ID: " + getSourceID() );
return sb.toString();
}
public String getWACN()
{
return mMessage.getHex( WACN, 5 );
}
public String getSystemID()
{
return mMessage.getHex( SYSTEM_ID, 3 );
}
public String getSourceID()
{
return mMessage.getHex( SOURCE_ID, 6 );
}
@Override
public String getToID()
{
return getSourceID();
}
}

View File

@@ -0,0 +1,62 @@
package module.decode.p25.message.tsbk.osp.control;
import module.decode.p25.message.tsbk.TSBKMessage;
import module.decode.p25.reference.DataUnitID;
import module.decode.p25.reference.Opcode;
import alias.AliasList;
import bits.BinaryMessage;
public class UnitRegistrationCommand 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_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 UnitRegistrationCommand( BinaryMessage message,
DataUnitID duid,
AliasList aliasList )
{
super( message, duid, aliasList );
}
@Override
public String getEventType()
{
return Opcode.UNIT_REGISTRATION_COMMAND.getDescription();
}
public String getMessage()
{
StringBuilder sb = new StringBuilder();
sb.append( getMessageStub() );
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,71 @@
package module.decode.p25.message.tsbk.osp.control;
import module.decode.p25.message.tsbk.TSBKMessage;
import module.decode.p25.reference.DataUnitID;
import module.decode.p25.reference.Opcode;
import module.decode.p25.reference.Response;
import alias.AliasList;
import bits.BinaryMessage;
public class UnitRegistrationResponse extends TSBKMessage
{
public static final int[] REGISTRATION_RESPONSE = { 82,83 };
public static final int[] SYSTEM_ID = { 84,85,86,87,88,89,90,91,92,93,94,95 };
public static final int[] SOURCE_ID = { 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 UnitRegistrationResponse( BinaryMessage message,
DataUnitID duid,
AliasList aliasList )
{
super( message, duid, aliasList );
}
@Override
public String getEventType()
{
return Opcode.UNIT_REGISTRATION_RESPONSE.getDescription();
}
public String getMessage()
{
StringBuilder sb = new StringBuilder();
sb.append( getMessageStub() );
sb.append( " REGISTRATION:" + getResponse().name() );
sb.append( " SYSTEM:" + getSystemID() );
sb.append( " SRC ID: " + getSourceID() );
sb.append( " SRC ADDR: " + getSourceAddress() );
return sb.toString();
}
public Response getResponse()
{
return Response.fromValue( mMessage.getInt( REGISTRATION_RESPONSE ) );
}
public String getSystemID()
{
return mMessage.getHex( SYSTEM_ID, 3 );
}
public String getSourceID()
{
return mMessage.getHex( SOURCE_ID, 6 );
}
public String getSourceAddress()
{
return mMessage.getHex( SOURCE_ADDRESS, 6 );
}
@Override
public String getToID()
{
return getSourceAddress();
}
}