From 23901c7a2f9fb6d5542c69de5c4c3307a74f8733 Mon Sep 17 00:00:00 2001 From: "dennis.sheirer" Date: Sun, 23 Nov 2014 23:13:58 +0000 Subject: [PATCH] P25 work in progress - final commit of TSBK message parsers --- src/decode/DecoderType.java | 2 +- src/decode/p25/P25CallEvent.java | 154 +++++++++++++++ src/decode/p25/P25ChannelState.java | 17 +- src/decode/p25/P25Decoder.java | 1 + src/decode/p25/P25MessageProcessor.java | 57 ++++++ src/decode/p25/message/tsbk/ChannelGrant.java | 35 +--- .../p25/message/tsbk/ServiceMessage.java | 45 +++++ src/decode/p25/message/tsbk/TSBKMessage.java | 24 +++ .../p25/message/tsbk/TSBKMessageFactory.java | 52 ++++- .../tsbk/motorola/ChannelCWIDUpdate.java | 184 ++++++++++++++++++ .../message/tsbk/motorola/MotorolaOpcode.java | 50 +++++ .../tsbk/motorola/MotorolaTSBKMessage.java | 42 ++++ .../message/tsbk/motorola/SystemLoading.java | 34 ++++ .../osp/control/AdjacentStatusBroadcast.java | 50 ++++- .../tsbk/osp/control/IdentifierUpdate.java | 124 ++---------- .../osp/control/IdentifierUpdateNonVUHF.java | 73 +++++++ .../osp/control/IdentifierUpdateReceiver.java | 13 ++ .../osp/control/IdentifierUpdateVUHF.java | 85 ++++++++ .../osp/control/NetworkStatusBroadcast.java | 46 ++++- .../tsbk/osp/control/RFSSStatusBroadcast.java | 46 ++++- .../SecondaryControlChannelBroadcast.java | 115 +++++++++-- ...ondaryControlChannelBroadcastExplicit.java | 60 ++++++ .../osp/control/TimeAndDateAnnouncement.java | 155 +++++++++++++++ .../p25/message/tsbk/osp/data/SNDCPData.java | 24 +++ .../SNDCPDataChannelAnnouncementExplicit.java | 148 ++++++++++++++ .../tsbk/osp/data/SNDCPDataChannelGrant.java | 123 ++++++++++++ .../tsbk/osp/data/SNDCPDataPageRequest.java | 51 +++++ src/decode/p25/reference/Opcode.java | 2 +- src/decode/p25/reference/Vendor.java | 2 +- 29 files changed, 1630 insertions(+), 184 deletions(-) create mode 100644 src/decode/p25/P25CallEvent.java create mode 100644 src/decode/p25/message/tsbk/ServiceMessage.java create mode 100644 src/decode/p25/message/tsbk/motorola/ChannelCWIDUpdate.java create mode 100644 src/decode/p25/message/tsbk/motorola/MotorolaOpcode.java create mode 100644 src/decode/p25/message/tsbk/motorola/MotorolaTSBKMessage.java create mode 100644 src/decode/p25/message/tsbk/motorola/SystemLoading.java create mode 100644 src/decode/p25/message/tsbk/osp/control/IdentifierUpdateNonVUHF.java create mode 100644 src/decode/p25/message/tsbk/osp/control/IdentifierUpdateReceiver.java create mode 100644 src/decode/p25/message/tsbk/osp/control/IdentifierUpdateVUHF.java create mode 100644 src/decode/p25/message/tsbk/osp/control/SecondaryControlChannelBroadcastExplicit.java create mode 100644 src/decode/p25/message/tsbk/osp/control/TimeAndDateAnnouncement.java create mode 100644 src/decode/p25/message/tsbk/osp/data/SNDCPData.java create mode 100644 src/decode/p25/message/tsbk/osp/data/SNDCPDataChannelAnnouncementExplicit.java create mode 100644 src/decode/p25/message/tsbk/osp/data/SNDCPDataChannelGrant.java create mode 100644 src/decode/p25/message/tsbk/osp/data/SNDCPDataPageRequest.java diff --git a/src/decode/DecoderType.java b/src/decode/DecoderType.java index 2a96eb57..8487051b 100644 --- a/src/decode/DecoderType.java +++ b/src/decode/DecoderType.java @@ -60,7 +60,7 @@ public enum DecoderType DecoderType.LTR_STANDARD, DecoderType.MPT1327, DecoderType.NBFM, -// DecoderType.P25_PHASE1, + DecoderType.P25_PHASE1, DecoderType.PASSPORT ); } diff --git a/src/decode/p25/P25CallEvent.java b/src/decode/p25/P25CallEvent.java new file mode 100644 index 00000000..22dfdaad --- /dev/null +++ b/src/decode/p25/P25CallEvent.java @@ -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 + ******************************************************************************/ +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 ); + } + +} diff --git a/src/decode/p25/P25ChannelState.java b/src/decode/p25/P25ChannelState.java index 4603c32e..bc23528b 100644 --- a/src/decode/p25/P25ChannelState.java +++ b/src/decode/p25/P25ChannelState.java @@ -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() { diff --git a/src/decode/p25/P25Decoder.java b/src/decode/p25/P25Decoder.java index edced6fb..9d7ec70c 100644 --- a/src/decode/p25/P25Decoder.java +++ b/src/decode/p25/P25Decoder.java @@ -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 ); diff --git a/src/decode/p25/P25MessageProcessor.java b/src/decode/p25/P25MessageProcessor.java index 993fce9c..2afb8536 100644 --- a/src/decode/p25/P25MessageProcessor.java +++ b/src/decode/p25/P25MessageProcessor.java @@ -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 { private final static Logger mLog = LoggerFactory.getLogger( P25MessageProcessor.class ); + private Broadcaster mBroadcaster = new Broadcaster(); + + /* 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 mIdentifierMap = + new HashMap(); + private AliasList mAliasList; public P25MessageProcessor( AliasList aliasList ) @@ -24,6 +40,29 @@ public class P25MessageProcessor implements Listener @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 { mLog.debug( message.getMessage() + "\t" + message.getBinaryMessage() ); } + + mBroadcaster.broadcast( message ); + } + + public void dispose() + { + mIdentifierMap.clear(); + mBroadcaster.dispose(); + } + + public void addMessageListener( Listener listener ) + { + mBroadcaster.addListener( listener ); + } + + public void removeMessageListener( Listener listener ) + { + mBroadcaster.removeListener( listener ); } } diff --git a/src/decode/p25/message/tsbk/ChannelGrant.java b/src/decode/p25/message/tsbk/ChannelGrant.java index 2750725d..575f4c3a 100644 --- a/src/decode/p25/message/tsbk/ChannelGrant.java +++ b/src/decode/p25/message/tsbk/ChannelGrant.java @@ -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 */ diff --git a/src/decode/p25/message/tsbk/ServiceMessage.java b/src/decode/p25/message/tsbk/ServiceMessage.java new file mode 100644 index 00000000..ec8aa8e4 --- /dev/null +++ b/src/decode/p25/message/tsbk/ServiceMessage.java @@ -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; + } +} diff --git a/src/decode/p25/message/tsbk/TSBKMessage.java b/src/decode/p25/message/tsbk/TSBKMessage.java index fec05dbc..42b0f025 100644 --- a/src/decode/p25/message/tsbk/TSBKMessage.java +++ b/src/decode/p25/message/tsbk/TSBKMessage.java @@ -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; + } } diff --git a/src/decode/p25/message/tsbk/TSBKMessageFactory.java b/src/decode/p25/message/tsbk/TSBKMessageFactory.java index fee8444a..b18631ba 100644 --- a/src/decode/p25/message/tsbk/TSBKMessageFactory.java +++ b/src/decode/p25/message/tsbk/TSBKMessageFactory.java @@ -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 ); } diff --git a/src/decode/p25/message/tsbk/motorola/ChannelCWIDUpdate.java b/src/decode/p25/message/tsbk/motorola/ChannelCWIDUpdate.java new file mode 100644 index 00000000..f1a91ff9 --- /dev/null +++ b/src/decode/p25/message/tsbk/motorola/ChannelCWIDUpdate.java @@ -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; + } +} diff --git a/src/decode/p25/message/tsbk/motorola/MotorolaOpcode.java b/src/decode/p25/message/tsbk/motorola/MotorolaOpcode.java new file mode 100644 index 00000000..b1e1b7ff --- /dev/null +++ b/src/decode/p25/message/tsbk/motorola/MotorolaOpcode.java @@ -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; + } +} diff --git a/src/decode/p25/message/tsbk/motorola/MotorolaTSBKMessage.java b/src/decode/p25/message/tsbk/motorola/MotorolaTSBKMessage.java new file mode 100644 index 00000000..d73b6394 --- /dev/null +++ b/src/decode/p25/message/tsbk/motorola/MotorolaTSBKMessage.java @@ -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 ) ); + } +} diff --git a/src/decode/p25/message/tsbk/motorola/SystemLoading.java b/src/decode/p25/message/tsbk/motorola/SystemLoading.java new file mode 100644 index 00000000..c5885872 --- /dev/null +++ b/src/decode/p25/message/tsbk/motorola/SystemLoading.java @@ -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(); + } + +} diff --git a/src/decode/p25/message/tsbk/osp/control/AdjacentStatusBroadcast.java b/src/decode/p25/message/tsbk/osp/control/AdjacentStatusBroadcast.java index 0071ea3e..b40b0b60 100644 --- a/src/decode/p25/message/tsbk/osp/control/AdjacentStatusBroadcast.java +++ b/src/decode/p25/message/tsbk/osp/control/AdjacentStatusBroadcast.java @@ -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; + } } diff --git a/src/decode/p25/message/tsbk/osp/control/IdentifierUpdate.java b/src/decode/p25/message/tsbk/osp/control/IdentifierUpdate.java index b5671515..5481954b 100644 --- a/src/decode/p25/message/tsbk/osp/control/IdentifierUpdate.java +++ b/src/decode/p25/message/tsbk/osp/control/IdentifierUpdate.java @@ -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(); } diff --git a/src/decode/p25/message/tsbk/osp/control/IdentifierUpdateNonVUHF.java b/src/decode/p25/message/tsbk/osp/control/IdentifierUpdateNonVUHF.java new file mode 100644 index 00000000..f64d4d19 --- /dev/null +++ b/src/decode/p25/message/tsbk/osp/control/IdentifierUpdateNonVUHF.java @@ -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; + } + } +} diff --git a/src/decode/p25/message/tsbk/osp/control/IdentifierUpdateReceiver.java b/src/decode/p25/message/tsbk/osp/control/IdentifierUpdateReceiver.java new file mode 100644 index 00000000..6c5ca26e --- /dev/null +++ b/src/decode/p25/message/tsbk/osp/control/IdentifierUpdateReceiver.java @@ -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(); +} diff --git a/src/decode/p25/message/tsbk/osp/control/IdentifierUpdateVUHF.java b/src/decode/p25/message/tsbk/osp/control/IdentifierUpdateVUHF.java new file mode 100644 index 00000000..70420048 --- /dev/null +++ b/src/decode/p25/message/tsbk/osp/control/IdentifierUpdateVUHF.java @@ -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; + } + } +} diff --git a/src/decode/p25/message/tsbk/osp/control/NetworkStatusBroadcast.java b/src/decode/p25/message/tsbk/osp/control/NetworkStatusBroadcast.java index 922b22fd..ab2ac3c6 100644 --- a/src/decode/p25/message/tsbk/osp/control/NetworkStatusBroadcast.java +++ b/src/decode/p25/message/tsbk/osp/control/NetworkStatusBroadcast.java @@ -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; + } } diff --git a/src/decode/p25/message/tsbk/osp/control/RFSSStatusBroadcast.java b/src/decode/p25/message/tsbk/osp/control/RFSSStatusBroadcast.java index 21042adf..728c376b 100644 --- a/src/decode/p25/message/tsbk/osp/control/RFSSStatusBroadcast.java +++ b/src/decode/p25/message/tsbk/osp/control/RFSSStatusBroadcast.java @@ -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; + } } diff --git a/src/decode/p25/message/tsbk/osp/control/SecondaryControlChannelBroadcast.java b/src/decode/p25/message/tsbk/osp/control/SecondaryControlChannelBroadcast.java index 4f404d0a..75cc0e9a 100644 --- a/src/decode/p25/message/tsbk/osp/control/SecondaryControlChannelBroadcast.java +++ b/src/decode/p25/message/tsbk/osp/control/SecondaryControlChannelBroadcast.java @@ -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; + } } diff --git a/src/decode/p25/message/tsbk/osp/control/SecondaryControlChannelBroadcastExplicit.java b/src/decode/p25/message/tsbk/osp/control/SecondaryControlChannelBroadcastExplicit.java new file mode 100644 index 00000000..6d7aa2f6 --- /dev/null +++ b/src/decode/p25/message/tsbk/osp/control/SecondaryControlChannelBroadcastExplicit.java @@ -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(); + } + + +} diff --git a/src/decode/p25/message/tsbk/osp/control/TimeAndDateAnnouncement.java b/src/decode/p25/message/tsbk/osp/control/TimeAndDateAnnouncement.java new file mode 100644 index 00000000..d55a6548 --- /dev/null +++ b/src/decode/p25/message/tsbk/osp/control/TimeAndDateAnnouncement.java @@ -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 ); + } +} diff --git a/src/decode/p25/message/tsbk/osp/data/SNDCPData.java b/src/decode/p25/message/tsbk/osp/data/SNDCPData.java new file mode 100644 index 00000000..6a30607b --- /dev/null +++ b/src/decode/p25/message/tsbk/osp/data/SNDCPData.java @@ -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 ); + } +} diff --git a/src/decode/p25/message/tsbk/osp/data/SNDCPDataChannelAnnouncementExplicit.java b/src/decode/p25/message/tsbk/osp/data/SNDCPDataChannelAnnouncementExplicit.java new file mode 100644 index 00000000..9c4b0777 --- /dev/null +++ b/src/decode/p25/message/tsbk/osp/data/SNDCPDataChannelAnnouncementExplicit.java @@ -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() ); + } +} diff --git a/src/decode/p25/message/tsbk/osp/data/SNDCPDataChannelGrant.java b/src/decode/p25/message/tsbk/osp/data/SNDCPDataChannelGrant.java new file mode 100644 index 00000000..ae398a4f --- /dev/null +++ b/src/decode/p25/message/tsbk/osp/data/SNDCPDataChannelGrant.java @@ -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() ); + } + + +} diff --git a/src/decode/p25/message/tsbk/osp/data/SNDCPDataPageRequest.java b/src/decode/p25/message/tsbk/osp/data/SNDCPDataPageRequest.java new file mode 100644 index 00000000..cd51844b --- /dev/null +++ b/src/decode/p25/message/tsbk/osp/data/SNDCPDataPageRequest.java @@ -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 ); + } +} diff --git a/src/decode/p25/reference/Opcode.java b/src/decode/p25/reference/Opcode.java index 6f963e20..fa828a45 100644 --- a/src/decode/p25/reference/Opcode.java +++ b/src/decode/p25/reference/Opcode.java @@ -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 ); diff --git a/src/decode/p25/reference/Vendor.java b/src/decode/p25/reference/Vendor.java index 7014b8e9..07b504fa 100644 --- a/src/decode/p25/reference/Vendor.java +++ b/src/decode/p25/reference/Vendor.java @@ -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),