mirror of
https://github.com/DSheirer/sdrtrunk.git
synced 2026-11-12 08:37:25 -05:00
P25 work in progress - final commit of TSBK message parsers
This commit is contained in:
@@ -60,7 +60,7 @@ public enum DecoderType
|
||||
DecoderType.LTR_STANDARD,
|
||||
DecoderType.MPT1327,
|
||||
DecoderType.NBFM,
|
||||
// DecoderType.P25_PHASE1,
|
||||
DecoderType.P25_PHASE1,
|
||||
DecoderType.PASSPORT );
|
||||
}
|
||||
|
||||
|
||||
154
src/decode/p25/P25CallEvent.java
Normal file
154
src/decode/p25/P25CallEvent.java
Normal file
@@ -0,0 +1,154 @@
|
||||
/*******************************************************************************
|
||||
* SDR Trunk
|
||||
* Copyright (C) 2014 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
******************************************************************************/
|
||||
package decode.p25;
|
||||
|
||||
import alias.Alias;
|
||||
import alias.AliasList;
|
||||
import controller.activity.CallEvent;
|
||||
import decode.DecoderType;
|
||||
|
||||
public class P25CallEvent extends CallEvent
|
||||
{
|
||||
private int mChannel;
|
||||
private long mFrequency;
|
||||
|
||||
public P25CallEvent( CallEventType callEventType,
|
||||
AliasList aliasList,
|
||||
String fromID,
|
||||
String toID,
|
||||
int channel,
|
||||
long frequency,
|
||||
String details )
|
||||
{
|
||||
super( DecoderType.MPT1327, callEventType,
|
||||
aliasList, fromID, toID, details );
|
||||
|
||||
mChannel = channel;
|
||||
mFrequency = frequency;
|
||||
}
|
||||
|
||||
private Alias getAlias( String mpt1327Talkgroup )
|
||||
{
|
||||
if( hasAliasList() )
|
||||
{
|
||||
return getAliasList().getMPT1327Alias( mpt1327Talkgroup );
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Alias getFromIDAlias()
|
||||
{
|
||||
return getAlias( getFromID() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Alias getToIDAlias()
|
||||
{
|
||||
return getAlias( getToID() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getChannel()
|
||||
{
|
||||
return mChannel;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getFrequency()
|
||||
{
|
||||
return mFrequency;
|
||||
}
|
||||
|
||||
public static class Builder
|
||||
{
|
||||
/* Required parameters */
|
||||
private CallEventType mCallEventType;
|
||||
|
||||
/* Optional parameters */
|
||||
private AliasList mAliasList;
|
||||
private String mFromID;
|
||||
private String mToID;
|
||||
private String mDetails;
|
||||
private int mChannel;
|
||||
private long mFrequency;
|
||||
|
||||
public Builder( CallEventType callEventType )
|
||||
{
|
||||
mCallEventType = callEventType;
|
||||
}
|
||||
|
||||
public Builder aliasList( AliasList aliasList )
|
||||
{
|
||||
mAliasList = aliasList;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder from( String val )
|
||||
{
|
||||
mFromID = val;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder channel( int channel )
|
||||
{
|
||||
mChannel = channel;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder details( String details )
|
||||
{
|
||||
mDetails = details;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder frequency( long frequency )
|
||||
{
|
||||
mFrequency = frequency;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder to( String toID )
|
||||
{
|
||||
mToID = toID;
|
||||
return this;
|
||||
}
|
||||
|
||||
public P25CallEvent build()
|
||||
{
|
||||
return new P25CallEvent( this );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Private constructor for the builder
|
||||
*/
|
||||
private P25CallEvent( Builder builder )
|
||||
{
|
||||
this( builder.mCallEventType,
|
||||
builder.mAliasList,
|
||||
builder.mFromID,
|
||||
builder.mToID,
|
||||
builder.mChannel,
|
||||
builder.mFrequency,
|
||||
builder.mDetails );
|
||||
}
|
||||
|
||||
}
|
||||
@@ -17,12 +17,14 @@
|
||||
******************************************************************************/
|
||||
package decode.p25;
|
||||
|
||||
import message.Message;
|
||||
import alias.AliasList;
|
||||
import audio.SquelchListener;
|
||||
import audio.SquelchListener.SquelchState;
|
||||
import controller.channel.ProcessingChain;
|
||||
import controller.state.AuxChannelState;
|
||||
import controller.state.ChannelState;
|
||||
import decode.p25.message.P25Message;
|
||||
|
||||
public class P25ChannelState extends ChannelState
|
||||
{
|
||||
@@ -31,21 +33,30 @@ public class P25ChannelState extends ChannelState
|
||||
super( chain, aliasList );
|
||||
}
|
||||
|
||||
/**
|
||||
* Make the ConventionalChannelState always unsquelched
|
||||
*/
|
||||
public void addListener( SquelchListener listener )
|
||||
{
|
||||
super.addListener( listener );
|
||||
|
||||
super.setSquelchState( SquelchState.UNSQUELCH );
|
||||
}
|
||||
|
||||
public void receive( Message message )
|
||||
{
|
||||
super.receive( message );
|
||||
|
||||
if( message instanceof P25Message )
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void setSquelchState( SquelchState state )
|
||||
{
|
||||
//do nothing ... we want the squelch state always unsquelched (for now)
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getActivitySummary()
|
||||
{
|
||||
|
||||
@@ -85,6 +85,7 @@ public class P25Decoder extends Decoder implements Instrumentable
|
||||
mSymbolFilter.setListener( mSlicer );
|
||||
|
||||
mMessageProcessor = new P25MessageProcessor( mAliasList );
|
||||
mMessageProcessor.addMessageListener( this );
|
||||
|
||||
mNormalFramer = new P25MessageFramer(
|
||||
FrameSync.P25_PHASE1.getSync(), 64, false, mAliasList );
|
||||
|
||||
@@ -1,19 +1,35 @@
|
||||
package decode.p25;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
|
||||
import message.Message;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import bits.BitSetBuffer;
|
||||
import sample.Broadcaster;
|
||||
import sample.Listener;
|
||||
import alias.AliasList;
|
||||
import decode.mpt1327.MPT1327Message;
|
||||
import decode.p25.message.tsbk.TSBKMessage;
|
||||
import decode.p25.message.tsbk.osp.control.IdentifierUpdate;
|
||||
import decode.p25.message.tsbk.osp.control.IdentifierUpdateReceiver;
|
||||
|
||||
public class P25MessageProcessor implements Listener<Message>
|
||||
{
|
||||
private final static Logger mLog =
|
||||
LoggerFactory.getLogger( P25MessageProcessor.class );
|
||||
|
||||
private Broadcaster<Message> mBroadcaster = new Broadcaster<Message>();
|
||||
|
||||
/* Map of up to 16 band identifiers per RFSS. These identifier update
|
||||
* messages are inserted into any message that conveys channel information
|
||||
* so that the uplink/downlink frequencies can be calculated */
|
||||
private HashMap<Integer,IdentifierUpdate> mIdentifierMap =
|
||||
new HashMap<Integer,IdentifierUpdate>();
|
||||
|
||||
private AliasList mAliasList;
|
||||
|
||||
public P25MessageProcessor( AliasList aliasList )
|
||||
@@ -24,6 +40,29 @@ public class P25MessageProcessor implements Listener<Message>
|
||||
@Override
|
||||
public void receive( Message message )
|
||||
{
|
||||
/* Insert band identifier update messages into channel-type messages */
|
||||
if( message instanceof IdentifierUpdateReceiver )
|
||||
{
|
||||
IdentifierUpdateReceiver receiver = (IdentifierUpdateReceiver)message;
|
||||
|
||||
int[] identifiers = receiver.getIdentifiers();
|
||||
|
||||
for( int identifier: identifiers )
|
||||
{
|
||||
receiver.setIdentifierMessage( identifier,
|
||||
mIdentifierMap.get( identifier ) );
|
||||
}
|
||||
}
|
||||
|
||||
/* Store band identifiers so that they can be injected into channel
|
||||
* type messages */
|
||||
if( message instanceof IdentifierUpdate )
|
||||
{
|
||||
IdentifierUpdate identifierUpdate = (IdentifierUpdate)message;
|
||||
|
||||
mIdentifierMap.put( identifierUpdate.getIdentifier(), identifierUpdate );
|
||||
}
|
||||
|
||||
if( message instanceof TSBKMessage )
|
||||
{
|
||||
mLog.debug( message.getMessage() );
|
||||
@@ -32,5 +71,23 @@ public class P25MessageProcessor implements Listener<Message>
|
||||
{
|
||||
mLog.debug( message.getMessage() + "\t" + message.getBinaryMessage() );
|
||||
}
|
||||
|
||||
mBroadcaster.broadcast( message );
|
||||
}
|
||||
|
||||
public void dispose()
|
||||
{
|
||||
mIdentifierMap.clear();
|
||||
mBroadcaster.dispose();
|
||||
}
|
||||
|
||||
public void addMessageListener( Listener<Message> listener )
|
||||
{
|
||||
mBroadcaster.addListener( listener );
|
||||
}
|
||||
|
||||
public void removeMessageListener( Listener<Message> listener )
|
||||
{
|
||||
mBroadcaster.removeListener( listener );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,49 +4,20 @@ import alias.AliasList;
|
||||
import bits.BitSetBuffer;
|
||||
import decode.p25.reference.DataUnitID;
|
||||
|
||||
public abstract class ChannelGrant extends TSBKMessage
|
||||
public abstract class ChannelGrant extends ServiceMessage
|
||||
{
|
||||
/* Service Options */
|
||||
public static final int EMERGENCY_FLAG = 80;
|
||||
public static final int ENCRYPTED_CHANNEL_FLAG = 81;
|
||||
public static final int DUPLEX_MODE = 82;
|
||||
public static final int SESSION_MODE = 83;
|
||||
public static final int[] PRIORITY = { 85,86,87 };
|
||||
public static final int[] CHANNEL_ID = { 88,89,90,91 };
|
||||
public static final int[] CHANNEL_NUMBER = { 92,93,94,95,96,97,98,99,100,
|
||||
101,102,103 };
|
||||
|
||||
public enum DuplexMode { HALF, FULL };
|
||||
public enum SessionMode { PACKET, CIRCUIT };
|
||||
|
||||
public ChannelGrant( BitSetBuffer message,
|
||||
DataUnitID duid,
|
||||
AliasList aliasList )
|
||||
DataUnitID duid,
|
||||
AliasList aliasList )
|
||||
{
|
||||
super( message, duid, aliasList );
|
||||
}
|
||||
|
||||
public boolean isEmergency()
|
||||
{
|
||||
return mMessage.get( EMERGENCY_FLAG );
|
||||
}
|
||||
|
||||
public boolean isEncryptedChannel()
|
||||
{
|
||||
return mMessage.get( ENCRYPTED_CHANNEL_FLAG );
|
||||
}
|
||||
|
||||
public DuplexMode getDuplexMode()
|
||||
{
|
||||
return mMessage.get( DUPLEX_MODE ) ? DuplexMode.FULL : DuplexMode.HALF;
|
||||
}
|
||||
|
||||
public SessionMode getSessionMode()
|
||||
{
|
||||
return mMessage.get( SESSION_MODE ) ?
|
||||
SessionMode.CIRCUIT : SessionMode.PACKET;
|
||||
}
|
||||
|
||||
/**
|
||||
* 1 = Lowest, 4 = Default, 7 = Highest
|
||||
*/
|
||||
|
||||
45
src/decode/p25/message/tsbk/ServiceMessage.java
Normal file
45
src/decode/p25/message/tsbk/ServiceMessage.java
Normal file
@@ -0,0 +1,45 @@
|
||||
package decode.p25.message.tsbk;
|
||||
|
||||
import alias.AliasList;
|
||||
import bits.BitSetBuffer;
|
||||
import decode.p25.reference.DataUnitID;
|
||||
|
||||
public abstract class ServiceMessage extends TSBKMessage
|
||||
{
|
||||
/* Service Options */
|
||||
public static final int EMERGENCY_FLAG = 80;
|
||||
public static final int ENCRYPTED_CHANNEL_FLAG = 81;
|
||||
public static final int DUPLEX_MODE = 82;
|
||||
public static final int SESSION_MODE = 83;
|
||||
|
||||
public enum DuplexMode { HALF, FULL };
|
||||
public enum SessionMode { PACKET, CIRCUIT };
|
||||
|
||||
public ServiceMessage( BitSetBuffer message,
|
||||
DataUnitID duid,
|
||||
AliasList aliasList )
|
||||
{
|
||||
super( message, duid, aliasList );
|
||||
}
|
||||
|
||||
public boolean isEmergency()
|
||||
{
|
||||
return mMessage.get( EMERGENCY_FLAG );
|
||||
}
|
||||
|
||||
public boolean isEncryptedChannel()
|
||||
{
|
||||
return mMessage.get( ENCRYPTED_CHANNEL_FLAG );
|
||||
}
|
||||
|
||||
public DuplexMode getDuplexMode()
|
||||
{
|
||||
return mMessage.get( DUPLEX_MODE ) ? DuplexMode.FULL : DuplexMode.HALF;
|
||||
}
|
||||
|
||||
public SessionMode getSessionMode()
|
||||
{
|
||||
return mMessage.get( SESSION_MODE ) ?
|
||||
SessionMode.CIRCUIT : SessionMode.PACKET;
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,7 @@ package decode.p25.message.tsbk;
|
||||
import alias.AliasList;
|
||||
import bits.BitSetBuffer;
|
||||
import decode.p25.message.P25Message;
|
||||
import decode.p25.message.tsbk.osp.control.IdentifierUpdate;
|
||||
import decode.p25.reference.DataUnitID;
|
||||
import decode.p25.reference.Opcode;
|
||||
import decode.p25.reference.Vendor;
|
||||
@@ -128,4 +129,27 @@ public class TSBKMessage extends P25Message
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
protected static long calculateUplink( IdentifierUpdate iden, int channel )
|
||||
{
|
||||
long downlink = calculateDownlink( iden, channel );
|
||||
|
||||
if( downlink > 0 && iden != null )
|
||||
{
|
||||
return downlink + iden.getTransmitOffset();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
protected static long calculateDownlink( IdentifierUpdate iden, int channel )
|
||||
{
|
||||
if( iden != null )
|
||||
{
|
||||
return iden.getBaseFrequency() +
|
||||
( channel * iden.getChannelSpacing() );
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,10 @@ package decode.p25.message.tsbk;
|
||||
|
||||
import alias.AliasList;
|
||||
import bits.BitSetBuffer;
|
||||
import decode.p25.message.tsbk.motorola.ChannelCWIDUpdate;
|
||||
import decode.p25.message.tsbk.motorola.MotorolaOpcode;
|
||||
import decode.p25.message.tsbk.motorola.MotorolaTSBKMessage;
|
||||
import decode.p25.message.tsbk.motorola.SystemLoading;
|
||||
import decode.p25.message.tsbk.osp.control.AcknowledgeResponse;
|
||||
import decode.p25.message.tsbk.osp.control.AdjacentStatusBroadcast;
|
||||
import decode.p25.message.tsbk.osp.control.AuthenticationCommand;
|
||||
@@ -10,7 +14,8 @@ 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.IdentifierUpdateNonVUHF;
|
||||
import decode.p25.message.tsbk.osp.control.IdentifierUpdateVUHF;
|
||||
import decode.p25.message.tsbk.osp.control.LocationRegistrationResponse;
|
||||
import decode.p25.message.tsbk.osp.control.MessageUpdate;
|
||||
import decode.p25.message.tsbk.osp.control.NetworkStatusBroadcast;
|
||||
@@ -19,9 +24,11 @@ import decode.p25.message.tsbk.osp.control.RFSSStatusBroadcast;
|
||||
import decode.p25.message.tsbk.osp.control.RadioUnitMonitorCommand;
|
||||
import decode.p25.message.tsbk.osp.control.RoamingAddressCommand;
|
||||
import decode.p25.message.tsbk.osp.control.SecondaryControlChannelBroadcast;
|
||||
import decode.p25.message.tsbk.osp.control.SecondaryControlChannelBroadcastExplicit;
|
||||
import decode.p25.message.tsbk.osp.control.StatusQuery;
|
||||
import decode.p25.message.tsbk.osp.control.StatusUpdate;
|
||||
import decode.p25.message.tsbk.osp.control.SystemServiceBroadcast;
|
||||
import decode.p25.message.tsbk.osp.control.TimeAndDateAnnouncement;
|
||||
import decode.p25.message.tsbk.osp.control.UnitDeregistrationAcknowledge;
|
||||
import decode.p25.message.tsbk.osp.control.UnitRegistrationCommand;
|
||||
import decode.p25.message.tsbk.osp.control.UnitRegistrationResponse;
|
||||
@@ -29,6 +36,9 @@ 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.data.SNDCPDataChannelAnnouncementExplicit;
|
||||
import decode.p25.message.tsbk.osp.data.SNDCPDataChannelGrant;
|
||||
import decode.p25.message.tsbk.osp.data.SNDCPDataPageRequest;
|
||||
import decode.p25.message.tsbk.osp.voice.GroupVoiceChannelGrant;
|
||||
import decode.p25.message.tsbk.osp.voice.GroupVoiceChannelGrantUpdate;
|
||||
import decode.p25.message.tsbk.osp.voice.GroupVoiceChannelGrantUpdateExplicit;
|
||||
@@ -47,14 +57,15 @@ public class TSBKMessageFactory
|
||||
DataUnitID duid,
|
||||
AliasList aliasList )
|
||||
{
|
||||
Opcode opcode = Opcode.fromValue( message.getInt( TSBKMessage.OPCODE ) );
|
||||
|
||||
Vendor vendor = Vendor.fromValue(
|
||||
message.getInt( TSBKMessage.VENDOR_ID ) );
|
||||
|
||||
switch( vendor )
|
||||
{
|
||||
case STANDARD:
|
||||
Opcode opcode =
|
||||
Opcode.fromValue( message.getInt( TSBKMessage.OPCODE ) );
|
||||
|
||||
switch( opcode )
|
||||
{
|
||||
case ACKNOWLEDGE_RESPONSE_FNE:
|
||||
@@ -97,9 +108,12 @@ public class TSBKMessageFactory
|
||||
case GROUP_VOICE_CHANNEL_GRANT_UPDATE_EXPLICIT:
|
||||
return new GroupVoiceChannelGrantUpdateExplicit( message,
|
||||
duid, aliasList );
|
||||
case IDENTIFIER_UPDATE:
|
||||
case IDENTIFIER_UPDATE_NON_VUHF:
|
||||
return new IdentifierUpdateNonVUHF( message, duid,
|
||||
aliasList );
|
||||
case IDENTIFIER_UPDATE_VHF_UHF_BANDS:
|
||||
return new IdentifierUpdate( message, duid, aliasList );
|
||||
return new IdentifierUpdateVUHF( message, duid,
|
||||
aliasList );
|
||||
case INDIVIDUAL_DATA_CHANNEL_GRANT:
|
||||
return new IndividualDataChannelGrant( message, duid,
|
||||
aliasList );
|
||||
@@ -126,6 +140,18 @@ public class TSBKMessageFactory
|
||||
case SECONDARY_CONTROL_CHANNEL_BROADCAST:
|
||||
return new SecondaryControlChannelBroadcast( message,
|
||||
duid, aliasList );
|
||||
case SECONDARY_CONTROL_CHANNEL_BROADCAST_EXPLICIT:
|
||||
return new SecondaryControlChannelBroadcastExplicit(
|
||||
message, duid, aliasList );
|
||||
case SNDCP_DATA_CHANNEL_GRANT:
|
||||
return new SNDCPDataChannelGrant( message, duid,
|
||||
aliasList );
|
||||
case SNDCP_DATA_CHANNEL_ANNOUNCEMENT_EXPLICIT:
|
||||
return new SNDCPDataChannelAnnouncementExplicit(
|
||||
message, duid, aliasList );
|
||||
case SNDCP_DATA_PAGE_REQUEST:
|
||||
return new SNDCPDataPageRequest( message, duid,
|
||||
aliasList );
|
||||
case STATUS_QUERY:
|
||||
return new StatusQuery( message, duid, aliasList );
|
||||
case STATUS_UPDATE:
|
||||
@@ -139,6 +165,9 @@ public class TSBKMessageFactory
|
||||
case TELEPHONE_INTERCONNECT_VOICE_CHANNEL_GRANT:
|
||||
return new TelephoneInterconnectVoiceChannelGrant(
|
||||
message, duid, aliasList );
|
||||
case TIME_DATE_ANNOUNCEMENT:
|
||||
return new TimeAndDateAnnouncement( message, duid,
|
||||
aliasList );
|
||||
case UNIT_DEREGISTRATION_ACKNOWLEDGE:
|
||||
return new UnitDeregistrationAcknowledge( message,
|
||||
duid, aliasList );
|
||||
@@ -162,6 +191,19 @@ public class TSBKMessageFactory
|
||||
}
|
||||
|
||||
case MOTOROLA:
|
||||
MotorolaOpcode motorolaOpcode = MotorolaOpcode.
|
||||
fromValue( message.getInt( TSBKMessage.OPCODE ) );
|
||||
|
||||
switch( motorolaOpcode )
|
||||
{
|
||||
case CHANNEL_CWID_UPDATE:
|
||||
return new ChannelCWIDUpdate( message, duid, aliasList );
|
||||
case SYSTEM_LOADING:
|
||||
return new SystemLoading( message, duid, aliasList );
|
||||
default:
|
||||
}
|
||||
|
||||
return new MotorolaTSBKMessage( message, duid, aliasList );
|
||||
default:
|
||||
return new TSBKMessage( message, duid, aliasList );
|
||||
}
|
||||
|
||||
184
src/decode/p25/message/tsbk/motorola/ChannelCWIDUpdate.java
Normal file
184
src/decode/p25/message/tsbk/motorola/ChannelCWIDUpdate.java
Normal file
@@ -0,0 +1,184 @@
|
||||
package decode.p25.message.tsbk.motorola;
|
||||
|
||||
import alias.AliasList;
|
||||
import bits.BitSetBuffer;
|
||||
import decode.p25.message.tsbk.osp.control.IdentifierUpdate;
|
||||
import decode.p25.message.tsbk.osp.control.IdentifierUpdateReceiver;
|
||||
import decode.p25.reference.DataUnitID;
|
||||
|
||||
public class ChannelCWIDUpdate extends MotorolaTSBKMessage
|
||||
implements IdentifierUpdateReceiver
|
||||
{
|
||||
public static final int[] CHARACTER_1 = { 80,81,82,83,84,85 };
|
||||
public static final int[] CHARACTER_2 = { 86,87,88,89,90,91 };
|
||||
public static final int[] CHARACTER_3 = { 92,93,94,95,96,97 };
|
||||
public static final int[] CHARACTER_4 = { 98,99,100,101,102,103 };
|
||||
public static final int[] CHARACTER_5 = { 104,105,106,107,108,109 };
|
||||
public static final int[] CHARACTER_6 = { 110,111,112,113,114,115 };
|
||||
public static final int[] CHARACTER_7 = { 116,117,118,119,120,121 };
|
||||
public static final int[] CHARACTER_8 = { 122,123,124,125,126,127 };
|
||||
|
||||
public static final int[] IDENTIFIER = { 128,129,130,131 };
|
||||
public static final int[] CHANNEL = { 132,133,134,135,136,137,138,139,140,
|
||||
141,142,143 };
|
||||
|
||||
private IdentifierUpdate mIdentifierUpdate;
|
||||
|
||||
public ChannelCWIDUpdate( BitSetBuffer message,
|
||||
DataUnitID duid,
|
||||
AliasList aliasList )
|
||||
{
|
||||
super( message, duid, aliasList );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getEventType()
|
||||
{
|
||||
return MotorolaOpcode.CHANNEL_CWID_UPDATE.getDescription();
|
||||
}
|
||||
|
||||
public String getMessage()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append( getMessageStub() );
|
||||
|
||||
sb.append( " CHAN:" + getIdentifier() + "-" + getChannel() );
|
||||
|
||||
sb.append( " CWID:" + getCWID() );
|
||||
|
||||
sb.append( " DN:" + getDownlinkFrequency() );
|
||||
|
||||
sb.append( " UP:" + getUplinkFrequency() );
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
|
||||
public String getCWID()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
int char1 = mMessage.getInt( CHARACTER_1 );
|
||||
|
||||
if( char1 != 0 )
|
||||
{
|
||||
sb.append( (char)( char1 + 46 ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
int char2 = mMessage.getInt( CHARACTER_2 );
|
||||
|
||||
if( char2 != 0 )
|
||||
{
|
||||
sb.append( (char)( char2 + 46 ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
int char3 = mMessage.getInt( CHARACTER_3 );
|
||||
|
||||
if( char3 != 0 )
|
||||
{
|
||||
sb.append( (char)( char3 + 46 ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
int char4 = mMessage.getInt( CHARACTER_4 );
|
||||
|
||||
if( char4 != 0 )
|
||||
{
|
||||
sb.append( (char)( char4 + 46 ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
int char5 = mMessage.getInt( CHARACTER_5 );
|
||||
|
||||
if( char5 != 0 )
|
||||
{
|
||||
sb.append( (char)( char5 + 46 ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
int char6 = mMessage.getInt( CHARACTER_6 );
|
||||
|
||||
if( char6 != 0 )
|
||||
{
|
||||
sb.append( (char)( char6 + 46 ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
int char7 = mMessage.getInt( CHARACTER_7 );
|
||||
|
||||
if( char7 != 0 )
|
||||
{
|
||||
sb.append( (char)( char7 + 46 ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
int char8 = mMessage.getInt( CHARACTER_8 );
|
||||
|
||||
if( char8 != 0 )
|
||||
{
|
||||
sb.append( (char)( char8 + 46 ) );
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public int getIdentifier()
|
||||
{
|
||||
return mMessage.getInt( IDENTIFIER );
|
||||
}
|
||||
|
||||
public int getChannel()
|
||||
{
|
||||
return mMessage.getInt( CHANNEL );
|
||||
}
|
||||
|
||||
public long getUplinkFrequency()
|
||||
{
|
||||
return calculateUplink( mIdentifierUpdate, getChannel() );
|
||||
}
|
||||
|
||||
public long getDownlinkFrequency()
|
||||
{
|
||||
return calculateDownlink( mIdentifierUpdate, getChannel() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setIdentifierMessage( int identifier, IdentifierUpdate message )
|
||||
{
|
||||
mIdentifierUpdate = message;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] getIdentifiers()
|
||||
{
|
||||
int[] identifiers = new int[ 1 ];
|
||||
|
||||
identifiers[ 0 ] = getIdentifier();
|
||||
|
||||
return identifiers;
|
||||
}
|
||||
}
|
||||
50
src/decode/p25/message/tsbk/motorola/MotorolaOpcode.java
Normal file
50
src/decode/p25/message/tsbk/motorola/MotorolaOpcode.java
Normal file
@@ -0,0 +1,50 @@
|
||||
package decode.p25.message.tsbk.motorola;
|
||||
|
||||
public enum MotorolaOpcode
|
||||
{
|
||||
UNKNOWN_OPCODE_5( "MOTO OPCODE 05 ", "Unknown Opcode 0x05", 0x05 ),
|
||||
SYSTEM_LOADING( "SYSTEM_LOADING ", "System Loading", 0x09 ),
|
||||
CHANNEL_CWID_UPDATE( "CHAN_CWID_UPDATE", "Channel FCC Callsign Update", 0x0B ),
|
||||
UNKNOWN( "UNKNOWN ", "Unknown", -1 );
|
||||
|
||||
private String mLabel;
|
||||
private String mDescription;
|
||||
private int mCode;
|
||||
|
||||
private MotorolaOpcode( String label, String description, int code )
|
||||
{
|
||||
mLabel = label;
|
||||
mDescription = description;
|
||||
mCode = code;
|
||||
}
|
||||
|
||||
public String getLabel()
|
||||
{
|
||||
return mLabel;
|
||||
}
|
||||
|
||||
public String getDescription()
|
||||
{
|
||||
return mDescription;
|
||||
}
|
||||
|
||||
public int getCode()
|
||||
{
|
||||
return mCode;
|
||||
}
|
||||
|
||||
public static MotorolaOpcode fromValue( int value )
|
||||
{
|
||||
switch( value )
|
||||
{
|
||||
case 0x05:
|
||||
return UNKNOWN_OPCODE_5;
|
||||
case 0x09:
|
||||
return SYSTEM_LOADING;
|
||||
case 0x0B:
|
||||
return CHANNEL_CWID_UPDATE;
|
||||
}
|
||||
|
||||
return UNKNOWN;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
package decode.p25.message.tsbk.motorola;
|
||||
|
||||
import alias.AliasList;
|
||||
import bits.BitSetBuffer;
|
||||
import decode.p25.message.tsbk.TSBKMessage;
|
||||
import decode.p25.reference.DataUnitID;
|
||||
|
||||
public class MotorolaTSBKMessage extends TSBKMessage
|
||||
{
|
||||
public MotorolaTSBKMessage( BitSetBuffer message, DataUnitID duid,
|
||||
AliasList aliasList )
|
||||
{
|
||||
super( message, duid, aliasList );
|
||||
}
|
||||
|
||||
protected String getMessageStub()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append( "SYS:" );
|
||||
sb.append( getNAC() ); /* NAC is the system id for TSBK messages */
|
||||
sb.append( " " );
|
||||
sb.append( getDUID().getLabel() );
|
||||
|
||||
sb.append( " MOTOROLA" );
|
||||
|
||||
if( isEncrypted() )
|
||||
{
|
||||
sb.append( " ENCRYPTED" );
|
||||
}
|
||||
|
||||
sb.append( " OPCD:" );
|
||||
sb.append( getMotorolaOpcode().getLabel() );
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public MotorolaOpcode getMotorolaOpcode()
|
||||
{
|
||||
return MotorolaOpcode.fromValue( mMessage.getInt( OPCODE ) );
|
||||
}
|
||||
}
|
||||
34
src/decode/p25/message/tsbk/motorola/SystemLoading.java
Normal file
34
src/decode/p25/message/tsbk/motorola/SystemLoading.java
Normal file
@@ -0,0 +1,34 @@
|
||||
package decode.p25.message.tsbk.motorola;
|
||||
|
||||
import alias.AliasList;
|
||||
import bits.BitSetBuffer;
|
||||
import decode.p25.message.tsbk.TSBKMessage;
|
||||
import decode.p25.reference.DataUnitID;
|
||||
|
||||
public class SystemLoading extends MotorolaTSBKMessage
|
||||
{
|
||||
public SystemLoading( BitSetBuffer message, DataUnitID duid,
|
||||
AliasList aliasList )
|
||||
{
|
||||
super( message, duid, aliasList );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getEventType()
|
||||
{
|
||||
return MotorolaOpcode.SYSTEM_LOADING.getLabel();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMessage()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append( getMessageStub() );
|
||||
|
||||
sb.append( " - " + getMessageHex() );
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -6,7 +6,7 @@ import decode.p25.message.tsbk.TSBKMessage;
|
||||
import decode.p25.reference.DataUnitID;
|
||||
import decode.p25.reference.Opcode;
|
||||
|
||||
public class AdjacentStatusBroadcast extends TSBKMessage
|
||||
public class AdjacentStatusBroadcast extends TSBKMessage implements IdentifierUpdateReceiver
|
||||
{
|
||||
public static final int[] LOCATION_REGISTRATION_AREA = { 80,81,82,83,84,85,
|
||||
86,87 };
|
||||
@@ -18,14 +18,17 @@ public class AdjacentStatusBroadcast extends TSBKMessage
|
||||
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[] 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 IdentifierUpdate mIdentifierUpdate;
|
||||
|
||||
public AdjacentStatusBroadcast( BitSetBuffer message,
|
||||
DataUnitID duid,
|
||||
AliasList aliasList )
|
||||
DataUnitID duid,
|
||||
AliasList aliasList )
|
||||
{
|
||||
super( message, duid, aliasList );
|
||||
}
|
||||
@@ -50,7 +53,11 @@ public class AdjacentStatusBroadcast extends TSBKMessage
|
||||
|
||||
sb.append( " SITE:" + getSiteID() );
|
||||
|
||||
sb.append( " CHAN:" + getChannel() );
|
||||
sb.append( " CHAN:" + getIdentifier() + "-" + getChannel() );
|
||||
|
||||
sb.append( " DN:" + getDownlinkFrequency() );
|
||||
|
||||
sb.append( " UP:" + getUplinkFrequency() );
|
||||
|
||||
if( isConventionalChannel() )
|
||||
{
|
||||
@@ -122,8 +129,39 @@ public class AdjacentStatusBroadcast extends TSBKMessage
|
||||
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, IdentifierUpdate 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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,22 +4,13 @@ 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 abstract class IdentifierUpdate extends TSBKMessage
|
||||
{
|
||||
public static final int[] CHANNEL_IDENTIFIER = { 80,81,82,83 };
|
||||
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[] 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 };
|
||||
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,
|
||||
@@ -32,42 +23,20 @@ public class IdentifierUpdate extends TSBKMessage
|
||||
super( message, duid, aliasList );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getEventType()
|
||||
{
|
||||
return getOpcode().getDescription();
|
||||
}
|
||||
|
||||
public String getMessage()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append( getMessageStub() );
|
||||
|
||||
sb.append( " CHAN:" + getIdentifier() );
|
||||
|
||||
sb.append( " DOWNLINK:" + getDownlinkFrequency() );
|
||||
|
||||
sb.append( " UPLINK:" + ( getUplinkFrequency() ) );
|
||||
|
||||
sb.append( " BW:" + getBandwidth() );
|
||||
|
||||
sb.append( " SPACING:" + getChannelSpacing() );
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* (Band) Identifier
|
||||
*/
|
||||
public int getIdentifier()
|
||||
{
|
||||
return mMessage.getInt( CHANNEL_IDENTIFIER );
|
||||
return mMessage.getInt( IDENTIFIER );
|
||||
}
|
||||
|
||||
/**
|
||||
* Channel spacing in hertz
|
||||
*/
|
||||
public int getChannelSpacing()
|
||||
public long getChannelSpacing()
|
||||
{
|
||||
return mMessage.getInt( CHANNEL_SPACING ) * 125; //Hertz
|
||||
return mMessage.getLong( CHANNEL_SPACING ) * 125l;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -75,79 +44,8 @@ public class IdentifierUpdate extends TSBKMessage
|
||||
*/
|
||||
public long getBaseFrequency()
|
||||
{
|
||||
return mMessage.getLong( BASE_FREQUENCY ) * 5l; //Hertz
|
||||
return mMessage.getLong( BASE_FREQUENCY ) * 5l;
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
public abstract long getTransmitOffset();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,73 @@
|
||||
package decode.p25.message.tsbk.osp.control;
|
||||
|
||||
import alias.AliasList;
|
||||
import bits.BitSetBuffer;
|
||||
import decode.p25.reference.DataUnitID;
|
||||
import decode.p25.reference.Opcode;
|
||||
|
||||
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( BitSetBuffer 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package decode.p25.message.tsbk.osp.control;
|
||||
|
||||
/**
|
||||
* Interface to allow messages to be augmented with IdentiferUpdateXXX type
|
||||
* messages that provide the channel information necessary to calculate the
|
||||
* uplink and downlink frequency for the channel.
|
||||
*/
|
||||
public interface IdentifierUpdateReceiver
|
||||
{
|
||||
public void setIdentifierMessage( int identifier, IdentifierUpdate message );
|
||||
|
||||
public int[] getIdentifiers();
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
package decode.p25.message.tsbk.osp.control;
|
||||
|
||||
import alias.AliasList;
|
||||
import bits.BitSetBuffer;
|
||||
import decode.p25.reference.DataUnitID;
|
||||
import decode.p25.reference.Opcode;
|
||||
|
||||
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( BitSetBuffer 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6,7 +6,7 @@ import decode.p25.message.tsbk.TSBKMessage;
|
||||
import decode.p25.reference.DataUnitID;
|
||||
import decode.p25.reference.Opcode;
|
||||
|
||||
public class NetworkStatusBroadcast extends TSBKMessage
|
||||
public class NetworkStatusBroadcast extends TSBKMessage implements IdentifierUpdateReceiver
|
||||
{
|
||||
public static final int[] LOCATION_REGISTRATION_AREA = { 80,81,82,83,84,85,
|
||||
86,87 };
|
||||
@@ -14,11 +14,14 @@ public class NetworkStatusBroadcast extends TSBKMessage
|
||||
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[] 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 IdentifierUpdate mIdentifierUpdate;
|
||||
|
||||
public NetworkStatusBroadcast( BitSetBuffer message,
|
||||
DataUnitID duid,
|
||||
AliasList aliasList )
|
||||
@@ -44,7 +47,11 @@ public class NetworkStatusBroadcast extends TSBKMessage
|
||||
|
||||
sb.append( " SYS:" + getSystemID() );
|
||||
|
||||
sb.append( " CNTRL CHAN:" + getChannel() );
|
||||
sb.append( " CTRL CHAN:" + getIdentifier() + "-" + getChannel() );
|
||||
|
||||
sb.append( " DN:" + getDownlinkFrequency() );
|
||||
|
||||
sb.append( " UP:" + getUplinkFrequency() );
|
||||
|
||||
sb.append( " SYS SVC CLASS:" +
|
||||
SystemService.toString( getSystemServiceClass() ) );
|
||||
@@ -66,6 +73,11 @@ public class NetworkStatusBroadcast extends TSBKMessage
|
||||
{
|
||||
return mMessage.getHex( SYSTEM_ID, 3 );
|
||||
}
|
||||
|
||||
public int getIdentifier()
|
||||
{
|
||||
return mMessage.getInt( IDENTIFIER );
|
||||
}
|
||||
|
||||
public int getChannel()
|
||||
{
|
||||
@@ -76,4 +88,30 @@ public class NetworkStatusBroadcast extends TSBKMessage
|
||||
{
|
||||
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, IdentifierUpdate 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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ import decode.p25.message.tsbk.TSBKMessage;
|
||||
import decode.p25.reference.DataUnitID;
|
||||
import decode.p25.reference.Opcode;
|
||||
|
||||
public class RFSSStatusBroadcast extends TSBKMessage
|
||||
public class RFSSStatusBroadcast extends TSBKMessage implements IdentifierUpdateReceiver
|
||||
{
|
||||
public static final int[] LOCATION_REGISTRATION_AREA = { 80,81,82,83,84,85,
|
||||
86,87 };
|
||||
@@ -15,11 +15,14 @@ public class RFSSStatusBroadcast extends TSBKMessage
|
||||
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[] 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 IdentifierUpdate mIdentifierUpdate;
|
||||
|
||||
public RFSSStatusBroadcast( BitSetBuffer message,
|
||||
DataUnitID duid,
|
||||
AliasList aliasList )
|
||||
@@ -47,8 +50,12 @@ public class RFSSStatusBroadcast extends TSBKMessage
|
||||
|
||||
sb.append( " SITE:" + getSiteID() );
|
||||
|
||||
sb.append( " CHAN:" + getChannel() );
|
||||
sb.append( " CHAN:" + getIdentifier() + "-" + getChannel() );
|
||||
|
||||
sb.append( " DN:" + getDownlinkFrequency() );
|
||||
|
||||
sb.append( " UP:" + getUplinkFrequency() );
|
||||
|
||||
if( hasActiveNetworkConnection() )
|
||||
{
|
||||
sb.append( " ACTIVE-NETWORK-CONN" );
|
||||
@@ -83,6 +90,11 @@ public class RFSSStatusBroadcast extends TSBKMessage
|
||||
{
|
||||
return mMessage.getHex( SITE_ID, 2 );
|
||||
}
|
||||
|
||||
public int getIdentifier()
|
||||
{
|
||||
return mMessage.getInt( IDENTIFIER );
|
||||
}
|
||||
|
||||
public int getChannel()
|
||||
{
|
||||
@@ -93,4 +105,30 @@ public class RFSSStatusBroadcast extends TSBKMessage
|
||||
{
|
||||
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, IdentifierUpdate 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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,24 +1,36 @@
|
||||
package decode.p25.message.tsbk.osp.control;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import alias.AliasList;
|
||||
import bits.BitSetBuffer;
|
||||
import decode.p25.message.tsbk.TSBKMessage;
|
||||
import decode.p25.reference.DataUnitID;
|
||||
import decode.p25.reference.Opcode;
|
||||
|
||||
public class SecondaryControlChannelBroadcast extends TSBKMessage
|
||||
public class SecondaryControlChannelBroadcast extends TSBKMessage
|
||||
implements IdentifierUpdateReceiver
|
||||
{
|
||||
public static final int[] RFSS_ID = { 80,81,82,83,84,85,86,87 };
|
||||
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[] CHANNEL_1 = { 96,97,98,99,100,101,102,103,104,105,
|
||||
106,107,108,109,110,111 };
|
||||
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[] CHANNEL_2 = { 120,121,122,123,124,125,126,127,
|
||||
128,129,130,131,132,133,134,135 };
|
||||
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 IdentifierUpdate mIdentifierUpdate1;
|
||||
private IdentifierUpdate mIdentifierUpdate2;
|
||||
|
||||
public SecondaryControlChannelBroadcast( BitSetBuffer message,
|
||||
DataUnitID duid,
|
||||
AliasList aliasList )
|
||||
@@ -42,22 +54,27 @@ public class SecondaryControlChannelBroadcast extends TSBKMessage
|
||||
|
||||
sb.append( " SITE:" + getSiteID() );
|
||||
|
||||
sb.append( " CHAN 1:" + getChannel1() );
|
||||
sb.append( " CHAN1:" + getIdentifier1() + "-" + getChannel1() );
|
||||
|
||||
sb.append( " SVC CLASS 1:" +
|
||||
sb.append( " DN1:" + getDownlinkFrequency1() );
|
||||
|
||||
sb.append( " UP1:" + getUplinkFrequency1() );
|
||||
|
||||
sb.append( " SVC1:" +
|
||||
SystemService.toString( getSystemServiceClass1() ) );
|
||||
|
||||
if( hasChannel2() )
|
||||
{
|
||||
sb.append( " CHAN 2:" + getChannel2() );
|
||||
sb.append( " CHAN2:" + getIdentifier2() + "-" + getChannel2() );
|
||||
|
||||
sb.append( " SVC CLASS 2:" +
|
||||
sb.append( " DN2:" + getDownlinkFrequency2() );
|
||||
|
||||
sb.append( " UP2:" + getUplinkFrequency2() );
|
||||
|
||||
sb.append( " SVC2:" +
|
||||
SystemService.toString( getSystemServiceClass2() ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.append( " CHAN 2: empty" );
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
@@ -71,6 +88,11 @@ public class SecondaryControlChannelBroadcast extends TSBKMessage
|
||||
return mMessage.getHex( SITE_ID, 2 );
|
||||
}
|
||||
|
||||
public int getIdentifier1()
|
||||
{
|
||||
return mMessage.getInt( IDENTIFIER_1 );
|
||||
}
|
||||
|
||||
public int getChannel1()
|
||||
{
|
||||
return mMessage.getInt( CHANNEL_1 );
|
||||
@@ -80,6 +102,11 @@ public class SecondaryControlChannelBroadcast extends TSBKMessage
|
||||
{
|
||||
return mMessage.getInt( SYSTEM_SERVICE_CLASS_1 );
|
||||
}
|
||||
|
||||
public int getIdentifier2()
|
||||
{
|
||||
return mMessage.getInt( IDENTIFIER_2 );
|
||||
}
|
||||
|
||||
public int getChannel2()
|
||||
{
|
||||
@@ -95,4 +122,64 @@ public class SecondaryControlChannelBroadcast extends TSBKMessage
|
||||
{
|
||||
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, IdentifierUpdate message )
|
||||
{
|
||||
if( identifier == getIdentifier1() )
|
||||
{
|
||||
mIdentifierUpdate1 = message;
|
||||
}
|
||||
else if( identifier == getIdentifier2() )
|
||||
{
|
||||
mIdentifierUpdate2 = message;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new IllegalArgumentException( "Unexpected identifier update "
|
||||
+ "message for identifier [" + identifier + "]" );
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
package decode.p25.message.tsbk.osp.control;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import alias.AliasList;
|
||||
import bits.BitSetBuffer;
|
||||
import decode.p25.reference.DataUnitID;
|
||||
import decode.p25.reference.Opcode;
|
||||
|
||||
public class SecondaryControlChannelBroadcastExplicit
|
||||
extends SecondaryControlChannelBroadcast
|
||||
{
|
||||
private final static Logger mLog = LoggerFactory.getLogger(
|
||||
SecondaryControlChannelBroadcastExplicit.class );
|
||||
|
||||
public SecondaryControlChannelBroadcastExplicit( BitSetBuffer 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( " RFSS:" + getRFSS() );
|
||||
|
||||
sb.append( " SITE:" + 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();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,155 @@
|
||||
package 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 alias.AliasList;
|
||||
import bits.BitSetBuffer;
|
||||
import decode.p25.message.tsbk.TSBKMessage;
|
||||
import decode.p25.reference.DataUnitID;
|
||||
import decode.p25.reference.Opcode;
|
||||
|
||||
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( BitSetBuffer 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( 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 );
|
||||
}
|
||||
}
|
||||
24
src/decode/p25/message/tsbk/osp/data/SNDCPData.java
Normal file
24
src/decode/p25/message/tsbk/osp/data/SNDCPData.java
Normal file
@@ -0,0 +1,24 @@
|
||||
package decode.p25.message.tsbk.osp.data;
|
||||
|
||||
import alias.AliasList;
|
||||
import bits.BitSetBuffer;
|
||||
import decode.p25.message.tsbk.ServiceMessage;
|
||||
import decode.p25.reference.DataUnitID;
|
||||
|
||||
public abstract class SNDCPData extends ServiceMessage
|
||||
{
|
||||
public static final int[] NETWORK_SERVICE_ACCESS_POINT_ID = { 84,85,86,87 };
|
||||
|
||||
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 SNDCPData( BitSetBuffer message,
|
||||
DataUnitID duid,
|
||||
AliasList aliasList )
|
||||
{
|
||||
super( message, duid, aliasList );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,148 @@
|
||||
package decode.p25.message.tsbk.osp.data;
|
||||
|
||||
import alias.AliasList;
|
||||
import bits.BitSetBuffer;
|
||||
import decode.p25.message.tsbk.osp.control.IdentifierUpdate;
|
||||
import decode.p25.message.tsbk.osp.control.IdentifierUpdateReceiver;
|
||||
import decode.p25.reference.DataUnitID;
|
||||
|
||||
public class SNDCPDataChannelAnnouncementExplicit extends SNDCPData
|
||||
implements IdentifierUpdateReceiver
|
||||
{
|
||||
public static final int AUTONOMOUS_ACCESS_AVAILABLE_INDICATOR = 88;
|
||||
public static final int REQUESTED_ACCESS_AVAILABLE_INDICATOR = 89;
|
||||
|
||||
public static final int[] TRANSMIT_IDENTIFIER = { 96,97,98,99 };
|
||||
public static final int[] TRANSMIT_CHANNEL = { 100,101,102,103,104,105,106,
|
||||
107,108,109,110,111 };
|
||||
public static final int[] RECEIVE_IDENTIFIER = { 112,113,114,115 };
|
||||
public static final int[] RECEIVE_CHANNEL = { 116,117,118,119,120,121,122,
|
||||
123,124,125,126,127 };
|
||||
|
||||
public static final int[] DATA_ACCESS_CONTROL = { 128,129,130,131,132,133,
|
||||
134,135,136,137,138,139,140,141,142,143 };
|
||||
|
||||
private IdentifierUpdate mIdentifierUpdateTransmit;
|
||||
private IdentifierUpdate mIdentifierUpdateReceive;
|
||||
|
||||
public SNDCPDataChannelAnnouncementExplicit( BitSetBuffer message,
|
||||
DataUnitID duid,
|
||||
AliasList aliasList )
|
||||
{
|
||||
super( message, duid, aliasList );
|
||||
}
|
||||
|
||||
public String getMessage()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append( getMessageStub() );
|
||||
|
||||
if( isEmergency() )
|
||||
{
|
||||
sb.append( " EMERGENCY" );
|
||||
}
|
||||
|
||||
if( isAutonomousAccessAvailable() )
|
||||
{
|
||||
sb.append( " AUTONOMOUS ACCESS" );
|
||||
}
|
||||
|
||||
if( isRequestedAccessAvailable() )
|
||||
{
|
||||
sb.append( " DOWNLINK:" );
|
||||
sb.append( getTransmitIdentifier() + "-" + getTransmitChannel() );
|
||||
|
||||
sb.append( " " + getUplinkFrequency() );
|
||||
|
||||
sb.append( " UPLINK:" );
|
||||
sb.append( getReceiveIdentifier() + "-" + getReceiveChannel() );
|
||||
|
||||
sb.append( " " + getDownlinkFrequency() );
|
||||
|
||||
sb.append( " DATA ACCESS CONTROL:" );
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.append( " ACCESS DENIED TO DATA ACCESS CONTROL:" );
|
||||
}
|
||||
|
||||
sb.append( getDataAccessControl() );
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public boolean isAutonomousAccessAvailable()
|
||||
{
|
||||
return mMessage.get( AUTONOMOUS_ACCESS_AVAILABLE_INDICATOR );
|
||||
}
|
||||
|
||||
public boolean isRequestedAccessAvailable()
|
||||
{
|
||||
return mMessage.get( REQUESTED_ACCESS_AVAILABLE_INDICATOR );
|
||||
}
|
||||
|
||||
public int getTransmitIdentifier()
|
||||
{
|
||||
return mMessage.getInt( TRANSMIT_IDENTIFIER );
|
||||
}
|
||||
|
||||
public int getTransmitChannel()
|
||||
{
|
||||
return mMessage.getInt( TRANSMIT_CHANNEL );
|
||||
}
|
||||
|
||||
public int getReceiveIdentifier()
|
||||
{
|
||||
return mMessage.getInt( RECEIVE_IDENTIFIER );
|
||||
}
|
||||
|
||||
public int getReceiveChannel()
|
||||
{
|
||||
return mMessage.getInt( RECEIVE_CHANNEL );
|
||||
}
|
||||
|
||||
public String getDataAccessControl()
|
||||
{
|
||||
return mMessage.getHex( DATA_ACCESS_CONTROL, 4 );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setIdentifierMessage( int identifier, IdentifierUpdate message )
|
||||
{
|
||||
if( identifier == getTransmitIdentifier() )
|
||||
{
|
||||
mIdentifierUpdateTransmit = message;
|
||||
}
|
||||
else if( identifier == getReceiveIdentifier() )
|
||||
{
|
||||
mIdentifierUpdateReceive = message;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new IllegalArgumentException( "unexpected channel band "
|
||||
+ "identifier [" + identifier + "]" );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] getIdentifiers()
|
||||
{
|
||||
int[] identifiers = new int[ 2 ];
|
||||
|
||||
identifiers[ 0 ] = getTransmitIdentifier();
|
||||
identifiers[ 1 ] = getReceiveIdentifier();
|
||||
|
||||
return identifiers;
|
||||
}
|
||||
|
||||
public long getDownlinkFrequency()
|
||||
{
|
||||
return calculateDownlink( mIdentifierUpdateTransmit, getReceiveChannel() );
|
||||
}
|
||||
|
||||
public long getUplinkFrequency()
|
||||
{
|
||||
return calculateUplink( mIdentifierUpdateReceive, getTransmitChannel() );
|
||||
}
|
||||
}
|
||||
123
src/decode/p25/message/tsbk/osp/data/SNDCPDataChannelGrant.java
Normal file
123
src/decode/p25/message/tsbk/osp/data/SNDCPDataChannelGrant.java
Normal file
@@ -0,0 +1,123 @@
|
||||
package decode.p25.message.tsbk.osp.data;
|
||||
|
||||
import alias.AliasList;
|
||||
import bits.BitSetBuffer;
|
||||
import decode.p25.message.tsbk.osp.control.IdentifierUpdate;
|
||||
import decode.p25.message.tsbk.osp.control.IdentifierUpdateReceiver;
|
||||
import decode.p25.reference.DataUnitID;
|
||||
|
||||
public class SNDCPDataChannelGrant extends SNDCPData implements IdentifierUpdateReceiver
|
||||
{
|
||||
public static final int[] TRANSMIT_IDENTIFIER = { 88,89,90,91 };
|
||||
public static final int[] TRANSMIT_CHANNEL = { 92,93,94,95,96,97,98,99,100,
|
||||
101,102,103 };
|
||||
public static final int[] RECEIVE_IDENTIFIER = { 104,105,106,107 };
|
||||
public static final int[] RECEIVE_CHANNEL = { 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 };
|
||||
|
||||
private IdentifierUpdate mIdentifierUpdateTransmit;
|
||||
private IdentifierUpdate mIdentifierUpdateReceive;
|
||||
|
||||
public SNDCPDataChannelGrant( BitSetBuffer message,
|
||||
DataUnitID duid,
|
||||
AliasList aliasList )
|
||||
{
|
||||
super( message, duid, aliasList );
|
||||
}
|
||||
|
||||
public String getMessage()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append( getMessageStub() );
|
||||
|
||||
if( isEmergency() )
|
||||
{
|
||||
sb.append( " EMERGENCY" );
|
||||
}
|
||||
|
||||
sb.append( " UPLINK:" );
|
||||
sb.append( getTransmitIdentifier() + "-" + getTransmitChannel() );
|
||||
|
||||
sb.append( " " + getUplinkFrequency() );
|
||||
|
||||
sb.append( " DOWNLINK:" );
|
||||
sb.append( getReceiveIdentifier() + "-" + getReceiveChannel() );
|
||||
|
||||
sb.append( " " + getDownlinkFrequency() );
|
||||
|
||||
sb.append( " TGT:" );
|
||||
sb.append( getTargetAddress() );
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public int getTransmitIdentifier()
|
||||
{
|
||||
return mMessage.getInt( TRANSMIT_IDENTIFIER );
|
||||
}
|
||||
|
||||
public int getTransmitChannel()
|
||||
{
|
||||
return mMessage.getInt( TRANSMIT_CHANNEL );
|
||||
}
|
||||
|
||||
public int getReceiveIdentifier()
|
||||
{
|
||||
return mMessage.getInt( RECEIVE_IDENTIFIER );
|
||||
}
|
||||
|
||||
public int getReceiveChannel()
|
||||
{
|
||||
return mMessage.getInt( RECEIVE_CHANNEL );
|
||||
}
|
||||
|
||||
public String getTargetAddress()
|
||||
{
|
||||
return mMessage.getHex( TARGET_ADDRESS, 6 );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setIdentifierMessage( int identifier, IdentifierUpdate message )
|
||||
{
|
||||
if( identifier == getTransmitIdentifier() )
|
||||
{
|
||||
mIdentifierUpdateTransmit = message;
|
||||
}
|
||||
else if( identifier == getReceiveIdentifier() )
|
||||
{
|
||||
mIdentifierUpdateReceive = message;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new IllegalArgumentException( "unexpected channel band "
|
||||
+ "identifier [" + identifier + "]" );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] getIdentifiers()
|
||||
{
|
||||
int[] identifiers = new int[ 2 ];
|
||||
|
||||
identifiers[ 0 ] = getTransmitIdentifier();
|
||||
identifiers[ 1 ] = getReceiveIdentifier();
|
||||
|
||||
return identifiers;
|
||||
}
|
||||
|
||||
public long getDownlinkFrequency()
|
||||
{
|
||||
return calculateDownlink( mIdentifierUpdateReceive, getReceiveChannel() );
|
||||
}
|
||||
|
||||
public long getUplinkFrequency()
|
||||
{
|
||||
return calculateUplink( mIdentifierUpdateTransmit, getTransmitChannel() );
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
package decode.p25.message.tsbk.osp.data;
|
||||
|
||||
import alias.AliasList;
|
||||
import bits.BitSetBuffer;
|
||||
import decode.p25.reference.DataUnitID;
|
||||
|
||||
public class SNDCPDataPageRequest extends SNDCPData
|
||||
{
|
||||
public static final int[] DATA_ACCESS_CONTROL = { 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 SNDCPDataPageRequest( BitSetBuffer message,
|
||||
DataUnitID duid,
|
||||
AliasList aliasList )
|
||||
{
|
||||
super( message, duid, aliasList );
|
||||
}
|
||||
|
||||
public String getMessage()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append( getMessageStub() );
|
||||
|
||||
if( isEmergency() )
|
||||
{
|
||||
sb.append( " EMERGENCY" );
|
||||
}
|
||||
|
||||
sb.append( " TGT:" );
|
||||
sb.append( getTargetAddress() );
|
||||
|
||||
sb.append( " DAC:" );
|
||||
sb.append( getDataAccessControl() );
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public String getDataAccessControl()
|
||||
{
|
||||
return mMessage.getHex( DATA_ACCESS_CONTROL, 4 );
|
||||
}
|
||||
|
||||
public String getTargetAddress()
|
||||
{
|
||||
return mMessage.getHex( TARGET_ADDRESS, 6 );
|
||||
}
|
||||
}
|
||||
@@ -63,7 +63,7 @@ public enum Opcode
|
||||
RFSS_STATUS_BROADCAST( "RFSS_STATUS_BCST", "RFSS Status Broadcast", 58 ),
|
||||
NETWORK_STATUS_BROADCAST( "NET_STATUS_BCAST", "Network Status Broadcast", 59 ),
|
||||
ADJACENT_STATUS_BROADCAST( "NGHBR_STAT_BCAST", "Adjacent Status Broadcast", 60 ),
|
||||
IDENTIFIER_UPDATE( "IDEN_UPDATE ", "Identifier Update", 61 ),
|
||||
IDENTIFIER_UPDATE_NON_VUHF( "IDEN_UPDATE ", "Identifier Update", 61 ),
|
||||
PROTECTION_PARAMETER_BROADCAST( "ENCRYPT_PAR_BCST", "Protection Parameter Broadcast", 62 ),
|
||||
PROTECTION_PARAMETER_UPDATE( "ENCRYPT_PAR_UPDT", "Protection Parameter Update", 63 ),
|
||||
UNKNOWN( "UNKNOWN ", "Unknown", -1 );
|
||||
|
||||
@@ -3,7 +3,7 @@ package decode.p25.reference;
|
||||
public enum Vendor
|
||||
{
|
||||
STANDARD( "STANDARD", "STANDARD", 0),
|
||||
V1( "VENDOR01", "V_01", 1),
|
||||
STANDARD_V1( "STANDARD", "STANDARD_01", 1),
|
||||
V2( "VENDOR02", "V_02", 2),
|
||||
V3( "VENDOR03", "V_03", 3),
|
||||
V4( "VENDOR04", "V_04", 4),
|
||||
|
||||
Reference in New Issue
Block a user