mirror of
https://github.com/DSheirer/sdrtrunk.git
synced 2026-11-12 16:47:31 -05:00
Initial commit of redesigned internal processing and audio management.
Note: Several of the decoders are currently non-functioning in this commit. If you want the latest functioning codebase, please checkout the commit prior to this one. All decoders will eventually be updated with this new architecture. Currently broken: - Logging and recording - Aux decoders (Fleetsync/MDC/LoJack/Tait) - LTR/Passport decoders Changes in this commit: - Module architecture for decoders and components with central provisioning by the DecoderFactory - Transition from Complex sample stream processing to float buffer processing for improved memory management - Redesigned filter structures - to support buffers and streams - Resolved several memory leak issues - Universal sharing of the thread pool manager - Added centralized audio management with call/user prioritization and new gui with mute/volume controls - Embedded audio metadata for eventual streaming support - Redesigned ProcessingChain to support independent re-use - Added new TrafficChannelManager to handle traffic channel allocations - Traffic Channel pool size and Call timeout available in P25 and MPT1327 configs - Redesigned channel and decoder gui components
This commit is contained in:
32
src/module/decode/p25/message/IBandIdentifier.java
Normal file
32
src/module/decode/p25/message/IBandIdentifier.java
Normal file
@@ -0,0 +1,32 @@
|
||||
package module.decode.p25.message;
|
||||
|
||||
public interface IBandIdentifier
|
||||
{
|
||||
|
||||
/**
|
||||
* (Band) Identifier
|
||||
*/
|
||||
public abstract int getIdentifier();
|
||||
|
||||
/**
|
||||
* Channel spacing in hertz
|
||||
*/
|
||||
public abstract long getChannelSpacing();
|
||||
|
||||
/**
|
||||
* Base frequency in hertz
|
||||
*/
|
||||
public abstract long getBaseFrequency();
|
||||
|
||||
|
||||
/**
|
||||
* Channel bandwidth in hertz
|
||||
*/
|
||||
public abstract int getBandwidth();
|
||||
|
||||
/**
|
||||
* Transmit offset in hertz
|
||||
*/
|
||||
public abstract long getTransmitOffset();
|
||||
|
||||
}
|
||||
14
src/module/decode/p25/message/IdentifierReceiver.java
Normal file
14
src/module/decode/p25/message/IdentifierReceiver.java
Normal file
@@ -0,0 +1,14 @@
|
||||
package module.decode.p25.message;
|
||||
|
||||
|
||||
/**
|
||||
* 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 IdentifierReceiver
|
||||
{
|
||||
public void setIdentifierMessage( int identifier, IBandIdentifier message );
|
||||
|
||||
public int[] getIdentifiers();
|
||||
}
|
||||
213
src/module/decode/p25/message/P25Message.java
Normal file
213
src/module/decode/p25/message/P25Message.java
Normal file
@@ -0,0 +1,213 @@
|
||||
package module.decode.p25.message;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
|
||||
import map.Plottable;
|
||||
import message.Message;
|
||||
import module.decode.p25.reference.DataUnitID;
|
||||
import alias.Alias;
|
||||
import alias.AliasList;
|
||||
import bits.BinaryMessage;
|
||||
import edac.CRC;
|
||||
|
||||
public class P25Message extends Message
|
||||
{
|
||||
public enum DuplexMode { HALF, FULL };
|
||||
public enum SessionMode { PACKET, CIRCUIT };
|
||||
|
||||
public static final int[] NAC = { 0,1,2,3,4,5,6,7,8,9,10,11 };
|
||||
public static final int[] DUID = { 12,13,14,15 };
|
||||
public static final int[] BCH = { 16,17,18,19,20,21,22,23,24,25,26,27,28,29,
|
||||
30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,
|
||||
54,55,56,57,58,59,60,61,62,63 };
|
||||
|
||||
protected SimpleDateFormat mTimeDurationFormat =
|
||||
new SimpleDateFormat( "HH:mm:ss.SSS");
|
||||
|
||||
protected BinaryMessage mMessage;
|
||||
protected DataUnitID mDUID;
|
||||
protected AliasList mAliasList;
|
||||
|
||||
protected CRC[] mCRC;
|
||||
|
||||
public P25Message( BinaryMessage message,
|
||||
DataUnitID duid,
|
||||
AliasList aliasList )
|
||||
{
|
||||
super();
|
||||
|
||||
mMessage = message;
|
||||
mDUID = duid;
|
||||
mAliasList = aliasList;
|
||||
}
|
||||
|
||||
public CRC[] getCRCResults()
|
||||
{
|
||||
return mCRC;
|
||||
}
|
||||
|
||||
public BinaryMessage getSourceMessage()
|
||||
{
|
||||
return mMessage;
|
||||
}
|
||||
|
||||
public AliasList getAliasList()
|
||||
{
|
||||
return mAliasList;
|
||||
}
|
||||
|
||||
public String getNAC()
|
||||
{
|
||||
return mMessage.getHex( NAC, 3 );
|
||||
}
|
||||
|
||||
public DataUnitID getDUID()
|
||||
{
|
||||
return mDUID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getErrorStatus()
|
||||
{
|
||||
if( mCRC == null )
|
||||
{
|
||||
return "UNKNOWN";
|
||||
}
|
||||
|
||||
return CRC.format( mCRC );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMessage()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append( "NAC:" );
|
||||
sb.append( getNAC() );
|
||||
sb.append( " " );
|
||||
sb.append( getDUID().getLabel() );
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getBinaryMessage()
|
||||
{
|
||||
return mMessage.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getProtocol()
|
||||
{
|
||||
return "P25 Phase 1";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getEventType()
|
||||
{
|
||||
return mDUID.name();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFromID()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Alias getFromIDAlias()
|
||||
{
|
||||
if( mAliasList != null )
|
||||
{
|
||||
return mAliasList.getTalkgroupAlias( getFromID() );
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getToID()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Alias getToIDAlias()
|
||||
{
|
||||
if( mAliasList != null )
|
||||
{
|
||||
return mAliasList.getTalkgroupAlias( getToID() );
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Plottable getPlottable()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return getMessage();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValid()
|
||||
{
|
||||
if( mCRC != null )
|
||||
{
|
||||
for( CRC crc: mCRC )
|
||||
{
|
||||
if( crc == CRC.FAILED_CRC )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the frequency of the uplink channel using the channel number
|
||||
* and the IdentifierUpdate message.
|
||||
*
|
||||
* @param iden - Identifier Update message
|
||||
* @param channel - channel number
|
||||
* @return - frequency in Hertz
|
||||
*/
|
||||
protected static long calculateUplink( IBandIdentifier iden, int channel )
|
||||
{
|
||||
long downlink = calculateDownlink( iden, channel );
|
||||
|
||||
if( downlink > 0 && iden != null )
|
||||
{
|
||||
return downlink + iden.getTransmitOffset();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the frequency of the downlink channel using the channel number
|
||||
* and the IdentifierUpdate message.
|
||||
*
|
||||
* @param iden - Identifier Update message
|
||||
* @param channel - channel number
|
||||
* @return - frequency in Hertz
|
||||
*/
|
||||
protected static long calculateDownlink( IBandIdentifier iden, int channel )
|
||||
{
|
||||
if( iden != null )
|
||||
{
|
||||
return iden.getBaseFrequency() +
|
||||
( channel * iden.getChannelSpacing() );
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
||||
36
src/module/decode/p25/message/filter/HDUMessageFilter.java
Normal file
36
src/module/decode/p25/message/filter/HDUMessageFilter.java
Normal file
@@ -0,0 +1,36 @@
|
||||
package module.decode.p25.message.filter;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import message.Message;
|
||||
import module.decode.p25.message.hdu.HDUMessage;
|
||||
import module.decode.p25.message.tdu.lc.TDULinkControlMessage;
|
||||
import filter.Filter;
|
||||
import filter.FilterElement;
|
||||
|
||||
public class HDUMessageFilter extends Filter<Message>
|
||||
{
|
||||
public HDUMessageFilter()
|
||||
{
|
||||
super( "Header Data Unit" );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean passes( Message message )
|
||||
{
|
||||
return mEnabled && canProcess( message );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canProcess( Message message )
|
||||
{
|
||||
return message instanceof HDUMessage;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<FilterElement<?>> getFilterElements()
|
||||
{
|
||||
return Collections.EMPTY_LIST;
|
||||
}
|
||||
}
|
||||
35
src/module/decode/p25/message/filter/LDUMessageFilter.java
Normal file
35
src/module/decode/p25/message/filter/LDUMessageFilter.java
Normal file
@@ -0,0 +1,35 @@
|
||||
package module.decode.p25.message.filter;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import message.Message;
|
||||
import module.decode.p25.message.ldu.LDUMessage;
|
||||
import filter.Filter;
|
||||
import filter.FilterElement;
|
||||
|
||||
public class LDUMessageFilter extends Filter<Message>
|
||||
{
|
||||
public LDUMessageFilter()
|
||||
{
|
||||
super( "Link Data Unit" );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean passes( Message message )
|
||||
{
|
||||
return mEnabled && canProcess( message );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canProcess( Message message )
|
||||
{
|
||||
return message instanceof LDUMessage;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<FilterElement<?>> getFilterElements()
|
||||
{
|
||||
return Collections.EMPTY_LIST;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package module.decode.p25.message.filter;
|
||||
|
||||
import message.Message;
|
||||
import module.decode.p25.message.P25Message;
|
||||
import filter.FilterSet;
|
||||
|
||||
public class P25MessageFilterSet extends FilterSet<Message>
|
||||
{
|
||||
public P25MessageFilterSet()
|
||||
{
|
||||
super( "P25 Message Filter" );
|
||||
|
||||
addFilter( new HDUMessageFilter() );
|
||||
addFilter( new LDUMessageFilter() );
|
||||
addFilter( new PDUMessageFilter() );
|
||||
addFilter( new TDUMessageFilter() );
|
||||
addFilter( new TDULCMessageFilter() );
|
||||
addFilter( new TSBKMessageFilterSet() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canProcess( Message message )
|
||||
{
|
||||
return message instanceof P25Message;
|
||||
}
|
||||
}
|
||||
54
src/module/decode/p25/message/filter/PDUMessageFilter.java
Normal file
54
src/module/decode/p25/message/filter/PDUMessageFilter.java
Normal file
@@ -0,0 +1,54 @@
|
||||
package module.decode.p25.message.filter;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
import message.Message;
|
||||
import module.decode.p25.message.pdu.PDUMessage;
|
||||
import module.decode.p25.reference.Opcode;
|
||||
import filter.Filter;
|
||||
import filter.FilterElement;
|
||||
|
||||
public class PDUMessageFilter extends Filter<Message>
|
||||
{
|
||||
private HashMap<Opcode,FilterElement<Opcode>> mOpcodeFilterElements =
|
||||
new HashMap<Opcode,FilterElement<Opcode>>();
|
||||
|
||||
public PDUMessageFilter()
|
||||
{
|
||||
super( "PDU - Packet Data Unit" );
|
||||
|
||||
for( Opcode opcode: Opcode.values() )
|
||||
{
|
||||
mOpcodeFilterElements.put( opcode, new FilterElement<Opcode>( opcode ) );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean passes( Message message )
|
||||
{
|
||||
if( mEnabled && message instanceof PDUMessage )
|
||||
{
|
||||
PDUMessage pdu = (PDUMessage)message;
|
||||
|
||||
Opcode opcode = pdu.getOpcode();
|
||||
|
||||
return mOpcodeFilterElements.get( opcode ).isEnabled();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canProcess( Message message )
|
||||
{
|
||||
return message instanceof PDUMessage;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<FilterElement<?>> getFilterElements()
|
||||
{
|
||||
return new ArrayList<FilterElement<?>>( mOpcodeFilterElements.values() );
|
||||
}
|
||||
}
|
||||
36
src/module/decode/p25/message/filter/TDULCMessageFilter.java
Normal file
36
src/module/decode/p25/message/filter/TDULCMessageFilter.java
Normal file
@@ -0,0 +1,36 @@
|
||||
package module.decode.p25.message.filter;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import message.Message;
|
||||
import module.decode.p25.message.tdu.TDUMessage;
|
||||
import module.decode.p25.message.tdu.lc.TDULinkControlMessage;
|
||||
import filter.Filter;
|
||||
import filter.FilterElement;
|
||||
|
||||
public class TDULCMessageFilter extends Filter<Message>
|
||||
{
|
||||
public TDULCMessageFilter()
|
||||
{
|
||||
super( "TDU Terminator Data Unit with Link Control" );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean passes( Message message )
|
||||
{
|
||||
return mEnabled && canProcess( message );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canProcess( Message message )
|
||||
{
|
||||
return message instanceof TDULinkControlMessage;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<FilterElement<?>> getFilterElements()
|
||||
{
|
||||
return Collections.EMPTY_LIST;
|
||||
}
|
||||
}
|
||||
35
src/module/decode/p25/message/filter/TDUMessageFilter.java
Normal file
35
src/module/decode/p25/message/filter/TDUMessageFilter.java
Normal file
@@ -0,0 +1,35 @@
|
||||
package module.decode.p25.message.filter;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import message.Message;
|
||||
import module.decode.p25.message.tdu.TDUMessage;
|
||||
import filter.Filter;
|
||||
import filter.FilterElement;
|
||||
|
||||
public class TDUMessageFilter extends Filter<Message>
|
||||
{
|
||||
public TDUMessageFilter()
|
||||
{
|
||||
super( "TDU Terminator Data Unit" );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean passes( Message message )
|
||||
{
|
||||
return mEnabled && canProcess( message );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canProcess( Message message )
|
||||
{
|
||||
return message instanceof TDUMessage;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<FilterElement<?>> getFilterElements()
|
||||
{
|
||||
return Collections.EMPTY_LIST;
|
||||
}
|
||||
}
|
||||
200
src/module/decode/p25/message/filter/TSBKMessageFilterSet.java
Normal file
200
src/module/decode/p25/message/filter/TSBKMessageFilterSet.java
Normal file
@@ -0,0 +1,200 @@
|
||||
package module.decode.p25.message.filter;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
import message.Message;
|
||||
import module.decode.p25.message.tsbk.TSBKMessage;
|
||||
import module.decode.p25.message.tsbk.motorola.MotorolaOpcode;
|
||||
import module.decode.p25.message.tsbk.vendor.VendorOpcode;
|
||||
import module.decode.p25.reference.Opcode;
|
||||
import module.decode.p25.reference.Vendor;
|
||||
import filter.Filter;
|
||||
import filter.FilterElement;
|
||||
import filter.FilterSet;
|
||||
|
||||
public class TSBKMessageFilterSet extends FilterSet<Message>
|
||||
{
|
||||
public TSBKMessageFilterSet()
|
||||
{
|
||||
super( "TSBK Trunking Signalling Block" );
|
||||
|
||||
addFilter( new StandardOpcodeFilter() );
|
||||
addFilter( new MotorolaOpcodeFilter() );
|
||||
addFilter( new VendorOpcodeFilter() );
|
||||
}
|
||||
|
||||
// @Override
|
||||
// public boolean passes( Message message )
|
||||
// {
|
||||
// if( mEnabled && canProcess( message ) )
|
||||
// {
|
||||
// TSBKMessage tsbk = (TSBKMessage)message;
|
||||
//
|
||||
// switch( tsbk.getVendor() )
|
||||
// {
|
||||
// case STANDARD:
|
||||
// return
|
||||
// }
|
||||
// Opcode opcode = tsbk.getOpcode();
|
||||
//
|
||||
// return mFilterElements.get( opcode ).isEnabled();
|
||||
// }
|
||||
//
|
||||
// return false;
|
||||
// }
|
||||
|
||||
@Override
|
||||
public boolean canProcess( Message message )
|
||||
{
|
||||
return message instanceof TSBKMessage;
|
||||
}
|
||||
|
||||
public class StandardOpcodeFilter extends Filter<Message>
|
||||
{
|
||||
private HashMap<Opcode,FilterElement<Opcode>> mStandardElements =
|
||||
new HashMap<Opcode,FilterElement<Opcode>>();
|
||||
|
||||
public StandardOpcodeFilter()
|
||||
{
|
||||
super( "Standard Opcode Filter" );
|
||||
|
||||
for( Opcode opcode: Opcode.values() )
|
||||
{
|
||||
if( opcode != Opcode.UNKNOWN )
|
||||
{
|
||||
mStandardElements.put( opcode,
|
||||
new FilterElement<Opcode>( opcode ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean passes( Message message )
|
||||
{
|
||||
if( mEnabled && canProcess( message ) )
|
||||
{
|
||||
Opcode opcode = ((TSBKMessage)message).getOpcode();
|
||||
|
||||
if( mStandardElements.containsKey( opcode ) )
|
||||
{
|
||||
return mStandardElements.get( opcode ).isEnabled();
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canProcess( Message message )
|
||||
{
|
||||
|
||||
return ((TSBKMessage)message).getVendor() == Vendor.STANDARD;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<FilterElement<?>> getFilterElements()
|
||||
{
|
||||
return new ArrayList<FilterElement<?>>( mStandardElements.values() );
|
||||
}
|
||||
}
|
||||
|
||||
public class MotorolaOpcodeFilter extends Filter<Message>
|
||||
{
|
||||
private HashMap<MotorolaOpcode,FilterElement<MotorolaOpcode>> mMotorolaElements =
|
||||
new HashMap<MotorolaOpcode,FilterElement<MotorolaOpcode>>();
|
||||
|
||||
public MotorolaOpcodeFilter()
|
||||
{
|
||||
super( "Motorola Opcode Filter" );
|
||||
|
||||
for( MotorolaOpcode opcode: MotorolaOpcode.values() )
|
||||
{
|
||||
if( opcode != MotorolaOpcode.UNKNOWN )
|
||||
{
|
||||
mMotorolaElements.put( opcode,
|
||||
new FilterElement<MotorolaOpcode>( opcode ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean passes( Message message )
|
||||
{
|
||||
if( mEnabled && canProcess( message ) )
|
||||
{
|
||||
MotorolaOpcode opcode = ((TSBKMessage)message).getMotorolaOpcode();
|
||||
|
||||
if( mMotorolaElements.containsKey( opcode ) )
|
||||
{
|
||||
return mMotorolaElements.get( opcode ).isEnabled();
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canProcess( Message message )
|
||||
{
|
||||
return ((TSBKMessage)message).getVendor() == Vendor.MOTOROLA;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<FilterElement<?>> getFilterElements()
|
||||
{
|
||||
return new ArrayList<FilterElement<?>>( mMotorolaElements.values() );
|
||||
}
|
||||
}
|
||||
|
||||
public class VendorOpcodeFilter extends Filter<Message>
|
||||
{
|
||||
private HashMap<VendorOpcode,FilterElement<VendorOpcode>> mVendorElements =
|
||||
new HashMap<VendorOpcode,FilterElement<VendorOpcode>>();
|
||||
|
||||
public VendorOpcodeFilter()
|
||||
{
|
||||
super( "Vendor Opcode Filter" );
|
||||
|
||||
for( VendorOpcode opcode: VendorOpcode.values() )
|
||||
{
|
||||
if( opcode != VendorOpcode.UNKNOWN )
|
||||
{
|
||||
mVendorElements.put( opcode,
|
||||
new FilterElement<VendorOpcode>( opcode ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean passes( Message message )
|
||||
{
|
||||
if( mEnabled && canProcess( message ) )
|
||||
{
|
||||
MotorolaOpcode opcode = ((TSBKMessage)message).getMotorolaOpcode();
|
||||
|
||||
if( mVendorElements.containsKey( opcode ) )
|
||||
{
|
||||
return mVendorElements.get( opcode ).isEnabled();
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canProcess( Message message )
|
||||
{
|
||||
Vendor vendor = ((TSBKMessage)message).getVendor();
|
||||
|
||||
return vendor != Vendor.STANDARD && vendor != Vendor.MOTOROLA;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<FilterElement<?>> getFilterElements()
|
||||
{
|
||||
return new ArrayList<FilterElement<?>>( mVendorElements.values() );
|
||||
}
|
||||
}
|
||||
}
|
||||
273
src/module/decode/p25/message/hdu/HDUMessage.java
Normal file
273
src/module/decode/p25/message/hdu/HDUMessage.java
Normal file
@@ -0,0 +1,273 @@
|
||||
package module.decode.p25.message.hdu;
|
||||
|
||||
import module.decode.p25.message.P25Message;
|
||||
import module.decode.p25.reference.DataUnitID;
|
||||
import module.decode.p25.reference.Encryption;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import alias.AliasList;
|
||||
import bits.BinaryMessage;
|
||||
import edac.CRC;
|
||||
import edac.Golay18;
|
||||
import edac.ReedSolomon_63_47_17;
|
||||
|
||||
public class HDUMessage extends P25Message
|
||||
{
|
||||
private final static Logger mLog = LoggerFactory.getLogger( HDUMessage.class );
|
||||
|
||||
public static final int[] MESSAGE_INDICATOR_A = { 64,65,66,67,68,69,82,83,
|
||||
84,85,86,87,100,101,102,103,104,105,118,119,120,121,122,123,136,137,138,
|
||||
139,140,141,154,155,156,157,158,159 };
|
||||
public static final int[] MESSAGE_INDICATOR_B = { 172,173,174,175,176,177,
|
||||
190,191,192,193,194,195,208,209,210,211,212,213,226,227,228,229,230,231,
|
||||
244,245,246,247,248,249,262,263,264,265,266,267 };
|
||||
public static final int[] VENDOR_ID = { 280,281,282,283,284,285,298,299 };
|
||||
public static final int[] ALGORITHM_ID = { 300,301,302,303,316,317,318,319 };
|
||||
public static final int[] KEY_ID = { 320,321,334,335,336,337,338,339,352,
|
||||
353,354,355,356,357,370,371 };
|
||||
public static final int[] TALKGROUP_ID = { 372,373,374,375,388,389,390,391,
|
||||
392,393,406,407,408,409,410,411 };
|
||||
|
||||
public static final int[] GOLAY_WORD_STARTS = { 64,82,100,118,136,154,172,
|
||||
190,208,226,244,262,280,298,316,334,352,370,388,406,424,442,460,478,
|
||||
496,514,532,550,568,586,604,622,640,658,676,694 };
|
||||
|
||||
public static final int[] CW_HEX_0 = { 64,65,66,67,68,69 };
|
||||
public static final int[] CW_HEX_1 = { 82,83,84,85,86,87 };
|
||||
public static final int[] CW_HEX_2 = { 100,101,102,103,104,105 };
|
||||
public static final int[] CW_HEX_3 = { 118,119,120,121,122,123 };
|
||||
public static final int[] CW_HEX_4 = { 136,137,138,139,140,141 };
|
||||
public static final int[] CW_HEX_5 = { 154,155,156,157,158,159 };
|
||||
public static final int[] CW_HEX_6 = { 172,173,174,175,176,177 };
|
||||
public static final int[] CW_HEX_7 = { 190,191,192,193,194,195 };
|
||||
public static final int[] CW_HEX_8 = { 208,209,210,211,212,213 };
|
||||
public static final int[] CW_HEX_9 = { 226,227,228,229,230,231 };
|
||||
public static final int[] CW_HEX_10 = { 244,245,246,247,248,249 };
|
||||
public static final int[] CW_HEX_11 = { 262,263,264,265,266,267 };
|
||||
public static final int[] CW_HEX_12 = { 280,281,282,283,284,285 };
|
||||
public static final int[] CW_HEX_13 = { 298,299,300,301,302,303 };
|
||||
public static final int[] CW_HEX_14 = { 316,317,318,319,320,321 };
|
||||
public static final int[] CW_HEX_15 = { 334,335,336,337,338,339 };
|
||||
public static final int[] CW_HEX_16 = { 352,353,354,355,356,357 };
|
||||
public static final int[] CW_HEX_17 = { 370,371,372,373,374,375 };
|
||||
public static final int[] CW_HEX_18 = { 388,389,390,391,392,393 };
|
||||
public static final int[] CW_HEX_19 = { 406,407,408,409,410,411 };
|
||||
public static final int[] RS_HEX_0 = { 424,425,426,427,428,429 };
|
||||
public static final int[] RS_HEX_1 = { 442,443,444,445,446,447 };
|
||||
public static final int[] RS_HEX_2 = { 460,461,462,463,464,465 };
|
||||
public static final int[] RS_HEX_3 = { 478,479,480,481,482,483 };
|
||||
public static final int[] RS_HEX_4 = { 496,497,498,499,500,501 };
|
||||
public static final int[] RS_HEX_5 = { 514,515,516,517,518,519 };
|
||||
public static final int[] RS_HEX_6 = { 532,533,534,535,536,537 };
|
||||
public static final int[] RS_HEX_7 = { 550,551,552,553,554,555 };
|
||||
public static final int[] RS_HEX_8 = { 568,569,570,571,572,573 };
|
||||
public static final int[] RS_HEX_9 = { 586,587,588,589,590,591 };
|
||||
public static final int[] RS_HEX_10 = { 604,605,606,607,608,609 };
|
||||
public static final int[] RS_HEX_11 = { 622,623,624,625,626,627 };
|
||||
public static final int[] RS_HEX_12 = { 640,641,642,643,644,645 };
|
||||
public static final int[] RS_HEX_13 = { 658,659,660,661,662,663 };
|
||||
public static final int[] RS_HEX_14 = { 676,677,678,679,680,681 };
|
||||
public static final int[] RS_HEX_15 = { 694,695,696,697,698,699 };
|
||||
|
||||
/* Reed-Solomon(36,20,17) code protects the header word. Maximum
|
||||
* correctable errors are: Hamming Distance(17) / 2 = 8 */
|
||||
public static final ReedSolomon_63_47_17 mReedSolomonDecoder =
|
||||
new ReedSolomon_63_47_17( 8 );
|
||||
|
||||
public HDUMessage( BinaryMessage message, DataUnitID duid,
|
||||
AliasList aliasList )
|
||||
{
|
||||
super( message, duid, aliasList );
|
||||
|
||||
/* NID CRC is checked in the message framer, thus a constructed message
|
||||
* means it passed the CRC */
|
||||
mCRC = new CRC[ 3 ];
|
||||
mCRC[ 0 ] = CRC.PASSED;
|
||||
|
||||
checkCRC();
|
||||
}
|
||||
|
||||
private void checkCRC()
|
||||
{
|
||||
/* Golay( 18,6,18 ) error detection and correction */
|
||||
for( int index: GOLAY_WORD_STARTS )
|
||||
{
|
||||
Golay18.checkAndCorrect( mMessage, index );
|
||||
}
|
||||
|
||||
mCRC[ 1 ] = CRC.PASSED;
|
||||
|
||||
/* Reed-Solomon( 36,20,17 ) error detection and correction
|
||||
* Check the Reed-Solomon parity bits. The RS decoder expects the link
|
||||
* control data and reed solomon parity hex codewords in reverse order.
|
||||
* The RS(24,12,13) code used by P25 removes the left-hand 47 data hex
|
||||
* words, so we replace them with zeros. */
|
||||
int[] input = new int [63];
|
||||
int[] output = new int [63];
|
||||
|
||||
input[ 0 ] = mMessage.getInt( RS_HEX_15 );
|
||||
input[ 1 ] = mMessage.getInt( RS_HEX_14 );
|
||||
input[ 2 ] = mMessage.getInt( RS_HEX_13 );
|
||||
input[ 3 ] = mMessage.getInt( RS_HEX_12 );
|
||||
input[ 4 ] = mMessage.getInt( RS_HEX_11 );
|
||||
input[ 5 ] = mMessage.getInt( RS_HEX_10 );
|
||||
input[ 6 ] = mMessage.getInt( RS_HEX_9 );
|
||||
input[ 7 ] = mMessage.getInt( RS_HEX_8 );
|
||||
input[ 8 ] = mMessage.getInt( RS_HEX_7 );
|
||||
input[ 9 ] = mMessage.getInt( RS_HEX_6 );
|
||||
input[ 10 ] = mMessage.getInt( RS_HEX_5 );
|
||||
input[ 11 ] = mMessage.getInt( RS_HEX_4 );
|
||||
input[ 12 ] = mMessage.getInt( RS_HEX_3 );
|
||||
input[ 13 ] = mMessage.getInt( RS_HEX_2 );
|
||||
input[ 14 ] = mMessage.getInt( RS_HEX_1 );
|
||||
input[ 15 ] = mMessage.getInt( RS_HEX_0 );
|
||||
|
||||
input[ 16 ] = mMessage.getInt( CW_HEX_19 );
|
||||
input[ 17 ] = mMessage.getInt( CW_HEX_18 );
|
||||
input[ 18 ] = mMessage.getInt( CW_HEX_17 );
|
||||
input[ 19 ] = mMessage.getInt( CW_HEX_16 );
|
||||
input[ 20 ] = mMessage.getInt( CW_HEX_15 );
|
||||
input[ 21 ] = mMessage.getInt( CW_HEX_14 );
|
||||
input[ 22 ] = mMessage.getInt( CW_HEX_13 );
|
||||
input[ 23 ] = mMessage.getInt( CW_HEX_12 );
|
||||
input[ 24 ] = mMessage.getInt( CW_HEX_11 );
|
||||
input[ 25 ] = mMessage.getInt( CW_HEX_10 );
|
||||
input[ 26 ] = mMessage.getInt( CW_HEX_9 );
|
||||
input[ 27 ] = mMessage.getInt( CW_HEX_8 );
|
||||
input[ 28 ] = mMessage.getInt( CW_HEX_7 );
|
||||
input[ 29 ] = mMessage.getInt( CW_HEX_6 );
|
||||
input[ 30 ] = mMessage.getInt( CW_HEX_5 );
|
||||
input[ 31 ] = mMessage.getInt( CW_HEX_4 );
|
||||
input[ 32 ] = mMessage.getInt( CW_HEX_3 );
|
||||
input[ 33 ] = mMessage.getInt( CW_HEX_2 );
|
||||
input[ 34 ] = mMessage.getInt( CW_HEX_1 );
|
||||
input[ 35 ] = mMessage.getInt( CW_HEX_0 );
|
||||
/* indexes 36 - 62 are defaulted to zero */
|
||||
|
||||
boolean irrecoverableErrors = mReedSolomonDecoder.decode( input, output );
|
||||
|
||||
if( irrecoverableErrors )
|
||||
{
|
||||
mCRC[ 2 ] = CRC.FAILED_CRC;
|
||||
}
|
||||
else
|
||||
{
|
||||
mCRC[ 2 ] = CRC.PASSED;
|
||||
|
||||
/* Only fix the codeword data hex codewords */
|
||||
repairHexCodeword( input, output, 16, CW_HEX_19 );
|
||||
repairHexCodeword( input, output, 17, CW_HEX_18 );
|
||||
repairHexCodeword( input, output, 18, CW_HEX_17 );
|
||||
repairHexCodeword( input, output, 19, CW_HEX_16 );
|
||||
repairHexCodeword( input, output, 20, CW_HEX_15 );
|
||||
repairHexCodeword( input, output, 21, CW_HEX_14 );
|
||||
repairHexCodeword( input, output, 22, CW_HEX_13 );
|
||||
repairHexCodeword( input, output, 23, CW_HEX_12 );
|
||||
repairHexCodeword( input, output, 24, CW_HEX_11 );
|
||||
repairHexCodeword( input, output, 25, CW_HEX_10 );
|
||||
repairHexCodeword( input, output, 26, CW_HEX_9 );
|
||||
repairHexCodeword( input, output, 27, CW_HEX_8 );
|
||||
repairHexCodeword( input, output, 28, CW_HEX_7 );
|
||||
repairHexCodeword( input, output, 29, CW_HEX_6 );
|
||||
repairHexCodeword( input, output, 30, CW_HEX_5 );
|
||||
repairHexCodeword( input, output, 31, CW_HEX_4 );
|
||||
repairHexCodeword( input, output, 32, CW_HEX_3 );
|
||||
repairHexCodeword( input, output, 33, CW_HEX_2 );
|
||||
repairHexCodeword( input, output, 34, CW_HEX_1 );
|
||||
repairHexCodeword( input, output, 35, CW_HEX_0 );
|
||||
}
|
||||
}
|
||||
|
||||
private void repairHexCodeword( int[] input, int[] output, int index, int[] indexSet )
|
||||
{
|
||||
if( input[ index ] != output[ index ] )
|
||||
{
|
||||
mMessage.load( indexSet[ 0 ], 6, output[ index ] );
|
||||
mCRC[ 2 ] = CRC.CORRECTED;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMessage()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append( "NAC:" );
|
||||
sb.append( getNAC() );
|
||||
sb.append( " " );
|
||||
sb.append( getDUID().getLabel() );
|
||||
|
||||
sb.append( " TALKGROUP:" + getTalkgroupID() );
|
||||
|
||||
Encryption encryption = getEncryption();
|
||||
|
||||
if( encryption != Encryption.UNENCRYPTED )
|
||||
{
|
||||
sb.append( " ENCRYPTION:" );
|
||||
|
||||
if( encryption == Encryption.UNKNOWN )
|
||||
{
|
||||
sb.append( "UNK ALGO ID:" );
|
||||
sb.append( mMessage.getInt( ALGORITHM_ID ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.append( encryption.name() );
|
||||
}
|
||||
sb.append( " KEY ID:" + getKeyID() );
|
||||
sb.append( " MSG INDICATOR:" + getMessageIndicator() );
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.append( " UNENCRYPTED" );
|
||||
}
|
||||
|
||||
sb.append( " " );
|
||||
sb.append( mMessage.toString() );
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public String getMessageIndicator()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append( mMessage.getHex( MESSAGE_INDICATOR_A, 9 ) );
|
||||
sb.append( mMessage.getHex( MESSAGE_INDICATOR_B, 9 ) );
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public Encryption getEncryption()
|
||||
{
|
||||
return Encryption.fromValue( mMessage.getInt( ALGORITHM_ID ) );
|
||||
}
|
||||
|
||||
public boolean isEncrypted()
|
||||
{
|
||||
return getEncryption() != Encryption.UNENCRYPTED;
|
||||
}
|
||||
|
||||
public int getKeyID()
|
||||
{
|
||||
return mMessage.getInt( KEY_ID );
|
||||
}
|
||||
|
||||
public String getTalkgroupID()
|
||||
{
|
||||
return mMessage.getHex( TALKGROUP_ID, 4 );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getToID()
|
||||
{
|
||||
return getTalkgroupID();
|
||||
}
|
||||
|
||||
public boolean isValid()
|
||||
{
|
||||
return mCRC[ 2 ] != null && mCRC[ 2 ] != CRC.FAILED_CRC;
|
||||
}
|
||||
}
|
||||
244
src/module/decode/p25/message/ldu/LDU1Message.java
Normal file
244
src/module/decode/p25/message/ldu/LDU1Message.java
Normal file
@@ -0,0 +1,244 @@
|
||||
package module.decode.p25.message.ldu;
|
||||
|
||||
import module.decode.p25.reference.DataUnitID;
|
||||
import module.decode.p25.reference.LinkControlOpcode;
|
||||
import module.decode.p25.reference.Vendor;
|
||||
import module.decode.p25.reference.VendorLinkControlOpcode;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import alias.AliasList;
|
||||
import bits.BinaryMessage;
|
||||
import edac.CRC;
|
||||
import edac.Hamming10;
|
||||
import edac.ReedSolomon_63_47_17;
|
||||
|
||||
public class LDU1Message extends LDUMessage
|
||||
{
|
||||
private final static Logger mLog = LoggerFactory.getLogger( LDU1Message.class );
|
||||
|
||||
public static final int ENCRYPTION_FLAG = 352;
|
||||
public static final int IMPLICIT_VENDOR_FLAG = 353;
|
||||
public static final int[] OPCODE = { 354,355,356,357,362,363 };
|
||||
public static final int[] VENDOR = { 364,365,366,367,372,373,374,375 };
|
||||
|
||||
public static final int[] GOLAY_WORD_STARTS = {
|
||||
352,362,372,382,536,546,556,566,720,730,740,750,904,914,924,934,1088,
|
||||
1098,1108,1118,1272,1282,1292,1302 };
|
||||
|
||||
public static final int[] CW_HEX_0 = { 352,353,354,355,356,357 };
|
||||
public static final int[] CW_HEX_1 = { 362,363,364,365,366,367 };
|
||||
public static final int[] CW_HEX_2 = { 372,373,374,375,376,377 };
|
||||
public static final int[] CW_HEX_3 = { 382,383,384,385,386,387 };
|
||||
public static final int[] CW_HEX_4 = { 536,537,538,539,540,541 };
|
||||
public static final int[] CW_HEX_5 = { 546,547,548,549,550,551 };
|
||||
public static final int[] CW_HEX_6 = { 556,557,558,559,560,561 };
|
||||
public static final int[] CW_HEX_7 = { 566,567,568,569,570,571 };
|
||||
public static final int[] CW_HEX_8 = { 720,721,722,723,724,725 };
|
||||
public static final int[] CW_HEX_9 = { 730,731,732,733,734,735 };
|
||||
public static final int[] CW_HEX_10 = { 740,741,742,743,744,745 };
|
||||
public static final int[] CW_HEX_11 = { 750,751,752,753,754,755 };
|
||||
public static final int[] RS_HEX_0 = { 904,905,906,907,908,909 };
|
||||
public static final int[] RS_HEX_1 = { 914,915,916,917,918,919 };
|
||||
public static final int[] RS_HEX_2 = { 924,925,926,927,928,929 };
|
||||
public static final int[] RS_HEX_3 = { 934,935,936,937,938,939 };
|
||||
public static final int[] RS_HEX_4 = { 1088,1089,1090,1091,1092,1093 };
|
||||
public static final int[] RS_HEX_5 = { 1098,1099,1100,1101,1102,1103 };
|
||||
public static final int[] RS_HEX_6 = { 1108,1109,1110,1111,1112,1113 };
|
||||
public static final int[] RS_HEX_7 = { 1118,1119,1120,1121,1122,1123 };
|
||||
public static final int[] RS_HEX_8 = { 1272,1273,1274,1275,1276,1277 };
|
||||
public static final int[] RS_HEX_9 = { 1282,1283,1284,1285,1286,1287 };
|
||||
public static final int[] RS_HEX_10 = { 1292,1293,1294,1295,1296,1297 };
|
||||
public static final int[] RS_HEX_11 = { 1302,1303,1304,1305,1306,1307 };
|
||||
|
||||
/* Reed-Solomon(24,12,13) code protects the link control word. Maximum
|
||||
* correctable errors are: Hamming Distance(13) / 2 = 6 */
|
||||
public static final ReedSolomon_63_47_17 mReedSolomonDecoder =
|
||||
new ReedSolomon_63_47_17( 6 );
|
||||
|
||||
public LDU1Message( BinaryMessage message, DataUnitID duid,
|
||||
AliasList aliasList )
|
||||
{
|
||||
super( message, duid, aliasList );
|
||||
|
||||
|
||||
/* NID CRC is checked in the message framer, thus a constructed message
|
||||
* means it passed the CRC */
|
||||
mCRC = new CRC[ 3 ];
|
||||
mCRC[ 0 ] = CRC.PASSED;
|
||||
|
||||
checkCRC();
|
||||
}
|
||||
|
||||
/**
|
||||
* Subclass constructor from an existing LDU1Message
|
||||
*/
|
||||
protected LDU1Message( LDU1Message message )
|
||||
{
|
||||
super( message.getSourceMessage(), DataUnitID.LDU1, message.getAliasList() );
|
||||
|
||||
mCRC = message.mCRC;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEncrypted()
|
||||
{
|
||||
return mMessage.get( ENCRYPTION_FLAG );
|
||||
}
|
||||
|
||||
private void checkCRC()
|
||||
{
|
||||
mCRC[ 1 ] = CRC.PASSED;
|
||||
|
||||
/* Hamming( 10,6,3 ) error detection and correction */
|
||||
for( int index: GOLAY_WORD_STARTS )
|
||||
{
|
||||
int errors = Hamming10.checkAndCorrect( mMessage, index );
|
||||
|
||||
if( errors > 1 )
|
||||
{
|
||||
mCRC[ 1 ] = CRC.FAILED_CRC;
|
||||
}
|
||||
}
|
||||
|
||||
/* Reed-Solomon( 24,16,9 ) error detection and correction
|
||||
* Check the Reed-Solomon parity bits. The RS decoder expects the code
|
||||
* words and reed solomon parity hex codewords in reverse order.
|
||||
*
|
||||
* Since this is a truncated RS(63) codes, we pad the code with zeros */
|
||||
int[] input = new int [63];
|
||||
int[] output = new int [63];
|
||||
|
||||
input[ 0 ] = mMessage.getInt( RS_HEX_11 );
|
||||
input[ 1 ] = mMessage.getInt( RS_HEX_10 );
|
||||
input[ 2 ] = mMessage.getInt( RS_HEX_9 );
|
||||
input[ 3 ] = mMessage.getInt( RS_HEX_8 );
|
||||
input[ 4 ] = mMessage.getInt( RS_HEX_7 );
|
||||
input[ 5 ] = mMessage.getInt( RS_HEX_6 );
|
||||
input[ 6 ] = mMessage.getInt( RS_HEX_5 );
|
||||
input[ 7 ] = mMessage.getInt( RS_HEX_4 );
|
||||
input[ 8 ] = mMessage.getInt( RS_HEX_3 );
|
||||
input[ 9 ] = mMessage.getInt( RS_HEX_2 );
|
||||
input[ 10 ] = mMessage.getInt( RS_HEX_1 );
|
||||
input[ 11 ] = mMessage.getInt( RS_HEX_0 );
|
||||
|
||||
input[ 12 ] = mMessage.getInt( CW_HEX_11 );
|
||||
input[ 13 ] = mMessage.getInt( CW_HEX_10 );
|
||||
input[ 14 ] = mMessage.getInt( CW_HEX_9 );
|
||||
input[ 15 ] = mMessage.getInt( CW_HEX_8 );
|
||||
input[ 16 ] = mMessage.getInt( CW_HEX_7 );
|
||||
input[ 17 ] = mMessage.getInt( CW_HEX_6 );
|
||||
input[ 18 ] = mMessage.getInt( CW_HEX_5 );
|
||||
input[ 19 ] = mMessage.getInt( CW_HEX_4 );
|
||||
input[ 20 ] = mMessage.getInt( CW_HEX_3 );
|
||||
input[ 21 ] = mMessage.getInt( CW_HEX_2 );
|
||||
input[ 22 ] = mMessage.getInt( CW_HEX_1 );
|
||||
input[ 23 ] = mMessage.getInt( CW_HEX_0 );
|
||||
/* indexes 24 - 62 are defaulted to zero */
|
||||
|
||||
boolean irrecoverableErrors = mReedSolomonDecoder.decode( input, output );
|
||||
|
||||
if( irrecoverableErrors )
|
||||
{
|
||||
mCRC[ 2 ] = CRC.FAILED_CRC;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Since we've detected that we can correct the RS words, mark the
|
||||
* hamming crc as corrected as well, if it is currently failed */
|
||||
if( mCRC[ 1 ] == CRC.FAILED_CRC )
|
||||
{
|
||||
mCRC[ 1 ] = CRC.CORRECTED;
|
||||
}
|
||||
|
||||
mCRC[ 2 ] = CRC.PASSED;
|
||||
|
||||
/* Only fix the codeword data hex codewords */
|
||||
repairHexCodeword( input, output, 12, CW_HEX_11 );
|
||||
repairHexCodeword( input, output, 13, CW_HEX_10 );
|
||||
repairHexCodeword( input, output, 14, CW_HEX_9 );
|
||||
repairHexCodeword( input, output, 15, CW_HEX_8 );
|
||||
repairHexCodeword( input, output, 16, CW_HEX_7 );
|
||||
repairHexCodeword( input, output, 17, CW_HEX_6 );
|
||||
repairHexCodeword( input, output, 18, CW_HEX_5 );
|
||||
repairHexCodeword( input, output, 19, CW_HEX_4 );
|
||||
repairHexCodeword( input, output, 20, CW_HEX_3 );
|
||||
repairHexCodeword( input, output, 21, CW_HEX_2 );
|
||||
repairHexCodeword( input, output, 22, CW_HEX_1 );
|
||||
repairHexCodeword( input, output, 23, CW_HEX_0 );
|
||||
}
|
||||
}
|
||||
|
||||
private void repairHexCodeword( int[] input, int[] output, int index, int[] indexSet )
|
||||
{
|
||||
if( input[ index ] != output[ index ] )
|
||||
{
|
||||
mMessage.load( indexSet[ 0 ], 6, output[ index ] );
|
||||
mCRC[ 2 ] = CRC.CORRECTED;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMessage()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append( getMessageStub() );
|
||||
sb.append( " " );
|
||||
sb.append( mMessage.toString() );
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public String getMessageStub()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append( super.getMessageStub() );
|
||||
|
||||
if( isEncrypted() )
|
||||
{
|
||||
sb.append( "ENCRYPTED" );
|
||||
}
|
||||
else
|
||||
{
|
||||
if( isImplicitFormat() || getVendor() == Vendor.STANDARD )
|
||||
{
|
||||
sb.append( getOpcode().getLabel() );
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.append( "VENDOR:" + getVendor().getLabel() + " " );
|
||||
sb.append( getVendorOpcode().getLabel() );
|
||||
}
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public boolean isImplicitFormat()
|
||||
{
|
||||
return mMessage.get( IMPLICIT_VENDOR_FLAG );
|
||||
}
|
||||
|
||||
public LinkControlOpcode getOpcode()
|
||||
{
|
||||
return LinkControlOpcode.fromValue( mMessage.getInt( OPCODE ) );
|
||||
}
|
||||
|
||||
public VendorLinkControlOpcode getVendorOpcode()
|
||||
{
|
||||
return VendorLinkControlOpcode.fromValue( mMessage.getInt( OPCODE ) );
|
||||
}
|
||||
|
||||
public Vendor getVendor()
|
||||
{
|
||||
if( isImplicitFormat() )
|
||||
{
|
||||
return Vendor.STANDARD;
|
||||
}
|
||||
|
||||
return Vendor.fromValue( mMessage.getInt( VENDOR ) );
|
||||
}
|
||||
}
|
||||
241
src/module/decode/p25/message/ldu/LDU2Message.java
Normal file
241
src/module/decode/p25/message/ldu/LDU2Message.java
Normal file
@@ -0,0 +1,241 @@
|
||||
package module.decode.p25.message.ldu;
|
||||
|
||||
import module.decode.p25.reference.DataUnitID;
|
||||
import module.decode.p25.reference.Encryption;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import alias.AliasList;
|
||||
import bits.BinaryMessage;
|
||||
import edac.CRC;
|
||||
import edac.Hamming10;
|
||||
import edac.ReedSolomon_63_47_17;
|
||||
|
||||
public class LDU2Message extends LDUMessage
|
||||
{
|
||||
private final static Logger mLog = LoggerFactory.getLogger( LDU2Message.class );
|
||||
|
||||
public static final int[] MESSAGE_INDICATOR_A = { 352,353,354,355,356,357,
|
||||
362,363,364,365,366,367,372,373,374,375,376,377,382,383,384,385,386,387,
|
||||
536,537,538,539,540,541,546,547,548,549,550,551 };
|
||||
public static final int[] MESSAGE_INDICATOR_B = { 556,557,558,559,560,561,
|
||||
566,567,568,569,570,571,720,721,722,723,724,725,730,731,732,733,734,735,
|
||||
740,741,742,743,744,745,750,751,752,753,754,755 };
|
||||
public static final int[] ALGORITHM_ID = { 904,905,906,907,908,909,914,915 };
|
||||
public static final int[] KEY_ID = { 916,917,918,919,924,925,926,927,928,
|
||||
929,934,935,936,937,938,939 };
|
||||
|
||||
public static final int[] GOLAY_WORD_STARTS = {
|
||||
352,362,372,382,536,546,556,566,720,730,740,750,904,914,924,934,1088,
|
||||
1098,1108,1118,1272,1282,1292,1302 };
|
||||
|
||||
public static final int[] CW_HEX_0 = { 352,353,354,355,356,357 };
|
||||
public static final int[] CW_HEX_1 = { 362,363,364,365,366,367 };
|
||||
public static final int[] CW_HEX_2 = { 372,373,374,375,376,377 };
|
||||
public static final int[] CW_HEX_3 = { 382,383,384,385,386,387 };
|
||||
public static final int[] CW_HEX_4 = { 536,537,538,539,540,541 };
|
||||
public static final int[] CW_HEX_5 = { 546,547,548,549,550,551 };
|
||||
public static final int[] CW_HEX_6 = { 556,557,558,559,560,561 };
|
||||
public static final int[] CW_HEX_7 = { 566,567,568,569,570,571 };
|
||||
public static final int[] CW_HEX_8 = { 720,721,722,723,724,725 };
|
||||
public static final int[] CW_HEX_9 = { 730,731,732,733,734,735 };
|
||||
public static final int[] CW_HEX_10 = { 740,741,742,743,744,745 };
|
||||
public static final int[] CW_HEX_11 = { 750,751,752,753,754,755 };
|
||||
public static final int[] CW_HEX_12 = { 904,905,906,907,908,909 };
|
||||
public static final int[] CW_HEX_13 = { 914,915,916,917,918,919 };
|
||||
public static final int[] CW_HEX_14 = { 924,925,926,927,928,929 };
|
||||
public static final int[] CW_HEX_15 = { 934,935,936,937,938,939 };
|
||||
public static final int[] RS_HEX_0 = { 1088,1089,1090,1091,1092,1093 };
|
||||
public static final int[] RS_HEX_1 = { 1098,1099,1100,1101,1102,1103 };
|
||||
public static final int[] RS_HEX_2 = { 1108,1109,1110,1111,1112,1113 };
|
||||
public static final int[] RS_HEX_3 = { 1118,1119,1120,1121,1122,1123 };
|
||||
public static final int[] RS_HEX_4 = { 1272,1273,1274,1275,1276,1277 };
|
||||
public static final int[] RS_HEX_5 = { 1282,1283,1284,1285,1286,1287 };
|
||||
public static final int[] RS_HEX_6 = { 1292,1293,1294,1295,1296,1297 };
|
||||
public static final int[] RS_HEX_7 = { 1302,1303,1304,1305,1306,1307 };
|
||||
|
||||
/* Reed-Solomon(24,16,9) code protects the encryption sync word. Maximum
|
||||
* correctable errors are: Hamming Distance(9) / 2 = 4 */
|
||||
public static final ReedSolomon_63_47_17 mReedSolomonDecoder =
|
||||
new ReedSolomon_63_47_17( 4 );
|
||||
|
||||
public LDU2Message( BinaryMessage message, DataUnitID duid,
|
||||
AliasList aliasList )
|
||||
{
|
||||
super( message, duid, aliasList );
|
||||
|
||||
/* NID CRC is checked in the message framer, thus a constructed message
|
||||
* means it passed the CRC */
|
||||
mCRC = new CRC[ 3 ];
|
||||
mCRC[ 0 ] = CRC.PASSED;
|
||||
|
||||
checkCRC();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEncrypted()
|
||||
{
|
||||
return getEncryption() != Encryption.UNENCRYPTED;
|
||||
}
|
||||
|
||||
private void checkCRC()
|
||||
{
|
||||
mCRC[ 1 ] = CRC.PASSED;
|
||||
|
||||
/* Hamming( 10,6,3 ) error detection and correction */
|
||||
for( int index: GOLAY_WORD_STARTS )
|
||||
{
|
||||
int errors = Hamming10.checkAndCorrect( mMessage, index );
|
||||
|
||||
if( errors > 1 )
|
||||
{
|
||||
mCRC[ 1 ] = CRC.FAILED_CRC;
|
||||
}
|
||||
}
|
||||
|
||||
/* Reed-Solomon( 24,16,9 ) error detection and correction
|
||||
* Check the Reed-Solomon parity bits. The RS decoder expects the code
|
||||
* words and reed solomon parity hex codewords in reverse order.
|
||||
*
|
||||
* Since this is a truncated RS(63) codes, we pad the code with zeros */
|
||||
int[] input = new int [63];
|
||||
int[] output = new int [63];
|
||||
|
||||
input[ 0 ] = mMessage.getInt( RS_HEX_7 );
|
||||
input[ 1 ] = mMessage.getInt( RS_HEX_6 );
|
||||
input[ 2 ] = mMessage.getInt( RS_HEX_5 );
|
||||
input[ 3 ] = mMessage.getInt( RS_HEX_4 );
|
||||
input[ 4 ] = mMessage.getInt( RS_HEX_3 );
|
||||
input[ 5 ] = mMessage.getInt( RS_HEX_2 );
|
||||
input[ 6 ] = mMessage.getInt( RS_HEX_1 );
|
||||
input[ 7 ] = mMessage.getInt( RS_HEX_0 );
|
||||
|
||||
input[ 8 ] = mMessage.getInt( CW_HEX_15 );
|
||||
input[ 9 ] = mMessage.getInt( CW_HEX_14 );
|
||||
input[ 10 ] = mMessage.getInt( CW_HEX_13 );
|
||||
input[ 11 ] = mMessage.getInt( CW_HEX_12 );
|
||||
input[ 12 ] = mMessage.getInt( CW_HEX_11 );
|
||||
input[ 13 ] = mMessage.getInt( CW_HEX_10 );
|
||||
input[ 14 ] = mMessage.getInt( CW_HEX_9 );
|
||||
input[ 15 ] = mMessage.getInt( CW_HEX_8 );
|
||||
input[ 16 ] = mMessage.getInt( CW_HEX_7 );
|
||||
input[ 17 ] = mMessage.getInt( CW_HEX_6 );
|
||||
input[ 18 ] = mMessage.getInt( CW_HEX_5 );
|
||||
input[ 19 ] = mMessage.getInt( CW_HEX_4 );
|
||||
input[ 20 ] = mMessage.getInt( CW_HEX_3 );
|
||||
input[ 21 ] = mMessage.getInt( CW_HEX_2 );
|
||||
input[ 22 ] = mMessage.getInt( CW_HEX_1 );
|
||||
input[ 23 ] = mMessage.getInt( CW_HEX_0 );
|
||||
/* indexes 24 - 62 are defaulted to zero */
|
||||
|
||||
boolean irrecoverableErrors = mReedSolomonDecoder.decode( input, output );
|
||||
|
||||
if( irrecoverableErrors )
|
||||
{
|
||||
mCRC[ 2 ] = CRC.FAILED_CRC;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Since we've detected that we can correct the RS words, mark the
|
||||
* hamming crc as corrected as well, if it is currently failed */
|
||||
if( mCRC[ 1 ] == CRC.FAILED_CRC )
|
||||
{
|
||||
mCRC[ 1 ] = CRC.CORRECTED;
|
||||
}
|
||||
|
||||
mCRC[ 2 ] = CRC.PASSED;
|
||||
|
||||
/* Only fix the codeword data hex codewords */
|
||||
repairHexCodeword( input, output, 8, CW_HEX_15 );
|
||||
repairHexCodeword( input, output, 9, CW_HEX_14 );
|
||||
repairHexCodeword( input, output, 10, CW_HEX_13 );
|
||||
repairHexCodeword( input, output, 11, CW_HEX_12 );
|
||||
repairHexCodeword( input, output, 12, CW_HEX_11 );
|
||||
repairHexCodeword( input, output, 13, CW_HEX_10 );
|
||||
repairHexCodeword( input, output, 14, CW_HEX_9 );
|
||||
repairHexCodeword( input, output, 15, CW_HEX_8 );
|
||||
repairHexCodeword( input, output, 16, CW_HEX_7 );
|
||||
repairHexCodeword( input, output, 17, CW_HEX_6 );
|
||||
repairHexCodeword( input, output, 18, CW_HEX_5 );
|
||||
repairHexCodeword( input, output, 19, CW_HEX_4 );
|
||||
repairHexCodeword( input, output, 20, CW_HEX_3 );
|
||||
repairHexCodeword( input, output, 21, CW_HEX_2 );
|
||||
repairHexCodeword( input, output, 22, CW_HEX_1 );
|
||||
repairHexCodeword( input, output, 23, CW_HEX_0 );
|
||||
}
|
||||
}
|
||||
|
||||
private void repairHexCodeword( int[] input, int[] output, int index, int[] indexSet )
|
||||
{
|
||||
if( input[ index ] != output[ index ] )
|
||||
{
|
||||
mMessage.load( indexSet[ 0 ], 6, output[ index ] );
|
||||
mCRC[ 2 ] = CRC.CORRECTED;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMessage()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
|
||||
Encryption encryption = getEncryption();
|
||||
|
||||
if( encryption != Encryption.UNENCRYPTED )
|
||||
{
|
||||
sb.append( "NAC:" );
|
||||
sb.append( getNAC() );
|
||||
sb.append( " " );
|
||||
sb.append( getDUID().getLabel() );
|
||||
|
||||
sb.append( " ENCRYPTED VOICE:" );
|
||||
sb.append( encryption.name() );
|
||||
sb.append( " KEY ID:" + getKeyID() );
|
||||
sb.append( " MSG INDICATOR:" + getMessageIndicator() );
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.append( super.getMessageStub() );
|
||||
sb.append( "UNENCRYPTED" );
|
||||
}
|
||||
|
||||
sb.append( " " );
|
||||
sb.append( mMessage.toString() );
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public String getMessageIndicator()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append( mMessage.getHex( MESSAGE_INDICATOR_A, 9 ) );
|
||||
sb.append( mMessage.getHex( MESSAGE_INDICATOR_B, 9 ) );
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public Encryption getEncryption()
|
||||
{
|
||||
return Encryption.fromValue( mMessage.getInt( ALGORITHM_ID ) );
|
||||
}
|
||||
|
||||
public int getKeyID()
|
||||
{
|
||||
return mMessage.getInt( KEY_ID );
|
||||
}
|
||||
|
||||
public static void main( String[] args )
|
||||
{
|
||||
String msg = "001010100000101010011010001001001001010011000111000111110111001100000010000101001011110111111000001100111100110000000010001110011011001101101101101101110011110011010000101111001111000011000010110010011110110010000100101101101001100000100000100001011100000000001110011111011000100100000000011011100000111111111101111010110111000111100011010111111110111000000000000000000000000000000000000000000100100001110110101111011000011010010100011001000101001011100101111011000001101100010101111001000100001111011111011001111110100111001100110110000000000000000000000000000000000000000000000101000001011110111010110010000100010110001100001101001110111001000111100100111011011011110101011111011000010100110111001000101000010011101010000000000000000000000000000000000000000001001000001000011011110110011110011001111100100000111000101001110111011110101001000101001100001110001100000000110000110000001011110000000101100110000011100000000000000000000000000000000111011001010000111111111111110000110110011000100101011000001111110000101000101111010101010101000100110111000100100111110010101010000100111010111010111010001011010010001011011001001001011100000101000010010010111100000110010000101010000110101100101111100110111100010001011011110101001011010100010000111000010000001001001001101000100110101011110100111100011111110101100000011011011001000001010100011001010100110000111100101011100110110011111100011011111110100111011101011111100001111011000101100011101000110001101000000000000000000000000000000000010001101101011101111010101010000111011011101001011111001110111001000010101011010000001011010111010000011011001100010110001010001000010001101101";
|
||||
|
||||
BinaryMessage message = BinaryMessage.load( msg );
|
||||
|
||||
LDU2Message ldu2 = new LDU2Message( message, DataUnitID.LDU2, null );
|
||||
|
||||
mLog.debug( ldu2.getMessage() );
|
||||
mLog.debug( "CRC: " + CRC.format( ldu2.getCRCResults() ));
|
||||
}
|
||||
}
|
||||
93
src/module/decode/p25/message/ldu/LDUMessage.java
Normal file
93
src/module/decode/p25/message/ldu/LDUMessage.java
Normal file
@@ -0,0 +1,93 @@
|
||||
package module.decode.p25.message.ldu;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import module.decode.p25.message.P25Message;
|
||||
import module.decode.p25.reference.DataUnitID;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import alias.AliasList;
|
||||
import bits.BinaryMessage;
|
||||
|
||||
public abstract class LDUMessage extends P25Message
|
||||
{
|
||||
private final static Logger mLog = LoggerFactory.getLogger( LDUMessage.class );
|
||||
|
||||
public static final int IMBE_FRAME_1 = 64;
|
||||
public static final int IMBE_FRAME_2 = 208;
|
||||
public static final int IMBE_FRAME_3 = 392;
|
||||
public static final int IMBE_FRAME_4 = 576;
|
||||
public static final int IMBE_FRAME_5 = 760;
|
||||
public static final int IMBE_FRAME_6 = 944;
|
||||
public static final int IMBE_FRAME_7 = 1128;
|
||||
public static final int IMBE_FRAME_8 = 1312;
|
||||
public static final int IMBE_FRAME_9 = 1488;
|
||||
|
||||
public static final int[] LOW_SPEED_DATA = { 1456,1457,1458,1459,1460,1461,
|
||||
1462,1463,1472,1473,1474,1475,1476,1477,1478,1479 };
|
||||
|
||||
public LDUMessage( BinaryMessage message, DataUnitID duid,
|
||||
AliasList aliasList )
|
||||
{
|
||||
super( message, duid, aliasList );
|
||||
}
|
||||
|
||||
public abstract boolean isEncrypted();
|
||||
|
||||
@Override
|
||||
public String getMessage()
|
||||
{
|
||||
return getMessageStub();
|
||||
}
|
||||
|
||||
public String getMessageStub()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append( "NAC:" );
|
||||
sb.append( getNAC() );
|
||||
sb.append( " " );
|
||||
sb.append( getDUID().getLabel() );
|
||||
sb.append( " VOICE LSD:" );
|
||||
sb.append( getLowSpeedData() );
|
||||
sb.append( " " );
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public String getLowSpeedData()
|
||||
{
|
||||
return mMessage.getHex( LOW_SPEED_DATA, 4 );
|
||||
}
|
||||
|
||||
public boolean isValid()
|
||||
{
|
||||
// return mCRC[ 2 ] != null && mCRC[ 2 ] != CRC.FAILED_CRC;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a 162 byte array containing 9 IMBE voice frames of 18-bytes
|
||||
* (144-bits) each. Each frame is intact as transmitted and requires
|
||||
* deinterleaving, error correction, derandomizing, etc.
|
||||
*/
|
||||
public List<byte[]> getIMBEFrames()
|
||||
{
|
||||
List<byte[]> frames = new ArrayList<byte[]>();
|
||||
|
||||
frames.add( mMessage.get( IMBE_FRAME_1, IMBE_FRAME_1 + 144 ).toByteArray() );
|
||||
frames.add( mMessage.get( IMBE_FRAME_2, IMBE_FRAME_2 + 144 ).toByteArray() );
|
||||
frames.add( mMessage.get( IMBE_FRAME_3, IMBE_FRAME_3 + 144 ).toByteArray() );
|
||||
frames.add( mMessage.get( IMBE_FRAME_4, IMBE_FRAME_4 + 144 ).toByteArray() );
|
||||
frames.add( mMessage.get( IMBE_FRAME_5, IMBE_FRAME_5 + 144 ).toByteArray() );
|
||||
frames.add( mMessage.get( IMBE_FRAME_6, IMBE_FRAME_6 + 144 ).toByteArray() );
|
||||
frames.add( mMessage.get( IMBE_FRAME_7, IMBE_FRAME_7 + 144 ).toByteArray() );
|
||||
frames.add( mMessage.get( IMBE_FRAME_8, IMBE_FRAME_8 + 144 ).toByteArray() );
|
||||
frames.add( mMessage.get( IMBE_FRAME_9, IMBE_FRAME_9 + 144 ).toByteArray() );
|
||||
|
||||
return frames;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,127 @@
|
||||
package module.decode.p25.message.ldu.lc;
|
||||
|
||||
import module.decode.p25.message.IBandIdentifier;
|
||||
import module.decode.p25.message.IdentifierReceiver;
|
||||
import module.decode.p25.message.ldu.LDU1Message;
|
||||
import module.decode.p25.reference.LinkControlOpcode;
|
||||
import module.decode.p25.reference.Service;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class AdjacentSiteStatusBroadcast extends LDU1Message
|
||||
implements IdentifierReceiver
|
||||
{
|
||||
private final static Logger mLog =
|
||||
LoggerFactory.getLogger( AdjacentSiteStatusBroadcast.class );
|
||||
|
||||
public static final int[] LRA = { 364,365,366,367,372,373,374,375 };
|
||||
public static final int[] SYSTEM_ID = { 384,385,386,387,536,537,538,539,540,
|
||||
541,546,547 };
|
||||
public static final int[] RFSS_ID = { 548,549,550,551,556,557,558,559 };
|
||||
public static final int[] SITE_ID = { 560,561,566,567,568,569,570,571 };
|
||||
public static final int[] IDENTIFIER = { 720,721,722,723 };
|
||||
public static final int[] CHANNEL = { 724,725,730,731,732,733,734,735,740,
|
||||
741,742,743 };
|
||||
public static final int[] SYSTEM_SERVICE_CLASS = { 744,745,750,751,752,753,
|
||||
754,755 };
|
||||
|
||||
private IBandIdentifier mIdentifierUpdate;
|
||||
|
||||
public AdjacentSiteStatusBroadcast( LDU1Message message )
|
||||
{
|
||||
super( message );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getEventType()
|
||||
{
|
||||
return LinkControlOpcode.ADJACENT_SITE_STATUS_BROADCAST.getDescription();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMessage()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append( getMessageStub() );
|
||||
|
||||
sb.append( " LRA:" + getLocationRegistrationArea() );
|
||||
|
||||
sb.append( " SYS:" + getSystemID() );
|
||||
|
||||
sb.append( " SITE:" + getRFSubsystemID() + "-" + getSiteID() );
|
||||
|
||||
sb.append( " CHAN:" + getChannel() );
|
||||
|
||||
sb.append( " " + Service.getServices( getSystemServiceClass() ).toString() );
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public String getLocationRegistrationArea()
|
||||
{
|
||||
return mMessage.getHex( LRA, 2 );
|
||||
}
|
||||
|
||||
public String getSystemID()
|
||||
{
|
||||
return mMessage.getHex( SYSTEM_ID, 3 );
|
||||
}
|
||||
|
||||
public String getRFSubsystemID()
|
||||
{
|
||||
return mMessage.getHex( RFSS_ID, 2 );
|
||||
}
|
||||
|
||||
public String getSiteID()
|
||||
{
|
||||
return mMessage.getHex( SITE_ID, 2 );
|
||||
}
|
||||
|
||||
public int getIdentifier()
|
||||
{
|
||||
return mMessage.getInt( IDENTIFIER );
|
||||
}
|
||||
|
||||
public String getChannel()
|
||||
{
|
||||
return getIdentifier() + "-" + getChannelNumber();
|
||||
}
|
||||
|
||||
public int getChannelNumber()
|
||||
{
|
||||
return mMessage.getInt( CHANNEL );
|
||||
}
|
||||
|
||||
public int getSystemServiceClass()
|
||||
{
|
||||
return mMessage.getInt( SYSTEM_SERVICE_CLASS );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setIdentifierMessage( int identifier, IBandIdentifier message )
|
||||
{
|
||||
mIdentifierUpdate = message;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] getIdentifiers()
|
||||
{
|
||||
int[] identifiers = new int[ 1 ];
|
||||
|
||||
identifiers[ 0 ] = getIdentifier();
|
||||
|
||||
return identifiers;
|
||||
}
|
||||
|
||||
public long getDownlinkFrequency()
|
||||
{
|
||||
return calculateDownlink( mIdentifierUpdate, getChannelNumber() );
|
||||
}
|
||||
|
||||
public long getUplinkFrequencyB()
|
||||
{
|
||||
return calculateUplink( mIdentifierUpdate, getChannelNumber() );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
package module.decode.p25.message.ldu.lc;
|
||||
|
||||
import module.decode.p25.message.ldu.LDU1Message;
|
||||
import module.decode.p25.reference.LinkControlOpcode;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class AdjacentSiteStatusBroadcastExplicit extends LDU1Message
|
||||
{
|
||||
private final static Logger mLog =
|
||||
LoggerFactory.getLogger( AdjacentSiteStatusBroadcastExplicit.class );
|
||||
|
||||
public static final int[] LRA = { 364,365,366,367,372,373,374,375 };
|
||||
public static final int[] TRANSMIT_IDENTIFIER = { 376,377,382,383 };
|
||||
public static final int[] TRANSMIT_CHANNEL = { 384,385,386,387,536,537,538,
|
||||
539,540,541,546,547 };
|
||||
public static final int[] RFSS_ID = { 548,549,550,551,556,557,558,559 };
|
||||
public static final int[] SITE_ID = { 560,561,566,567,568,569,570,571 };
|
||||
|
||||
public static final int[] RECEIVE_IDENTIFIER = { 720,721,722,723 };
|
||||
public static final int[] RECEIVE_CHANNEL = { 724,725,730,731,732,733,734,
|
||||
735,740,741,742,743 };
|
||||
|
||||
public AdjacentSiteStatusBroadcastExplicit( LDU1Message message )
|
||||
{
|
||||
super( message );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getEventType()
|
||||
{
|
||||
return LinkControlOpcode.ADJACENT_SITE_STATUS_BROADCAST_EXPLICIT.getDescription();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMessage()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append( getMessageStub() );
|
||||
|
||||
sb.append( " LRA:" + getLocationRegistrationArea() );
|
||||
|
||||
sb.append( " SITE:" + getRFSubsystemID() + "-" + getSiteID() );
|
||||
|
||||
sb.append( " DNLINK:" + getTransmitChannelNumber() );
|
||||
|
||||
sb.append( " UPLINK:" + getReceiveChannelNumber() );
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public String getLocationRegistrationArea()
|
||||
{
|
||||
return mMessage.getHex( LRA, 2 );
|
||||
}
|
||||
|
||||
public String getRFSubsystemID()
|
||||
{
|
||||
return mMessage.getHex( RFSS_ID, 2 );
|
||||
}
|
||||
|
||||
public String getSiteID()
|
||||
{
|
||||
return mMessage.getHex( SITE_ID, 2 );
|
||||
}
|
||||
|
||||
public int getTransmitIdentifier()
|
||||
{
|
||||
return mMessage.getInt( TRANSMIT_IDENTIFIER );
|
||||
}
|
||||
|
||||
public int getTransmitChannel()
|
||||
{
|
||||
return mMessage.getInt( TRANSMIT_CHANNEL );
|
||||
}
|
||||
|
||||
public String getTransmitChannelNumber()
|
||||
{
|
||||
return getTransmitIdentifier() + "-" + getTransmitChannel();
|
||||
}
|
||||
|
||||
public int getReceiveIdentifier()
|
||||
{
|
||||
return mMessage.getInt( RECEIVE_IDENTIFIER );
|
||||
}
|
||||
|
||||
public int getReceiveChannel()
|
||||
{
|
||||
return mMessage.getInt( RECEIVE_CHANNEL );
|
||||
}
|
||||
|
||||
public String getReceiveChannelNumber()
|
||||
{
|
||||
return getReceiveIdentifier() + "-" + getReceiveChannel();
|
||||
}
|
||||
}
|
||||
50
src/module/decode/p25/message/ldu/lc/CallAlert.java
Normal file
50
src/module/decode/p25/message/ldu/lc/CallAlert.java
Normal file
@@ -0,0 +1,50 @@
|
||||
package module.decode.p25.message.ldu.lc;
|
||||
|
||||
import module.decode.p25.message.ldu.LDU1Message;
|
||||
import module.decode.p25.reference.LinkControlOpcode;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class CallAlert extends LDU1Message
|
||||
{
|
||||
private final static Logger mLog =
|
||||
LoggerFactory.getLogger( CallAlert.class );
|
||||
public static final int[] TARGET_ADDRESS = { 536,537,538,539,540,541,546,
|
||||
547,548,549,550,551,556,557,558,559,560,561,566,567,568,569,570,571 };
|
||||
public static final int[] SOURCE_ADDRESS = { 720,721,722,723,724,725,730,
|
||||
731,732,733,734,735,740,741,742,743,744,745,750,751,752,753,754,755 };
|
||||
|
||||
public CallAlert( LDU1Message message )
|
||||
{
|
||||
super( message );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getEventType()
|
||||
{
|
||||
return LinkControlOpcode.CALL_ALERT.getDescription();
|
||||
}
|
||||
|
||||
public String getMessage()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append( getMessageStub() );
|
||||
|
||||
sb.append( " SRC ADDR: " + getSourceAddress() );
|
||||
sb.append( " TGT ADDR: " + getTargetAddress() );
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public String getTargetAddress()
|
||||
{
|
||||
return mMessage.getHex( TARGET_ADDRESS, 6 );
|
||||
}
|
||||
|
||||
public String getSourceAddress()
|
||||
{
|
||||
return mMessage.getHex( SOURCE_ADDRESS, 6 );
|
||||
}
|
||||
}
|
||||
43
src/module/decode/p25/message/ldu/lc/CallTermination.java
Normal file
43
src/module/decode/p25/message/ldu/lc/CallTermination.java
Normal file
@@ -0,0 +1,43 @@
|
||||
package module.decode.p25.message.ldu.lc;
|
||||
|
||||
import module.decode.p25.message.ldu.LDU1Message;
|
||||
import module.decode.p25.reference.LinkControlOpcode;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class CallTermination extends LDU1Message
|
||||
{
|
||||
private final static Logger mLog = LoggerFactory.getLogger( CallTermination.class );
|
||||
|
||||
public static final int[] SOURCE_ADDRESS = { 720,721,722,723,724,725,730,
|
||||
731,732,733,734,735,740,741,742,743,744,745,750,751,752,753,754,755 };
|
||||
|
||||
public CallTermination( LDU1Message message )
|
||||
{
|
||||
super( message );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getEventType()
|
||||
{
|
||||
return LinkControlOpcode.CALL_TERMINATION_OR_CANCELLATION.getDescription();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMessage()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append( getMessageStub() );
|
||||
|
||||
sb.append( " FROM:" + getSourceAddress() );
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public String getSourceAddress()
|
||||
{
|
||||
return mMessage.getHex( SOURCE_ADDRESS, 6 );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
package module.decode.p25.message.ldu.lc;
|
||||
|
||||
import module.decode.p25.message.IBandIdentifier;
|
||||
import module.decode.p25.message.ldu.LDU1Message;
|
||||
import module.decode.p25.reference.LinkControlOpcode;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class ChannelIdentifierUpdate extends LDU1Message
|
||||
implements IBandIdentifier
|
||||
{
|
||||
private final static Logger mLog =
|
||||
LoggerFactory.getLogger( ChannelIdentifierUpdate.class );
|
||||
|
||||
public static final int[] IDENTIFIER = { 364,365,366,367 };
|
||||
public static final int[] BANDWIDTH = { 372,373,374,375,376,377,382,383,384 };
|
||||
public static final int[] TRANSMIT_OFFSET = { 385,386,387,536,537,538,539,
|
||||
540,541 };
|
||||
public static final int[] CHANNEL_SPACING = { 546,547,548,549,550,551,556,
|
||||
557,558,559 };
|
||||
public static final int[] BASE_FREQUENCY = { 560,561,566,567,568,569,570,
|
||||
571,720,721,722,723,724,725,730,731,732,733,734,735,740,741,742,743,744,
|
||||
745,750,751,752,753,754,755 };
|
||||
|
||||
public ChannelIdentifierUpdate( LDU1Message message )
|
||||
{
|
||||
super( message );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getEventType()
|
||||
{
|
||||
return LinkControlOpcode.CHANNEL_IDENTIFIER_UPDATE.getDescription();
|
||||
}
|
||||
|
||||
@Override
|
||||
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();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getIdentifier()
|
||||
{
|
||||
return mMessage.getInt( IDENTIFIER );
|
||||
}
|
||||
|
||||
/**
|
||||
* Channel bandwidth in hertz
|
||||
*/
|
||||
@Override
|
||||
public int getBandwidth()
|
||||
{
|
||||
return mMessage.getInt( BANDWIDTH ) * 125;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getChannelSpacing()
|
||||
{
|
||||
return mMessage.getLong( CHANNEL_SPACING ) * 125l;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getBaseFrequency()
|
||||
{
|
||||
return mMessage.getLong( BASE_FREQUENCY ) * 5l;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getTransmitOffset()
|
||||
{
|
||||
return -1 * mMessage.getLong( TRANSMIT_OFFSET ) * 250000l;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
package module.decode.p25.message.ldu.lc;
|
||||
|
||||
import module.decode.p25.message.IBandIdentifier;
|
||||
import module.decode.p25.message.ldu.LDU1Message;
|
||||
import module.decode.p25.reference.LinkControlOpcode;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class ChannelIdentifierUpdateExplicit extends LDU1Message
|
||||
implements IBandIdentifier
|
||||
{
|
||||
private final static Logger mLog =
|
||||
LoggerFactory.getLogger( ChannelIdentifierUpdateExplicit.class );
|
||||
|
||||
public static final int[] IDENTIFIER = { 364,365,366,367 };
|
||||
public static final int[] BANDWIDTH = { 372,373,374,375 };
|
||||
public static final int[] TRANSMIT_OFFSET = { 376,377,382,383,384,385,386,
|
||||
387,536,537,538,539,540,541 };
|
||||
public static final int[] CHANNEL_SPACING = { 546,547,548,549,550,551,556,
|
||||
557,558,559 };
|
||||
public static final int[] BASE_FREQUENCY = { 560,561,566,567,568,569,570,
|
||||
571,720,721,722,723,724,725,730,731,732,733,734,735,740,741,742,743,744,
|
||||
745,750,751,752,753,754,755 };
|
||||
|
||||
public ChannelIdentifierUpdateExplicit( LDU1Message source )
|
||||
{
|
||||
super( source );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getEventType()
|
||||
{
|
||||
return LinkControlOpcode.CHANNEL_IDENTIFIER_UPDATE_EXPLICIT.getDescription();
|
||||
}
|
||||
|
||||
@Override
|
||||
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();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getIdentifier()
|
||||
{
|
||||
return mMessage.getInt( IDENTIFIER );
|
||||
}
|
||||
|
||||
/**
|
||||
* Channel bandwidth in hertz
|
||||
*/
|
||||
@Override
|
||||
public int getBandwidth()
|
||||
{
|
||||
return mMessage.getInt( BANDWIDTH ) * 125;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getChannelSpacing()
|
||||
{
|
||||
return mMessage.getLong( CHANNEL_SPACING ) * 125l;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getBaseFrequency()
|
||||
{
|
||||
return mMessage.getLong( BASE_FREQUENCY ) * 5l;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getTransmitOffset()
|
||||
{
|
||||
return -1 * mMessage.getLong( TRANSMIT_OFFSET ) * 250000l;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
package module.decode.p25.message.ldu.lc;
|
||||
|
||||
import module.decode.p25.message.ldu.LDU1Message;
|
||||
import module.decode.p25.reference.ExtendedFunction;
|
||||
import module.decode.p25.reference.LinkControlOpcode;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class ExtendedFunctionCommand extends LDU1Message
|
||||
{
|
||||
private final static Logger mLog =
|
||||
LoggerFactory.getLogger( ExtendedFunctionCommand.class );
|
||||
public static final int[] EXTENDED_FUNCTION = { 364,365,366,367,372,373,374,
|
||||
375,376,377,382,383,384,385,386,387 };
|
||||
public static final int[] ARGUMENT = { 536,537,538,539,540,541,546,547,548,
|
||||
549,550,551,556,557,558,559,560,561,566,567,568,569,570,571 };
|
||||
public static final int[] TARGET_ADDRESS = { 720,721,722,723,724,725,730,
|
||||
731,732,733,734,735,740,741,742,743,744,745,750,751,752,753,754,755 };
|
||||
|
||||
public ExtendedFunctionCommand( LDU1Message source )
|
||||
{
|
||||
super( source );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getEventType()
|
||||
{
|
||||
return LinkControlOpcode.EXTENDED_FUNCTION_COMMAND.getDescription();
|
||||
}
|
||||
|
||||
public String getMessage()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append( getMessageStub() );
|
||||
|
||||
sb.append( " EXTENDED FUNCTION:" + getExtendedFunction().getLabel() );
|
||||
|
||||
sb.append( " ARGUMENT: " + getTargetAddress() );
|
||||
|
||||
sb.append( " TGT ADDR: " + getTargetAddress() );
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public ExtendedFunction getExtendedFunction()
|
||||
{
|
||||
return ExtendedFunction.fromValue( mMessage.getInt( EXTENDED_FUNCTION ) );
|
||||
}
|
||||
|
||||
public String getArgument()
|
||||
{
|
||||
return mMessage.getHex( ARGUMENT, 6 );
|
||||
}
|
||||
|
||||
public String getSourceAddress()
|
||||
{
|
||||
switch( getExtendedFunction() )
|
||||
{
|
||||
case RADIO_CHECK:
|
||||
case RADIO_CHECK_ACK:
|
||||
case RADIO_DETACH:
|
||||
case RADIO_DETACH_ACK:
|
||||
case RADIO_INHIBIT:
|
||||
case RADIO_INHIBIT_ACK:
|
||||
case RADIO_UNINHIBIT:
|
||||
case RADIO_UNINHIBIT_ACK:
|
||||
return getArgument();
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public String getTargetAddress()
|
||||
{
|
||||
return mMessage.getHex( TARGET_ADDRESS, 6 );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getToID()
|
||||
{
|
||||
return getTargetAddress();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
package module.decode.p25.message.ldu.lc;
|
||||
|
||||
import module.decode.p25.message.ldu.LDU1Message;
|
||||
import module.decode.p25.reference.LinkControlOpcode;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class GroupAffiliationQuery extends LDU1Message
|
||||
{
|
||||
private final static Logger mLog =
|
||||
LoggerFactory.getLogger( GroupAffiliationQuery.class );
|
||||
public static final int[] TARGET_ADDRESS = { 536,537,538,539,540,541,546,
|
||||
547,548,549,550,551,556,557,558,559,560,561,566,567,568,569,570,571 };
|
||||
public static final int[] SOURCE_ADDRESS = { 720,721,722,723,724,725,730,
|
||||
731,732,733,734,735,740,741,742,743,744,745,750,751,752,753,754,755 };
|
||||
|
||||
public GroupAffiliationQuery( LDU1Message message )
|
||||
{
|
||||
super( message );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getEventType()
|
||||
{
|
||||
return LinkControlOpcode.GROUP_AFFILIATION_QUERY.getDescription();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMessage()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append( getMessageStub() );
|
||||
|
||||
sb.append( " FROM:" + getSourceAddress() );
|
||||
|
||||
sb.append( " TO:" + getTargetAddress() );
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public String getTargetAddress()
|
||||
{
|
||||
return mMessage.getHex( TARGET_ADDRESS, 6 );
|
||||
}
|
||||
|
||||
public String getSourceAddress()
|
||||
{
|
||||
return mMessage.getHex( SOURCE_ADDRESS, 6 );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,160 @@
|
||||
package module.decode.p25.message.ldu.lc;
|
||||
|
||||
import module.decode.p25.message.IBandIdentifier;
|
||||
import module.decode.p25.message.IdentifierReceiver;
|
||||
import module.decode.p25.message.ldu.LDU1Message;
|
||||
import module.decode.p25.reference.LinkControlOpcode;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class GroupVoiceChannelUpdate extends LDU1Message
|
||||
implements IdentifierReceiver
|
||||
{
|
||||
private final static Logger mLog =
|
||||
LoggerFactory.getLogger( GroupVoiceChannelUpdate.class );
|
||||
|
||||
public static final int[] IDENTIFIER_A = { 364,365,366,367 };
|
||||
public static final int[] CHANNEL_A = { 372,373,374,375,376,377,382,383,384,
|
||||
385,386,387 };
|
||||
public static final int[] GROUP_ADDRESS_A = { 536,537,538,539,540,541,546,
|
||||
547,548,549,550,551,556,557,558,559 };
|
||||
public static final int[] IDENTIFIER_B = { 560,561,566,567 };
|
||||
public static final int[] CHANNEL_B = { 568,569,570,571,720,721,722,723,724,
|
||||
725,730,731 };
|
||||
public static final int[] GROUP_ADDRESS_B = { 732,733,734,735,740,741,742,
|
||||
743,744,745,750,751,752,753,754,755 };
|
||||
|
||||
private IBandIdentifier mIdentifierUpdateA;
|
||||
private IBandIdentifier mIdentifierUpdateB;
|
||||
|
||||
public GroupVoiceChannelUpdate( LDU1Message message )
|
||||
{
|
||||
super( message );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getEventType()
|
||||
{
|
||||
return LinkControlOpcode.GROUP_VOICE_CHANNEL_UPDATE.getDescription();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMessage()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append( getMessageStub() );
|
||||
|
||||
sb.append( " CHAN A:" + getChannelA() );
|
||||
|
||||
sb.append( " GRP A:" + getGroupAddressA() );
|
||||
|
||||
if( hasChannelB() )
|
||||
{
|
||||
sb.append( " CHAN B:" + getChannelA() );
|
||||
|
||||
sb.append( " GRP B:" + getGroupAddressA() );
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public int getChannelIdentifierA()
|
||||
{
|
||||
return mMessage.getInt( IDENTIFIER_A );
|
||||
}
|
||||
|
||||
public int getChannelNumberA()
|
||||
{
|
||||
return mMessage.getInt( CHANNEL_A );
|
||||
}
|
||||
|
||||
public String getChannelA()
|
||||
{
|
||||
return getChannelIdentifierA() + "-" + getChannelNumberA();
|
||||
}
|
||||
|
||||
public int getChannelIdentifierB()
|
||||
{
|
||||
return mMessage.getInt( IDENTIFIER_B );
|
||||
}
|
||||
|
||||
public int getChannelNumberB()
|
||||
{
|
||||
return mMessage.getInt( CHANNEL_B );
|
||||
}
|
||||
|
||||
public String getChannelB()
|
||||
{
|
||||
return getChannelIdentifierB() + "-" + getChannelNumberB();
|
||||
}
|
||||
|
||||
public boolean hasChannelB()
|
||||
{
|
||||
return getChannelNumberB() != 0;
|
||||
}
|
||||
|
||||
public String getGroupAddressA()
|
||||
{
|
||||
return mMessage.getHex( GROUP_ADDRESS_A, 4 );
|
||||
}
|
||||
|
||||
public String getGroupAddressB()
|
||||
{
|
||||
return mMessage.getHex( GROUP_ADDRESS_B, 4 );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setIdentifierMessage( int identifier, IBandIdentifier message )
|
||||
{
|
||||
if( identifier == getChannelIdentifierA() )
|
||||
{
|
||||
mIdentifierUpdateA = message;
|
||||
}
|
||||
if( identifier == getChannelIdentifierB() )
|
||||
{
|
||||
mIdentifierUpdateB = message;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] getIdentifiers()
|
||||
{
|
||||
if( hasChannelB() )
|
||||
{
|
||||
int[] identifiers = new int[ 2 ];
|
||||
identifiers[ 0 ] = getChannelIdentifierA();
|
||||
identifiers[ 1 ] = getChannelIdentifierB();
|
||||
|
||||
return identifiers;
|
||||
}
|
||||
else
|
||||
{
|
||||
int[] identifiers = new int[ 1 ];
|
||||
identifiers[ 0 ] = getChannelIdentifierA();
|
||||
|
||||
return identifiers;
|
||||
}
|
||||
}
|
||||
|
||||
public long getDownlinkFrequencyA()
|
||||
{
|
||||
return calculateDownlink( mIdentifierUpdateA, getChannelNumberA() );
|
||||
}
|
||||
|
||||
public long getUplinkFrequencyA()
|
||||
{
|
||||
return calculateUplink( mIdentifierUpdateA, getChannelNumberA() );
|
||||
}
|
||||
|
||||
public long getDownlinkFrequencyB()
|
||||
{
|
||||
return calculateDownlink( mIdentifierUpdateB, getChannelNumberA() );
|
||||
}
|
||||
|
||||
public long getUplinkFrequencyB()
|
||||
{
|
||||
return calculateUplink( mIdentifierUpdateB, getChannelNumberA() );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,157 @@
|
||||
package module.decode.p25.message.ldu.lc;
|
||||
|
||||
import module.decode.p25.message.IBandIdentifier;
|
||||
import module.decode.p25.message.IdentifierReceiver;
|
||||
import module.decode.p25.message.P25Message.DuplexMode;
|
||||
import module.decode.p25.message.P25Message.SessionMode;
|
||||
import module.decode.p25.message.ldu.LDU1Message;
|
||||
import module.decode.p25.reference.LinkControlOpcode;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class GroupVoiceChannelUpdateExplicit extends LDU1Message
|
||||
implements IdentifierReceiver
|
||||
{
|
||||
private final static Logger mLog =
|
||||
LoggerFactory.getLogger( GroupVoiceChannelUpdateExplicit.class );
|
||||
|
||||
public static final int EMERGENCY_FLAG = 376;
|
||||
public static final int ENCRYPTED_CHANNEL_FLAG = 377;
|
||||
public static final int DUPLEX_MODE = 382;
|
||||
public static final int SESSION_MODE = 383;
|
||||
public static final int[] GROUP_ADDRESS = { 536,537,538,539,540,541,546,547,
|
||||
548,549,550,551,556,557,558,559 };
|
||||
public static final int[] TRANSMIT_IDENTIFIER = { 560,561,566,567 };
|
||||
public static final int[] TRANSMIT_CHANNEL = { 568,569,570,571,720,721,722,
|
||||
723,724,725,730,731 };
|
||||
public static final int[] RECEIVE_IDENTIFIER = { 732,733,734,735 };
|
||||
public static final int[] RECEIVE_CHANNEL = { 740,741,742,743,744,745,750,
|
||||
751,752,753,754,755 };
|
||||
|
||||
private IBandIdentifier mTransmitIdentifierUpdate;
|
||||
private IBandIdentifier mReceiveIdentifierUpdate;
|
||||
|
||||
public GroupVoiceChannelUpdateExplicit( LDU1Message message )
|
||||
{
|
||||
super( message );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getEventType()
|
||||
{
|
||||
return LinkControlOpcode.GROUP_VOICE_CHANNEL_UPDATE_EXPLICIT.getDescription();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMessage()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append( getMessageStub() );
|
||||
|
||||
if( isEmergency() )
|
||||
{
|
||||
sb.append( " EMERGENCY" );
|
||||
}
|
||||
if( isEncryptedChannel() )
|
||||
{
|
||||
sb.append( " ENCRYPTED CHANNEL" );
|
||||
}
|
||||
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
public int getTransmitChannelIdentifier()
|
||||
{
|
||||
return mMessage.getInt( TRANSMIT_IDENTIFIER );
|
||||
}
|
||||
|
||||
public int getTransmitChannelNumber()
|
||||
{
|
||||
return mMessage.getInt( TRANSMIT_CHANNEL );
|
||||
}
|
||||
|
||||
public String getTransmitChannel()
|
||||
{
|
||||
return getTransmitChannelIdentifier() + "-" + getTransmitChannelNumber();
|
||||
}
|
||||
|
||||
public int getReceiveChannelIdentifier()
|
||||
{
|
||||
return mMessage.getInt( RECEIVE_IDENTIFIER );
|
||||
}
|
||||
|
||||
public int getReceiveChannelNumber()
|
||||
{
|
||||
return mMessage.getInt( RECEIVE_CHANNEL );
|
||||
}
|
||||
|
||||
public String getReceiveChannel()
|
||||
{
|
||||
return getReceiveChannelIdentifier() + "-" + getReceiveChannelNumber();
|
||||
}
|
||||
|
||||
public String getGroupAddress()
|
||||
{
|
||||
return mMessage.getHex( GROUP_ADDRESS, 4 );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setIdentifierMessage( int identifier, IBandIdentifier message )
|
||||
{
|
||||
if( identifier == getTransmitChannelIdentifier() )
|
||||
{
|
||||
mTransmitIdentifierUpdate = message;
|
||||
}
|
||||
if( identifier == getReceiveChannelIdentifier() )
|
||||
{
|
||||
mReceiveIdentifierUpdate = message;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] getIdentifiers()
|
||||
{
|
||||
int[] identifiers = new int[ 2 ];
|
||||
|
||||
identifiers[ 0 ] = getTransmitChannelIdentifier();
|
||||
identifiers[ 1 ] = getReceiveChannelIdentifier();
|
||||
|
||||
return identifiers;
|
||||
}
|
||||
|
||||
public long getDownlinkFrequency()
|
||||
{
|
||||
return calculateDownlink( mTransmitIdentifierUpdate,
|
||||
getTransmitChannelNumber() );
|
||||
}
|
||||
|
||||
public long getUplinkFrequency()
|
||||
{
|
||||
return calculateUplink( mReceiveIdentifierUpdate,
|
||||
getReceiveChannelNumber() );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
package module.decode.p25.message.ldu.lc;
|
||||
|
||||
import module.decode.p25.message.ldu.LDU1Message;
|
||||
import module.decode.p25.reference.LinkControlOpcode;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class GroupVoiceChannelUser extends LDU1Message
|
||||
{
|
||||
private final static Logger mLog =
|
||||
LoggerFactory.getLogger( GroupVoiceChannelUser.class );
|
||||
/* Service Options */
|
||||
public static final int EMERGENCY_FLAG = 376;
|
||||
public static final int ENCRYPTED_CHANNEL_FLAG = 377;
|
||||
public static final int DUPLEX_MODE = 378;
|
||||
public static final int SESSION_MODE = 379;
|
||||
public static final int[] GROUP_ADDRESS = { 548,549,550,551,556,557,558,559,
|
||||
560,561,566,567,568,569,570,571 };
|
||||
public static final int[] SOURCE_ADDRESS = { 720,721,722,723,724,725,730,
|
||||
731,732,733,734,735,740,741,742,743,744,745,750,751,752,753,754,755 };
|
||||
|
||||
public GroupVoiceChannelUser( LDU1Message message )
|
||||
{
|
||||
super( message );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getEventType()
|
||||
{
|
||||
return LinkControlOpcode.GROUP_VOICE_CHANNEL_USER.getDescription();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMessage()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append( getMessageStub() );
|
||||
|
||||
if( isEmergency() )
|
||||
{
|
||||
sb.append( " EMERGENCY" );
|
||||
}
|
||||
if( isEncryptedChannel() )
|
||||
{
|
||||
sb.append( " ENCRYPTED CHANNEL" );
|
||||
}
|
||||
|
||||
sb.append( " FROM:" + getSourceAddress() );
|
||||
|
||||
sb.append( " TO:" + getGroupAddress() );
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
public String getGroupAddress()
|
||||
{
|
||||
return mMessage.getHex( GROUP_ADDRESS, 4 );
|
||||
}
|
||||
|
||||
public String getSourceAddress()
|
||||
{
|
||||
return mMessage.getHex( SOURCE_ADDRESS, 6 );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
package module.decode.p25.message.ldu.lc;
|
||||
|
||||
import module.decode.p25.message.ldu.LDU1Message;
|
||||
import module.decode.p25.reference.Vendor;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
|
||||
public class LDULCMessageFactory
|
||||
{
|
||||
private final static Logger mLog =
|
||||
LoggerFactory.getLogger( LDULCMessageFactory.class );
|
||||
|
||||
/**
|
||||
* Constructs a new sub-class of the TDULC message if the opcode is recognized
|
||||
* or returns the original message.
|
||||
*/
|
||||
public static LDU1Message getMessage( LDU1Message message )
|
||||
{
|
||||
if( message.isImplicitFormat() || message.getVendor() == Vendor.STANDARD )
|
||||
{
|
||||
switch( message.getOpcode() )
|
||||
{
|
||||
case ADJACENT_SITE_STATUS_BROADCAST:
|
||||
return new AdjacentSiteStatusBroadcast( message );
|
||||
case ADJACENT_SITE_STATUS_BROADCAST_EXPLICIT:
|
||||
return new AdjacentSiteStatusBroadcastExplicit( message );
|
||||
case CALL_ALERT:
|
||||
return new CallAlert( message );
|
||||
case CALL_TERMINATION_OR_CANCELLATION:
|
||||
return new CallTermination( message );
|
||||
case CHANNEL_IDENTIFIER_UPDATE:
|
||||
return new ChannelIdentifierUpdate( message );
|
||||
case CHANNEL_IDENTIFIER_UPDATE_EXPLICIT:
|
||||
return new ChannelIdentifierUpdateExplicit( message );
|
||||
case EXTENDED_FUNCTION_COMMAND:
|
||||
return new ExtendedFunctionCommand( message );
|
||||
case GROUP_AFFILIATION_QUERY:
|
||||
return new GroupAffiliationQuery( message );
|
||||
case GROUP_VOICE_CHANNEL_UPDATE:
|
||||
return new GroupVoiceChannelUpdate( message );
|
||||
case GROUP_VOICE_CHANNEL_UPDATE_EXPLICIT:
|
||||
return new GroupVoiceChannelUpdateExplicit( message );
|
||||
case GROUP_VOICE_CHANNEL_USER:
|
||||
return new GroupVoiceChannelUser( message );
|
||||
case MESSAGE_UPDATE:
|
||||
return new MessageUpdate( message );
|
||||
case NETWORK_STATUS_BROADCAST:
|
||||
return new NetworkStatusBroadcast( message );
|
||||
case NETWORK_STATUS_BROADCAST_EXPLICIT:
|
||||
return new NetworkStatusBroadcastExplicit( message );
|
||||
case PROTECTION_PARAMETER_BROADCAST:
|
||||
return new ProtectionParameterBroadcast( message );
|
||||
case RFSS_STATUS_BROADCAST:
|
||||
return new RFSSStatusBroadcast( message );
|
||||
case RFSS_STATUS_BROADCAST_EXPLICIT:
|
||||
return new RFSSStatusBroadcastExplicit( message );
|
||||
case SECONDARY_CONTROL_CHANNEL_BROADCAST:
|
||||
return new SecondaryControlChannelBroadcast( message );
|
||||
case SECONDARY_CONTROL_CHANNEL_BROADCAST_EXPLICIT:
|
||||
return new SecondaryControlChannelBroadcastExplicit( message );
|
||||
case STATUS_QUERY:
|
||||
return new StatusQuery( message );
|
||||
case STATUS_UPDATE:
|
||||
return new StatusUpdate( message );
|
||||
case SYSTEM_SERVICE_BROADCAST:
|
||||
return new SystemServiceBroadcast( message );
|
||||
case TELEPHONE_INTERCONNECT_ANSWER_REQUEST:
|
||||
return new TelephoneInterconnectAnswerRequest( message );
|
||||
case TELEPHONE_INTERCONNECT_VOICE_CHANNEL_USER:
|
||||
return new TelephoneInterconnectVoiceChannelUser( message );
|
||||
case UNIT_AUTHENTICATION_COMMAND:
|
||||
return new UnitAuthenticationCommand( message );
|
||||
case UNIT_REGISTRATION_COMMAND:
|
||||
return new UnitRegistrationCommand( message );
|
||||
case UNIT_TO_UNIT_ANSWER_REQUEST:
|
||||
return new UnitToUnitAnswerRequest( message );
|
||||
case UNIT_TO_UNIT_VOICE_CHANNEL_USER:
|
||||
return new UnitToUnitVoiceChannelUser( message );
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch( message.getVendor() )
|
||||
{
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return message;
|
||||
}
|
||||
}
|
||||
58
src/module/decode/p25/message/ldu/lc/MessageUpdate.java
Normal file
58
src/module/decode/p25/message/ldu/lc/MessageUpdate.java
Normal file
@@ -0,0 +1,58 @@
|
||||
package module.decode.p25.message.ldu.lc;
|
||||
|
||||
import module.decode.p25.message.ldu.LDU1Message;
|
||||
import module.decode.p25.reference.LinkControlOpcode;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class MessageUpdate extends LDU1Message
|
||||
{
|
||||
private final static Logger mLog =
|
||||
LoggerFactory.getLogger( MessageUpdate.class );
|
||||
public static final int[] SHORT_DATA_MESSAGE = { 364,365,366,367,372,373,
|
||||
374,375,376,377,382,383,384,385,386,387 };
|
||||
public static final int[] TARGET_ADDRESS = { 536,537,538,539,540,541,546,
|
||||
547,548,549,550,551,556,557,558,559,560,561,566,567,568,569,570,571 };
|
||||
public static final int[] SOURCE_ADDRESS = { 720,721,722,723,724,725,730,
|
||||
731,732,733,734,735,740,741,742,743,744,745,750,751,752,753,754,755 };
|
||||
|
||||
public MessageUpdate( LDU1Message message )
|
||||
{
|
||||
super( message );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getEventType()
|
||||
{
|
||||
return LinkControlOpcode.MESSAGE_UPDATE.getDescription();
|
||||
}
|
||||
|
||||
public String getMessage()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append( getMessageStub() );
|
||||
|
||||
sb.append( " MSG:" + getShortDataMessage() );
|
||||
sb.append( " SRC ADDR: " + getSourceAddress() );
|
||||
sb.append( " TGT ADDR: " + getTargetAddress() );
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public String getShortDataMessage()
|
||||
{
|
||||
return mMessage.getHex( SHORT_DATA_MESSAGE, 4 );
|
||||
}
|
||||
|
||||
public String getTargetAddress()
|
||||
{
|
||||
return mMessage.getHex( TARGET_ADDRESS, 6 );
|
||||
}
|
||||
|
||||
public String getSourceAddress()
|
||||
{
|
||||
return mMessage.getHex( SOURCE_ADDRESS, 6 );
|
||||
}
|
||||
}
|
||||
110
src/module/decode/p25/message/ldu/lc/NetworkStatusBroadcast.java
Normal file
110
src/module/decode/p25/message/ldu/lc/NetworkStatusBroadcast.java
Normal file
@@ -0,0 +1,110 @@
|
||||
package module.decode.p25.message.ldu.lc;
|
||||
|
||||
import module.decode.p25.message.IBandIdentifier;
|
||||
import module.decode.p25.message.IdentifierReceiver;
|
||||
import module.decode.p25.message.ldu.LDU1Message;
|
||||
import module.decode.p25.reference.LinkControlOpcode;
|
||||
import module.decode.p25.reference.Service;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class NetworkStatusBroadcast extends LDU1Message
|
||||
implements IdentifierReceiver
|
||||
{
|
||||
private final static Logger mLog =
|
||||
LoggerFactory.getLogger( NetworkStatusBroadcast.class );
|
||||
public static final int[] NETWORK_ID = { 376,377,382,383,384,385,386,387,
|
||||
536,537,538,539,540,541,546,547,548,549,550,551 };
|
||||
public static final int[] SYSTEM_ID = { 556,557,558,559,560,561,566,567,568,
|
||||
569,570,571 };
|
||||
public static final int[] IDENTIFIER = { 720,721,722,723 };
|
||||
public static final int[] CHANNEL = { 724,725,730,731,732,733,734,735,740,
|
||||
741,742,743 };
|
||||
public static final int[] SYSTEM_SERVICE_CLASS = { 744,745,750,751,752,753,
|
||||
754,755 };
|
||||
|
||||
private IBandIdentifier mIdentifierUpdate;
|
||||
|
||||
public NetworkStatusBroadcast( LDU1Message source )
|
||||
{
|
||||
super( source );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getEventType()
|
||||
{
|
||||
return LinkControlOpcode.NETWORK_STATUS_BROADCAST.getDescription();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMessage()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append( getMessageStub() );
|
||||
|
||||
sb.append( " NETWORK:" + getNetworkID() );
|
||||
sb.append( " SYS:" + getSystem() );
|
||||
sb.append( " CHAN:" + getChannel() );
|
||||
sb.append( " " + Service.getServices( getSystemServiceClass() ).toString() );
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public String getNetworkID()
|
||||
{
|
||||
return mMessage.getHex( NETWORK_ID, 5 );
|
||||
}
|
||||
|
||||
public String getSystem()
|
||||
{
|
||||
return mMessage.getHex( SYSTEM_ID, 3 );
|
||||
}
|
||||
|
||||
public int getIdentifier()
|
||||
{
|
||||
return mMessage.getInt( IDENTIFIER );
|
||||
}
|
||||
|
||||
public int getChannelNumber()
|
||||
{
|
||||
return mMessage.getInt( CHANNEL );
|
||||
}
|
||||
|
||||
public String getChannel()
|
||||
{
|
||||
return getIdentifier() + "-" + getChannelNumber();
|
||||
}
|
||||
|
||||
public int getSystemServiceClass()
|
||||
{
|
||||
return mMessage.getInt( SYSTEM_SERVICE_CLASS );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setIdentifierMessage( int identifier, IBandIdentifier message )
|
||||
{
|
||||
mIdentifierUpdate = message;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] getIdentifiers()
|
||||
{
|
||||
int[] identifiers = new int[ 1 ];
|
||||
|
||||
identifiers[ 0 ] = getIdentifier();
|
||||
|
||||
return identifiers;
|
||||
}
|
||||
|
||||
public long getDownlinkFrequency()
|
||||
{
|
||||
return calculateDownlink( mIdentifierUpdate, getChannelNumber() );
|
||||
}
|
||||
|
||||
public long getUplinkFrequency()
|
||||
{
|
||||
return calculateUplink( mIdentifierUpdate, getChannelNumber() );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,131 @@
|
||||
package module.decode.p25.message.ldu.lc;
|
||||
|
||||
import module.decode.p25.message.IBandIdentifier;
|
||||
import module.decode.p25.message.IdentifierReceiver;
|
||||
import module.decode.p25.message.ldu.LDU1Message;
|
||||
import module.decode.p25.reference.LinkControlOpcode;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class NetworkStatusBroadcastExplicit extends LDU1Message
|
||||
implements IdentifierReceiver
|
||||
{
|
||||
private final static Logger mLog =
|
||||
LoggerFactory.getLogger( NetworkStatusBroadcastExplicit.class );
|
||||
public static final int[] NETWORK_ID = { 364,365,366,367,372,373,374,375,
|
||||
376,377,382,383,384,385,386,387,536,537,538,539 };
|
||||
public static final int[] SYSTEM_ID = { 540,541,546,547,548,549,550,551,556,
|
||||
557,558,559 };
|
||||
public static final int[] TRANSMIT_IDENTIFIER = { 560,561,566,567 };
|
||||
public static final int[] TRANSMIT_CHANNEL = { 568,569,570,571,720,721,722,
|
||||
723,724,725,730,731 };
|
||||
public static final int[] RECEIVE_IDENTIFIER = { 732,733,734,735 };
|
||||
public static final int[] RECEIVE_CHANNEL = { 740,741,742,743,744,745,750,
|
||||
751,752,753,754,755 };
|
||||
|
||||
private IBandIdentifier mTransmitIdentifierUpdate;
|
||||
private IBandIdentifier mReceiveIdentifierUpdate;
|
||||
|
||||
public NetworkStatusBroadcastExplicit( LDU1Message message )
|
||||
{
|
||||
super( message );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getEventType()
|
||||
{
|
||||
return LinkControlOpcode.NETWORK_STATUS_BROADCAST_EXPLICIT.getDescription();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMessage()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append( getMessageStub() );
|
||||
|
||||
sb.append( " NETWORK:" + getNetworkID() );
|
||||
sb.append( " SYS:" + getSystem() );
|
||||
sb.append( " TRANSMIT:" + getTransmitChannel() );
|
||||
sb.append( " RECEIVE:" + getReceiveChannel() );
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public String getNetworkID()
|
||||
{
|
||||
return mMessage.getHex( NETWORK_ID, 5 );
|
||||
}
|
||||
|
||||
public String getSystem()
|
||||
{
|
||||
return mMessage.getHex( SYSTEM_ID, 3 );
|
||||
}
|
||||
|
||||
public int getTransmitIdentifier()
|
||||
{
|
||||
return mMessage.getInt( TRANSMIT_IDENTIFIER );
|
||||
}
|
||||
|
||||
public int getTransmitChannelNumber()
|
||||
{
|
||||
return mMessage.getInt( TRANSMIT_CHANNEL );
|
||||
}
|
||||
|
||||
public String getTransmitChannel()
|
||||
{
|
||||
return getTransmitIdentifier() + "-" + getTransmitChannelNumber();
|
||||
}
|
||||
|
||||
public int getReceiveIdentifier()
|
||||
{
|
||||
return mMessage.getInt( RECEIVE_IDENTIFIER );
|
||||
}
|
||||
|
||||
public int getReceiveChannelNumber()
|
||||
{
|
||||
return mMessage.getInt( RECEIVE_CHANNEL );
|
||||
}
|
||||
|
||||
public String getReceiveChannel()
|
||||
{
|
||||
return getReceiveIdentifier() + "-" + getReceiveChannelNumber();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setIdentifierMessage( int identifier, IBandIdentifier message )
|
||||
{
|
||||
if( identifier == getTransmitIdentifier() )
|
||||
{
|
||||
mTransmitIdentifierUpdate = message;
|
||||
}
|
||||
if( identifier == getReceiveIdentifier() )
|
||||
{
|
||||
mReceiveIdentifierUpdate = message;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] getIdentifiers()
|
||||
{
|
||||
int[] identifiers = new int[ 2 ];
|
||||
|
||||
identifiers[ 0 ] = getTransmitIdentifier();
|
||||
identifiers[ 1 ] = getReceiveIdentifier();
|
||||
|
||||
return identifiers;
|
||||
}
|
||||
|
||||
public long getDownlinkFrequency()
|
||||
{
|
||||
return calculateDownlink( mTransmitIdentifierUpdate,
|
||||
getTransmitChannelNumber() );
|
||||
}
|
||||
|
||||
public long getUplinkFrequency()
|
||||
{
|
||||
return calculateUplink( mReceiveIdentifierUpdate,
|
||||
getReceiveChannelNumber() );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
package module.decode.p25.message.ldu.lc;
|
||||
|
||||
import module.decode.p25.message.ldu.LDU1Message;
|
||||
import module.decode.p25.reference.Encryption;
|
||||
import module.decode.p25.reference.LinkControlOpcode;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class ProtectionParameterBroadcast extends LDU1Message
|
||||
{
|
||||
private final static Logger mLog =
|
||||
LoggerFactory.getLogger( ProtectionParameterBroadcast.class );
|
||||
|
||||
public static final int[] ALGORITHM_ID = { 536,537,538,539,540,541,546,547 };
|
||||
public static final int[] KEY_ID = { 548,549,550,551,556,557,558,559,560,
|
||||
561,566,567,568,569,570,571 };
|
||||
public static final int[] TARGET_ADDRESS = { 720,721,722,723,724,725,730,
|
||||
731,732,733,734,735,740,741,742,743,744,745,750,751,752,753,754,755 };
|
||||
|
||||
public ProtectionParameterBroadcast( LDU1Message message )
|
||||
{
|
||||
super( message );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getEventType()
|
||||
{
|
||||
return LinkControlOpcode.PROTECTION_PARAMETER_BROADCAST.getDescription();
|
||||
}
|
||||
|
||||
public String getMessage()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append( getMessageStub() );
|
||||
|
||||
sb.append( " ENCRYPTION:" + getEncryption().name() );
|
||||
sb.append( " KEY:" + getEncryptionKey() );
|
||||
sb.append( " ADDRESSS:" + getTargetAddress() );
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public Encryption getEncryption()
|
||||
{
|
||||
return Encryption.fromValue( mMessage.getInt( ALGORITHM_ID ) );
|
||||
}
|
||||
|
||||
public int getEncryptionKey()
|
||||
{
|
||||
return mMessage.getInt( KEY_ID );
|
||||
}
|
||||
|
||||
public String getTargetAddress()
|
||||
{
|
||||
return mMessage.getHex( TARGET_ADDRESS, 6 );
|
||||
}
|
||||
}
|
||||
130
src/module/decode/p25/message/ldu/lc/RFSSStatusBroadcast.java
Normal file
130
src/module/decode/p25/message/ldu/lc/RFSSStatusBroadcast.java
Normal file
@@ -0,0 +1,130 @@
|
||||
package module.decode.p25.message.ldu.lc;
|
||||
|
||||
import module.decode.p25.message.IBandIdentifier;
|
||||
import module.decode.p25.message.IdentifierReceiver;
|
||||
import module.decode.p25.message.ldu.LDU1Message;
|
||||
import module.decode.p25.message.tsbk.osp.control.SystemService;
|
||||
import module.decode.p25.reference.LinkControlOpcode;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class RFSSStatusBroadcast extends LDU1Message
|
||||
implements IdentifierReceiver
|
||||
{
|
||||
private final static Logger mLog =
|
||||
LoggerFactory.getLogger( RFSSStatusBroadcast.class );
|
||||
|
||||
public static final int[] LRA = { 364,365,366,367,372,373,374,375 };
|
||||
public static final int[] SYSTEM_ID = { 384,385,386,387,536,537,538,539,540,
|
||||
541,546,547 };
|
||||
public static final int[] RFSS_ID = { 548,549,550,551,556,557,558,559 };
|
||||
public static final int[] SITE_ID = { 560,561,566,567,568,569,570,571 };
|
||||
public static final int[] IDENTIFIER = { 720,721,722,723 };
|
||||
public static final int[] CHANNEL = { 724,725,730,731,732,733,734,735,740,
|
||||
741,742,743 };
|
||||
public static final int[] SYSTEM_SERVICE_CLASS = { 744,745,750,751,752,753,
|
||||
754,755 };
|
||||
|
||||
private IBandIdentifier mIdentifierUpdate;
|
||||
|
||||
public RFSSStatusBroadcast( LDU1Message message )
|
||||
{
|
||||
super( message );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getEventType()
|
||||
{
|
||||
return LinkControlOpcode.RFSS_STATUS_BROADCAST.getDescription();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMessage()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append( getMessageStub() );
|
||||
|
||||
sb.append( " LRA:" + getLocationRegistrationArea() );
|
||||
|
||||
sb.append( " SYS:" + getSystem() );
|
||||
|
||||
sb.append( " SITE:" + getRFSubsystemID() + "-" + getSiteID() );
|
||||
|
||||
sb.append( " CHAN:" + getChannelNumber() );
|
||||
|
||||
sb.append( " " + SystemService.toString( getSystemServiceClass() ) );
|
||||
|
||||
sb.append( " " + mMessage.toString() );
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public String getLocationRegistrationArea()
|
||||
{
|
||||
return mMessage.getHex( LRA, 2 );
|
||||
}
|
||||
|
||||
public String getSystem()
|
||||
{
|
||||
return mMessage.getHex( SYSTEM_ID, 3 );
|
||||
}
|
||||
|
||||
public String getRFSubsystemID()
|
||||
{
|
||||
return mMessage.getHex( RFSS_ID, 2 );
|
||||
}
|
||||
|
||||
public String getSiteID()
|
||||
{
|
||||
return mMessage.getHex( SITE_ID, 2 );
|
||||
}
|
||||
|
||||
public int getIdentifier()
|
||||
{
|
||||
return mMessage.getInt( IDENTIFIER );
|
||||
}
|
||||
|
||||
public String getChannel()
|
||||
{
|
||||
return getIdentifier() + "-" + getChannelNumber();
|
||||
}
|
||||
|
||||
public int getChannelNumber()
|
||||
{
|
||||
return mMessage.getInt( CHANNEL );
|
||||
}
|
||||
|
||||
public int getSystemServiceClass()
|
||||
{
|
||||
return mMessage.getInt( SYSTEM_SERVICE_CLASS );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setIdentifierMessage( int identifier, IBandIdentifier message )
|
||||
{
|
||||
mIdentifierUpdate = message;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] getIdentifiers()
|
||||
{
|
||||
int[] identifiers = new int[ 1 ];
|
||||
|
||||
identifiers[ 0 ] = getIdentifier();
|
||||
|
||||
return identifiers;
|
||||
}
|
||||
|
||||
public long getDownlinkFrequency()
|
||||
{
|
||||
return calculateDownlink( mIdentifierUpdate, getChannelNumber() );
|
||||
}
|
||||
|
||||
public long getUplinkFrequency()
|
||||
{
|
||||
return calculateUplink( mIdentifierUpdate, getChannelNumber() );
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,150 @@
|
||||
package module.decode.p25.message.ldu.lc;
|
||||
|
||||
import module.decode.p25.message.IBandIdentifier;
|
||||
import module.decode.p25.message.IdentifierReceiver;
|
||||
import module.decode.p25.message.ldu.LDU1Message;
|
||||
import module.decode.p25.message.tsbk.osp.control.SystemService;
|
||||
import module.decode.p25.reference.LinkControlOpcode;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class RFSSStatusBroadcastExplicit extends LDU1Message
|
||||
implements IdentifierReceiver
|
||||
{
|
||||
private final static Logger mLog =
|
||||
LoggerFactory.getLogger( RFSSStatusBroadcastExplicit.class );
|
||||
|
||||
public static final int[] LRA = { 364,365,366,367,372,373,374,375 };
|
||||
public static final int[] RECEIVE_IDENTIFIER = { 376,377,382,383 };
|
||||
public static final int[] RECEIVE_CHANNEL = { 384,385,386,387,536,537,538,
|
||||
539,540,541,546,547 };
|
||||
public static final int[] RFSS_ID = { 548,549,550,551,556,557,558,559 };
|
||||
public static final int[] SITE_ID = { 560,561,566,567,568,569,570,571 };
|
||||
public static final int[] TRANSMIT_IDENTIFIER = { 720,721,722,723 };
|
||||
public static final int[] TRANSMIT_CHANNEL = { 724,725,730,731,732,733,734,
|
||||
735,740,741,742,743 };
|
||||
public static final int[] SYSTEM_SERVICE_CLASS = { 744,745,750,751,752,753,754,755 };
|
||||
|
||||
private IBandIdentifier mTransmitIdentifierUpdate;
|
||||
private IBandIdentifier mReceiveIdentifierUpdate;
|
||||
|
||||
public RFSSStatusBroadcastExplicit( LDU1Message source )
|
||||
{
|
||||
super( source );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getEventType()
|
||||
{
|
||||
return LinkControlOpcode.RFSS_STATUS_BROADCAST_EXPLICIT.getDescription();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMessage()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append( getMessageStub() );
|
||||
|
||||
sb.append( " LRA:" + getLocationRegistrationArea() );
|
||||
|
||||
sb.append( " SITE:" + getRFSubsystemID() + "-" + getSiteID() );
|
||||
|
||||
sb.append( " TRANSMIT:" + getTransmitChannelNumber() );
|
||||
|
||||
sb.append( " RECEIVE:" + getReceiveChannelNumber() );
|
||||
|
||||
sb.append( " " + SystemService.toString( getSystemServiceClass() ) );
|
||||
|
||||
sb.append( " " + mMessage.toString() );
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public String getLocationRegistrationArea()
|
||||
{
|
||||
return mMessage.getHex( LRA, 2 );
|
||||
}
|
||||
|
||||
public String getRFSubsystemID()
|
||||
{
|
||||
return mMessage.getHex( RFSS_ID, 2 );
|
||||
}
|
||||
|
||||
public String getSiteID()
|
||||
{
|
||||
return mMessage.getHex( SITE_ID, 2 );
|
||||
}
|
||||
|
||||
public int getTransmitIdentifier()
|
||||
{
|
||||
return mMessage.getInt( TRANSMIT_IDENTIFIER );
|
||||
}
|
||||
|
||||
public String getTransmitChannel()
|
||||
{
|
||||
return getTransmitIdentifier() + "-" + getTransmitChannelNumber();
|
||||
}
|
||||
|
||||
public int getTransmitChannelNumber()
|
||||
{
|
||||
return mMessage.getInt( TRANSMIT_CHANNEL );
|
||||
}
|
||||
|
||||
public int getReceiveIdentifier()
|
||||
{
|
||||
return mMessage.getInt( RECEIVE_IDENTIFIER );
|
||||
}
|
||||
|
||||
public String getReceiveChannel()
|
||||
{
|
||||
return getReceiveIdentifier() + "-" + getReceiveChannelNumber();
|
||||
}
|
||||
|
||||
public int getReceiveChannelNumber()
|
||||
{
|
||||
return mMessage.getInt( RECEIVE_CHANNEL );
|
||||
}
|
||||
|
||||
public int getSystemServiceClass()
|
||||
{
|
||||
return mMessage.getInt( SYSTEM_SERVICE_CLASS );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setIdentifierMessage( int identifier, IBandIdentifier message )
|
||||
{
|
||||
if( identifier == getTransmitIdentifier() )
|
||||
{
|
||||
mTransmitIdentifierUpdate = message;
|
||||
}
|
||||
|
||||
if( identifier == getReceiveIdentifier() )
|
||||
{
|
||||
mReceiveIdentifierUpdate = message;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] getIdentifiers()
|
||||
{
|
||||
int[] identifiers = new int[ 2 ];
|
||||
|
||||
identifiers[ 0 ] = getTransmitIdentifier();
|
||||
identifiers[ 1 ] = getReceiveIdentifier();
|
||||
|
||||
return identifiers;
|
||||
}
|
||||
|
||||
public long getDownlinkFrequency()
|
||||
{
|
||||
return calculateDownlink( mTransmitIdentifierUpdate, getTransmitChannelNumber() );
|
||||
}
|
||||
|
||||
public long getUplinkFrequency()
|
||||
{
|
||||
return calculateUplink( mReceiveIdentifierUpdate, getReceiveChannelNumber() );
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,156 @@
|
||||
package module.decode.p25.message.ldu.lc;
|
||||
|
||||
import module.decode.p25.message.IBandIdentifier;
|
||||
import module.decode.p25.message.IdentifierReceiver;
|
||||
import module.decode.p25.message.ldu.LDU1Message;
|
||||
import module.decode.p25.message.tsbk.osp.control.SystemService;
|
||||
import module.decode.p25.reference.LinkControlOpcode;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class SecondaryControlChannelBroadcast extends LDU1Message
|
||||
implements IdentifierReceiver
|
||||
{
|
||||
private final static Logger mLog =
|
||||
LoggerFactory.getLogger( SecondaryControlChannelBroadcast.class );
|
||||
|
||||
public static final int[] RFSS_ID = { 364,365,366,367,372,373,374,375 };
|
||||
public static final int[] SITE_ID = { 376,377,382,383,384,385,386,387 };
|
||||
public static final int[] IDENTIFIER_A = { 536,537,538,539 };
|
||||
public static final int[] CHANNEL_A = { 540,541,546,547,548,549,550,551,
|
||||
556,557,558,559 };
|
||||
public static final int[] SYSTEM_SERVICE_CLASS_A = { 560,561,566,567,568,569,570,571 };
|
||||
public static final int[] IDENTIFIER_B = { 720,721,722,723 };
|
||||
public static final int[] CHANNEL_B = { 724,725,730,731,732,733,734,735,740,
|
||||
741,742,743 };
|
||||
public static final int[] SYSTEM_SERVICE_CLASS_B = { 744,745,750,751,752,753,754,755 };
|
||||
|
||||
private IBandIdentifier mIdentifierProviderA;
|
||||
private IBandIdentifier mIdentifierProviderB;
|
||||
|
||||
public SecondaryControlChannelBroadcast( LDU1Message message )
|
||||
{
|
||||
super( message );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getEventType()
|
||||
{
|
||||
return LinkControlOpcode.SECONDARY_CONTROL_CHANNEL_BROADCAST.getDescription();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMessage()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append( getMessageStub() );
|
||||
|
||||
sb.append( " SITE:" + getRFSubsystemID() + "-" + getSiteID() );
|
||||
|
||||
sb.append( " CHAN A:" + getChannelA() );
|
||||
|
||||
sb.append( " " + SystemService.toString( getSystemServiceClassA() ) );
|
||||
|
||||
sb.append( " CHAN B:" + getChannelB() );
|
||||
|
||||
sb.append( " " + SystemService.toString( getSystemServiceClassB() ) );
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public String getRFSubsystemID()
|
||||
{
|
||||
return mMessage.getHex( RFSS_ID, 2 );
|
||||
}
|
||||
|
||||
public String getSiteID()
|
||||
{
|
||||
return mMessage.getHex( SITE_ID, 2 );
|
||||
}
|
||||
|
||||
public int getIdentifierA()
|
||||
{
|
||||
return mMessage.getInt( IDENTIFIER_A );
|
||||
}
|
||||
|
||||
public int getChannelA()
|
||||
{
|
||||
return mMessage.getInt( CHANNEL_A );
|
||||
}
|
||||
|
||||
public String getChannelNumberA()
|
||||
{
|
||||
return getIdentifierA() + "-" + getChannelA();
|
||||
}
|
||||
|
||||
public int getIdentifierB()
|
||||
{
|
||||
return mMessage.getInt( IDENTIFIER_B );
|
||||
}
|
||||
|
||||
public int getChannelB()
|
||||
{
|
||||
return mMessage.getInt( CHANNEL_B );
|
||||
}
|
||||
|
||||
public String getChannelNumberB()
|
||||
{
|
||||
return getIdentifierB() + "-" + getChannelB();
|
||||
}
|
||||
|
||||
public int getSystemServiceClassA()
|
||||
{
|
||||
return mMessage.getInt( SYSTEM_SERVICE_CLASS_A );
|
||||
}
|
||||
|
||||
public int getSystemServiceClassB()
|
||||
{
|
||||
return mMessage.getInt( SYSTEM_SERVICE_CLASS_B );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setIdentifierMessage( int identifier, IBandIdentifier message )
|
||||
{
|
||||
if( identifier == getIdentifierA() )
|
||||
{
|
||||
mIdentifierProviderA = message;
|
||||
}
|
||||
if( identifier == getIdentifierB() )
|
||||
{
|
||||
mIdentifierProviderB = message;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] getIdentifiers()
|
||||
{
|
||||
int[] identifiers = new int[ 2 ];
|
||||
|
||||
identifiers[ 0 ] = getIdentifierA();
|
||||
identifiers[ 1 ] = getIdentifierB();
|
||||
|
||||
return identifiers;
|
||||
}
|
||||
|
||||
public long getDownlinkFrequencyA()
|
||||
{
|
||||
return calculateDownlink( mIdentifierProviderA, getChannelA() );
|
||||
}
|
||||
|
||||
public long getUplinkFrequencyA()
|
||||
{
|
||||
return calculateUplink( mIdentifierProviderA, getChannelA() );
|
||||
}
|
||||
|
||||
public long getDownlinkFrequencyB()
|
||||
{
|
||||
return calculateDownlink( mIdentifierProviderB, getChannelB() );
|
||||
}
|
||||
|
||||
public long getUplinkFrequencyB()
|
||||
{
|
||||
return calculateUplink( mIdentifierProviderB, getChannelB() );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,141 @@
|
||||
package module.decode.p25.message.ldu.lc;
|
||||
|
||||
import module.decode.p25.message.IBandIdentifier;
|
||||
import module.decode.p25.message.IdentifierReceiver;
|
||||
import module.decode.p25.message.ldu.LDU1Message;
|
||||
import module.decode.p25.message.tsbk.osp.control.SystemService;
|
||||
import module.decode.p25.reference.LinkControlOpcode;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class SecondaryControlChannelBroadcastExplicit
|
||||
extends LDU1Message implements IdentifierReceiver
|
||||
{
|
||||
private final static Logger mLog =
|
||||
LoggerFactory.getLogger( SecondaryControlChannelBroadcastExplicit.class );
|
||||
|
||||
public static final int[] RFSS_ID = { 364,365,366,367,372,373,374,375 };
|
||||
public static final int[] SITE_ID = { 376,377,382,383,384,385,386,387 };
|
||||
public static final int[] TRANSMIT_IDENTIFIER = { 536,537,538,539 };
|
||||
public static final int[] TRANSMIT_CHANNEL = { 540,541,546,547,548,549,550,
|
||||
551,556,557,558,559 };
|
||||
public static final int[] RECEIVE_IDENTIFIER = { 560,561,566,567 };
|
||||
public static final int[] RECEIVE_CHANNEL = { 568,569,570,571,720,721,722,
|
||||
723,724,725,730,731 };
|
||||
public static final int[] SYSTEM_SERVICE_CLASS = { 732,733,734,735,740,741,
|
||||
742,743 };
|
||||
|
||||
private IBandIdentifier mTransmitIdentifierProvider;
|
||||
private IBandIdentifier mReceiveIdentifierProvider;
|
||||
|
||||
public SecondaryControlChannelBroadcastExplicit( LDU1Message message )
|
||||
{
|
||||
super( message );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getEventType()
|
||||
{
|
||||
return LinkControlOpcode.SECONDARY_CONTROL_CHANNEL_BROADCAST_EXPLICIT.getDescription();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMessage()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append( getMessageStub() );
|
||||
|
||||
sb.append( " SITE:" + getRFSubsystemID() + "-" + getSiteID() );
|
||||
|
||||
sb.append( " TRANSMIT:" + getTransmitChannel() );
|
||||
|
||||
sb.append( " RECEIVE:" + getReceiveChannel() );
|
||||
|
||||
sb.append( " " + SystemService.toString( getSystemServiceClass() ) );
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public String getRFSubsystemID()
|
||||
{
|
||||
return mMessage.getHex( RFSS_ID, 2 );
|
||||
}
|
||||
|
||||
public String getSiteID()
|
||||
{
|
||||
return mMessage.getHex( SITE_ID, 2 );
|
||||
}
|
||||
|
||||
public int getTransmitIdentifier()
|
||||
{
|
||||
return mMessage.getInt( TRANSMIT_IDENTIFIER );
|
||||
}
|
||||
|
||||
public int getTransmitChannelNumber()
|
||||
{
|
||||
return mMessage.getInt( TRANSMIT_CHANNEL );
|
||||
}
|
||||
|
||||
public String getTransmitChannel()
|
||||
{
|
||||
return getTransmitIdentifier() + "-" + getTransmitChannelNumber();
|
||||
}
|
||||
|
||||
public int getReceiveIdentifier()
|
||||
{
|
||||
return mMessage.getInt( RECEIVE_IDENTIFIER );
|
||||
}
|
||||
|
||||
public int getReceiveChannelNumber()
|
||||
{
|
||||
return mMessage.getInt( RECEIVE_CHANNEL );
|
||||
}
|
||||
|
||||
public String getReceiveChannel()
|
||||
{
|
||||
return getReceiveIdentifier() + "-" + getReceiveChannelNumber();
|
||||
}
|
||||
|
||||
public int getSystemServiceClass()
|
||||
{
|
||||
return mMessage.getInt( SYSTEM_SERVICE_CLASS );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setIdentifierMessage( int identifier, IBandIdentifier message )
|
||||
{
|
||||
if( identifier == getTransmitIdentifier() )
|
||||
{
|
||||
mTransmitIdentifierProvider = message;
|
||||
}
|
||||
if( identifier == getReceiveIdentifier() )
|
||||
{
|
||||
mReceiveIdentifierProvider = message;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] getIdentifiers()
|
||||
{
|
||||
int[] identifiers = new int[ 2 ];
|
||||
|
||||
identifiers[ 0 ] = getTransmitIdentifier();
|
||||
identifiers[ 1 ] = getReceiveIdentifier();
|
||||
|
||||
return identifiers;
|
||||
}
|
||||
|
||||
public long getDownlinkFrequency()
|
||||
{
|
||||
return calculateDownlink( mTransmitIdentifierProvider,
|
||||
getTransmitChannelNumber() );
|
||||
}
|
||||
|
||||
public long getUplinkFrequency()
|
||||
{
|
||||
return calculateUplink( mReceiveIdentifierProvider,
|
||||
getReceiveChannelNumber() );
|
||||
}
|
||||
}
|
||||
52
src/module/decode/p25/message/ldu/lc/StatusQuery.java
Normal file
52
src/module/decode/p25/message/ldu/lc/StatusQuery.java
Normal file
@@ -0,0 +1,52 @@
|
||||
package module.decode.p25.message.ldu.lc;
|
||||
|
||||
import module.decode.p25.message.ldu.LDU1Message;
|
||||
import module.decode.p25.reference.LinkControlOpcode;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class StatusQuery extends LDU1Message
|
||||
{
|
||||
private final static Logger mLog =
|
||||
LoggerFactory.getLogger( StatusQuery.class );
|
||||
public static final int[] TARGET_ADDRESS = { 536,537,538,539,540,541,546,
|
||||
547,548,549,550,551,556,557,558,559,560,561,566,567,568,569,570,571 };
|
||||
public static final int[] SOURCE_ADDRESS = { 720,721,722,723,724,725,730,
|
||||
731,732,733,734,735,740,741,742,743,744,745,750,751,752,753,754,755 };
|
||||
|
||||
public StatusQuery( LDU1Message message )
|
||||
{
|
||||
super( message );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getEventType()
|
||||
{
|
||||
return LinkControlOpcode.STATUS_QUERY.getDescription();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMessage()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append( getMessageStub() );
|
||||
|
||||
sb.append( " FROM:" + getSourceAddress() );
|
||||
|
||||
sb.append( " TO:" + getTargetAddress() );
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public String getTargetAddress()
|
||||
{
|
||||
return mMessage.getHex( TARGET_ADDRESS, 6 );
|
||||
}
|
||||
|
||||
public String getSourceAddress()
|
||||
{
|
||||
return mMessage.getHex( SOURCE_ADDRESS, 6 );
|
||||
}
|
||||
}
|
||||
65
src/module/decode/p25/message/ldu/lc/StatusUpdate.java
Normal file
65
src/module/decode/p25/message/ldu/lc/StatusUpdate.java
Normal file
@@ -0,0 +1,65 @@
|
||||
package module.decode.p25.message.ldu.lc;
|
||||
|
||||
import module.decode.p25.message.ldu.LDU1Message;
|
||||
import module.decode.p25.reference.LinkControlOpcode;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class StatusUpdate extends LDU1Message
|
||||
{
|
||||
private final static Logger mLog =
|
||||
LoggerFactory.getLogger( StatusUpdate.class );
|
||||
public static final int[] USER_STATUS = { 364,365,366,367,372,373,374,375 };
|
||||
public static final int[] UNIT_STATUS = { 376,377,382,383,384,385,386,387 };
|
||||
public static final int[] TARGET_ADDRESS = { 536,537,538,539,540,541,546,
|
||||
547,548,549,550,551,556,557,558,559,560,561,566,567,568,569,570,571 };
|
||||
public static final int[] SOURCE_ADDRESS = { 720,721,722,723,724,725,730,
|
||||
731,732,733,734,735,740,741,742,743,744,745,750,751,752,753,754,755 };
|
||||
|
||||
public StatusUpdate( LDU1Message message )
|
||||
{
|
||||
super( message );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getEventType()
|
||||
{
|
||||
return LinkControlOpcode.STATUS_UPDATE.getDescription();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMessage()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append( getMessageStub() );
|
||||
|
||||
sb.append( " STATUS USER:" + getUserStatus() );
|
||||
sb.append( " UNIT:" + getUnitStatus() );
|
||||
sb.append( " FROM:" + getSourceAddress() );
|
||||
sb.append( " TO:" + getTargetAddress() );
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public String getUserStatus()
|
||||
{
|
||||
return mMessage.getHex( USER_STATUS, 2 );
|
||||
}
|
||||
|
||||
public String getUnitStatus()
|
||||
{
|
||||
return mMessage.getHex( UNIT_STATUS, 2 );
|
||||
}
|
||||
|
||||
public String getTargetAddress()
|
||||
{
|
||||
return mMessage.getHex( TARGET_ADDRESS, 6 );
|
||||
}
|
||||
|
||||
public String getSourceAddress()
|
||||
{
|
||||
return mMessage.getHex( SOURCE_ADDRESS, 6 );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
package module.decode.p25.message.ldu.lc;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import module.decode.p25.message.ldu.LDU1Message;
|
||||
import module.decode.p25.reference.LinkControlOpcode;
|
||||
import module.decode.p25.reference.Service;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class SystemServiceBroadcast extends LDU1Message
|
||||
{
|
||||
private final static Logger mLog =
|
||||
LoggerFactory.getLogger( SystemServiceBroadcast.class );
|
||||
public static final int[] REQUEST_PRIORITY_LEVEL = { 384,385,386,387 };
|
||||
public static final int[] AVAILABLE_SERVICES = { 536,537,538,539,540,541,
|
||||
546,547,548,549,550,551,556,557,558,559,560,561,566,567,568,569,570,571 };
|
||||
public static final int[] SUPPORTED_SERVICES = { 720,721,722,723,724,725,
|
||||
730,731,732,733,734,735,740,741,742,743,744,745,750,751,752,753,754,755 };
|
||||
|
||||
public SystemServiceBroadcast( LDU1Message message )
|
||||
{
|
||||
super( message );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getEventType()
|
||||
{
|
||||
return LinkControlOpcode.SYSTEM_SERVICE_BROADCAST.getDescription();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMessage()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append( getMessageStub() );
|
||||
|
||||
sb.append( " SERVICES AVAILABLE " );
|
||||
|
||||
sb.append( getAvailableServices() );
|
||||
|
||||
sb.append( " SUPPORTED " );
|
||||
|
||||
sb.append( getSupportedServices() );
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public List<Service> getAvailableServices()
|
||||
{
|
||||
long bitmap = mMessage.getLong( AVAILABLE_SERVICES );
|
||||
|
||||
return Service.getServices( bitmap );
|
||||
}
|
||||
|
||||
public List<Service> getSupportedServices()
|
||||
{
|
||||
long bitmap = mMessage.getLong( SUPPORTED_SERVICES );
|
||||
|
||||
return Service.getServices( bitmap );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
package module.decode.p25.message.ldu.lc;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import module.decode.p25.message.ldu.LDU1Message;
|
||||
import module.decode.p25.reference.Digit;
|
||||
import module.decode.p25.reference.LinkControlOpcode;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class TelephoneInterconnectAnswerRequest extends LDU1Message
|
||||
{
|
||||
private final static Logger mLog = LoggerFactory.getLogger(
|
||||
TelephoneInterconnectAnswerRequest.class );
|
||||
|
||||
public static final int[] DIGIT_1 = { 364,365,366,367 };
|
||||
public static final int[] DIGIT_2 = { 372,373,374,375 };
|
||||
public static final int[] DIGIT_3 = { 376,377,382,383 };
|
||||
public static final int[] DIGIT_4 = { 384,385,386,387 };
|
||||
public static final int[] DIGIT_5 = { 536,537,538,539 };
|
||||
public static final int[] DIGIT_6 = { 540,541,546,547 };
|
||||
public static final int[] DIGIT_7 = { 548,549,550,551 };
|
||||
public static final int[] DIGIT_8 = { 556,557,558,559 };
|
||||
public static final int[] DIGIT_9 = { 560,561,566,567 };
|
||||
public static final int[] DIGIT_10 = { 568,569,570,571 };
|
||||
public static final int[] TARGET_ADDRESS = { 720,721,722,723,724,725,730,
|
||||
731,732,733,734,735,740,741,742,743,744,745,750,751,752,753,754,755 };
|
||||
|
||||
public TelephoneInterconnectAnswerRequest( LDU1Message message )
|
||||
{
|
||||
super( message );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getEventType()
|
||||
{
|
||||
return LinkControlOpcode.TELEPHONE_INTERCONNECT_ANSWER_REQUEST.getDescription();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMessage()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append( getMessageStub() );
|
||||
|
||||
sb.append( " TO:" );
|
||||
sb.append( getTargetAddress() );
|
||||
|
||||
sb.append( " TEL:" );
|
||||
sb.append( getTelephoneNumber() );
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public String getTargetAddress()
|
||||
{
|
||||
return mMessage.getHex( TARGET_ADDRESS, 6 );
|
||||
}
|
||||
|
||||
public String getTelephoneNumber()
|
||||
{
|
||||
List<Integer> digits = new ArrayList<Integer>();
|
||||
|
||||
digits.add( mMessage.getInt( DIGIT_1 ) );
|
||||
digits.add( mMessage.getInt( DIGIT_2 ) );
|
||||
digits.add( mMessage.getInt( DIGIT_3 ) );
|
||||
digits.add( mMessage.getInt( DIGIT_4 ) );
|
||||
digits.add( mMessage.getInt( DIGIT_5 ) );
|
||||
digits.add( mMessage.getInt( DIGIT_6 ) );
|
||||
digits.add( mMessage.getInt( DIGIT_7 ) );
|
||||
digits.add( mMessage.getInt( DIGIT_8 ) );
|
||||
digits.add( mMessage.getInt( DIGIT_9 ) );
|
||||
digits.add( mMessage.getInt( DIGIT_10 ) );
|
||||
|
||||
return Digit.decode( digits );
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
package module.decode.p25.message.ldu.lc;
|
||||
|
||||
import module.decode.p25.message.P25Message.DuplexMode;
|
||||
import module.decode.p25.message.P25Message.SessionMode;
|
||||
import module.decode.p25.message.ldu.LDU1Message;
|
||||
import module.decode.p25.reference.LinkControlOpcode;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class TelephoneInterconnectVoiceChannelUser extends LDU1Message
|
||||
{
|
||||
private final static Logger mLog =
|
||||
LoggerFactory.getLogger( TelephoneInterconnectVoiceChannelUser.class );
|
||||
|
||||
/* Service Options */
|
||||
public static final int EMERGENCY_FLAG = 376;
|
||||
public static final int ENCRYPTED_CHANNEL_FLAG = 377;
|
||||
public static final int DUPLEX_MODE = 382;
|
||||
public static final int SESSION_MODE = 383;
|
||||
public static final int[] CALL_TIMER = { 548,549,550,551,556,557,558,559,
|
||||
560,561,566,567,568,569,570,571 };
|
||||
public static final int[] ADDRESS = { 720,721,722,723,724,725,730,731,732,
|
||||
733,734,735,740,741,742,743,744,745,750,751,752,753,754,755 };
|
||||
|
||||
public TelephoneInterconnectVoiceChannelUser( LDU1Message message )
|
||||
{
|
||||
super( message );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getEventType()
|
||||
{
|
||||
return LinkControlOpcode.TELEPHONE_INTERCONNECT_VOICE_CHANNEL_USER.getDescription();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMessage()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append( getMessageStub() );
|
||||
|
||||
if( isEmergency() )
|
||||
{
|
||||
sb.append( " EMERGENCY" );
|
||||
}
|
||||
if( isEncryptedChannel() )
|
||||
{
|
||||
sb.append( " ENCRYPTED CHANNEL" );
|
||||
}
|
||||
|
||||
sb.append( " TIMER:" + getCallTimer() + " SECS" );
|
||||
|
||||
sb.append( " ADDR:" + getAddress() );
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
public String getAddress()
|
||||
{
|
||||
return mMessage.getHex( ADDRESS, 6 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Call timer in seconds
|
||||
*/
|
||||
public int getCallTimer()
|
||||
{
|
||||
int units = mMessage.getInt( CALL_TIMER );
|
||||
|
||||
return (int)( units / 10 );
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
package module.decode.p25.message.ldu.lc;
|
||||
|
||||
import module.decode.p25.message.ldu.LDU1Message;
|
||||
import module.decode.p25.reference.LinkControlOpcode;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class UnitAuthenticationCommand extends LDU1Message
|
||||
{
|
||||
private final static Logger mLog =
|
||||
LoggerFactory.getLogger( UnitAuthenticationCommand.class );
|
||||
public static final int[] NETWORK_ID = { 364,365,366,367,372,373,374,375,
|
||||
376,377,382,383,384,385,386,387,536,537,538,539 };
|
||||
public static final int[] SYSTEM_ID = { 540,541,546,547,548,549,550,551,556,
|
||||
557,558,559 };
|
||||
public static final int[] TARGET_ID = { 560,561,566,567,568,569,570,571,720,
|
||||
721,722,723,724,725,730,731,732,733,734,735,740,741,742,743 };
|
||||
|
||||
public UnitAuthenticationCommand( LDU1Message message )
|
||||
{
|
||||
super( message );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getEventType()
|
||||
{
|
||||
return LinkControlOpcode.UNIT_AUTHENTICATION_COMMAND.getDescription();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMessage()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append( getMessageStub() );
|
||||
|
||||
sb.append( " ADDRESS:" + getCompleteTargetAddress() );
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public String getCompleteTargetAddress()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append( getNetworkID() );
|
||||
sb.append( ":" );
|
||||
sb.append( getSystemID() );
|
||||
sb.append( ":" );
|
||||
sb.append( getTargetID() );
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public String getNetworkID()
|
||||
{
|
||||
return mMessage.getHex( NETWORK_ID, 5 );
|
||||
}
|
||||
|
||||
public String getSystemID()
|
||||
{
|
||||
return mMessage.getHex( SYSTEM_ID, 3 );
|
||||
}
|
||||
|
||||
public String getTargetID()
|
||||
{
|
||||
return mMessage.getHex( TARGET_ID, 6 );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
package module.decode.p25.message.ldu.lc;
|
||||
|
||||
import module.decode.p25.message.ldu.LDU1Message;
|
||||
import module.decode.p25.reference.LinkControlOpcode;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class UnitRegistrationCommand extends LDU1Message
|
||||
{
|
||||
private final static Logger mLog =
|
||||
LoggerFactory.getLogger( UnitRegistrationCommand.class );
|
||||
public static final int[] NETWORK_ID = { 364,365,366,367,372,373,374,375,
|
||||
376,377,382,383,384,385,386,387,536,537,538,539 };
|
||||
public static final int[] SYSTEM_ID = { 540,541,546,547,548,549,550,551,556,
|
||||
557,558,559 };
|
||||
public static final int[] TARGET_ID = { 560,561,566,567,568,569,570,571,720,
|
||||
721,722,723,724,725,730,731,732,733,734,735,740,741,742,743 };
|
||||
|
||||
public UnitRegistrationCommand( LDU1Message message )
|
||||
{
|
||||
super( message );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getEventType()
|
||||
{
|
||||
return LinkControlOpcode.UNIT_REGISTRATION_COMMAND.getDescription();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMessage()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append( getMessageStub() );
|
||||
|
||||
sb.append( " ADDRESS:" + getCompleteTargetAddress() );
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public String getCompleteTargetAddress()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append( getNetworkID() );
|
||||
sb.append( ":" );
|
||||
sb.append( getSystemID() );
|
||||
sb.append( ":" );
|
||||
sb.append( getTargetID() );
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
|
||||
public String getNetworkID()
|
||||
{
|
||||
return mMessage.getHex( NETWORK_ID, 5 );
|
||||
}
|
||||
|
||||
public String getSystemID()
|
||||
{
|
||||
return mMessage.getHex( SYSTEM_ID, 3 );
|
||||
}
|
||||
|
||||
public String getTargetID()
|
||||
{
|
||||
return mMessage.getHex( TARGET_ID, 6 );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
package module.decode.p25.message.ldu.lc;
|
||||
|
||||
import module.decode.p25.message.P25Message.DuplexMode;
|
||||
import module.decode.p25.message.P25Message.SessionMode;
|
||||
import module.decode.p25.message.ldu.LDU1Message;
|
||||
import module.decode.p25.reference.LinkControlOpcode;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class UnitToUnitAnswerRequest extends LDU1Message
|
||||
{
|
||||
private final static Logger mLog =
|
||||
LoggerFactory.getLogger( UnitToUnitAnswerRequest.class );
|
||||
/* Service Options */
|
||||
public static final int EMERGENCY_FLAG = 364;
|
||||
public static final int ENCRYPTED_CHANNEL_FLAG = 365;
|
||||
public static final int DUPLEX_MODE = 366;
|
||||
public static final int SESSION_MODE = 367;
|
||||
public static final int[] TARGET_ADDRESS = { 536,537,538,539,540,541,546,
|
||||
547,548,549,550,551,556,557,558,559,560,561,566,567,568,569,570,571 };
|
||||
public static final int[] SOURCE_ADDRESS = { 720,721,722,723,724,725,730,
|
||||
731,732,733,734,735,740,741,742,743,744,745,750,751,752,753,754,755 };
|
||||
|
||||
public UnitToUnitAnswerRequest( LDU1Message message )
|
||||
{
|
||||
super( message );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getEventType()
|
||||
{
|
||||
return LinkControlOpcode.UNIT_TO_UNIT_ANSWER_REQUEST.getDescription();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMessage()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append( getMessageStub() );
|
||||
|
||||
if( isEmergency() )
|
||||
{
|
||||
sb.append( " EMERGENCY" );
|
||||
}
|
||||
if( isEncryptedChannel() )
|
||||
{
|
||||
sb.append( " ENCRYPTED CHANNEL" );
|
||||
}
|
||||
|
||||
sb.append( " FROM:" + getSourceAddress() );
|
||||
|
||||
sb.append( " TO:" + getTargetAddress() );
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
public String getTargetAddress()
|
||||
{
|
||||
return mMessage.getHex( TARGET_ADDRESS, 6 );
|
||||
}
|
||||
|
||||
public String getSourceAddress()
|
||||
{
|
||||
return mMessage.getHex( SOURCE_ADDRESS, 6 );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
package module.decode.p25.message.ldu.lc;
|
||||
|
||||
import module.decode.p25.message.P25Message.DuplexMode;
|
||||
import module.decode.p25.message.P25Message.SessionMode;
|
||||
import module.decode.p25.message.ldu.LDU1Message;
|
||||
import module.decode.p25.reference.LinkControlOpcode;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class UnitToUnitVoiceChannelUser extends LDU1Message
|
||||
{
|
||||
private final static Logger mLog =
|
||||
LoggerFactory.getLogger( UnitToUnitVoiceChannelUser.class );
|
||||
/* Service Options */
|
||||
public static final int EMERGENCY_FLAG = 376;
|
||||
public static final int ENCRYPTED_CHANNEL_FLAG = 377;
|
||||
public static final int DUPLEX_MODE = 382;
|
||||
public static final int SESSION_MODE = 383;
|
||||
public static final int[] TARGET_ADDRESS = { 536,537,538,539,540,541,546,
|
||||
547,548,549,550,551,556,557,558,559,560,561,566,567,568,569,570,571 };
|
||||
public static final int[] SOURCE_ADDRESS = { 720,721,722,723,724,725,730,
|
||||
731,732,733,734,735,740,741,742,743,744,745,750,751,752,753,754,755 };
|
||||
|
||||
public UnitToUnitVoiceChannelUser( LDU1Message message )
|
||||
{
|
||||
super( message );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getEventType()
|
||||
{
|
||||
return LinkControlOpcode.UNIT_TO_UNIT_VOICE_CHANNEL_USER.getDescription();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMessage()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append( getMessageStub() );
|
||||
|
||||
if( isEmergency() )
|
||||
{
|
||||
sb.append( " EMERGENCY" );
|
||||
}
|
||||
if( isEncryptedChannel() )
|
||||
{
|
||||
sb.append( " ENCRYPTED CHANNEL" );
|
||||
}
|
||||
|
||||
sb.append( " FROM:" + getSourceAddress() );
|
||||
|
||||
sb.append( " TO:" + getTargetAddress() );
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
public String getTargetAddress()
|
||||
{
|
||||
return mMessage.getHex( TARGET_ADDRESS, 6 );
|
||||
}
|
||||
|
||||
public String getSourceAddress()
|
||||
{
|
||||
return mMessage.getHex( SOURCE_ADDRESS, 6 );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
package module.decode.p25.message.ldu.lc.motorola;
|
||||
|
||||
import module.decode.p25.message.ldu.LDU1Message;
|
||||
import module.decode.p25.reference.LinkControlOpcode;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class MotorolaOpcode_0 extends LDU1Message
|
||||
{
|
||||
private final static Logger mLog =
|
||||
LoggerFactory.getLogger( MotorolaOpcode_0.class );
|
||||
public static final int[] TARGET_ADDRESS = { 536,537,538,539,540,541,546,
|
||||
547,548,549,550,551,556,557,558,559,560,561,566,567,568,569,570,571 };
|
||||
public static final int[] SOURCE_ADDRESS = { 720,721,722,723,724,725,730,
|
||||
731,732,733,734,735,740,741,742,743,744,745,750,751,752,753,754,755 };
|
||||
|
||||
public MotorolaOpcode_0( LDU1Message message )
|
||||
{
|
||||
super( message );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getEventType()
|
||||
{
|
||||
return LinkControlOpcode.STATUS_QUERY.getDescription();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMessage()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append( getMessageStub() );
|
||||
|
||||
sb.append( " FROM:" + getSourceAddress() );
|
||||
|
||||
sb.append( " TO:" + getTargetAddress() );
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public String getTargetAddress()
|
||||
{
|
||||
return mMessage.getHex( TARGET_ADDRESS, 6 );
|
||||
}
|
||||
|
||||
public String getSourceAddress()
|
||||
{
|
||||
return mMessage.getHex( SOURCE_ADDRESS, 6 );
|
||||
}
|
||||
}
|
||||
169
src/module/decode/p25/message/pdu/PDUMessage.java
Normal file
169
src/module/decode/p25/message/pdu/PDUMessage.java
Normal file
@@ -0,0 +1,169 @@
|
||||
package module.decode.p25.message.pdu;
|
||||
|
||||
import module.decode.p25.message.P25Message;
|
||||
import module.decode.p25.message.tsbk.vendor.VendorOpcode;
|
||||
import module.decode.p25.reference.DataUnitID;
|
||||
import module.decode.p25.reference.Opcode;
|
||||
import module.decode.p25.reference.PDUFormat;
|
||||
import module.decode.p25.reference.ServiceAccessPoint;
|
||||
import module.decode.p25.reference.Vendor;
|
||||
import alias.AliasList;
|
||||
import bits.BinaryMessage;
|
||||
import edac.CRC;
|
||||
|
||||
public class PDUMessage extends P25Message
|
||||
{
|
||||
public static final int CONFIRMATION_REQUIRED_INDICATOR = 65;
|
||||
public static final int PACKET_DIRECTION_INDICATOR = 66;
|
||||
public static final int[] FORMAT = { 67,68,69,70,71 };
|
||||
public static final int[] SAP_ID = { 74,75,76,77,78,79 };
|
||||
public static final int[] VENDOR_ID = { 80,81,82,83,84,85,86,87 };
|
||||
public static final int[] LOGICAL_LINK_ID = { 88,89,90,91,92,93,94,95,96,97,
|
||||
98,99,100,101,102,103,104,105,106,107,108,109,110,111 };
|
||||
public static final int[] BLOCKS_TO_FOLLOW = { 113,114,115,116,117,118,119 };
|
||||
public static final int[] PAD_OCTET_COUNT = { 123,124,125,126,127 };
|
||||
public static final int[] OPCODE = { 122,123,124,125,126,127 };
|
||||
public static final int[] DATA_HEADER_OFFSET = { 138,139,140,141,142,143 };
|
||||
public static final int[] PDU_CRC = { 144,145,146,147,148,149,150,151,152,
|
||||
153,154,155,156,157,158,159 };
|
||||
|
||||
public PDUMessage( BinaryMessage message, DataUnitID duid, AliasList aliasList )
|
||||
{
|
||||
super( message, duid, aliasList );
|
||||
|
||||
/* Setup a CRC array to hold the header CRC and the multi-block CRC */
|
||||
mCRC = new CRC[ 2 ];
|
||||
mCRC[ 0 ] = CRC.PASSED;
|
||||
}
|
||||
|
||||
protected String getMessageStub()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
Vendor vendor = getVendor();
|
||||
|
||||
sb.append( "NAC:" );
|
||||
sb.append( getNAC() );
|
||||
sb.append( " " );
|
||||
sb.append( getDUID().getLabel() );
|
||||
|
||||
if( vendor == Vendor.STANDARD )
|
||||
{
|
||||
sb.append( " " );
|
||||
sb.append( getOpcode().getLabel() );
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.append( " " );
|
||||
sb.append( vendor.getLabel() );
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMessage()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append( getMessageStub() );
|
||||
|
||||
switch( getFormat() )
|
||||
{
|
||||
case ALTERNATE_MULTI_BLOCK_TRUNKING_CONTROL:
|
||||
break;
|
||||
case UNCONFIRMED_MULTI_BLOCK_TRUNKING_CONTROL:
|
||||
sb.append( " PAD OCTETS:" + getPadOctetCount() );
|
||||
sb.append( " DATA HDR OFFSET:" + getDataHeaderOffset() );
|
||||
break;
|
||||
default:
|
||||
}
|
||||
|
||||
sb.append( " " );
|
||||
sb.append( getConfirmation() );
|
||||
sb.append( " " );
|
||||
sb.append( getDirection() );
|
||||
sb.append( " FMT:" );
|
||||
sb.append( getFormat().getLabel() );
|
||||
sb.append( " SAP:" );
|
||||
sb.append( getServiceAccessPoint().name() );
|
||||
sb.append( " VEND:" );
|
||||
sb.append( getVendor().getLabel() );
|
||||
sb.append( " LLID:" );
|
||||
sb.append( getLogicalLinkID() );
|
||||
sb.append( " BLKS TO FOLLOW:" );
|
||||
sb.append( getBlocksToFollowCount() );
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public String getConfirmation()
|
||||
{
|
||||
return mMessage.get( CONFIRMATION_REQUIRED_INDICATOR ) ? "CONFIRMED" : "UNCONFIRMED";
|
||||
}
|
||||
|
||||
public String getDirection()
|
||||
{
|
||||
return mMessage.get( PACKET_DIRECTION_INDICATOR ) ? "OSP" : "ISP";
|
||||
}
|
||||
|
||||
public boolean isOutbound()
|
||||
{
|
||||
return mMessage.get( PACKET_DIRECTION_INDICATOR );
|
||||
}
|
||||
|
||||
public PDUFormat getFormat()
|
||||
{
|
||||
return PDUFormat.fromValue( mMessage.getInt( FORMAT ) );
|
||||
}
|
||||
|
||||
public ServiceAccessPoint getServiceAccessPoint()
|
||||
{
|
||||
return ServiceAccessPoint.fromValue( mMessage.getInt( SAP_ID ) );
|
||||
}
|
||||
|
||||
public Vendor getVendor()
|
||||
{
|
||||
return Vendor.fromValue( mMessage.getInt( VENDOR_ID ) );
|
||||
}
|
||||
|
||||
public String getLogicalLinkID()
|
||||
{
|
||||
return mMessage.getHex( LOGICAL_LINK_ID, 6 );
|
||||
}
|
||||
|
||||
public int getBlocksToFollowCount()
|
||||
{
|
||||
return mMessage.getInt( BLOCKS_TO_FOLLOW );
|
||||
}
|
||||
|
||||
public int getPadOctetCount()
|
||||
{
|
||||
return mMessage.getInt( PAD_OCTET_COUNT );
|
||||
}
|
||||
|
||||
public Opcode getOpcode()
|
||||
{
|
||||
if( getFormat() == PDUFormat.ALTERNATE_MULTI_BLOCK_TRUNKING_CONTROL )
|
||||
{
|
||||
return Opcode.fromValue( mMessage.getInt( OPCODE ) );
|
||||
}
|
||||
|
||||
return Opcode.UNKNOWN;
|
||||
}
|
||||
|
||||
public VendorOpcode getVendorOpcode()
|
||||
{
|
||||
if( getFormat() == PDUFormat.ALTERNATE_MULTI_BLOCK_TRUNKING_CONTROL )
|
||||
{
|
||||
return VendorOpcode.fromValue( mMessage.getInt( OPCODE ) );
|
||||
}
|
||||
|
||||
return VendorOpcode.UNKNOWN;
|
||||
}
|
||||
|
||||
public int getDataHeaderOffset()
|
||||
{
|
||||
return mMessage.getInt( DATA_HEADER_OFFSET );
|
||||
}
|
||||
}
|
||||
131
src/module/decode/p25/message/pdu/PDUMessageFactory.java
Normal file
131
src/module/decode/p25/message/pdu/PDUMessageFactory.java
Normal file
@@ -0,0 +1,131 @@
|
||||
package module.decode.p25.message.pdu;
|
||||
|
||||
import module.decode.p25.message.pdu.osp.control.AdjacentStatusBroadcastExtended;
|
||||
import module.decode.p25.message.pdu.osp.control.CallAlertExtended;
|
||||
import module.decode.p25.message.pdu.osp.control.GroupAffiliationQueryExtended;
|
||||
import module.decode.p25.message.pdu.osp.control.GroupAffiliationResponseExtended;
|
||||
import module.decode.p25.message.pdu.osp.control.MessageUpdateExtended;
|
||||
import module.decode.p25.message.pdu.osp.control.NetworkStatusBroadcastExtended;
|
||||
import module.decode.p25.message.pdu.osp.control.ProtectionParameterBroadcast;
|
||||
import module.decode.p25.message.pdu.osp.control.RFSSStatusBroadcastExtended;
|
||||
import module.decode.p25.message.pdu.osp.control.RoamingAddressUpdateExtended;
|
||||
import module.decode.p25.message.pdu.osp.control.StatusQueryExtended;
|
||||
import module.decode.p25.message.pdu.osp.control.StatusUpdateExtended;
|
||||
import module.decode.p25.message.pdu.osp.control.UnitRegistrationResponseExtended;
|
||||
import module.decode.p25.message.pdu.osp.data.GroupDataChannelGrantExtended;
|
||||
import module.decode.p25.message.pdu.osp.data.IndividualDataChannelGrantExtended;
|
||||
import module.decode.p25.message.pdu.osp.voice.GroupVoiceChannelGrantExplicit;
|
||||
import module.decode.p25.message.pdu.osp.voice.TelephoneInterconnectChannelGrantExplicit;
|
||||
import module.decode.p25.message.pdu.osp.voice.TelephoneInterconnectChannelGrantUpdateExplicit;
|
||||
import module.decode.p25.message.pdu.osp.voice.UnitToUnitAnswerRequestExplicit;
|
||||
import module.decode.p25.message.pdu.osp.voice.UnitToUnitVoiceChannelGrantExtended;
|
||||
import module.decode.p25.message.pdu.osp.voice.UnitToUnitVoiceChannelGrantUpdateExtended;
|
||||
import module.decode.p25.reference.DataUnitID;
|
||||
import module.decode.p25.reference.Opcode;
|
||||
import module.decode.p25.reference.PDUFormat;
|
||||
import module.decode.p25.reference.Vendor;
|
||||
import alias.AliasList;
|
||||
import bits.BinaryMessage;
|
||||
|
||||
public class PDUMessageFactory
|
||||
{
|
||||
public static PDUMessage getMessage( BinaryMessage message,
|
||||
DataUnitID duid,
|
||||
AliasList aliasList )
|
||||
{
|
||||
PDUFormat format = PDUFormat.fromValue(
|
||||
message.getInt( PDUMessage.FORMAT ) );
|
||||
|
||||
switch( format )
|
||||
{
|
||||
case ALTERNATE_MULTI_BLOCK_TRUNKING_CONTROL:
|
||||
Vendor vendor = Vendor.fromValue(
|
||||
message.getInt( PDUMessage.VENDOR_ID ) );
|
||||
|
||||
switch( vendor )
|
||||
{
|
||||
case STANDARD:
|
||||
Opcode opcode = Opcode.fromValue(
|
||||
message.getInt( PDUMessage.OPCODE ) );
|
||||
|
||||
switch( opcode )
|
||||
{
|
||||
case ADJACENT_STATUS_BROADCAST:
|
||||
return new AdjacentStatusBroadcastExtended(
|
||||
message, duid, aliasList );
|
||||
case CALL_ALERT:
|
||||
return new CallAlertExtended( message, duid,
|
||||
aliasList );
|
||||
case GROUP_AFFILIATION_QUERY:
|
||||
return new GroupAffiliationQueryExtended(
|
||||
message, duid, aliasList );
|
||||
case GROUP_AFFILIATION_RESPONSE:
|
||||
return new GroupAffiliationResponseExtended(
|
||||
message, duid, aliasList );
|
||||
case GROUP_DATA_CHANNEL_GRANT:
|
||||
return new GroupDataChannelGrantExtended(
|
||||
message, duid, aliasList );
|
||||
case GROUP_VOICE_CHANNEL_GRANT:
|
||||
return new GroupVoiceChannelGrantExplicit(
|
||||
message, duid, aliasList );
|
||||
case INDIVIDUAL_DATA_CHANNEL_GRANT:
|
||||
return new IndividualDataChannelGrantExtended(
|
||||
message, duid, aliasList );
|
||||
case MESSAGE_UPDATE:
|
||||
return new MessageUpdateExtended( message, duid,
|
||||
aliasList );
|
||||
case NETWORK_STATUS_BROADCAST:
|
||||
return new NetworkStatusBroadcastExtended(
|
||||
message, duid, aliasList );
|
||||
case PROTECTION_PARAMETER_BROADCAST:
|
||||
return new ProtectionParameterBroadcast(
|
||||
message, duid, aliasList );
|
||||
case RFSS_STATUS_BROADCAST:
|
||||
return new RFSSStatusBroadcastExtended( message,
|
||||
duid, aliasList );
|
||||
case ROAMING_ADDRESS_UPDATE:
|
||||
return new RoamingAddressUpdateExtended(
|
||||
message, duid, aliasList );
|
||||
case STATUS_QUERY:
|
||||
return new StatusQueryExtended( message, duid,
|
||||
aliasList );
|
||||
case STATUS_UPDATE:
|
||||
return new StatusUpdateExtended( message, duid,
|
||||
aliasList );
|
||||
case TELEPHONE_INTERCONNECT_VOICE_CHANNEL_GRANT:
|
||||
return new TelephoneInterconnectChannelGrantExplicit(
|
||||
message, duid, aliasList );
|
||||
case TELEPHONE_INTERCONNECT_VOICE_CHANNEL_GRANT_UPDATE:
|
||||
return new TelephoneInterconnectChannelGrantUpdateExplicit(
|
||||
message, duid, aliasList );
|
||||
case UNIT_REGISTRATION_RESPONSE:
|
||||
return new UnitRegistrationResponseExtended(
|
||||
message, duid, aliasList );
|
||||
case UNIT_TO_UNIT_ANSWER_REQUEST:
|
||||
return new UnitToUnitAnswerRequestExplicit(
|
||||
message, duid, aliasList );
|
||||
case UNIT_TO_UNIT_VOICE_CHANNEL_GRANT:
|
||||
return new UnitToUnitVoiceChannelGrantExtended(
|
||||
message, duid, aliasList );
|
||||
case UNIT_TO_UNIT_VOICE_CHANNEL_GRANT_UPDATE:
|
||||
return new UnitToUnitVoiceChannelGrantUpdateExtended(
|
||||
message, duid, aliasList );
|
||||
default:
|
||||
break;
|
||||
}
|
||||
case MOTOROLA:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return new PDUMessage( message, duid, aliasList );
|
||||
|
||||
case UNCONFIRMED_MULTI_BLOCK_TRUNKING_CONTROL:
|
||||
return new PDUMessage( message, duid, aliasList );
|
||||
|
||||
default:
|
||||
return new PDUMessage( message, duid, aliasList );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,200 @@
|
||||
package module.decode.p25.message.pdu;
|
||||
|
||||
import module.decode.p25.message.IBandIdentifier;
|
||||
import module.decode.p25.message.IdentifierReceiver;
|
||||
import module.decode.p25.reference.DataUnitID;
|
||||
import module.decode.p25.reference.Opcode;
|
||||
import alias.AliasList;
|
||||
import bits.BinaryMessage;
|
||||
import edac.CRCP25;
|
||||
|
||||
public abstract class UnitToUnitChannelGrantExtended extends PDUMessage
|
||||
implements IdentifierReceiver
|
||||
{
|
||||
/* Service Options */
|
||||
public static final int EMERGENCY_FLAG = 128;
|
||||
public static final int ENCRYPTED_CHANNEL_FLAG = 129;
|
||||
public static final int DUPLEX_MODE = 130;
|
||||
public static final int SESSION_MODE = 131;
|
||||
|
||||
public static final int[] SOURCE_ADDRESS = { 88,89,90,91,92,93,94,95,96,97,
|
||||
98,99,100,101,102,103,104,105,106,107,108,109,110,111 };
|
||||
public static final int[] SERVICE_OPTIONS = { 128,129,130,131,132,133,134,
|
||||
135 };
|
||||
public static final int[] SOURCE_WACN = { 160,161,162,163,164,165,166,167,
|
||||
168,169,170,171,172,173,174,175,176,177,178,179 };
|
||||
public static final int[] SOURCE_SYSTEM_ID = { 180,181,182,183,184,185,186,
|
||||
187,188,189,190,191 };
|
||||
public static final int[] SOURCE_ID = { 192,193,194,195,196,197,198,199,200,
|
||||
201,202,203,204,205,206,207,208,209,210,211,212,213,214,215 };
|
||||
public static final int[] TARGET_ADDRESS = { 216,217,218,219,220,221,222,
|
||||
223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239 };
|
||||
public static final int[] TRANSMIT_IDENTIFIER = { 240,241,242,243 };
|
||||
public static final int[] TRANSMIT_NUMBER = { 244,245,246,247,248,249,250,
|
||||
251,252,253,254,255 };
|
||||
public static final int[] RECEIVE_IDENTIFIER = { 256,257,258,259 };
|
||||
public static final int[] RECEIVE_NUMBER = { 260,261,262,263,264,265,266,
|
||||
267,268,269,270,271 };
|
||||
public static final int[] MULTIPLE_BLOCK_CRC = { 320,321,322,323,324,325,
|
||||
326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,
|
||||
343,344,345,346,347,348,349,350,351 };
|
||||
|
||||
private IBandIdentifier mTransmitIdentifierUpdate;
|
||||
private IBandIdentifier mReceiveIdentifierUpdate;
|
||||
|
||||
public UnitToUnitChannelGrantExtended( BinaryMessage message,
|
||||
DataUnitID duid, AliasList aliasList )
|
||||
{
|
||||
super( message, duid, aliasList );
|
||||
|
||||
/* Header block is already error detected/corrected - perform error
|
||||
* detection correction on the intermediate and final data blocks */
|
||||
mMessage = CRCP25.correctPDU2( mMessage );
|
||||
mCRC[ 1 ] = mMessage.getCRC();
|
||||
}
|
||||
|
||||
public String getMessage()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append( getMessageStub() );
|
||||
|
||||
if( isEmergency() )
|
||||
{
|
||||
sb.append( " EMERGENCY" );
|
||||
}
|
||||
|
||||
sb.append( " FROM ADDR:" );
|
||||
sb.append( getSourceAddress() );
|
||||
|
||||
sb.append( " ID:" );
|
||||
sb.append( getSourceID() );
|
||||
|
||||
sb.append( " TO:" );
|
||||
sb.append( getTargetAddress() );
|
||||
|
||||
sb.append( " WACN:" );
|
||||
sb.append( getSourceWACN() );
|
||||
|
||||
sb.append( " SYS:" );
|
||||
sb.append( getSourceSystemID() );
|
||||
|
||||
sb.append( " CHAN DN:" + getTransmitChannelIdentifier() + "-" + getTransmitChannelNumber() );
|
||||
sb.append( " " + getDownlinkFrequency() );
|
||||
|
||||
sb.append( " CHAN UP:" + getReceiveChannelIdentifier() + "-" + getReceiveChannelNumber() );
|
||||
sb.append( " " + getUplinkFrequency() );
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public boolean isEmergency()
|
||||
{
|
||||
return mMessage.get( EMERGENCY_FLAG );
|
||||
}
|
||||
|
||||
public boolean isEncrypted()
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
public String getSourceAddress()
|
||||
{
|
||||
return mMessage.getHex( SOURCE_ADDRESS, 6 );
|
||||
}
|
||||
|
||||
public String getSourceID()
|
||||
{
|
||||
return mMessage.getHex( SOURCE_ID, 6 );
|
||||
}
|
||||
|
||||
public String getSourceWACN()
|
||||
{
|
||||
return mMessage.getHex( SOURCE_WACN, 5 );
|
||||
}
|
||||
|
||||
public String getSourceSystemID()
|
||||
{
|
||||
return mMessage.getHex( SOURCE_SYSTEM_ID, 3 );
|
||||
}
|
||||
|
||||
public String getTargetAddress()
|
||||
{
|
||||
return mMessage.getHex( TARGET_ADDRESS, 6 );
|
||||
}
|
||||
|
||||
public int getTransmitChannelIdentifier()
|
||||
{
|
||||
return mMessage.getInt( TRANSMIT_IDENTIFIER );
|
||||
}
|
||||
|
||||
public int getTransmitChannelNumber()
|
||||
{
|
||||
return mMessage.getInt( TRANSMIT_NUMBER );
|
||||
}
|
||||
|
||||
public String getTransmitChannel()
|
||||
{
|
||||
return getTransmitChannelIdentifier() + "-" + getTransmitChannelNumber();
|
||||
}
|
||||
|
||||
public int getReceiveChannelIdentifier()
|
||||
{
|
||||
return mMessage.getInt( RECEIVE_IDENTIFIER );
|
||||
}
|
||||
|
||||
public int getReceiveChannelNumber()
|
||||
{
|
||||
return mMessage.getInt( RECEIVE_NUMBER );
|
||||
}
|
||||
|
||||
public String getReceiveChannel()
|
||||
{
|
||||
return getReceiveChannelIdentifier() + "-" + getReceiveChannelNumber();
|
||||
}
|
||||
|
||||
public long getDownlinkFrequency()
|
||||
{
|
||||
return calculateDownlink( mTransmitIdentifierUpdate, getTransmitChannelNumber() );
|
||||
}
|
||||
|
||||
public long getUplinkFrequency()
|
||||
{
|
||||
return calculateUplink( mReceiveIdentifierUpdate, getReceiveChannelNumber() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setIdentifierMessage( int identifier, IBandIdentifier message )
|
||||
{
|
||||
if( identifier == getTransmitChannelIdentifier() )
|
||||
{
|
||||
mTransmitIdentifierUpdate = message;
|
||||
}
|
||||
|
||||
if( identifier == getReceiveChannelIdentifier() )
|
||||
{
|
||||
mReceiveIdentifierUpdate = message;
|
||||
}
|
||||
}
|
||||
|
||||
public int[] getIdentifiers()
|
||||
{
|
||||
int[] idens = new int[ 2 ];
|
||||
|
||||
idens[ 0 ] = getTransmitChannelIdentifier();
|
||||
idens[ 1 ] = getReceiveChannelIdentifier();
|
||||
|
||||
return idens;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,209 @@
|
||||
package module.decode.p25.message.pdu.confirmed;
|
||||
|
||||
import module.decode.p25.message.pdu.PDUMessage;
|
||||
import module.decode.p25.reference.DataUnitID;
|
||||
import module.decode.p25.reference.PDUType;
|
||||
import module.decode.p25.reference.Vendor;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import alias.AliasList;
|
||||
import bits.BinaryMessage;
|
||||
import edac.CRC;
|
||||
import edac.CRCP25;
|
||||
|
||||
public class PDUConfirmedMessage extends PDUMessage
|
||||
{
|
||||
public final static Logger mLog =
|
||||
LoggerFactory.getLogger( PDUConfirmedMessage.class );
|
||||
|
||||
public static final int SEQUENCE_RESET_FLAG = 128; //SYN
|
||||
public static final int[] PACKET_SEQUENCE_NUMBER = { 129,130,131 };
|
||||
public static final int FINAL_FRAGMENT_FLAG = 132;
|
||||
public static final int[] FRAGMENT_SEQUENCE_NUMBER = { 133,134,135 };
|
||||
public static final int[] PDU_TYPE = { 176,177,178,179 };
|
||||
|
||||
public PDUConfirmedMessage( BinaryMessage message, AliasList aliasList )
|
||||
{
|
||||
super( message, DataUnitID.PDUC, aliasList );
|
||||
|
||||
checkCRC();
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor to support subclassing of this message. Initial construction
|
||||
* of the message enables CRC checks to be calculated and message type to
|
||||
* be inspected so that we can construct an accurate subclass message,
|
||||
* without having to recalculate CRC checksums.
|
||||
*/
|
||||
protected PDUConfirmedMessage( PDUConfirmedMessage message )
|
||||
{
|
||||
super( message.getSourceMessage(), DataUnitID.PDUC, message.getAliasList() );
|
||||
mCRC = message.getCRCResults();
|
||||
}
|
||||
|
||||
private void checkCRC()
|
||||
{
|
||||
int blocks = getBlocksToFollowCount();
|
||||
|
||||
/* The NID and Header have already passed CRC */
|
||||
mCRC = new CRC[ 2 + blocks ];
|
||||
mCRC[ 0 ] = CRC.PASSED;
|
||||
mCRC[ 1 ] = CRC.PASSED;
|
||||
|
||||
for( int x = 0; x < getBlocksToFollowCount(); x++ )
|
||||
{
|
||||
/* Data blocks start at 160 and every 144 thereafter */
|
||||
mCRC[ x + 2 ] = CRCP25.checkCRC9( mMessage, 160 + ( x * 144 ) );
|
||||
}
|
||||
|
||||
//TODO: check the final 4-byte end of block sequence CRC
|
||||
}
|
||||
|
||||
/* Override for now */
|
||||
public boolean isValid()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMessage()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append( "[" + this.getClass() + "]" );
|
||||
sb.append( "NAC:" );
|
||||
sb.append( getNAC() );
|
||||
sb.append( " " );
|
||||
sb.append( getDUID().getLabel() );
|
||||
sb.append( " " );
|
||||
sb.append( getDirection() );
|
||||
sb.append( " CRC[" );
|
||||
sb.append( getErrorStatus() );
|
||||
sb.append( "] LLID:" );
|
||||
sb.append( getLogicalLinkID() );
|
||||
|
||||
sb.append( " " );
|
||||
sb.append( getFormat().getLabel() );
|
||||
sb.append( " SAP:" );
|
||||
sb.append( getServiceAccessPoint().getLabel() );
|
||||
|
||||
if( getVendor() != Vendor.STANDARD )
|
||||
{
|
||||
sb.append( " VEND:" );
|
||||
sb.append( getVendor().getLabel() );
|
||||
}
|
||||
|
||||
sb.append( " PACKET #" );
|
||||
sb.append( getPacketSequenceNumber() );
|
||||
|
||||
if( isFinalFragment() && getFragmentSequenceNumber() == 0 )
|
||||
{
|
||||
sb.append( ".C" );
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.append( "." );
|
||||
sb.append( getFragmentSequenceNumber() );
|
||||
|
||||
if( isFinalFragment() )
|
||||
{
|
||||
sb.append( "C" );
|
||||
}
|
||||
}
|
||||
|
||||
sb.append( " BLOCKS:" );
|
||||
sb.append( getBlocksToFollowCount() );
|
||||
|
||||
sb.append( " " );
|
||||
sb.append( mMessage.toString() );
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Packet Data Unit Type
|
||||
*/
|
||||
public PDUType getPDUType()
|
||||
{
|
||||
return PDUType.fromValue( mMessage.getInt( PDU_TYPE ), isOutbound() );
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Number of bytes/octets contained in the message, exclusive of the data
|
||||
* header.
|
||||
*/
|
||||
public int getOctetCount()
|
||||
{
|
||||
/* 16 octets per block, and 12 octets in final block */
|
||||
int count = getBlocksToFollowCount() * 16 - 4;
|
||||
|
||||
int padding = getPadOctetCount();
|
||||
|
||||
/* Hack: motorola sndcp packet data control - when it says there are 15
|
||||
* pad octets and only 1 data block of 12 data octets, that means there
|
||||
* are more pad octets than available data and they appear to suppress
|
||||
* the final padded data block containing the 12 pad octets. The data
|
||||
* block count should be 2, but it says 1, so they're either not sending
|
||||
* the final block, or there is an error in the block count */
|
||||
if( padding > count )
|
||||
{
|
||||
count -= ( padding - 12 );
|
||||
}
|
||||
else
|
||||
{
|
||||
count -= padding;
|
||||
}
|
||||
|
||||
|
||||
count -= getDataHeaderOffset();
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates that the receiver should accept this packet, despite the
|
||||
* apparent out-of-order packet and fragment sequence numbering. This
|
||||
* indicates that something happened to the synchronization between
|
||||
* the tower and the radio and now the tower commands the radio to reset
|
||||
* the sequence numbers and accept this packet/fragment instead of discarding
|
||||
* it as a duplicate.
|
||||
*/
|
||||
public boolean isSequenceReset()
|
||||
{
|
||||
return mMessage.get( SEQUENCE_RESET_FLAG );
|
||||
}
|
||||
|
||||
/**
|
||||
* Packet sequence number. Numbers run from 0 to 7 and will continually
|
||||
* roll-over if there are more than 8 total packets.
|
||||
*/
|
||||
public int getPacketSequenceNumber()
|
||||
{
|
||||
return mMessage.getInt( PACKET_SEQUENCE_NUMBER );
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates that this packet fragment is the final fragment
|
||||
*/
|
||||
public boolean isFinalFragment()
|
||||
{
|
||||
return mMessage.get( FINAL_FRAGMENT_FLAG );
|
||||
}
|
||||
|
||||
/**
|
||||
* Packet fragment sequence number
|
||||
*/
|
||||
public int getFragmentSequenceNumber()
|
||||
{
|
||||
return mMessage.getInt( FRAGMENT_SEQUENCE_NUMBER );
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{
|
||||
return getMessage();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
package module.decode.p25.message.pdu.confirmed;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
|
||||
public class PDUConfirmedMessageFactory
|
||||
{
|
||||
public final static Logger mLog =
|
||||
LoggerFactory.getLogger( PDUConfirmedMessage.class );
|
||||
|
||||
public static PDUConfirmedMessage getMessage( PDUConfirmedMessage message )
|
||||
{
|
||||
switch( message.getServiceAccessPoint() )
|
||||
{
|
||||
case ADDRESS_RESOLUTION_PROTOCOL:
|
||||
break;
|
||||
case CHANNEL_REASSIGNMENT:
|
||||
break;
|
||||
case CIRCUIT_DATA:
|
||||
break;
|
||||
case CIRCUIT_DATA_CONTROL:
|
||||
break;
|
||||
case ENCRYPTED_KEY_MANAGEMENT_MESSAGE:
|
||||
break;
|
||||
case ENCRYPTED_TRUNKING_CONTROL:
|
||||
break;
|
||||
case ENCRYPTED_USER_DATA:
|
||||
break;
|
||||
case EXTENDED_ADDRESS:
|
||||
break;
|
||||
case MR_CONFIGURATION:
|
||||
break;
|
||||
case MR_LOOPBACK:
|
||||
break;
|
||||
case MR_OUT_OF_SERVICE:
|
||||
break;
|
||||
case MR_PAGING:
|
||||
break;
|
||||
case MR_STATISTICS:
|
||||
break;
|
||||
case PACKET_DATA:
|
||||
break;
|
||||
case REGISTRATION_AND_AUTHORIZATION:
|
||||
break;
|
||||
/* Deliberate fall-through */
|
||||
case SNDCP_PACKET_DATA_CONTROL:
|
||||
case UNENCRYPTED_USER_DATA:
|
||||
switch( message.getPDUType() )
|
||||
{
|
||||
case SN_ACTIVATE_TDS_CONTEXT_ACCEPT:
|
||||
return new SNDCPActivateTDSContextAccept( message );
|
||||
case SN_ACTIVATE_TDS_CONTEXT_REJECT:
|
||||
return new SNDCPActivateTDSContextReject( message );
|
||||
case SN_ACTIVATE_TDS_CONTEXT_REQUEST:
|
||||
return new SNDCPActivateTDSContextRequest( message );
|
||||
case SN_DEACTIVATE_TDS_CONTEXT_ACCEPT:
|
||||
case SN_DEACTIVATE_TDS_CONTEXT_REQUEST:
|
||||
return new SNDCPDeactivateTDSContext( message );
|
||||
case SN_RF_CONFIRMED_DATA:
|
||||
return new SNDCPUserData( message );
|
||||
case SN_RF_UNCONFIRMED_DATA:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case SYSTEM_CONFIGURATION:
|
||||
break;
|
||||
case UNENCRYPTED_KEY_MANAGEMENT_MESSAGE:
|
||||
break;
|
||||
case UNENCRYPTED_TRUNKING_CONTROL:
|
||||
break;
|
||||
default:
|
||||
|
||||
}
|
||||
|
||||
return message;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,253 @@
|
||||
package module.decode.p25.message.pdu.confirmed;
|
||||
|
||||
import module.decode.p25.message.pdu.PDUMessage;
|
||||
import module.decode.p25.reference.DataUnitID;
|
||||
import module.decode.p25.reference.MDPConfigurationOption;
|
||||
import module.decode.p25.reference.PDUType;
|
||||
import module.decode.p25.reference.SNDCPActivationRejectReason;
|
||||
import module.decode.p25.reference.Vendor;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import alias.AliasList;
|
||||
import bits.BinaryMessage;
|
||||
import edac.CRC;
|
||||
import edac.CRCP25;
|
||||
|
||||
public class SNDCPActivateTDSContextAccept extends PDUConfirmedMessage
|
||||
{
|
||||
public final static Logger mLog =
|
||||
LoggerFactory.getLogger( SNDCPActivateTDSContextAccept.class );
|
||||
|
||||
/* SN-Activate TDS Context Accept */
|
||||
public static final int[] NSAPI = { 180,181,182,183 };
|
||||
public static final int[] PDUPM = { 184,185,186,187 };
|
||||
public static final int[] READY = { 188,189,190,191 };
|
||||
public static final int[] STANDBY = { 192,193,194,195 };
|
||||
public static final int[] NAT = { 196,197,198,199 };
|
||||
public static final int[] IP_1 = { 200,201,202,203,204,205,206,207 };
|
||||
public static final int[] IP_2 = { 208,209,210,211,212,213,214,215 };
|
||||
public static final int[] IP_3 = { 216,217,218,219,220,221,222,223 };
|
||||
public static final int[] IP_4 = { 224,225,226,227,228,229,230,231 };
|
||||
public static final int[] IPHC = { 232,233,234,235,236,237,238,239 };
|
||||
public static final int[] TCPSS = { 240,241,242,243 };
|
||||
public static final int[] UDPSS = { 244,245,246,247 };
|
||||
public static final int[] MTU = { 248,249,250,251 };
|
||||
public static final int[] UDPC = { 252,253,254,255 };
|
||||
public static final int[] MDPCO = { 256,257,258,259,260,261,262,263 };
|
||||
public static final int[] DATA_ACCESS_CONTROL = { 264,265,266,267,268,
|
||||
269,270,271,272,273,274,275,276,277,278,279 };
|
||||
|
||||
public SNDCPActivateTDSContextAccept( PDUConfirmedMessage message )
|
||||
{
|
||||
super( message );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMessage()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append( "NAC:" );
|
||||
sb.append( getNAC() );
|
||||
sb.append( " PDUC LLID:" );
|
||||
sb.append( getLogicalLinkID() );
|
||||
sb.append( " ACCEPT SNDCP PACKET DATA ACTIVATE " );
|
||||
sb.append( getNetworkAddressType() );
|
||||
sb.append( " " );
|
||||
sb.append( getIPAddress() );
|
||||
sb.append( " NSAPI:" );
|
||||
sb.append( getNSAPI() );
|
||||
sb.append( " MTU:" );
|
||||
sb.append( getMaximumTransmissionUnit() );
|
||||
sb.append( " CRC[" );
|
||||
sb.append( getErrorStatus() );
|
||||
sb.append( "]" );
|
||||
|
||||
sb.append( " PACKET #" );
|
||||
sb.append( getPacketSequenceNumber() );
|
||||
|
||||
if( isFinalFragment() && getFragmentSequenceNumber() == 0 )
|
||||
{
|
||||
sb.append( ".C" );
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.append( "." );
|
||||
sb.append( getFragmentSequenceNumber() );
|
||||
|
||||
if( isFinalFragment() )
|
||||
{
|
||||
sb.append( "C" );
|
||||
}
|
||||
}
|
||||
|
||||
sb.append( " " );
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Network Service Access Point Identifier - up to 14 NSAPI's can be
|
||||
* allocated to the mobile with each NSAPI to be used for a specific
|
||||
* protocol layer.
|
||||
*/
|
||||
public int getNSAPI()
|
||||
{
|
||||
return mMessage.getInt( NSAPI );
|
||||
}
|
||||
|
||||
public int getPDUPriorityMaximum()
|
||||
{
|
||||
return mMessage.getInt( PDUPM );
|
||||
}
|
||||
|
||||
public String getReadyTimer()
|
||||
{
|
||||
switch( mMessage.getInt( READY ) )
|
||||
{
|
||||
case 1:
|
||||
return "1 Second";
|
||||
case 2:
|
||||
return "2 Seconds";
|
||||
case 3:
|
||||
return "4 Seconds";
|
||||
case 4:
|
||||
return "6 Seconds";
|
||||
case 5:
|
||||
return "8 Seconds";
|
||||
case 6:
|
||||
return "10 Seconds";
|
||||
case 7:
|
||||
return "15 Seconds";
|
||||
case 8:
|
||||
return "20 Seconds";
|
||||
case 9:
|
||||
return "25 Seconds";
|
||||
case 10:
|
||||
return "30 Seconds";
|
||||
case 11:
|
||||
return "60 Seconds";
|
||||
case 12:
|
||||
return "120 Seconds";
|
||||
case 13:
|
||||
return "180 Seconds";
|
||||
case 14:
|
||||
return "300 Seconds";
|
||||
case 15:
|
||||
return "Always in Ready";
|
||||
}
|
||||
|
||||
return "UNKNOWN";
|
||||
}
|
||||
|
||||
|
||||
public String getStandbyTimer()
|
||||
{
|
||||
switch( mMessage.getInt( STANDBY ) )
|
||||
{
|
||||
case 1:
|
||||
return "10 Seconds";
|
||||
case 2:
|
||||
return "30 Seconds";
|
||||
case 3:
|
||||
return "1 Minutes";
|
||||
case 4:
|
||||
return "5 Minutes";
|
||||
case 5:
|
||||
return "10 Minutes";
|
||||
case 6:
|
||||
return "30 Minutes";
|
||||
case 7:
|
||||
return "1 Hour";
|
||||
case 8:
|
||||
return "2 Hours";
|
||||
case 9:
|
||||
return "4 Hours";
|
||||
case 10:
|
||||
return "8 Hours";
|
||||
case 11:
|
||||
return "12 Hours";
|
||||
case 12:
|
||||
return "24 Hours";
|
||||
case 13:
|
||||
return "48 Hours";
|
||||
case 14:
|
||||
return "72 Hours";
|
||||
case 15:
|
||||
return "Always in Ready";
|
||||
}
|
||||
|
||||
return "Unknown";
|
||||
}
|
||||
|
||||
public String getNetworkAddressType()
|
||||
{
|
||||
return mMessage.getInt( NAT ) == 0 ? "IPV4 STATIC" : "IPV4 DYNAMIC";
|
||||
}
|
||||
|
||||
public String getIPAddress()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append( mMessage.getInt( IP_1 ) );
|
||||
sb.append( "." );
|
||||
sb.append( mMessage.getInt( IP_2 ) );
|
||||
sb.append( "." );
|
||||
sb.append( mMessage.getInt( IP_3 ) );
|
||||
sb.append( "." );
|
||||
sb.append( mMessage.getInt( IP_4 ) );
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public boolean hasIPHeaderCompression()
|
||||
{
|
||||
return mMessage.getInt( IPHC ) == 1;
|
||||
}
|
||||
|
||||
public boolean hasUserDataPayloadCompression()
|
||||
{
|
||||
return mMessage.getInt( UDPC ) == 1;
|
||||
}
|
||||
|
||||
public int getTCPStateSlots()
|
||||
{
|
||||
return mMessage.getInt( TCPSS );
|
||||
}
|
||||
|
||||
public int getUDPStateSlots()
|
||||
{
|
||||
return mMessage.getInt( UDPSS );
|
||||
}
|
||||
|
||||
public String getMaximumTransmissionUnit()
|
||||
{
|
||||
int mtu = mMessage.getInt( MTU );
|
||||
|
||||
switch( mtu )
|
||||
{
|
||||
case 1:
|
||||
return "296 BYTES";
|
||||
case 2:
|
||||
return "510 BYTES";
|
||||
case 3:
|
||||
return "1020 BYTES";
|
||||
case 4:
|
||||
return "1500 BYTES";
|
||||
default:
|
||||
return "UNK-" + mtu;
|
||||
}
|
||||
}
|
||||
|
||||
public MDPConfigurationOption getMDPConfigurationOption()
|
||||
{
|
||||
return MDPConfigurationOption.fromValue( mMessage.getInt( MDPCO ) );
|
||||
}
|
||||
|
||||
public String getDataAccessControl()
|
||||
{
|
||||
return mMessage.getHex( DATA_ACCESS_CONTROL, 4 );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
package module.decode.p25.message.pdu.confirmed;
|
||||
|
||||
import module.decode.p25.reference.SNDCPActivationRejectReason;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class SNDCPActivateTDSContextReject extends PDUConfirmedMessage
|
||||
{
|
||||
public final static Logger mLog =
|
||||
LoggerFactory.getLogger( SNDCPActivateTDSContextReject.class );
|
||||
|
||||
public static final int[] NSAPI = { 180,181,182,183 };
|
||||
public static final int[] REJECT_CODE = { 184,185,186,187,188,189,190,191 };
|
||||
|
||||
public SNDCPActivateTDSContextReject( PDUConfirmedMessage message )
|
||||
{
|
||||
super( message );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMessage()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append( "NAC:" );
|
||||
sb.append( getNAC() );
|
||||
sb.append( " PDUC LLID:" );
|
||||
sb.append( getLogicalLinkID() );
|
||||
sb.append( " REJECT SNDCP PACKET DATA ACTIVATE - REASON:" );
|
||||
sb.append( getReason().getLabel() );
|
||||
sb.append( " CRC[" );
|
||||
sb.append( getErrorStatus() );
|
||||
sb.append( "] " );
|
||||
sb.append( mMessage.toString() );
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Network Service Access Point Identifier - up to 14 NSAPI's can be
|
||||
* allocated to the mobile with each NSAPI to be used for a specific
|
||||
* protocol layer.
|
||||
*/
|
||||
public int getNSAPI()
|
||||
{
|
||||
return mMessage.getInt( NSAPI );
|
||||
}
|
||||
|
||||
public SNDCPActivationRejectReason getReason()
|
||||
{
|
||||
return SNDCPActivationRejectReason.fromValue( mMessage.getInt( REJECT_CODE ) );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,149 @@
|
||||
package module.decode.p25.message.pdu.confirmed;
|
||||
|
||||
import module.decode.p25.reference.MDPConfigurationOption;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class SNDCPActivateTDSContextRequest extends PDUConfirmedMessage
|
||||
{
|
||||
public final static Logger mLog =
|
||||
LoggerFactory.getLogger( SNDCPActivateTDSContextRequest.class );
|
||||
|
||||
public static final int[] SNDCP_VERSION = { 180,181,182,183 };
|
||||
public static final int[] NSAPI = { 184,185,186,187 };
|
||||
public static final int[] NAT = { 188,189,190,191 };
|
||||
public static final int[] IP_1 = { 192,193,194,195,196,197,198,199 };
|
||||
public static final int[] IP_2 = { 200,201,202,203,204,205,206,207 };
|
||||
public static final int[] IP_3 = { 208,209,210,211,212,213,214,215 };
|
||||
public static final int[] IP_4 = { 216,217,218,219,220,221,222,223 };
|
||||
public static final int[] DSUT = { 224,225,226,227 };
|
||||
public static final int[] UDPC = { 228,229,230,231 };
|
||||
public static final int[] IPHC = { 232,233,234,235,236,237,238,239 };
|
||||
public static final int[] TCPSS = { 240,241,242,243 };
|
||||
public static final int[] UDPSS = { 244,245,246,247 };
|
||||
public static final int[] MDPCO = { 248,249,250,251,252,253,254,255 };
|
||||
|
||||
public SNDCPActivateTDSContextRequest( PDUConfirmedMessage message )
|
||||
{
|
||||
super( message );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMessage()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append( "NAC:" );
|
||||
sb.append( getNAC() );
|
||||
sb.append( " PDUC LLID:" );
|
||||
sb.append( getLogicalLinkID() );
|
||||
sb.append( " REQUEST SNDCP PACKET DATA ACTIVATE " );
|
||||
sb.append( getNetworkAddressType() );
|
||||
sb.append( " " );
|
||||
sb.append( getIPAddress() );
|
||||
sb.append( " NSAPI:" );
|
||||
sb.append( getNSAPI() );
|
||||
sb.append( " CRC[" );
|
||||
sb.append( getErrorStatus() );
|
||||
sb.append( "]" );
|
||||
|
||||
sb.append( " PACKET #" );
|
||||
sb.append( getPacketSequenceNumber() );
|
||||
|
||||
if( isFinalFragment() && getFragmentSequenceNumber() == 0 )
|
||||
{
|
||||
sb.append( ".C" );
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.append( "." );
|
||||
sb.append( getFragmentSequenceNumber() );
|
||||
|
||||
if( isFinalFragment() )
|
||||
{
|
||||
sb.append( "C" );
|
||||
}
|
||||
}
|
||||
|
||||
sb.append( " " );
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* SNDCP Version: 1 = P25 SNDCP Version 1
|
||||
*/
|
||||
public int getSNDCPVersion()
|
||||
{
|
||||
return mMessage.getInt( SNDCP_VERSION );
|
||||
}
|
||||
|
||||
/**
|
||||
* Network Service Access Point Identifier - up to 14 NSAPI's can be
|
||||
* allocated to the mobile with each NSAPI to be used for a specific
|
||||
* protocol layer.
|
||||
*/
|
||||
public int getNSAPI()
|
||||
{
|
||||
return mMessage.getInt( NSAPI );
|
||||
}
|
||||
|
||||
public String getNetworkAddressType()
|
||||
{
|
||||
return mMessage.getInt( NAT ) == 0 ? "IPV4 STATIC" : "IPV4 DYNAMIC";
|
||||
}
|
||||
|
||||
public String getIPAddress()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append( mMessage.getInt( IP_1 ) );
|
||||
sb.append( "." );
|
||||
sb.append( mMessage.getInt( IP_2 ) );
|
||||
sb.append( "." );
|
||||
sb.append( mMessage.getInt( IP_3 ) );
|
||||
sb.append( "." );
|
||||
sb.append( mMessage.getInt( IP_4 ) );
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public String getDataSubscriberUnitType()
|
||||
{
|
||||
switch( mMessage.getInt( DSUT ) )
|
||||
{
|
||||
case 0:
|
||||
return "DATA ONLY MRC";
|
||||
case 1:
|
||||
return "DATA AND VOICE MRC";
|
||||
}
|
||||
|
||||
return "UNKNOWN";
|
||||
}
|
||||
|
||||
public boolean hasIPHeaderCompression()
|
||||
{
|
||||
return mMessage.getInt( IPHC ) == 1;
|
||||
}
|
||||
|
||||
public boolean hasUserDataPayloadCompression()
|
||||
{
|
||||
return mMessage.getInt( UDPC ) == 1;
|
||||
}
|
||||
|
||||
public int getTCPStateSlots()
|
||||
{
|
||||
return mMessage.getInt( TCPSS );
|
||||
}
|
||||
|
||||
public int getUDPStateSlots()
|
||||
{
|
||||
return mMessage.getInt( UDPSS );
|
||||
}
|
||||
|
||||
public MDPConfigurationOption getMDPConfigurationOption()
|
||||
{
|
||||
return MDPConfigurationOption.fromValue( mMessage.getInt( MDPCO ) );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
package module.decode.p25.message.pdu.confirmed;
|
||||
|
||||
import module.decode.p25.reference.PDUType;
|
||||
import module.decode.p25.reference.SNDCPActivationRejectReason;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class SNDCPDeactivateTDSContext extends PDUConfirmedMessage
|
||||
{
|
||||
public final static Logger mLog =
|
||||
LoggerFactory.getLogger( SNDCPDeactivateTDSContext.class );
|
||||
|
||||
public static final int[] NSAPI = { 180,181,182,183 };
|
||||
public static final int[] DEACTIVATION_TYPE = { 184,185,186,187,188,189,
|
||||
190,191 };
|
||||
|
||||
public SNDCPDeactivateTDSContext( PDUConfirmedMessage message )
|
||||
{
|
||||
super( message );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMessage()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append( "NAC:" );
|
||||
sb.append( getNAC() );
|
||||
sb.append( " PDUC LLID:" );
|
||||
sb.append( getLogicalLinkID() );
|
||||
sb.append( " REQUEST SNDCP PACKET DATA DEACTIVATE " );
|
||||
sb.append( getDeactivationType() );
|
||||
sb.append( " CRC[" );
|
||||
sb.append( getErrorStatus() );
|
||||
sb.append( "] " );
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Network Service Access Point Identifier - up to 14 NSAPI's can be
|
||||
* allocated to the mobile with each NSAPI to be used for a specific
|
||||
* protocol layer.
|
||||
*/
|
||||
public int getNSAPI()
|
||||
{
|
||||
return mMessage.getInt( NSAPI );
|
||||
}
|
||||
|
||||
public String getDeactivationType()
|
||||
{
|
||||
if( getPDUType() == PDUType.SN_DEACTIVATE_TDS_CONTEXT_REQUEST )
|
||||
{
|
||||
return mMessage.getInt( DEACTIVATION_TYPE ) == 0 ?
|
||||
"ALL NSAPIS" : "THIS NSAPI";
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
356
src/module/decode/p25/message/pdu/confirmed/SNDCPUserData.java
Normal file
356
src/module/decode/p25/message/pdu/confirmed/SNDCPUserData.java
Normal file
@@ -0,0 +1,356 @@
|
||||
package module.decode.p25.message.pdu.confirmed;
|
||||
|
||||
import module.decode.p25.reference.IPHeaderCompression;
|
||||
import module.decode.p25.reference.IPProtocol;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class SNDCPUserData extends PDUConfirmedMessage
|
||||
{
|
||||
public final static Logger mLog =
|
||||
LoggerFactory.getLogger( SNDCPUserData.class );
|
||||
|
||||
public static final int DATA_BLOCK_START = 176;
|
||||
|
||||
public static final int[] NSAPI = { 180,181,182,183 };
|
||||
public static final int[] PCOMP = { 184,185,186,187 };
|
||||
public static final int[] DCOMP = { 188,189,190,191 };
|
||||
|
||||
/* IP Packet Header */
|
||||
public static final int[] IP_VERSION = { 192,193,194,195 };
|
||||
public static final int[] IHL = { 196,197,198,199 };
|
||||
public static final int[] DSCP = { 200,201,202,203,204,205 };
|
||||
public static final int[] ECN = { 206,207 };
|
||||
public static final int[] TOTAL_LENGTH = { 208,209,210,211,212,213,214,215,
|
||||
216,217,218,219,220,221,222,223 };
|
||||
public static final int[] IDENTIFICATION = { 224,225,226,227,228,229,230,231,
|
||||
232,233,234,235,236,237,238,239 };
|
||||
public static final int[] FLAGS = { 240,241,242 };
|
||||
public static final int[] FRAGMENT_OFFSET = { 243,244,245,246,247,248,249,
|
||||
250,251,252,253,254,255 };
|
||||
public static final int[] TTL = { 256,257,258,259,260,261,262,263 };
|
||||
public static final int[] PROTOCOL = { 264,265,266,267,268,269,270,271 };
|
||||
public static final int[] HEADER_CHECKSUM = { 272,273,274,275,276,277,278,
|
||||
279,280,281,282,283,284,285,286,287 };
|
||||
public static final int[] SOURCE_IP_1 = { 288,289,290,291,292,293,294,295 };
|
||||
public static final int[] SOURCE_IP_2 = { 296,297,298,299,300,301,302,303 };
|
||||
public static final int[] BLOCK_SERIAL_2 = { 304,305,306,307,308,309,310 };
|
||||
public static final int[] BLOCK_CRC9_2 = { 311,312,313,314,315,316,317,318,
|
||||
319 };
|
||||
public static final int[] SOURCE_IP_3 = { 320,321,322,323,324,325,326,327 };
|
||||
public static final int[] SOURCE_IP_4 = { 328,329,330,331,332,333,334,335 };
|
||||
public static final int[] DESTINATION_IP_1 = { 336,337,338,339,340,341,342,343 };
|
||||
public static final int[] DESTINATION_IP_2 = { 344,345,346,347,348,349,350,351 };
|
||||
public static final int[] DESTINATION_IP_3 = { 352,353,354,355,356,357,358,359 };
|
||||
public static final int[] DESTINATION_IP_4 = { 360,361,362,363,364,365,366,367 };
|
||||
|
||||
public static final int IP_DATA_START = 368;
|
||||
|
||||
/* User Datagram Protocol */
|
||||
public static final int[] UDP_SOURCE_PORT = { 368,369,370,371,372,373,374,
|
||||
375 };
|
||||
public static final int[] UDP_DESTINATION_PORT = { 376,377,378,379,380,381,
|
||||
382,383 };
|
||||
public static final int[] UDP_LENGTH = { 384,385,386,387,388,389,390,391,
|
||||
392,393,394,395,396,397,398,399 };
|
||||
public static final int[] UDP_CHECKSUM = { 400,401,402,403,404,405,406,407,
|
||||
408,409,410,411,412,413,414,415 };
|
||||
public static final int UDP_DATA_START = 416;
|
||||
|
||||
public SNDCPUserData( PDUConfirmedMessage message )
|
||||
{
|
||||
super( message );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMessage()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append( "NAC:" );
|
||||
sb.append( getNAC() );
|
||||
sb.append( " PDUC LLID:" );
|
||||
sb.append( getLogicalLinkID() );
|
||||
sb.append( " SNDCP NSAPI:" );
|
||||
sb.append( getNSAPI() );
|
||||
sb.append( " " );
|
||||
IPProtocol protocol = getIPProtocol();
|
||||
|
||||
sb.append( protocol.getLabel() );
|
||||
sb.append( "/IP" );
|
||||
|
||||
sb.append( " FM:" );
|
||||
sb.append( getSourceIPAddress() );
|
||||
|
||||
if( protocol == IPProtocol.UDP )
|
||||
{
|
||||
sb.append( ":" );
|
||||
sb.append( getUDPSourcePort() );
|
||||
}
|
||||
|
||||
sb.append( " TO:" );
|
||||
sb.append( getDestinationIPAddress() );
|
||||
|
||||
if( protocol == IPProtocol.UDP )
|
||||
{
|
||||
sb.append( ":" );
|
||||
sb.append( getUDPDestinationPort() );
|
||||
}
|
||||
|
||||
sb.append( " DATA:" );
|
||||
sb.append( getPayload() );
|
||||
|
||||
sb.append( " CRC[" );
|
||||
sb.append( getErrorStatus() );
|
||||
sb.append( "]" );
|
||||
|
||||
sb.append( " PACKET #" );
|
||||
sb.append( getPacketSequenceNumber() );
|
||||
|
||||
if( isFinalFragment() && getFragmentSequenceNumber() == 0 )
|
||||
{
|
||||
sb.append( ".C" );
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.append( "." );
|
||||
sb.append( getFragmentSequenceNumber() );
|
||||
|
||||
if( isFinalFragment() )
|
||||
{
|
||||
sb.append( "C" );
|
||||
}
|
||||
}
|
||||
|
||||
sb.append( " " );
|
||||
|
||||
sb.append( mMessage.toString() );
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Network Service Access Point Identifier - up to 14 NSAPI's can be
|
||||
* allocated to the mobile with each NSAPI to be used for a specific
|
||||
* protocol layer.
|
||||
*/
|
||||
public int getNSAPI()
|
||||
{
|
||||
return mMessage.getInt( NSAPI );
|
||||
}
|
||||
|
||||
public IPHeaderCompression getIPHeaderCompressionState()
|
||||
{
|
||||
return IPHeaderCompression.fromValue( mMessage.getInt( PCOMP ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* No enum values were defined for this
|
||||
*/
|
||||
public boolean hasUserDataCompression()
|
||||
{
|
||||
return mMessage.getInt( DCOMP ) > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* IP Version - should always be 4 (IPV4)
|
||||
*/
|
||||
public int getIPVersion()
|
||||
{
|
||||
return mMessage.getInt( IP_VERSION );
|
||||
}
|
||||
|
||||
/**
|
||||
* IP packet header length in 32-bit words
|
||||
*/
|
||||
public int getInternetHeaderLength()
|
||||
{
|
||||
return mMessage.getInt( IHL );
|
||||
}
|
||||
|
||||
/**
|
||||
* IP packet DSCP
|
||||
*/
|
||||
public int getDifferentiatedServicesCodePoint()
|
||||
{
|
||||
return mMessage.getInt( DSCP );
|
||||
}
|
||||
|
||||
/**
|
||||
* IP packet ECN
|
||||
*/
|
||||
public int getExplicitCongestionNotification()
|
||||
{
|
||||
return mMessage.getInt( ECN );
|
||||
}
|
||||
|
||||
/**
|
||||
* IP packet size in bytes, including header and data
|
||||
*/
|
||||
public int getTotalLength()
|
||||
{
|
||||
return mMessage.getInt( TOTAL_LENGTH );
|
||||
}
|
||||
|
||||
/**
|
||||
* IP packet identification
|
||||
*/
|
||||
public int getIdentification()
|
||||
{
|
||||
return mMessage.getInt( IDENTIFICATION );
|
||||
}
|
||||
|
||||
/**
|
||||
* IP packet flags. 0-Reserved, 1-Don't Fragment, 2-More Fragments
|
||||
*/
|
||||
public int getFlags()
|
||||
{
|
||||
return mMessage.getInt( FLAGS );
|
||||
}
|
||||
|
||||
public boolean isFragment()
|
||||
{
|
||||
return getFlags() > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* IP packet - identifies the offset value in 8-byte blocks (64-bit blocks)
|
||||
* for this packet fragment from the beginning.
|
||||
*/
|
||||
public int getFragmentOffset()
|
||||
{
|
||||
return mMessage.getInt( FRAGMENT_OFFSET );
|
||||
}
|
||||
|
||||
/**
|
||||
* IP packet time (hops) to live
|
||||
*/
|
||||
public int getTimeToLive()
|
||||
{
|
||||
return mMessage.getInt( TTL );
|
||||
}
|
||||
|
||||
/**
|
||||
* Identifies the IP protocol carried by the IP packet
|
||||
*/
|
||||
public IPProtocol getIPProtocol()
|
||||
{
|
||||
return IPProtocol.fromValue( mMessage.getInt( PROTOCOL ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Source IPV4 address
|
||||
*/
|
||||
public String getSourceIPAddress()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append( mMessage.getInt( SOURCE_IP_1 ) );
|
||||
sb.append( "." );
|
||||
sb.append( mMessage.getInt( SOURCE_IP_2 ) );
|
||||
sb.append( "." );
|
||||
sb.append( mMessage.getInt( SOURCE_IP_3 ) );
|
||||
sb.append( "." );
|
||||
sb.append( mMessage.getInt( SOURCE_IP_4 ) );
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Destination IPV4 address
|
||||
*/
|
||||
public String getDestinationIPAddress()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append( mMessage.getInt( DESTINATION_IP_1 ) );
|
||||
sb.append( "." );
|
||||
sb.append( mMessage.getInt( DESTINATION_IP_2 ) );
|
||||
sb.append( "." );
|
||||
sb.append( mMessage.getInt( DESTINATION_IP_3 ) );
|
||||
sb.append( "." );
|
||||
sb.append( mMessage.getInt( DESTINATION_IP_4 ) );
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* UDP source port
|
||||
*/
|
||||
public int getUDPSourcePort()
|
||||
{
|
||||
return mMessage.getInt( UDP_SOURCE_PORT );
|
||||
}
|
||||
|
||||
/**
|
||||
* UDP destination port
|
||||
*/
|
||||
public int getUDPDestinationPort()
|
||||
{
|
||||
return mMessage.getInt( UDP_DESTINATION_PORT );
|
||||
}
|
||||
|
||||
/**
|
||||
* UDP data payload size in bytes
|
||||
*/
|
||||
public int getUDPDataLength()
|
||||
{
|
||||
return mMessage.getInt( UDP_LENGTH );
|
||||
}
|
||||
/**
|
||||
* Hex string representation of the packet data, including packet header
|
||||
* data if present.
|
||||
*/
|
||||
public String getPayload()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
/* Adjust for PDU header (2 bytes) plus IP Packet header (20 bytes) */
|
||||
int start = 22;
|
||||
|
||||
if( getIPProtocol() == IPProtocol.UDP )
|
||||
{
|
||||
/* Adjust for UDP header (8 bytes) */
|
||||
start = 30;
|
||||
}
|
||||
|
||||
int spacingCounter = 0;
|
||||
|
||||
/* Append octets inserting a space between each 32-bit value */
|
||||
int octets = getOctetCount() + getDataHeaderOffset();
|
||||
|
||||
for( int x = start; x < octets; x++ )
|
||||
{
|
||||
sb.append( getPacketOctet( x ) );
|
||||
|
||||
spacingCounter++;
|
||||
|
||||
if( spacingCounter >= 4 )
|
||||
{
|
||||
sb.append( " " );
|
||||
spacingCounter = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the octet identified by the 0-indexed 'octet' argument location.
|
||||
* If there is a Data Header Offset, the 0 index points to the first octet
|
||||
* of the data header. Otherwise, the 0 index points to the first octet
|
||||
* of the packet. You must account for the data header offset when
|
||||
* specifying the octet.
|
||||
*/
|
||||
public String getPacketOctet( int octet )
|
||||
{
|
||||
int block = (int)( octet / 16 );
|
||||
int offset = octet % 16;
|
||||
|
||||
int start = DATA_BLOCK_START + ( block * 144 ) + ( offset * 8 );
|
||||
|
||||
return mMessage.getHex( start, start + 7, 2 );
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,161 @@
|
||||
package module.decode.p25.message.pdu.osp.control;
|
||||
|
||||
import module.decode.p25.message.IBandIdentifier;
|
||||
import module.decode.p25.message.IdentifierReceiver;
|
||||
import module.decode.p25.message.pdu.PDUMessage;
|
||||
import module.decode.p25.message.tsbk.osp.control.SystemService;
|
||||
import module.decode.p25.reference.DataUnitID;
|
||||
import module.decode.p25.reference.Opcode;
|
||||
import alias.AliasList;
|
||||
import bits.BinaryMessage;
|
||||
import edac.CRCP25;
|
||||
|
||||
public class AdjacentStatusBroadcastExtended extends PDUMessage
|
||||
implements IdentifierReceiver
|
||||
{
|
||||
public static final int[] LRA = { 88,89,90,91,92,93,94,95 };
|
||||
public static final int[] SYSTEM_ID = { 100,101,102,103,104,105,106,107,108,
|
||||
109,110,111 };
|
||||
public static final int[] RF_SUBSYSTEM_ID = { 128,129,130,131,132,133,134,
|
||||
135 };
|
||||
public static final int[] SITE_ID = { 136,137,138,139,140,141,142,143 };
|
||||
public static final int[] TRANSMIT_IDENTIFIER = { 160,161,162,163 };
|
||||
public static final int[] TRANSMIT_CHANNEL = { 164,165,166,167,168,169,170,
|
||||
171,172,173,174,175 };
|
||||
public static final int[] RECEIVE_IDENTIFIER = { 176,177,178,179 };
|
||||
public static final int[] RECEIVE_CHANNEL = { 180,181,182,183,184,185,186,
|
||||
187,188,189,190,191 };
|
||||
public static final int[] SYSTEM_SERVICE_CLASS = { 192,193,194,195,196,197,
|
||||
198,199 };
|
||||
public static final int[] MULTIPLE_BLOCK_CRC = { 224,225,226,227,228,229,
|
||||
230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,
|
||||
248,249,250,251,252,253,254,255 };
|
||||
|
||||
private IBandIdentifier mTransmitIdentifierProvider;
|
||||
private IBandIdentifier mReceiveIdentifierProvider;
|
||||
|
||||
public AdjacentStatusBroadcastExtended( BinaryMessage message,
|
||||
DataUnitID duid, AliasList aliasList )
|
||||
{
|
||||
super( message, duid, aliasList );
|
||||
|
||||
/* Header block is already error detected/corrected - perform error
|
||||
* detection correction on the intermediate and final data blocks */
|
||||
mMessage = CRCP25.correctPDU1( mMessage );
|
||||
mCRC[ 1 ] = mMessage.getCRC();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getEventType()
|
||||
{
|
||||
return Opcode.ADJACENT_STATUS_BROADCAST.getDescription();
|
||||
}
|
||||
|
||||
public String getMessage()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append( getMessageStub() );
|
||||
|
||||
sb.append( " LRA:" + getLocationRegistrationArea() );
|
||||
|
||||
sb.append( " SYS:" + getSystemID() );
|
||||
|
||||
sb.append( " RFSS:" + getRFSubsystemID() );
|
||||
|
||||
sb.append( " SITE:" + getSiteID() );
|
||||
|
||||
sb.append( " CTRL CHAN:" + getReceiveIdentifier() + "-" + getReceiveChannel() );
|
||||
|
||||
sb.append( " DN:" + getDownlinkFrequency() );
|
||||
|
||||
sb.append( " " + getTransmitIdentifier() + "-" + getTransmitChannel() );
|
||||
|
||||
sb.append( " UP:" + getUplinkFrequency() );
|
||||
|
||||
sb.append( " SYS SVC CLASS:" +
|
||||
SystemService.toString( getSystemServiceClass() ) );
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
|
||||
public String getLocationRegistrationArea()
|
||||
{
|
||||
return mMessage.getHex( LRA, 2 );
|
||||
}
|
||||
|
||||
public String getSystemID()
|
||||
{
|
||||
return mMessage.getHex( SYSTEM_ID, 3 );
|
||||
}
|
||||
|
||||
public String getRFSubsystemID()
|
||||
{
|
||||
return mMessage.getHex( RF_SUBSYSTEM_ID, 2 );
|
||||
}
|
||||
|
||||
public String getSiteID()
|
||||
{
|
||||
return mMessage.getHex( SITE_ID, 2 );
|
||||
}
|
||||
|
||||
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 int getSystemServiceClass()
|
||||
{
|
||||
return mMessage.getInt( SYSTEM_SERVICE_CLASS );
|
||||
}
|
||||
|
||||
public long getDownlinkFrequency()
|
||||
{
|
||||
return calculateDownlink( mTransmitIdentifierProvider, getTransmitChannel() );
|
||||
}
|
||||
|
||||
public long getUplinkFrequency()
|
||||
{
|
||||
return calculateUplink( mReceiveIdentifierProvider, getReceiveChannel() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setIdentifierMessage( int identifier, IBandIdentifier message )
|
||||
{
|
||||
if( identifier == getTransmitIdentifier() )
|
||||
{
|
||||
mTransmitIdentifierProvider = message;
|
||||
}
|
||||
|
||||
if( identifier == getReceiveIdentifier() )
|
||||
{
|
||||
mReceiveIdentifierProvider = message;
|
||||
}
|
||||
}
|
||||
|
||||
public int[] getIdentifiers()
|
||||
{
|
||||
int[] idens = new int[ 2 ];
|
||||
|
||||
idens[ 0 ] = getTransmitIdentifier();
|
||||
idens[ 1 ] = getReceiveIdentifier();
|
||||
|
||||
return idens;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
package module.decode.p25.message.pdu.osp.control;
|
||||
|
||||
import module.decode.p25.message.pdu.PDUMessage;
|
||||
import module.decode.p25.reference.DataUnitID;
|
||||
import module.decode.p25.reference.Opcode;
|
||||
import alias.AliasList;
|
||||
import bits.BinaryMessage;
|
||||
import edac.CRCP25;
|
||||
|
||||
public class CallAlertExtended extends PDUMessage
|
||||
{
|
||||
public static final int[] TARGET_ADDRESS = { 88,89,90,91,92,93,94,95,96,97,
|
||||
98,99,100,101,102,103,104,105,106,107,108,109,110,111 };
|
||||
public static final int[] WACN = { 128,129,130,131,132,133,134,135,136,137,
|
||||
138,139,140,141,142,143,160,161,162,163 };
|
||||
public static final int[] SYSTEM_ID = { 164,165,166,167,168,169,170,171,172,
|
||||
173,174,175 };
|
||||
public static final int[] SOURCE_ID = { 176,177,178,179,180,181,182,183,184,
|
||||
185,186,187,188,189,190,191,192,193,194,195,196,197,198,199 };
|
||||
public static final int[] MULTIPLE_BLOCK_CRC = { 224,225,226,227,228,229,
|
||||
230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,
|
||||
248,249,250,251,252,253,254,255 };
|
||||
|
||||
public CallAlertExtended( BinaryMessage message,
|
||||
DataUnitID duid, AliasList aliasList )
|
||||
{
|
||||
super( message, duid, aliasList );
|
||||
|
||||
/* Header block is already error detected/corrected - perform error
|
||||
* detection correction on the intermediate and final data blocks */
|
||||
mMessage = CRCP25.correctPDU1( mMessage );
|
||||
mCRC[ 1 ] = mMessage.getCRC();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getEventType()
|
||||
{
|
||||
return Opcode.CALL_ALERT.getDescription();
|
||||
}
|
||||
|
||||
public String getMessage()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append( getMessageStub() );
|
||||
|
||||
sb.append( " FROM:" );
|
||||
sb.append( getSourceID() );
|
||||
|
||||
sb.append( " TO:" );
|
||||
sb.append( getTargetAddress() );
|
||||
|
||||
sb.append( " WACN:" );
|
||||
sb.append( getWACN() );
|
||||
|
||||
sb.append( " SYS:" );
|
||||
sb.append( getSystemID() );
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public String getTargetAddress()
|
||||
{
|
||||
return mMessage.getHex( TARGET_ADDRESS, 6 );
|
||||
}
|
||||
|
||||
public String getWACN()
|
||||
{
|
||||
return mMessage.getHex( WACN, 5 );
|
||||
}
|
||||
|
||||
public String getSystemID()
|
||||
{
|
||||
return mMessage.getHex( SYSTEM_ID, 3 );
|
||||
}
|
||||
|
||||
public String getSourceID()
|
||||
{
|
||||
return mMessage.getHex( SOURCE_ID, 6 );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
package module.decode.p25.message.pdu.osp.control;
|
||||
|
||||
import module.decode.p25.message.pdu.PDUMessage;
|
||||
import module.decode.p25.reference.DataUnitID;
|
||||
import module.decode.p25.reference.Opcode;
|
||||
import alias.AliasList;
|
||||
import bits.BinaryMessage;
|
||||
import edac.CRCP25;
|
||||
|
||||
public class GroupAffiliationQueryExtended extends PDUMessage
|
||||
{
|
||||
public static final int[] TARGET_ADDRESS = { 88,89,90,91,92,93,94,95,96,97,
|
||||
98,99,100,101,102,103,104,105,106,107,108,109,110,111 };
|
||||
public static final int[] WACN = { 128,129,130,131,132,133,134,135,136,137,
|
||||
138,139,140,141,142,143,160,161,162,163 };
|
||||
public static final int[] SYSTEM_ID = { 164,165,166,167,168,169,170,171,172,
|
||||
173,174,175 };
|
||||
public static final int[] SOURCE_ID = { 176,177,178,179,180,181,182,183,184,
|
||||
185,186,187,188,189,190,191,192,193,194,195,196,197,198,199 };
|
||||
public static final int[] MULTIPLE_BLOCK_CRC = { 224,225,226,227,228,229,
|
||||
230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,
|
||||
248,249,250,251,252,253,254,255 };
|
||||
|
||||
public GroupAffiliationQueryExtended( BinaryMessage message,
|
||||
DataUnitID duid, AliasList aliasList )
|
||||
{
|
||||
super( message, duid, aliasList );
|
||||
|
||||
/* Header block is already error detected/corrected - perform error
|
||||
* detection correction on the intermediate and final data blocks */
|
||||
mMessage = CRCP25.correctPDU1( mMessage );
|
||||
mCRC[ 1 ] = mMessage.getCRC();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getEventType()
|
||||
{
|
||||
return Opcode.GROUP_AFFILIATION_QUERY.getDescription();
|
||||
}
|
||||
|
||||
public String getMessage()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append( getMessageStub() );
|
||||
|
||||
sb.append( " FROM:" );
|
||||
sb.append( getSourceID() );
|
||||
|
||||
sb.append( " TO:" );
|
||||
sb.append( getTargetAddress() );
|
||||
|
||||
sb.append( " WACN:" );
|
||||
sb.append( getWACN() );
|
||||
|
||||
sb.append( " SYS:" );
|
||||
sb.append( getSystemID() );
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public String getTargetAddress()
|
||||
{
|
||||
return mMessage.getHex( TARGET_ADDRESS, 6 );
|
||||
}
|
||||
|
||||
public String getWACN()
|
||||
{
|
||||
return mMessage.getHex( WACN, 5 );
|
||||
}
|
||||
|
||||
public String getSystemID()
|
||||
{
|
||||
return mMessage.getHex( SYSTEM_ID, 3 );
|
||||
}
|
||||
|
||||
public String getSourceID()
|
||||
{
|
||||
return mMessage.getHex( SOURCE_ID, 6 );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,132 @@
|
||||
package module.decode.p25.message.pdu.osp.control;
|
||||
|
||||
import module.decode.p25.message.pdu.PDUMessage;
|
||||
import module.decode.p25.reference.DataUnitID;
|
||||
import module.decode.p25.reference.Opcode;
|
||||
import module.decode.p25.reference.Response;
|
||||
import alias.AliasList;
|
||||
import bits.BinaryMessage;
|
||||
import edac.CRCP25;
|
||||
|
||||
public class GroupAffiliationResponseExtended extends PDUMessage
|
||||
{
|
||||
public static final int[] TARGET_ADDRESS = { 88,89,90,91,92,93,94,95,96,97,
|
||||
98,99,100,101,102,103,104,105,106,107,108,109,110,111 };
|
||||
public static final int[] SOURCE_WACN = { 128,129,130,131,132,133,134,135,
|
||||
136,137,138,139,140,141,142,143,160,161,162,163 };
|
||||
public static final int[] SOURCE_SYSTEM_ID = { 164,165,166,167,168,169,170,
|
||||
171,172,173,174,175 };
|
||||
public static final int[] SOURCE_ID = { 176,177,178,179,180,181,182,183,184,
|
||||
185,186,187,188,189,190,191,192,193,194,195,196,197,198,199 };
|
||||
public static final int[] GROUP_WACN = { 200,201,202,203,204,205,206,207,
|
||||
208,209,210,211,212,213,214,215,216,217,218,219 };
|
||||
public static final int[] GROUP_SYSTEM_ID = { 220,221,222,223,224,225,226,
|
||||
227,228,229,230,231 };
|
||||
public static final int[] GROUP_ID = { 232,233,234,235,236,237,238,239,240,
|
||||
241,242,243,244,245,246,247 };
|
||||
public static final int[] ANNOUNCEMENT_GROUP_ID = { 248,249,250,251,252,253,
|
||||
254,255,256,257,258,259,260,261,262,263 };
|
||||
public static final int[] GROUP_AFFILIATION_RESPONSE_VALUE = { 270,271 };
|
||||
public static final int[] MULTIPLE_BLOCK_CRC = { 320,321,322,323,324,325,
|
||||
326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,
|
||||
343,344,345,346,347,348,349,350,351 };
|
||||
|
||||
public GroupAffiliationResponseExtended( BinaryMessage message,
|
||||
DataUnitID duid, AliasList aliasList )
|
||||
{
|
||||
super( message, duid, aliasList );
|
||||
|
||||
/* Header block is already error detected/corrected - perform error
|
||||
* detection correction on the intermediate and final data blocks */
|
||||
mMessage = CRCP25.correctPDU1( mMessage );
|
||||
mCRC[ 1 ] = mMessage.getCRC();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getEventType()
|
||||
{
|
||||
return Opcode.GROUP_AFFILIATION_RESPONSE.getDescription();
|
||||
}
|
||||
|
||||
public String getMessage()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append( getMessageStub() );
|
||||
|
||||
sb.append( "AFFILIATION:" );
|
||||
sb.append( getResponse().name() );
|
||||
|
||||
sb.append( " TO:" );
|
||||
sb.append( getTargetAddress() );
|
||||
|
||||
sb.append( " FROM:" );
|
||||
sb.append( getSourceID() );
|
||||
|
||||
sb.append( " WACN:" );
|
||||
sb.append( getSourceWACN() );
|
||||
|
||||
sb.append( " SYS:" );
|
||||
sb.append( getSourceSystemID() );
|
||||
|
||||
sb.append( " GROUP:" );
|
||||
sb.append( getGroupID() );
|
||||
|
||||
sb.append( " WACN:" );
|
||||
sb.append( getGroupWACN() );
|
||||
|
||||
sb.append( " SYS:" );
|
||||
sb.append( getGroupSystemID() );
|
||||
|
||||
sb.append( " ANNOUNCEMENT GROUP:" );
|
||||
sb.append( getAnnouncementGroupID() );
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public String getTargetAddress()
|
||||
{
|
||||
return mMessage.getHex( TARGET_ADDRESS, 6 );
|
||||
}
|
||||
|
||||
public String getSourceWACN()
|
||||
{
|
||||
return mMessage.getHex( SOURCE_WACN, 5 );
|
||||
}
|
||||
|
||||
public String getSourceSystemID()
|
||||
{
|
||||
return mMessage.getHex( SOURCE_SYSTEM_ID, 3 );
|
||||
}
|
||||
|
||||
public String getSourceID()
|
||||
{
|
||||
return mMessage.getHex( SOURCE_ID, 6 );
|
||||
}
|
||||
|
||||
public String getGroupWACN()
|
||||
{
|
||||
return mMessage.getHex( GROUP_WACN, 5 );
|
||||
}
|
||||
|
||||
public String getGroupSystemID()
|
||||
{
|
||||
return mMessage.getHex( GROUP_SYSTEM_ID, 3 );
|
||||
}
|
||||
|
||||
public String getGroupID()
|
||||
{
|
||||
return mMessage.getHex( GROUP_ID, 4 );
|
||||
}
|
||||
|
||||
public String getAnnouncementGroupID()
|
||||
{
|
||||
return mMessage.getHex( GROUP_ID, 4 );
|
||||
}
|
||||
|
||||
public Response getResponse()
|
||||
{
|
||||
return Response.fromValue(
|
||||
mMessage.getInt( GROUP_AFFILIATION_RESPONSE_VALUE ) );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
package module.decode.p25.message.pdu.osp.control;
|
||||
|
||||
import module.decode.p25.message.pdu.PDUMessage;
|
||||
import module.decode.p25.reference.DataUnitID;
|
||||
import module.decode.p25.reference.Opcode;
|
||||
import alias.AliasList;
|
||||
import bits.BinaryMessage;
|
||||
import edac.CRCP25;
|
||||
|
||||
public class MessageUpdateExtended extends PDUMessage
|
||||
{
|
||||
public static final int[] TARGET_ADDRESS = { 88,89,90,91,92,93,94,95,96,97,
|
||||
98,99,100,101,102,103,104,105,106,107,108,109,110,111 };
|
||||
public static final int[] SOURCE_WACN = { 128,129,130,131,132,133,134,135,136,137,
|
||||
138,139,140,141,142,143,160,161,162,163 };
|
||||
public static final int[] SOURCE_SYSTEM_ID = { 164,165,166,167,168,169,170,171,172,
|
||||
173,174,175 };
|
||||
public static final int[] SOURCE_ID = { 176,177,178,179,180,181,182,183,184,
|
||||
185,186,187,188,189,190,191,192,193,194,195,196,197,198,199 };
|
||||
public static final int[] SHORT_DATA_MESSAGE = { 200,201,202,203,204,205,
|
||||
206,207,208,209,210,211,212,213,214,215 };
|
||||
public static final int[] MULTIPLE_BLOCK_CRC = { 224,225,226,227,228,229,
|
||||
230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,
|
||||
248,249,250,251,252,253,254,255 };
|
||||
|
||||
public MessageUpdateExtended( BinaryMessage message,
|
||||
DataUnitID duid, AliasList aliasList )
|
||||
{
|
||||
super( message, duid, aliasList );
|
||||
|
||||
/* Header block is already error detected/corrected - perform error
|
||||
* detection correction on the intermediate and final data blocks */
|
||||
mMessage = CRCP25.correctPDU1( mMessage );
|
||||
mCRC[ 1 ] = mMessage.getCRC();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getEventType()
|
||||
{
|
||||
return Opcode.CALL_ALERT.getDescription();
|
||||
}
|
||||
|
||||
public String getMessage()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append( getMessageStub() );
|
||||
|
||||
sb.append( " TO:" );
|
||||
sb.append( getTargetAddress() );
|
||||
|
||||
sb.append( " MSG:" );
|
||||
sb.append( getShortDataMessage() );
|
||||
|
||||
sb.append( " FROM:" );
|
||||
sb.append( getSourceID() );
|
||||
|
||||
sb.append( " WACN:" );
|
||||
sb.append( getSourceWACN() );
|
||||
|
||||
sb.append( " SYS:" );
|
||||
sb.append( getSourceSystemID() );
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public String getTargetAddress()
|
||||
{
|
||||
return mMessage.getHex( TARGET_ADDRESS, 6 );
|
||||
}
|
||||
|
||||
public String getSourceWACN()
|
||||
{
|
||||
return mMessage.getHex( SOURCE_WACN, 5 );
|
||||
}
|
||||
|
||||
public String getSourceSystemID()
|
||||
{
|
||||
return mMessage.getHex( SOURCE_SYSTEM_ID, 3 );
|
||||
}
|
||||
|
||||
public String getSourceID()
|
||||
{
|
||||
return mMessage.getHex( SOURCE_ID, 6 );
|
||||
}
|
||||
|
||||
public String getShortDataMessage()
|
||||
{
|
||||
return mMessage.getHex( SHORT_DATA_MESSAGE, 4 );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,160 @@
|
||||
package module.decode.p25.message.pdu.osp.control;
|
||||
|
||||
import module.decode.p25.message.IBandIdentifier;
|
||||
import module.decode.p25.message.IdentifierReceiver;
|
||||
import module.decode.p25.message.pdu.PDUMessage;
|
||||
import module.decode.p25.message.tsbk.osp.control.SystemService;
|
||||
import module.decode.p25.reference.DataUnitID;
|
||||
import module.decode.p25.reference.Opcode;
|
||||
import module.decode.p25.reference.P25NetworkCallsign;
|
||||
import alias.AliasList;
|
||||
import bits.BinaryMessage;
|
||||
import edac.CRCP25;
|
||||
|
||||
public class NetworkStatusBroadcastExtended extends PDUMessage
|
||||
implements IdentifierReceiver
|
||||
{
|
||||
public static final int[] LRA = { 88,89,90,91,92,93,94,95 };
|
||||
public static final int[] SYSTEM_ID = { 100,101,102,103,104,105,106,107,108,
|
||||
109,110,111 };
|
||||
public static final int[] WACN = { 160,161,162,163,164,165,166,167,168,169,
|
||||
170,171,172,173,174,175,176,177,178,179 };
|
||||
public static final int[] TRANSMIT_IDENTIFIER = { 184,185,186,187 };
|
||||
public static final int[] TRANSMIT_CHANNEL = { 188,189,190,191,192,193,194,
|
||||
195,196,197,198,199 };
|
||||
public static final int[] RECEIVE_IDENTIFIER = { 200,201,202,203 };
|
||||
public static final int[] RECEIVE_CHANNEL = { 204,205,206,207,208,209,210,
|
||||
211,212,213,214,215 };
|
||||
public static final int[] SYSTEM_SERVICE_CLASS = { 216,217,218,219,220,221,
|
||||
222,223 };
|
||||
public static final int[] MULTIPLE_BLOCK_CRC = { 224,225,226,227,228,229,
|
||||
230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,
|
||||
248,249,250,251,252,253,254,255 };
|
||||
|
||||
private IBandIdentifier mTransmitIdentifierUpdate;
|
||||
private IBandIdentifier mReceiveIdentifierUpdate;
|
||||
|
||||
public NetworkStatusBroadcastExtended( BinaryMessage message,
|
||||
DataUnitID duid, AliasList aliasList )
|
||||
{
|
||||
super( message, duid, aliasList );
|
||||
|
||||
/* Header block is already error detected/corrected - perform error
|
||||
* detection correction on the intermediate and final data blocks */
|
||||
mMessage = CRCP25.correctPDU1( mMessage );
|
||||
mCRC[ 1 ] = mMessage.getCRC();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getEventType()
|
||||
{
|
||||
return Opcode.NETWORK_STATUS_BROADCAST.getDescription();
|
||||
}
|
||||
|
||||
public String getMessage()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append( getMessageStub() );
|
||||
|
||||
sb.append( " LRA:" + getLocationRegistrationArea() );
|
||||
|
||||
sb.append( " WACN:" + getWACN() );
|
||||
|
||||
sb.append( " SYS:" + getSystemID() );
|
||||
|
||||
sb.append( " CTRL CHAN:" + getReceiveIdentifier() + "-" + getReceiveChannel() );
|
||||
|
||||
sb.append( " DN:" + getDownlinkFrequency() );
|
||||
|
||||
sb.append( " " + getTransmitIdentifier() + "-" + getTransmitChannel() );
|
||||
|
||||
sb.append( " UP:" + getUplinkFrequency() );
|
||||
|
||||
sb.append( " SYS SVC CLASS:" +
|
||||
SystemService.toString( getSystemServiceClass() ) );
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
|
||||
public String getLocationRegistrationArea()
|
||||
{
|
||||
return mMessage.getHex( LRA, 2 );
|
||||
}
|
||||
|
||||
public String getSystemID()
|
||||
{
|
||||
return mMessage.getHex( SYSTEM_ID, 3 );
|
||||
}
|
||||
|
||||
public String getWACN()
|
||||
{
|
||||
return mMessage.getHex( WACN, 5 );
|
||||
}
|
||||
|
||||
public String getNetworkCallsign()
|
||||
{
|
||||
return P25NetworkCallsign.getCallsign( mMessage.getInt( WACN ),
|
||||
mMessage.getInt( SYSTEM_ID ) );
|
||||
}
|
||||
|
||||
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 int getSystemServiceClass()
|
||||
{
|
||||
return mMessage.getInt( SYSTEM_SERVICE_CLASS );
|
||||
}
|
||||
|
||||
public long getDownlinkFrequency()
|
||||
{
|
||||
return calculateDownlink( mTransmitIdentifierUpdate, getTransmitChannel() );
|
||||
}
|
||||
|
||||
public long getUplinkFrequency()
|
||||
{
|
||||
return calculateUplink( mReceiveIdentifierUpdate, getReceiveChannel() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setIdentifierMessage( int identifier, IBandIdentifier message )
|
||||
{
|
||||
if( identifier == getTransmitIdentifier() )
|
||||
{
|
||||
mTransmitIdentifierUpdate = message;
|
||||
}
|
||||
|
||||
if( identifier == getReceiveIdentifier() )
|
||||
{
|
||||
mReceiveIdentifierUpdate = message;
|
||||
}
|
||||
}
|
||||
|
||||
public int[] getIdentifiers()
|
||||
{
|
||||
int[] idens = new int[ 2 ];
|
||||
|
||||
idens[ 0 ] = getTransmitIdentifier();
|
||||
idens[ 1 ] = getReceiveIdentifier();
|
||||
|
||||
return idens;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,113 @@
|
||||
package module.decode.p25.message.pdu.osp.control;
|
||||
|
||||
import module.decode.p25.message.pdu.PDUMessage;
|
||||
import module.decode.p25.reference.DataUnitID;
|
||||
import module.decode.p25.reference.Encryption;
|
||||
import module.decode.p25.reference.Opcode;
|
||||
import alias.AliasList;
|
||||
import bits.BinaryMessage;
|
||||
import edac.CRCP25;
|
||||
|
||||
public class ProtectionParameterBroadcast extends PDUMessage
|
||||
{
|
||||
public static final int[] TARGET_ADDRESS = { 88,89,90,91,92,93,94,95,96,97,
|
||||
98,99,100,101,102,103,104,105,106,107,108,109,110,111 };
|
||||
public static final int[] ENCRYPTION_TYPE = { 128,129,130,131,132,133,134,
|
||||
135 };
|
||||
public static final int[] ALGORITHM_ID = { 136,137,138,139,140,141,142,143 };
|
||||
public static final int[] KEY_ID = { 160,161,162,163,164,165,166,167,168,
|
||||
169,170,171,172,173,174,175 };
|
||||
public static final int[] INBOUND_INITIALIZATION_VECTOR_A = { 176,177,178,
|
||||
179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,
|
||||
197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,
|
||||
215 };
|
||||
public static final int[] INBOUND_INITIALIZATION_VECTOR_B = { 216,217,218,
|
||||
219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,
|
||||
237,238,239,240,241,242,243,244,245,246,247 };
|
||||
public static final int[] OUTBOUND_INITIALIZATION_VECTOR_A = { 248,249,250,
|
||||
251,252,253,254,255,256,257,258,259,260,261,262,263,264,265,266,267,268,
|
||||
269,270,271,272,273,274,275,276,277,278,279,280,281,282,283,284,285,286,
|
||||
287 };
|
||||
public static final int[] OUTBOUND_INITIALIZATION_VECTOR_B = { 288,289,290,
|
||||
291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,
|
||||
309,310,311,312,313,314,315,316,317,318,319 };
|
||||
public static final int[] MULTIPLE_BLOCK_CRC = { 320,321,322,323,324,325,
|
||||
326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,
|
||||
343,344,345,346,347,348,349,350,351 };
|
||||
|
||||
public ProtectionParameterBroadcast( BinaryMessage message,
|
||||
DataUnitID duid, AliasList aliasList )
|
||||
{
|
||||
super( message, duid, aliasList );
|
||||
|
||||
/* Header block is already error detected/corrected - perform error
|
||||
* detection correction on the intermediate and final data blocks */
|
||||
mMessage = CRCP25.correctPDU1( mMessage );
|
||||
mCRC[ 1 ] = mMessage.getCRC();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getEventType()
|
||||
{
|
||||
return Opcode.PROTECTION_PARAMETER_BROADCAST.getDescription();
|
||||
}
|
||||
|
||||
public String getMessage()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append( getMessageStub() );
|
||||
|
||||
sb.append( " TO:" );
|
||||
sb.append( getTargetAddress() );
|
||||
|
||||
sb.append( " ENCRYPTION:" );
|
||||
sb.append( getEncryptionType().name() );
|
||||
|
||||
sb.append( " ALGORITHM ID:" );
|
||||
sb.append( getAlgorithmID() );
|
||||
|
||||
sb.append( " KEY ID:" );
|
||||
sb.append( getKeyID() );
|
||||
|
||||
sb.append( " INBOUND IV:" );
|
||||
sb.append( getInboundInitializationVector() );
|
||||
|
||||
sb.append( " OUTBOUND IV:" );
|
||||
sb.append( getOutboundInitializationVector() );
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public String getTargetAddress()
|
||||
{
|
||||
return mMessage.getHex( TARGET_ADDRESS, 6 );
|
||||
}
|
||||
|
||||
public Encryption getEncryptionType()
|
||||
{
|
||||
return Encryption.fromValue( mMessage.getInt( ENCRYPTION_TYPE ) );
|
||||
}
|
||||
|
||||
public String getAlgorithmID()
|
||||
{
|
||||
return mMessage.getHex( ALGORITHM_ID, 2 );
|
||||
}
|
||||
|
||||
public String getKeyID()
|
||||
{
|
||||
return mMessage.getHex( KEY_ID, 4 );
|
||||
}
|
||||
|
||||
public String getInboundInitializationVector()
|
||||
{
|
||||
return mMessage.getHex( INBOUND_INITIALIZATION_VECTOR_A, 10 ) +
|
||||
mMessage.getHex( INBOUND_INITIALIZATION_VECTOR_B, 8 );
|
||||
}
|
||||
|
||||
public String getOutboundInitializationVector()
|
||||
{
|
||||
return mMessage.getHex( OUTBOUND_INITIALIZATION_VECTOR_A, 10 ) +
|
||||
mMessage.getHex( OUTBOUND_INITIALIZATION_VECTOR_B, 8 );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,164 @@
|
||||
package module.decode.p25.message.pdu.osp.control;
|
||||
|
||||
import module.decode.p25.message.IBandIdentifier;
|
||||
import module.decode.p25.message.IdentifierReceiver;
|
||||
import module.decode.p25.message.pdu.PDUMessage;
|
||||
import module.decode.p25.message.tsbk.osp.control.SystemService;
|
||||
import module.decode.p25.reference.DataUnitID;
|
||||
import module.decode.p25.reference.Opcode;
|
||||
import alias.AliasList;
|
||||
import bits.BinaryMessage;
|
||||
import edac.CRCP25;
|
||||
|
||||
public class RFSSStatusBroadcastExtended extends PDUMessage
|
||||
implements IdentifierReceiver
|
||||
{
|
||||
public static final int[] LRA = { 88,89,90,91,92,93,94,95 };
|
||||
public static final int ACTIVE_NETWORK_CONNECTION_INDICATOR = 99;
|
||||
public static final int[] SYSTEM_ID = { 100,101,102,103,104,105,106,107,108,
|
||||
109,110,111 };
|
||||
public static final int[] RFSS_ID = { 160,161,162,163,164,165,166,167 };
|
||||
public static final int[] SITE_ID = { 168,169,170,171,172,173,174,175 };
|
||||
public static final int[] TRANSMIT_IDENTIFIER = { 184,185,186,187 };
|
||||
public static final int[] TRANSMIT_CHANNEL = { 188,189,190,191,192,193,194,
|
||||
195,196,197,198,199 };
|
||||
public static final int[] RECEIVE_IDENTIFIER = { 200,201,202,203 };
|
||||
public static final int[] RECEIVE_CHANNEL = { 204,205,206,207,208,209,210,
|
||||
211,212,213,214,215 };
|
||||
public static final int[] SYSTEM_SERVICE_CLASS = { 216,217,218,219,220,221,
|
||||
222,223 };
|
||||
public static final int[] MULTIPLE_BLOCK_CRC = { 224,225,226,227,228,229,
|
||||
230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,
|
||||
248,249,250,251,252,253,254,255 };
|
||||
|
||||
private IBandIdentifier mTransmitIdentifierUpdate;
|
||||
private IBandIdentifier mReceiveIdentifierUpdate;
|
||||
|
||||
public RFSSStatusBroadcastExtended( BinaryMessage message,
|
||||
DataUnitID duid, AliasList aliasList )
|
||||
{
|
||||
super( message, duid, aliasList );
|
||||
|
||||
/* Header block is already error detected/corrected - perform error
|
||||
* detection correction on the intermediate and final data blocks */
|
||||
mMessage = CRCP25.correctPDU1( mMessage );
|
||||
mCRC[ 1 ] = mMessage.getCRC();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getEventType()
|
||||
{
|
||||
return Opcode.NETWORK_STATUS_BROADCAST.getDescription();
|
||||
}
|
||||
|
||||
public String getMessage()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append( getMessageStub() );
|
||||
|
||||
sb.append( " LRA:" + getLocationRegistrationArea() );
|
||||
|
||||
sb.append( " SYS:" + getSystemID() );
|
||||
|
||||
sb.append( " SITE:" + getRFSubsystemID() + "-" + getSiteID() );
|
||||
|
||||
sb.append( " CTRL CHAN:" + getReceiveIdentifier() + "-" + getReceiveChannel() );
|
||||
|
||||
sb.append( " DN:" + getDownlinkFrequency() );
|
||||
|
||||
sb.append( " " + getTransmitIdentifier() + "-" + getTransmitChannel() );
|
||||
|
||||
sb.append( " UP:" + getUplinkFrequency() );
|
||||
|
||||
sb.append( " SYS SVC CLASS:" +
|
||||
SystemService.toString( getSystemServiceClass() ) );
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
|
||||
public String getLocationRegistrationArea()
|
||||
{
|
||||
return mMessage.getHex( LRA, 2 );
|
||||
}
|
||||
|
||||
public boolean hasActiveNetworkConnection()
|
||||
{
|
||||
return mMessage.get( ACTIVE_NETWORK_CONNECTION_INDICATOR );
|
||||
}
|
||||
|
||||
public String getSystemID()
|
||||
{
|
||||
return mMessage.getHex( SYSTEM_ID, 3 );
|
||||
}
|
||||
|
||||
public String getRFSubsystemID()
|
||||
{
|
||||
return mMessage.getHex( RFSS_ID, 2 );
|
||||
}
|
||||
|
||||
public String getSiteID()
|
||||
{
|
||||
return mMessage.getHex( SITE_ID, 2 );
|
||||
}
|
||||
|
||||
public int 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 int getSystemServiceClass()
|
||||
{
|
||||
return mMessage.getInt( SYSTEM_SERVICE_CLASS );
|
||||
}
|
||||
|
||||
public long getDownlinkFrequency()
|
||||
{
|
||||
return calculateDownlink( mTransmitIdentifierUpdate, getTransmitChannel() );
|
||||
}
|
||||
|
||||
public long getUplinkFrequency()
|
||||
{
|
||||
return calculateUplink( mReceiveIdentifierUpdate, getReceiveChannel() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setIdentifierMessage( int identifier, IBandIdentifier message )
|
||||
{
|
||||
if( identifier == getTransmitIdentifier() )
|
||||
{
|
||||
mTransmitIdentifierUpdate = message;
|
||||
}
|
||||
|
||||
if( identifier == getReceiveIdentifier() )
|
||||
{
|
||||
mReceiveIdentifierUpdate = message;
|
||||
}
|
||||
}
|
||||
|
||||
public int[] getIdentifiers()
|
||||
{
|
||||
int[] idens = new int[ 2 ];
|
||||
|
||||
idens[ 0 ] = getTransmitIdentifier();
|
||||
idens[ 1 ] = getReceiveIdentifier();
|
||||
|
||||
return idens;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,269 @@
|
||||
package module.decode.p25.message.pdu.osp.control;
|
||||
|
||||
import module.decode.p25.P25MessageFramer;
|
||||
import module.decode.p25.message.pdu.PDUMessage;
|
||||
import module.decode.p25.reference.DataUnitID;
|
||||
import module.decode.p25.reference.Opcode;
|
||||
import alias.AliasList;
|
||||
import bits.BinaryMessage;
|
||||
import edac.CRCP25;
|
||||
|
||||
public class RoamingAddressUpdateExtended extends PDUMessage
|
||||
{
|
||||
public static final int[] TARGET_ADDRESS = { 88,89,90,91,92,93,94,95,96,97,
|
||||
98,99,100,101,102,103,104,105,106,107,108,109,110,111 };
|
||||
public static final int LAST_MESSAGE_INDICATOR = 128;
|
||||
public static final int[] MESSAGE_SEQUENCE_NUMBER = { 132,133,134,135 };
|
||||
public static final int[] WACN_A = { 136,137,138,139,140,141,142,143,160,
|
||||
161,162,163,164,165,166,167,168,169,170,171 };
|
||||
public static final int[] SYSTEM_ID_A = { 172,173,174,175,176,177,178,179,
|
||||
180,181,182,183 };
|
||||
public static final int[] SOURCE_ID_FORMAT_1 = { 184,185,186,187,188,189,
|
||||
190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207 };
|
||||
public static final int[] WACN_B = { 184,185,186,187,188,189,190,191,192,
|
||||
193,194,195,196,197,198,199,200,201,202,203 };
|
||||
public static final int[] SYSTEM_ID_B = { 204,205,206,207,208,209,210,211,
|
||||
212,213,214,215 };
|
||||
public static final int[] WACN_C = { 216,217,218,219,220,221,222,223,224,
|
||||
225,226,227,228,229,230,231,232,233,234,235 };
|
||||
public static final int[] SYSTEM_ID_C = { 236,237,238,239,240,241,242,243,
|
||||
244,245,246,247 };
|
||||
public static final int[] WACN_D = { 248,249,250,251,252,253,254,255,256,
|
||||
257,258,259,260,261,262,263,264,265,266,267 };
|
||||
public static final int[] SYSTEM_ID_D = { 268,269,270,271,272,273,274,275,
|
||||
276,277,278,279 };
|
||||
public static final int[] SOURCE_ID_FORMAT_2 = { 280,281,282,283,284,285,
|
||||
286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303 };
|
||||
public static final int[] WACN_E = { 280,281,282,283,284,285,
|
||||
286,287,288,289,290,291,292,293,294,295,296,297,298,299 };
|
||||
public static final int[] SYSTEM_ID_E = { 300,301,302,303,304,305,306,307,
|
||||
308,309,310,311 };
|
||||
public static final int[] WACN_F = { 312,313,314,315,316,317,318,319,320,
|
||||
321,322,323,324,325,326,327,328,329,330,331 };
|
||||
public static final int[] SYSTEM_ID_F = { 332,333,334,335,336,337,338,339,
|
||||
340,341,342,343 };
|
||||
public static final int[] WACN_G = { 344,345,346,347,348,349,350,351,352,
|
||||
353,354,355,356,357,358,359,360,361,362,363 };
|
||||
public static final int[] SYSTEM_ID_G = { 364,365,366,367,368,369,370,371,
|
||||
372,373,374,375 };
|
||||
public static final int[] SOURCE_ID_FORMAT_3 = { 376,377,378,379,380,381,
|
||||
382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399 };
|
||||
public static final int[] MULTIPLE_BLOCK_CRC_FORMAT_1 = { 224,225,226,227,
|
||||
228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,
|
||||
246,247,248,249,250,251,252,253,254,255 };
|
||||
public static final int[] MULTIPLE_BLOCK_CRC_FORMAT_2 = { 320,321,322,323,
|
||||
324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,
|
||||
342,343,344,345,346,347,348,349,350,351 };
|
||||
public static final int[] MULTIPLE_BLOCK_CRC_FORMAT_3 = { 416,417,418,419,
|
||||
420,421,422,423,424,425,426,427,428,429,430,431,432,433,434,435,436,437,
|
||||
438,439,440,441,442,443,444,445,446,447 };
|
||||
|
||||
private enum Format{ FORMAT_1, FORMAT_2, FORMAT_3 };
|
||||
|
||||
private Format mFormat;
|
||||
|
||||
public RoamingAddressUpdateExtended( BinaryMessage message,
|
||||
DataUnitID duid, AliasList aliasList )
|
||||
{
|
||||
super( message, duid, aliasList );
|
||||
|
||||
if( mMessage.size() == P25MessageFramer.PDU2_BEGIN )
|
||||
{
|
||||
mFormat = Format.FORMAT_1;
|
||||
|
||||
/* Header block is already error detected/corrected - perform error
|
||||
* detection correction on the intermediate and final data blocks */
|
||||
mMessage = CRCP25.correctPDU1( mMessage );
|
||||
mCRC[ 1 ] = mMessage.getCRC();
|
||||
}
|
||||
else if( mMessage.size() == P25MessageFramer.PDU3_BEGIN )
|
||||
{
|
||||
mFormat = Format.FORMAT_2;
|
||||
|
||||
/* Header block is already error detected/corrected - perform error
|
||||
* detection correction on the intermediate and final data blocks */
|
||||
mMessage = CRCP25.correctPDU2( mMessage );
|
||||
mCRC[ 1 ] = mMessage.getCRC();
|
||||
}
|
||||
else if( mMessage.size() == P25MessageFramer.PDU3_DECODED_END )
|
||||
{
|
||||
mFormat = Format.FORMAT_3;
|
||||
|
||||
/* Header block is already error detected/corrected - perform error
|
||||
* detection correction on the intermediate and final data blocks */
|
||||
mMessage = CRCP25.correctPDU3( mMessage );
|
||||
mCRC[ 1 ] = mMessage.getCRC();
|
||||
}
|
||||
else
|
||||
{
|
||||
mFormat = Format.FORMAT_1;
|
||||
|
||||
/* Header block is already error detected/corrected - perform error
|
||||
* detection correction on the intermediate and final data blocks */
|
||||
mMessage = CRCP25.correctPDU1( mMessage );
|
||||
mCRC[ 1 ] = mMessage.getCRC();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getEventType()
|
||||
{
|
||||
return Opcode.ROAMING_ADDRESS_UPDATE.getDescription();
|
||||
}
|
||||
|
||||
public String getMessage()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append( getMessageStub() );
|
||||
|
||||
sb.append( " ROAMING ADDRESS STACK FROM:" );
|
||||
sb.append( getSourceID() );
|
||||
|
||||
if( isLastBlock() )
|
||||
{
|
||||
sb.append( " LAST BLOCK" );
|
||||
}
|
||||
|
||||
sb.append( "MSG SEQ:" );
|
||||
sb.append( getMessageSequenceNumber() );
|
||||
|
||||
sb.append( " TO:" );
|
||||
sb.append( getTargetAddress() );
|
||||
|
||||
sb.append( " WACN A:" + getWACNA() );
|
||||
sb.append( " SYS A:" + getSystemIDA() );
|
||||
|
||||
if( isFormat2() )
|
||||
{
|
||||
sb.append( " WACN B:" + getWACNB() );
|
||||
sb.append( " SYS B:" + getSystemIDB() );
|
||||
sb.append( " WACN C:" + getWACNC() );
|
||||
sb.append( " SYS C:" + getSystemIDC() );
|
||||
sb.append( " WACN D:" + getWACND() );
|
||||
sb.append( " SYS D:" + getSystemIDD() );
|
||||
}
|
||||
|
||||
if( isFormat3() )
|
||||
{
|
||||
sb.append( " WACN E:" + getWACNE() );
|
||||
sb.append( " SYS E:" + getSystemIDE() );
|
||||
sb.append( " WACN F:" + getWACNF() );
|
||||
sb.append( " SYS F:" + getSystemIDF() );
|
||||
sb.append( " WACN G:" + getWACNG() );
|
||||
sb.append( " SYS G:" + getSystemIDG() );
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public boolean isLastBlock()
|
||||
{
|
||||
return mMessage.get( LAST_MESSAGE_INDICATOR );
|
||||
}
|
||||
|
||||
public int getMessageSequenceNumber()
|
||||
{
|
||||
return mMessage.getInt( MESSAGE_SEQUENCE_NUMBER );
|
||||
}
|
||||
|
||||
public String getTargetAddress()
|
||||
{
|
||||
return mMessage.getHex( TARGET_ADDRESS, 6 );
|
||||
}
|
||||
|
||||
public String getWACNA()
|
||||
{
|
||||
return mMessage.getHex( WACN_A, 5 );
|
||||
}
|
||||
|
||||
public String getSystemIDA()
|
||||
{
|
||||
return mMessage.getHex( SYSTEM_ID_A, 3 );
|
||||
}
|
||||
|
||||
public String getWACNB()
|
||||
{
|
||||
return isFormat2() ? mMessage.getHex( WACN_B, 5 ) : null;
|
||||
}
|
||||
|
||||
public String getSystemIDB()
|
||||
{
|
||||
return isFormat2() ? mMessage.getHex( SYSTEM_ID_B, 3 ) : null;
|
||||
}
|
||||
|
||||
public String getWACNC()
|
||||
{
|
||||
return isFormat2() ? mMessage.getHex( WACN_C, 5 ) : null;
|
||||
}
|
||||
|
||||
public String getSystemIDC()
|
||||
{
|
||||
return isFormat2() ? mMessage.getHex( SYSTEM_ID_C, 3 ) : null;
|
||||
}
|
||||
|
||||
public String getWACND()
|
||||
{
|
||||
return isFormat2() ? mMessage.getHex( WACN_D, 5 ) : null;
|
||||
}
|
||||
|
||||
public String getSystemIDD()
|
||||
{
|
||||
return isFormat2() ? mMessage.getHex( SYSTEM_ID_D, 3 ) : null;
|
||||
}
|
||||
|
||||
public String getWACNE()
|
||||
{
|
||||
return isFormat3() ? mMessage.getHex( WACN_E, 5 ) : null;
|
||||
}
|
||||
|
||||
public String getSystemIDE()
|
||||
{
|
||||
return isFormat3() ? mMessage.getHex( SYSTEM_ID_E, 3 ) : null;
|
||||
}
|
||||
|
||||
public String getWACNF()
|
||||
{
|
||||
return isFormat3() ? mMessage.getHex( WACN_F, 5 ) : null;
|
||||
}
|
||||
|
||||
public String getSystemIDF()
|
||||
{
|
||||
return isFormat3() ? mMessage.getHex( SYSTEM_ID_F, 3 ) : null;
|
||||
}
|
||||
|
||||
public String getWACNG()
|
||||
{
|
||||
return isFormat3() ? mMessage.getHex( WACN_G, 5 ) : null;
|
||||
}
|
||||
|
||||
public String getSystemIDG()
|
||||
{
|
||||
return isFormat3() ? mMessage.getHex( SYSTEM_ID_G, 3 ) : null;
|
||||
}
|
||||
|
||||
public String getSourceID()
|
||||
{
|
||||
switch( mFormat )
|
||||
{
|
||||
case FORMAT_1:
|
||||
return mMessage.getHex( SOURCE_ID_FORMAT_1, 6 );
|
||||
case FORMAT_2:
|
||||
return mMessage.getHex( SOURCE_ID_FORMAT_2, 6 );
|
||||
case FORMAT_3:
|
||||
return mMessage.getHex( SOURCE_ID_FORMAT_2, 6 );
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public boolean isFormat2()
|
||||
{
|
||||
return mFormat != Format.FORMAT_3;
|
||||
}
|
||||
|
||||
public boolean isFormat3()
|
||||
{
|
||||
return mFormat == Format.FORMAT_3;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
package module.decode.p25.message.pdu.osp.control;
|
||||
|
||||
import module.decode.p25.message.pdu.PDUMessage;
|
||||
import module.decode.p25.reference.DataUnitID;
|
||||
import module.decode.p25.reference.Opcode;
|
||||
import alias.AliasList;
|
||||
import bits.BinaryMessage;
|
||||
import edac.CRCP25;
|
||||
|
||||
public class StatusQueryExtended extends PDUMessage
|
||||
{
|
||||
public static final int[] TARGET_ADDRESS = { 88,89,90,91,92,93,94,95,96,97,
|
||||
98,99,100,101,102,103,104,105,106,107,108,109,110,111 };
|
||||
public static final int[] SOURCE_WACN = { 128,129,130,131,132,133,134,135,136,137,
|
||||
138,139,140,141,142,143,160,161,162,163 };
|
||||
public static final int[] SOURCE_SYSTEM_ID = { 164,165,166,167,168,169,170,171,172,
|
||||
173,174,175 };
|
||||
public static final int[] SOURCE_ID = { 176,177,178,179,180,181,182,183,184,
|
||||
185,186,187,188,189,190,191,192,193,194,195,196,197,198,199 };
|
||||
public static final int[] MULTIPLE_BLOCK_CRC = { 224,225,226,227,228,229,
|
||||
230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,
|
||||
248,249,250,251,252,253,254,255 };
|
||||
|
||||
public StatusQueryExtended( BinaryMessage message,
|
||||
DataUnitID duid, AliasList aliasList )
|
||||
{
|
||||
super( message, duid, aliasList );
|
||||
|
||||
/* Header block is already error detected/corrected - perform error
|
||||
* detection correction on the intermediate and final data blocks */
|
||||
mMessage = CRCP25.correctPDU1( mMessage );
|
||||
mCRC[ 1 ] = mMessage.getCRC();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getEventType()
|
||||
{
|
||||
return Opcode.STATUS_QUERY.getDescription();
|
||||
}
|
||||
|
||||
public String getMessage()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append( getMessageStub() );
|
||||
|
||||
sb.append( " TO:" );
|
||||
sb.append( getTargetAddress() );
|
||||
|
||||
sb.append( " FROM:" );
|
||||
sb.append( getSourceID() );
|
||||
|
||||
sb.append( " WACN:" );
|
||||
sb.append( getSourceWACN() );
|
||||
|
||||
sb.append( " SYS:" );
|
||||
sb.append( getSourceSystemID() );
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public String getTargetAddress()
|
||||
{
|
||||
return mMessage.getHex( TARGET_ADDRESS, 6 );
|
||||
}
|
||||
|
||||
public String getSourceWACN()
|
||||
{
|
||||
return mMessage.getHex( SOURCE_WACN, 5 );
|
||||
}
|
||||
|
||||
public String getSourceSystemID()
|
||||
{
|
||||
return mMessage.getHex( SOURCE_SYSTEM_ID, 3 );
|
||||
}
|
||||
|
||||
public String getSourceID()
|
||||
{
|
||||
return mMessage.getHex( SOURCE_ID, 6 );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
package module.decode.p25.message.pdu.osp.control;
|
||||
|
||||
import module.decode.p25.message.pdu.PDUMessage;
|
||||
import module.decode.p25.reference.DataUnitID;
|
||||
import module.decode.p25.reference.Opcode;
|
||||
import alias.AliasList;
|
||||
import bits.BinaryMessage;
|
||||
import edac.CRCP25;
|
||||
|
||||
public class StatusUpdateExtended extends PDUMessage
|
||||
{
|
||||
public static final int[] TARGET_ADDRESS = { 88,89,90,91,92,93,94,95,96,97,
|
||||
98,99,100,101,102,103,104,105,106,107,108,109,110,111 };
|
||||
public static final int[] SOURCE_WACN = { 128,129,130,131,132,133,134,135,136,137,
|
||||
138,139,140,141,142,143,160,161,162,163 };
|
||||
public static final int[] SOURCE_SYSTEM_ID = { 164,165,166,167,168,169,170,171,172,
|
||||
173,174,175 };
|
||||
public static final int[] SOURCE_ID = { 176,177,178,179,180,181,182,183,184,
|
||||
185,186,187,188,189,190,191,192,193,194,195,196,197,198,199 };
|
||||
public static final int[] UNIT_STATUS = { 200,201,202,203,204,205,206,207 };
|
||||
public static final int[] USER_STATUS = { 208,209,210,211,212,213,214,215 };
|
||||
public static final int[] MULTIPLE_BLOCK_CRC = { 224,225,226,227,228,229,
|
||||
230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,
|
||||
248,249,250,251,252,253,254,255 };
|
||||
|
||||
public StatusUpdateExtended( BinaryMessage message,
|
||||
DataUnitID duid, AliasList aliasList )
|
||||
{
|
||||
super( message, duid, aliasList );
|
||||
|
||||
/* Header block is already error detected/corrected - perform error
|
||||
* detection correction on the intermediate and final data blocks */
|
||||
mMessage = CRCP25.correctPDU1( mMessage );
|
||||
mCRC[ 1 ] = mMessage.getCRC();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getEventType()
|
||||
{
|
||||
return Opcode.STATUS_UPDATE.getDescription();
|
||||
}
|
||||
|
||||
public String getMessage()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append( getMessageStub() );
|
||||
|
||||
sb.append( " TO:" );
|
||||
sb.append( getTargetAddress() );
|
||||
|
||||
sb.append( " FROM:" );
|
||||
sb.append( getSourceID() );
|
||||
|
||||
sb.append( " WACN:" );
|
||||
sb.append( getSourceWACN() );
|
||||
|
||||
sb.append( " SYS:" );
|
||||
sb.append( getSourceSystemID() );
|
||||
|
||||
sb.append( " STATUS USER:" + getUserStatus() );
|
||||
sb.append( " UNIT:" + getUnitStatus() );
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public String getTargetAddress()
|
||||
{
|
||||
return mMessage.getHex( TARGET_ADDRESS, 6 );
|
||||
}
|
||||
|
||||
public String getSourceWACN()
|
||||
{
|
||||
return mMessage.getHex( SOURCE_WACN, 5 );
|
||||
}
|
||||
|
||||
public String getSourceSystemID()
|
||||
{
|
||||
return mMessage.getHex( SOURCE_SYSTEM_ID, 3 );
|
||||
}
|
||||
|
||||
public String getSourceID()
|
||||
{
|
||||
return mMessage.getHex( SOURCE_ID, 6 );
|
||||
}
|
||||
|
||||
public String getUserStatus()
|
||||
{
|
||||
return mMessage.getHex( USER_STATUS, 2 );
|
||||
}
|
||||
|
||||
public String getUnitStatus()
|
||||
{
|
||||
return mMessage.getHex( UNIT_STATUS, 2 );
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
package module.decode.p25.message.pdu.osp.control;
|
||||
|
||||
import module.decode.p25.message.pdu.PDUMessage;
|
||||
import module.decode.p25.reference.DataUnitID;
|
||||
import module.decode.p25.reference.Opcode;
|
||||
import module.decode.p25.reference.Response;
|
||||
import alias.AliasList;
|
||||
import bits.BinaryMessage;
|
||||
import edac.CRCP25;
|
||||
|
||||
public class UnitRegistrationResponseExtended extends PDUMessage
|
||||
{
|
||||
public static final int[] ASSIGNED_SOURCE_ADDRESS = { 88,89,90,91,92,
|
||||
93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111 };
|
||||
public static final int[] WACN = { 128,129,130,131,132,133,134,135,
|
||||
136,137,138,139,140,141,142,143,160,161,162,163 };
|
||||
public static final int[] SYSTEM_ID = { 164,165,166,167,168,169,170,
|
||||
171,172,173,174,175 };
|
||||
public static final int[] SOURCE_ID = { 176,177,178,179,180,181,182,183,184,
|
||||
185,186,187,188,189,190,191,192,193,194,195,196,197,198,199 };
|
||||
public static final int[] SOURCE_ADDRESS = { 200,201,202,203,204,205,206,
|
||||
207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223 };
|
||||
public static final int[] UNIT_REGISTRATION_RESPONSE_VALUE = { 230,231 };
|
||||
public static final int[] MULTIPLE_BLOCK_CRC = { 320,321,322,323,324,325,
|
||||
326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,
|
||||
343,344,345,346,347,348,349,350,351 };
|
||||
|
||||
public UnitRegistrationResponseExtended( BinaryMessage message,
|
||||
DataUnitID duid, AliasList aliasList )
|
||||
{
|
||||
super( message, duid, aliasList );
|
||||
|
||||
/* Header block is already error detected/corrected - perform error
|
||||
* detection correction on the intermediate and final data blocks */
|
||||
mMessage = CRCP25.correctPDU1( mMessage );
|
||||
mCRC[ 1 ] = mMessage.getCRC();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getEventType()
|
||||
{
|
||||
return Opcode.UNIT_REGISTRATION_RESPONSE.getDescription();
|
||||
}
|
||||
|
||||
public String getMessage()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append( getMessageStub() );
|
||||
|
||||
sb.append( "REGISTRATION:" );
|
||||
sb.append( getResponse().name() );
|
||||
|
||||
sb.append( " SRC ID:" );
|
||||
sb.append( getSourceID() );
|
||||
|
||||
sb.append( " ADDR:" );
|
||||
sb.append( getSourceAddress() );
|
||||
|
||||
sb.append( " WACN:" );
|
||||
sb.append( getWACN() );
|
||||
|
||||
sb.append( " SYS:" );
|
||||
sb.append( getSystemID() );
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public String getAssignedSourceAddress()
|
||||
{
|
||||
return mMessage.getHex( ASSIGNED_SOURCE_ADDRESS, 6 );
|
||||
}
|
||||
|
||||
public String getWACN()
|
||||
{
|
||||
return mMessage.getHex( WACN, 5 );
|
||||
}
|
||||
|
||||
public String getSystemID()
|
||||
{
|
||||
return mMessage.getHex( SYSTEM_ID, 3 );
|
||||
}
|
||||
|
||||
public String getSourceID()
|
||||
{
|
||||
return mMessage.getHex( SOURCE_ID, 6 );
|
||||
}
|
||||
|
||||
public String getSourceAddress()
|
||||
{
|
||||
return mMessage.getHex( SOURCE_ADDRESS, 6 );
|
||||
}
|
||||
|
||||
public Response getResponse()
|
||||
{
|
||||
return Response.fromValue(
|
||||
mMessage.getInt( UNIT_REGISTRATION_RESPONSE_VALUE ) );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,179 @@
|
||||
package module.decode.p25.message.pdu.osp.data;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import module.decode.p25.message.IBandIdentifier;
|
||||
import module.decode.p25.message.IdentifierReceiver;
|
||||
import module.decode.p25.message.pdu.PDUMessage;
|
||||
import module.decode.p25.reference.DataUnitID;
|
||||
import module.decode.p25.reference.Opcode;
|
||||
import alias.AliasList;
|
||||
import bits.BinaryMessage;
|
||||
import edac.CRCP25;
|
||||
|
||||
public class GroupDataChannelGrantExtended extends PDUMessage
|
||||
implements IdentifierReceiver
|
||||
{
|
||||
/* Service Options */
|
||||
public static final int EMERGENCY_FLAG = 128;
|
||||
public static final int ENCRYPTED_CHANNEL_FLAG = 129;
|
||||
public static final int DUPLEX_MODE = 130;
|
||||
public static final int SESSION_MODE = 131;
|
||||
|
||||
public static final int[] SOURCE_ADDRESS = { 88,89,90,91,92,93,94,95,96,97,
|
||||
98,99,100,101,102,103,104,105,106,107,108,109,110,111 };
|
||||
public static final int[] SERVICE_OPTIONS = { 128,129,130,131,132,133,134,
|
||||
135 };
|
||||
public static final int[] TRANSMIT_IDENTIFIER = { 160,161,162,163 };
|
||||
public static final int[] TRANSMIT_NUMBER = { 164,165,166,167,168,169,170,
|
||||
171,172,173,174,175 };
|
||||
public static final int[] RECEIVE_IDENTIFIER = { 176,177,178,179 };
|
||||
public static final int[] RECEIVE_NUMBER = { 180,181,182,183,184,185,186,
|
||||
187,188,189,190,191 };
|
||||
public static final int[] GROUP_ADDRESS = { 192,193,194,195,196,197,198,199,
|
||||
200,201,202,203,204,205,206,207 };
|
||||
public static final int[] MULTIPLE_BLOCK_CRC = { 224,225,226,227,228,229,
|
||||
230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,
|
||||
248,249,250,251,252,253,254,255 };
|
||||
|
||||
private IBandIdentifier mTransmitIdentifierUpdate;
|
||||
private IBandIdentifier mReceiveIdentifierUpdate;
|
||||
|
||||
public GroupDataChannelGrantExtended( BinaryMessage message,
|
||||
DataUnitID duid, AliasList aliasList )
|
||||
{
|
||||
super( message, duid, aliasList );
|
||||
|
||||
/* Header block is already error detected/corrected - perform error
|
||||
* detection correction on the intermediate and final data blocks */
|
||||
mMessage = CRCP25.correctPDU1( mMessage );
|
||||
mCRC[ 1 ] = mMessage.getCRC();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getEventType()
|
||||
{
|
||||
return Opcode.TELEPHONE_INTERCONNECT_VOICE_CHANNEL_GRANT.getDescription();
|
||||
}
|
||||
|
||||
public String getMessage()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append( getMessageStub() );
|
||||
|
||||
if( isEmergency() )
|
||||
{
|
||||
sb.append( " EMERGENCY" );
|
||||
}
|
||||
|
||||
sb.append( " FROM:" );
|
||||
sb.append( getSourceAddress() );
|
||||
|
||||
sb.append( " TO:" );
|
||||
sb.append( getGroupAddress() );
|
||||
|
||||
sb.append( " CHAN DN:" + getTransmitChannelIdentifier() + "-" + getTransmitChannelNumber() );
|
||||
sb.append( " " + getDownlinkFrequency() );
|
||||
|
||||
sb.append( " CHAN UP:" + getReceiveChannelIdentifier() + "-" + getReceiveChannelNumber() );
|
||||
sb.append( " " + getUplinkFrequency() );
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public boolean isEmergency()
|
||||
{
|
||||
return mMessage.get( EMERGENCY_FLAG );
|
||||
}
|
||||
|
||||
public boolean isEncrypted()
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
public String getSourceAddress()
|
||||
{
|
||||
return mMessage.getHex( SOURCE_ADDRESS, 6 );
|
||||
}
|
||||
|
||||
public String getGroupAddress()
|
||||
{
|
||||
return mMessage.getHex( GROUP_ADDRESS, 4 );
|
||||
}
|
||||
|
||||
public int getTransmitChannelIdentifier()
|
||||
{
|
||||
return mMessage.getInt( TRANSMIT_IDENTIFIER );
|
||||
}
|
||||
|
||||
public int getTransmitChannelNumber()
|
||||
{
|
||||
return mMessage.getInt( TRANSMIT_NUMBER );
|
||||
}
|
||||
|
||||
public String getTransmitChannel()
|
||||
{
|
||||
return getTransmitChannelIdentifier() + "-" + getTransmitChannelNumber();
|
||||
}
|
||||
|
||||
public int getReceiveChannelIdentifier()
|
||||
{
|
||||
return mMessage.getInt( RECEIVE_IDENTIFIER );
|
||||
}
|
||||
|
||||
public int getReceiveChannelNumber()
|
||||
{
|
||||
return mMessage.getInt( RECEIVE_NUMBER );
|
||||
}
|
||||
|
||||
public String getReceiveChannel()
|
||||
{
|
||||
return getReceiveChannelIdentifier() + "-" + getReceiveChannelNumber();
|
||||
}
|
||||
|
||||
public long getDownlinkFrequency()
|
||||
{
|
||||
return calculateDownlink( mTransmitIdentifierUpdate, getTransmitChannelNumber() );
|
||||
}
|
||||
|
||||
public long getUplinkFrequency()
|
||||
{
|
||||
return calculateUplink( mReceiveIdentifierUpdate, getReceiveChannelNumber() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setIdentifierMessage( int identifier, IBandIdentifier message )
|
||||
{
|
||||
if( identifier == getTransmitChannelIdentifier() )
|
||||
{
|
||||
mTransmitIdentifierUpdate = message;
|
||||
}
|
||||
|
||||
if( identifier == getReceiveChannelIdentifier() )
|
||||
{
|
||||
mReceiveIdentifierUpdate = message;
|
||||
}
|
||||
}
|
||||
|
||||
public int[] getIdentifiers()
|
||||
{
|
||||
int[] idens = new int[ 2 ];
|
||||
|
||||
idens[ 0 ] = getTransmitChannelIdentifier();
|
||||
idens[ 1 ] = getReceiveChannelIdentifier();
|
||||
|
||||
return idens;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package module.decode.p25.message.pdu.osp.data;
|
||||
|
||||
import module.decode.p25.message.IdentifierReceiver;
|
||||
import module.decode.p25.message.pdu.UnitToUnitChannelGrantExtended;
|
||||
import module.decode.p25.reference.DataUnitID;
|
||||
import module.decode.p25.reference.Opcode;
|
||||
import alias.AliasList;
|
||||
import bits.BinaryMessage;
|
||||
|
||||
public class IndividualDataChannelGrantExtended
|
||||
extends UnitToUnitChannelGrantExtended
|
||||
implements IdentifierReceiver
|
||||
{
|
||||
public IndividualDataChannelGrantExtended( BinaryMessage message,
|
||||
DataUnitID duid, AliasList aliasList )
|
||||
{
|
||||
super( message, duid, aliasList );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getEventType()
|
||||
{
|
||||
return Opcode.INDIVIDUAL_DATA_CHANNEL_GRANT.getDescription();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,177 @@
|
||||
package module.decode.p25.message.pdu.osp.voice;
|
||||
|
||||
import module.decode.p25.message.IBandIdentifier;
|
||||
import module.decode.p25.message.IdentifierReceiver;
|
||||
import module.decode.p25.message.pdu.PDUMessage;
|
||||
import module.decode.p25.reference.DataUnitID;
|
||||
import module.decode.p25.reference.Opcode;
|
||||
import alias.AliasList;
|
||||
import bits.BinaryMessage;
|
||||
import edac.CRCP25;
|
||||
|
||||
public class GroupVoiceChannelGrantExplicit extends PDUMessage
|
||||
implements IdentifierReceiver
|
||||
{
|
||||
/* Service Options */
|
||||
public static final int EMERGENCY_FLAG = 128;
|
||||
public static final int ENCRYPTED_CHANNEL_FLAG = 129;
|
||||
public static final int DUPLEX_MODE = 130;
|
||||
public static final int SESSION_MODE = 131;
|
||||
|
||||
public static final int[] SOURCE_ADDRESS = { 88,89,90,91,92,93,94,95,96,97,
|
||||
98,99,100,101,102,103,104,105,106,107,108,109,110,111 };
|
||||
public static final int[] SERVICE_OPTIONS = { 128,129,130,131,132,133,134,
|
||||
135 };
|
||||
public static final int[] TRANSMIT_IDENTIFIER = { 176,177,178,179 };
|
||||
public static final int[] TRANSMIT_NUMBER = { 180,181,182,183,184,185,186,
|
||||
187,188,189,190,191 };
|
||||
public static final int[] RECEIVE_IDENTIFIER = { 192,193,194,195 };
|
||||
public static final int[] RECEIVE_NUMBER = { 196,197,198,199,200,201,202,
|
||||
203,204,205,206,207 };
|
||||
public static final int[] GROUP_ADDRESS = { 208,209,210,211,212,213,214,215,
|
||||
216,217,218,219,220,221,222,223 };
|
||||
public static final int[] MULTIPLE_BLOCK_CRC = { 224,225,226,227,228,229,
|
||||
230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,
|
||||
248,249,250,251,252,253,254,255 };
|
||||
|
||||
private IBandIdentifier mTransmitIdentifierUpdate;
|
||||
private IBandIdentifier mReceiveIdentifierUpdate;
|
||||
|
||||
public GroupVoiceChannelGrantExplicit( BinaryMessage message,
|
||||
DataUnitID duid, AliasList aliasList )
|
||||
{
|
||||
super( message, duid, aliasList );
|
||||
|
||||
/* Header block is already error detected/corrected - perform error
|
||||
* detection correction on the intermediate and final data blocks */
|
||||
mMessage = CRCP25.correctPDU1( mMessage );
|
||||
mCRC[ 1 ] = mMessage.getCRC();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getEventType()
|
||||
{
|
||||
return Opcode.GROUP_VOICE_CHANNEL_GRANT.getDescription();
|
||||
}
|
||||
|
||||
public String getMessage()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append( getMessageStub() );
|
||||
|
||||
if( isEmergency() )
|
||||
{
|
||||
sb.append( " EMERGENCY" );
|
||||
}
|
||||
|
||||
sb.append( " FROM:" );
|
||||
sb.append( getSourceAddress() );
|
||||
|
||||
sb.append( " GRP:" );
|
||||
sb.append( getGroupAddress() );
|
||||
|
||||
sb.append( " CHAN DN:" + getTransmitChannelIdentifier() + "-" + getTransmitChannelNumber() );
|
||||
sb.append( " " + getDownlinkFrequency() );
|
||||
|
||||
sb.append( " CHAN UP:" + getReceiveChannelIdentifier() + "-" + getReceiveChannelNumber() );
|
||||
sb.append( " " + getUplinkFrequency() );
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public boolean isEmergency()
|
||||
{
|
||||
return mMessage.get( EMERGENCY_FLAG );
|
||||
}
|
||||
|
||||
public boolean isEncrypted()
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
public String getSourceAddress()
|
||||
{
|
||||
return mMessage.getHex( SOURCE_ADDRESS, 6 );
|
||||
}
|
||||
|
||||
public String getGroupAddress()
|
||||
{
|
||||
return mMessage.getHex( GROUP_ADDRESS, 4 );
|
||||
}
|
||||
|
||||
public int getTransmitChannelIdentifier()
|
||||
{
|
||||
return mMessage.getInt( TRANSMIT_IDENTIFIER );
|
||||
}
|
||||
|
||||
public int getTransmitChannelNumber()
|
||||
{
|
||||
return mMessage.getInt( TRANSMIT_NUMBER );
|
||||
}
|
||||
|
||||
public String getTransmitChannel()
|
||||
{
|
||||
return getTransmitChannelIdentifier() + "-" + getTransmitChannelNumber();
|
||||
}
|
||||
|
||||
public int getReceiveChannelIdentifier()
|
||||
{
|
||||
return mMessage.getInt( RECEIVE_IDENTIFIER );
|
||||
}
|
||||
|
||||
public int getReceiveChannelNumber()
|
||||
{
|
||||
return mMessage.getInt( RECEIVE_NUMBER );
|
||||
}
|
||||
|
||||
public String getReceiveChannel()
|
||||
{
|
||||
return getReceiveChannelIdentifier() + "-" + getReceiveChannelNumber();
|
||||
}
|
||||
|
||||
public long getDownlinkFrequency()
|
||||
{
|
||||
return calculateDownlink( mTransmitIdentifierUpdate, getTransmitChannelNumber() );
|
||||
}
|
||||
|
||||
public long getUplinkFrequency()
|
||||
{
|
||||
return calculateUplink( mReceiveIdentifierUpdate, getReceiveChannelNumber() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setIdentifierMessage( int identifier, IBandIdentifier message )
|
||||
{
|
||||
if( identifier == getTransmitChannelIdentifier() )
|
||||
{
|
||||
mTransmitIdentifierUpdate = message;
|
||||
}
|
||||
|
||||
if( identifier == getReceiveChannelIdentifier() )
|
||||
{
|
||||
mReceiveIdentifierUpdate = message;
|
||||
}
|
||||
}
|
||||
|
||||
public int[] getIdentifiers()
|
||||
{
|
||||
int[] idens = new int[ 2 ];
|
||||
|
||||
idens[ 0 ] = getTransmitChannelIdentifier();
|
||||
idens[ 1 ] = getReceiveChannelIdentifier();
|
||||
|
||||
return idens;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,184 @@
|
||||
package module.decode.p25.message.pdu.osp.voice;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import module.decode.p25.message.IBandIdentifier;
|
||||
import module.decode.p25.message.IdentifierReceiver;
|
||||
import module.decode.p25.message.pdu.PDUMessage;
|
||||
import module.decode.p25.reference.DataUnitID;
|
||||
import module.decode.p25.reference.Opcode;
|
||||
import alias.AliasList;
|
||||
import bits.BinaryMessage;
|
||||
import edac.CRCP25;
|
||||
|
||||
public class TelephoneInterconnectChannelGrantExplicit extends PDUMessage
|
||||
implements IdentifierReceiver
|
||||
{
|
||||
/* Service Options */
|
||||
public static final int EMERGENCY_FLAG = 128;
|
||||
public static final int ENCRYPTED_CHANNEL_FLAG = 129;
|
||||
public static final int DUPLEX_MODE = 130;
|
||||
public static final int SESSION_MODE = 131;
|
||||
|
||||
public static final int[] ADDRESS = { 88,89,90,91,92,93,94,95,96,97,
|
||||
98,99,100,101,102,103,104,105,106,107,108,109,110,111 };
|
||||
public static final int[] SERVICE_OPTIONS = { 128,129,130,131,132,133,134,
|
||||
135 };
|
||||
public static final int[] TRANSMIT_IDENTIFIER = { 160,161,162,163 };
|
||||
public static final int[] TRANSMIT_NUMBER = { 164,165,166,167,168,169,170,
|
||||
171,172,173,174,175 };
|
||||
public static final int[] RECEIVE_IDENTIFIER = { 176,177,178,179 };
|
||||
public static final int[] RECEIVE_NUMBER = { 180,181,182,183,184,185,186,
|
||||
187,188,189,190,191 };
|
||||
public static final int[] CALL_TIMER = { 192,193,194,195,196,197,198,199,
|
||||
200,201,202,203,204,205,206,207 };
|
||||
public static final int[] MULTIPLE_BLOCK_CRC = { 224,225,226,227,228,229,
|
||||
230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,
|
||||
248,249,250,251,252,253,254,255 };
|
||||
|
||||
private IBandIdentifier mTransmitIdentifierUpdate;
|
||||
private IBandIdentifier mReceiveIdentifierUpdate;
|
||||
|
||||
public TelephoneInterconnectChannelGrantExplicit( BinaryMessage message,
|
||||
DataUnitID duid, AliasList aliasList )
|
||||
{
|
||||
super( message, duid, aliasList );
|
||||
|
||||
/* Header block is already error detected/corrected - perform error
|
||||
* detection correction on the intermediate and final data blocks */
|
||||
mMessage = CRCP25.correctPDU1( mMessage );
|
||||
mCRC[ 1 ] = mMessage.getCRC();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getEventType()
|
||||
{
|
||||
return Opcode.TELEPHONE_INTERCONNECT_VOICE_CHANNEL_GRANT.getDescription();
|
||||
}
|
||||
|
||||
public String getMessage()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append( getMessageStub() );
|
||||
|
||||
if( isEmergency() )
|
||||
{
|
||||
sb.append( " EMERGENCY" );
|
||||
}
|
||||
|
||||
sb.append( " ADDR:" );
|
||||
sb.append( getAddress() );
|
||||
|
||||
sb.append( " CALL TIMER:" );
|
||||
sb.append( mTimeDurationFormat.format( new Date( getCallTimer() ) ) );
|
||||
|
||||
sb.append( " CHAN DN:" + getTransmitChannelIdentifier() + "-" + getTransmitChannelNumber() );
|
||||
sb.append( " " + getDownlinkFrequency() );
|
||||
|
||||
sb.append( " CHAN UP:" + getReceiveChannelIdentifier() + "-" + getReceiveChannelNumber() );
|
||||
sb.append( " " + getUplinkFrequency() );
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public boolean isEmergency()
|
||||
{
|
||||
return mMessage.get( EMERGENCY_FLAG );
|
||||
}
|
||||
|
||||
public boolean isEncrypted()
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
public String getAddress()
|
||||
{
|
||||
return mMessage.getHex( ADDRESS, 6 );
|
||||
}
|
||||
|
||||
/*
|
||||
* Call timer in milliseconds
|
||||
*/
|
||||
public long getCallTimer()
|
||||
{
|
||||
int timer = mMessage.getInt( CALL_TIMER );
|
||||
|
||||
return timer / 100;
|
||||
}
|
||||
|
||||
public int getTransmitChannelIdentifier()
|
||||
{
|
||||
return mMessage.getInt( TRANSMIT_IDENTIFIER );
|
||||
}
|
||||
|
||||
public int getTransmitChannelNumber()
|
||||
{
|
||||
return mMessage.getInt( TRANSMIT_NUMBER );
|
||||
}
|
||||
|
||||
public String getTransmitChannel()
|
||||
{
|
||||
return getTransmitChannelIdentifier() + "-" + getTransmitChannelNumber();
|
||||
}
|
||||
|
||||
public int getReceiveChannelIdentifier()
|
||||
{
|
||||
return mMessage.getInt( RECEIVE_IDENTIFIER );
|
||||
}
|
||||
|
||||
public int getReceiveChannelNumber()
|
||||
{
|
||||
return mMessage.getInt( RECEIVE_NUMBER );
|
||||
}
|
||||
|
||||
public String getReceiveChannel()
|
||||
{
|
||||
return getReceiveChannelIdentifier() + "-" + getReceiveChannelNumber();
|
||||
}
|
||||
|
||||
public long getDownlinkFrequency()
|
||||
{
|
||||
return calculateDownlink( mTransmitIdentifierUpdate, getTransmitChannelNumber() );
|
||||
}
|
||||
|
||||
public long getUplinkFrequency()
|
||||
{
|
||||
return calculateUplink( mReceiveIdentifierUpdate, getReceiveChannelNumber() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setIdentifierMessage( int identifier, IBandIdentifier message )
|
||||
{
|
||||
if( identifier == getTransmitChannelIdentifier() )
|
||||
{
|
||||
mTransmitIdentifierUpdate = message;
|
||||
}
|
||||
|
||||
if( identifier == getReceiveChannelIdentifier() )
|
||||
{
|
||||
mReceiveIdentifierUpdate = message;
|
||||
}
|
||||
}
|
||||
|
||||
public int[] getIdentifiers()
|
||||
{
|
||||
int[] idens = new int[ 2 ];
|
||||
|
||||
idens[ 0 ] = getTransmitChannelIdentifier();
|
||||
idens[ 1 ] = getReceiveChannelIdentifier();
|
||||
|
||||
return idens;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package module.decode.p25.message.pdu.osp.voice;
|
||||
|
||||
import module.decode.p25.reference.DataUnitID;
|
||||
import module.decode.p25.reference.Opcode;
|
||||
import alias.AliasList;
|
||||
import bits.BinaryMessage;
|
||||
|
||||
public class TelephoneInterconnectChannelGrantUpdateExplicit
|
||||
extends TelephoneInterconnectChannelGrantExplicit
|
||||
{
|
||||
public TelephoneInterconnectChannelGrantUpdateExplicit( BinaryMessage message,
|
||||
DataUnitID duid, AliasList aliasList )
|
||||
{
|
||||
super( message, duid, aliasList );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getEventType()
|
||||
{
|
||||
return Opcode.TELEPHONE_INTERCONNECT_VOICE_CHANNEL_GRANT_UPDATE.getDescription();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,111 @@
|
||||
package module.decode.p25.message.pdu.osp.voice;
|
||||
|
||||
import module.decode.p25.message.pdu.PDUMessage;
|
||||
import module.decode.p25.reference.DataUnitID;
|
||||
import module.decode.p25.reference.Opcode;
|
||||
import alias.AliasList;
|
||||
import bits.BinaryMessage;
|
||||
import edac.CRCP25;
|
||||
|
||||
public class UnitToUnitAnswerRequestExplicit extends PDUMessage
|
||||
{
|
||||
/* Service Options */
|
||||
public static final int EMERGENCY_FLAG = 128;
|
||||
public static final int ENCRYPTED_CHANNEL_FLAG = 129;
|
||||
public static final int DUPLEX_MODE = 130;
|
||||
public static final int SESSION_MODE = 131;
|
||||
|
||||
public static final int[] TARGET_ADDRESS = { 88,89,90,91,92,93,94,95,96,97,
|
||||
98,99,100,101,102,103,104,105,106,107,108,109,110,111 };
|
||||
public static final int[] WACN = { 168,169,170,171,172,173,174,175,176,177,
|
||||
178,179,180,181,182,183,184,185,186,187 };
|
||||
public static final int[] SYSTEM_ID = { 188,189,190,191,192,193,194,195,196,
|
||||
197,198,199 };
|
||||
public static final int[] SOURCE_ID = { 200,201,202,203,204,205,206,207,208,
|
||||
209,210,211,212,213,214,215,216,217,218,219,220,221,222,223 };
|
||||
public static final int[] MULTIPLE_BLOCK_CRC = { 224,225,226,227,228,229,
|
||||
230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,
|
||||
248,249,250,251,252,253,254,255 };
|
||||
|
||||
public UnitToUnitAnswerRequestExplicit( BinaryMessage message,
|
||||
DataUnitID duid, AliasList aliasList )
|
||||
{
|
||||
super( message, duid, aliasList );
|
||||
|
||||
/* Header block is already error detected/corrected - perform error
|
||||
* detection correction on the intermediate and final data blocks */
|
||||
mMessage = CRCP25.correctPDU1( mMessage );
|
||||
mCRC[ 1 ] = mMessage.getCRC();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getEventType()
|
||||
{
|
||||
return Opcode.UNIT_TO_UNIT_ANSWER_REQUEST.getDescription();
|
||||
}
|
||||
|
||||
public String getMessage()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append( getMessageStub() );
|
||||
|
||||
if( isEmergency() )
|
||||
{
|
||||
sb.append( " EMERGENCY" );
|
||||
}
|
||||
|
||||
sb.append( " FROM:" );
|
||||
sb.append( getSourceID() );
|
||||
|
||||
sb.append( " TO:" );
|
||||
sb.append( getTargetAddress() );
|
||||
|
||||
sb.append( " WACN:" + getWACN() );
|
||||
|
||||
sb.append( " SYS:" + getSystemID() );
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
public String getSystemID()
|
||||
{
|
||||
return mMessage.getHex( SYSTEM_ID, 3 );
|
||||
}
|
||||
|
||||
public String getWACN()
|
||||
{
|
||||
return mMessage.getHex( WACN, 5 );
|
||||
}
|
||||
|
||||
public String getSourceID()
|
||||
{
|
||||
return mMessage.getHex( SOURCE_ID, 6 );
|
||||
}
|
||||
|
||||
public String getTargetAddress()
|
||||
{
|
||||
return mMessage.getHex( TARGET_ADDRESS, 6 );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package module.decode.p25.message.pdu.osp.voice;
|
||||
|
||||
import module.decode.p25.message.IdentifierReceiver;
|
||||
import module.decode.p25.message.pdu.UnitToUnitChannelGrantExtended;
|
||||
import module.decode.p25.reference.DataUnitID;
|
||||
import module.decode.p25.reference.Opcode;
|
||||
import alias.AliasList;
|
||||
import bits.BinaryMessage;
|
||||
|
||||
public class UnitToUnitVoiceChannelGrantExtended
|
||||
extends UnitToUnitChannelGrantExtended
|
||||
implements IdentifierReceiver
|
||||
{
|
||||
public UnitToUnitVoiceChannelGrantExtended( BinaryMessage message,
|
||||
DataUnitID duid, AliasList aliasList )
|
||||
{
|
||||
super( message, duid, aliasList );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getEventType()
|
||||
{
|
||||
return Opcode.UNIT_TO_UNIT_VOICE_CHANNEL_GRANT.getDescription();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,207 @@
|
||||
package module.decode.p25.message.pdu.osp.voice;
|
||||
|
||||
import module.decode.p25.message.IBandIdentifier;
|
||||
import module.decode.p25.message.IdentifierReceiver;
|
||||
import module.decode.p25.message.pdu.PDUMessage;
|
||||
import module.decode.p25.reference.DataUnitID;
|
||||
import module.decode.p25.reference.Opcode;
|
||||
import alias.AliasList;
|
||||
import bits.BinaryMessage;
|
||||
import edac.CRCP25;
|
||||
|
||||
public class UnitToUnitVoiceChannelGrantUpdateExtended extends PDUMessage
|
||||
implements IdentifierReceiver
|
||||
{
|
||||
/* Service Options */
|
||||
public static final int EMERGENCY_FLAG = 128;
|
||||
public static final int ENCRYPTED_CHANNEL_FLAG = 129;
|
||||
public static final int DUPLEX_MODE = 130;
|
||||
public static final int SESSION_MODE = 131;
|
||||
|
||||
public static final int[] SOURCE_ADDRESS = { 88,89,90,91,92,93,94,95,96,97,
|
||||
98,99,100,101,102,103,104,105,106,107,108,109,110,111 };
|
||||
public static final int[] SERVICE_OPTIONS = { 128,129,130,131,132,133,134,
|
||||
135 };
|
||||
public static final int[] SOURCE_WACN = { 160,161,162,163,164,165,166,167,
|
||||
168,169,170,171,172,173,174,175,176,177,178,179 };
|
||||
public static final int[] SOURCE_SYSTEM_ID = { 180,181,182,183,184,185,186,
|
||||
187,188,189,190,191 };
|
||||
public static final int[] SOURCE_ID = { 192,193,194,195,196,197,198,199,200,
|
||||
201,202,203,204,205,206,207,208,209,210,211,212,213,214,215 };
|
||||
public static final int[] TARGET_ADDRESS = { 216,217,218,219,220,221,222,
|
||||
223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239 };
|
||||
public static final int[] TRANSMIT_IDENTIFIER = { 240,241,242,243 };
|
||||
public static final int[] TRANSMIT_NUMBER = { 244,245,246,247,248,249,250,
|
||||
251,252,253,254,255 };
|
||||
public static final int[] RECEIVE_IDENTIFIER = { 256,257,258,259 };
|
||||
public static final int[] RECEIVE_NUMBER = { 260,261,262,263,264,265,266,
|
||||
267,268,269,270,271 };
|
||||
public static final int[] MULTIPLE_BLOCK_CRC = { 320,321,322,323,324,325,
|
||||
326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,
|
||||
343,344,345,346,347,348,349,350,351 };
|
||||
|
||||
private IBandIdentifier mTransmitIdentifierUpdate;
|
||||
private IBandIdentifier mReceiveIdentifierUpdate;
|
||||
|
||||
public UnitToUnitVoiceChannelGrantUpdateExtended( BinaryMessage message,
|
||||
DataUnitID duid, AliasList aliasList )
|
||||
{
|
||||
super( message, duid, aliasList );
|
||||
|
||||
/* Header block is already error detected/corrected - perform error
|
||||
* detection correction on the intermediate and final data blocks */
|
||||
mMessage = CRCP25.correctPDU2( mMessage );
|
||||
mCRC[ 1 ] = mMessage.getCRC();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getEventType()
|
||||
{
|
||||
return Opcode.UNIT_TO_UNIT_VOICE_CHANNEL_GRANT_UPDATE.getDescription();
|
||||
}
|
||||
|
||||
public String getMessage()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append( getMessageStub() );
|
||||
|
||||
if( isEmergency() )
|
||||
{
|
||||
sb.append( " EMERGENCY" );
|
||||
}
|
||||
|
||||
sb.append( " FROM ADDR:" );
|
||||
sb.append( getSourceAddress() );
|
||||
|
||||
sb.append( " ID:" );
|
||||
sb.append( getSourceID() );
|
||||
|
||||
sb.append( " TO:" );
|
||||
sb.append( getTargetAddress() );
|
||||
|
||||
sb.append( " WACN:" );
|
||||
sb.append( getSourceWACN() );
|
||||
|
||||
sb.append( " SYS:" );
|
||||
sb.append( getSourceSystemID() );
|
||||
|
||||
sb.append( " CHAN DN:" + getTransmitChannelIdentifier() + "-" + getTransmitChannelNumber() );
|
||||
sb.append( " " + getDownlinkFrequency() );
|
||||
|
||||
sb.append( " CHAN UP:" + getReceiveChannelIdentifier() + "-" + getReceiveChannelNumber() );
|
||||
sb.append( " " + getUplinkFrequency() );
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public boolean isEmergency()
|
||||
{
|
||||
return mMessage.get( EMERGENCY_FLAG );
|
||||
}
|
||||
|
||||
public boolean isEncrypted()
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
public String getSourceAddress()
|
||||
{
|
||||
return mMessage.getHex( SOURCE_ADDRESS, 6 );
|
||||
}
|
||||
|
||||
public String getSourceID()
|
||||
{
|
||||
return mMessage.getHex( SOURCE_ID, 6 );
|
||||
}
|
||||
|
||||
public String getSourceWACN()
|
||||
{
|
||||
return mMessage.getHex( SOURCE_WACN, 5 );
|
||||
}
|
||||
|
||||
public String getSourceSystemID()
|
||||
{
|
||||
return mMessage.getHex( SOURCE_SYSTEM_ID, 3 );
|
||||
}
|
||||
|
||||
public String getTargetAddress()
|
||||
{
|
||||
return mMessage.getHex( TARGET_ADDRESS, 6 );
|
||||
}
|
||||
|
||||
public int getTransmitChannelIdentifier()
|
||||
{
|
||||
return mMessage.getInt( TRANSMIT_IDENTIFIER );
|
||||
}
|
||||
|
||||
public int getTransmitChannelNumber()
|
||||
{
|
||||
return mMessage.getInt( TRANSMIT_NUMBER );
|
||||
}
|
||||
|
||||
public String getTransmitChannel()
|
||||
{
|
||||
return getTransmitChannelIdentifier() + "-" + getTransmitChannelNumber();
|
||||
}
|
||||
|
||||
public int getReceiveChannelIdentifier()
|
||||
{
|
||||
return mMessage.getInt( RECEIVE_IDENTIFIER );
|
||||
}
|
||||
|
||||
public int getReceiveChannelNumber()
|
||||
{
|
||||
return mMessage.getInt( RECEIVE_NUMBER );
|
||||
}
|
||||
|
||||
public String getReceiveChannel()
|
||||
{
|
||||
return getReceiveChannelIdentifier() + "-" + getReceiveChannelNumber();
|
||||
}
|
||||
|
||||
public long getDownlinkFrequency()
|
||||
{
|
||||
return calculateDownlink( mTransmitIdentifierUpdate, getTransmitChannelNumber() );
|
||||
}
|
||||
|
||||
public long getUplinkFrequency()
|
||||
{
|
||||
return calculateUplink( mReceiveIdentifierUpdate, getReceiveChannelNumber() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setIdentifierMessage( int identifier, IBandIdentifier message )
|
||||
{
|
||||
if( identifier == getTransmitChannelIdentifier() )
|
||||
{
|
||||
mTransmitIdentifierUpdate = message;
|
||||
}
|
||||
|
||||
if( identifier == getReceiveChannelIdentifier() )
|
||||
{
|
||||
mReceiveIdentifierUpdate = message;
|
||||
}
|
||||
}
|
||||
|
||||
public int[] getIdentifiers()
|
||||
{
|
||||
int[] idens = new int[ 2 ];
|
||||
|
||||
idens[ 0 ] = getTransmitChannelIdentifier();
|
||||
idens[ 1 ] = getReceiveChannelIdentifier();
|
||||
|
||||
return idens;
|
||||
}
|
||||
}
|
||||
21
src/module/decode/p25/message/tdu/TDUMessage.java
Normal file
21
src/module/decode/p25/message/tdu/TDUMessage.java
Normal file
@@ -0,0 +1,21 @@
|
||||
package module.decode.p25.message.tdu;
|
||||
|
||||
import module.decode.p25.message.P25Message;
|
||||
import module.decode.p25.reference.DataUnitID;
|
||||
import alias.AliasList;
|
||||
import bits.BinaryMessage;
|
||||
import edac.CRC;
|
||||
|
||||
public class TDUMessage extends P25Message
|
||||
{
|
||||
public TDUMessage( BinaryMessage message, DataUnitID duid,
|
||||
AliasList aliasList )
|
||||
{
|
||||
super( message, duid, aliasList );
|
||||
|
||||
/* NID CRC is checked in the message framer, thus a constructed message
|
||||
* means it passed the CRC */
|
||||
mCRC = new CRC[ 1 ];
|
||||
mCRC[ 0 ] = CRC.PASSED;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,127 @@
|
||||
package module.decode.p25.message.tdu.lc;
|
||||
|
||||
import module.decode.p25.message.IBandIdentifier;
|
||||
import module.decode.p25.message.IdentifierReceiver;
|
||||
import module.decode.p25.message.tsbk.osp.control.SystemService;
|
||||
import module.decode.p25.reference.LinkControlOpcode;
|
||||
import module.decode.p25.reference.Service;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class AdjacentSiteStatusBroadcast extends TDULinkControlMessage
|
||||
implements IdentifierReceiver
|
||||
{
|
||||
private final static Logger mLog =
|
||||
LoggerFactory.getLogger( AdjacentSiteStatusBroadcast.class );
|
||||
|
||||
public static final int[] LRA = { 72,73,74,75,88,89,90,91 };
|
||||
public static final int[] SYSTEM_ID = { 96,97,98,99,112,113,114,115,
|
||||
116,117,118,119 };
|
||||
public static final int[] RFSS_ID = { 120,121,122,123,136,137,138,139 };
|
||||
public static final int[] SITE_ID = { 140,141,142,143,144,145,146,147 };
|
||||
public static final int[] IDENTIFIER = { 160,161,162,163 };
|
||||
public static final int[] CHANNEL = { 164,165,166,167,168,169,170,
|
||||
171,184,185,186,187 };
|
||||
public static final int[] SYSTEM_SERVICE_CLASS = { 188,189,190,191,192,193,
|
||||
194,195 };
|
||||
|
||||
private IBandIdentifier mIdentifierUpdate;
|
||||
|
||||
public AdjacentSiteStatusBroadcast( TDULinkControlMessage source )
|
||||
{
|
||||
super( source );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getEventType()
|
||||
{
|
||||
return LinkControlOpcode.ADJACENT_SITE_STATUS_BROADCAST.getDescription();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMessage()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append( getMessageStub() );
|
||||
|
||||
sb.append( " LRA:" + getLocationRegistrationArea() );
|
||||
|
||||
sb.append( " SYS:" + getSystemID() );
|
||||
|
||||
sb.append( " SITE:" + getRFSubsystemID() + "-" + getSiteID() );
|
||||
|
||||
sb.append( " CHAN:" + getChannel() );
|
||||
|
||||
sb.append( " " + Service.getServices( getSystemServiceClass() ).toString() );
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public String getLocationRegistrationArea()
|
||||
{
|
||||
return mMessage.getHex( LRA, 2 );
|
||||
}
|
||||
|
||||
public String getSystemID()
|
||||
{
|
||||
return mMessage.getHex( SYSTEM_ID, 3 );
|
||||
}
|
||||
|
||||
public String getRFSubsystemID()
|
||||
{
|
||||
return mMessage.getHex( RFSS_ID, 2 );
|
||||
}
|
||||
|
||||
public String getSiteID()
|
||||
{
|
||||
return mMessage.getHex( SITE_ID, 2 );
|
||||
}
|
||||
|
||||
public int getIdentifier()
|
||||
{
|
||||
return mMessage.getInt( IDENTIFIER );
|
||||
}
|
||||
|
||||
public String getChannel()
|
||||
{
|
||||
return getIdentifier() + "-" + getChannelNumber();
|
||||
}
|
||||
|
||||
public int getChannelNumber()
|
||||
{
|
||||
return mMessage.getInt( CHANNEL );
|
||||
}
|
||||
|
||||
public int getSystemServiceClass()
|
||||
{
|
||||
return mMessage.getInt( SYSTEM_SERVICE_CLASS );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setIdentifierMessage( int identifier, IBandIdentifier message )
|
||||
{
|
||||
mIdentifierUpdate = message;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] getIdentifiers()
|
||||
{
|
||||
int[] identifiers = new int[ 1 ];
|
||||
|
||||
identifiers[ 0 ] = getIdentifier();
|
||||
|
||||
return identifiers;
|
||||
}
|
||||
|
||||
public long getDownlinkFrequency()
|
||||
{
|
||||
return calculateDownlink( mIdentifierUpdate, getChannelNumber() );
|
||||
}
|
||||
|
||||
public long getUplinkFrequencyB()
|
||||
{
|
||||
return calculateUplink( mIdentifierUpdate, getChannelNumber() );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
package module.decode.p25.message.tdu.lc;
|
||||
|
||||
import module.decode.p25.message.tsbk.osp.control.SystemService;
|
||||
import module.decode.p25.reference.LinkControlOpcode;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class AdjacentSiteStatusBroadcastExplicit extends TDULinkControlMessage
|
||||
{
|
||||
private final static Logger mLog =
|
||||
LoggerFactory.getLogger( AdjacentSiteStatusBroadcastExplicit.class );
|
||||
|
||||
public static final int[] LRA = { 72,73,74,75,88,89,90,91 };
|
||||
public static final int[] TRANSMIT_IDENTIFIER = { 92,93,94,95 };
|
||||
public static final int[] TRANSMIT_CHANNEL = { 96,97,98,99,112,113,114,115,
|
||||
116,117,118,119 };
|
||||
public static final int[] RFSS_ID = { 120,121,122,123,136,137,138,139 };
|
||||
public static final int[] SITE_ID = { 140,141,142,143,144,145,146,147 };
|
||||
|
||||
public static final int[] RECEIVE_IDENTIFIER = { 160,161,162,163 };
|
||||
public static final int[] RECEIVE_CHANNEL = { 164,165,166,167,168,169,170,
|
||||
171,184,185,186,187 };
|
||||
|
||||
public AdjacentSiteStatusBroadcastExplicit( TDULinkControlMessage source )
|
||||
{
|
||||
super( source );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getEventType()
|
||||
{
|
||||
return LinkControlOpcode.ADJACENT_SITE_STATUS_BROADCAST_EXPLICIT.getDescription();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMessage()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append( getMessageStub() );
|
||||
|
||||
sb.append( " LRA:" + getLocationRegistrationArea() );
|
||||
|
||||
sb.append( " SITE:" + getRFSubsystemID() + "-" + getSiteID() );
|
||||
|
||||
sb.append( " DNLINK:" + getTransmitChannelNumber() );
|
||||
|
||||
sb.append( " UPLINK:" + getReceiveChannelNumber() );
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public String getLocationRegistrationArea()
|
||||
{
|
||||
return mMessage.getHex( LRA, 2 );
|
||||
}
|
||||
|
||||
public String getRFSubsystemID()
|
||||
{
|
||||
return mMessage.getHex( RFSS_ID, 2 );
|
||||
}
|
||||
|
||||
public String getSiteID()
|
||||
{
|
||||
return mMessage.getHex( SITE_ID, 2 );
|
||||
}
|
||||
|
||||
public int getTransmitIdentifier()
|
||||
{
|
||||
return mMessage.getInt( TRANSMIT_IDENTIFIER );
|
||||
}
|
||||
|
||||
public int getTransmitChannel()
|
||||
{
|
||||
return mMessage.getInt( TRANSMIT_CHANNEL );
|
||||
}
|
||||
|
||||
public String getTransmitChannelNumber()
|
||||
{
|
||||
return getTransmitIdentifier() + "-" + getTransmitChannel();
|
||||
}
|
||||
|
||||
public int getReceiveIdentifier()
|
||||
{
|
||||
return mMessage.getInt( RECEIVE_IDENTIFIER );
|
||||
}
|
||||
|
||||
public int getReceiveChannel()
|
||||
{
|
||||
return mMessage.getInt( RECEIVE_CHANNEL );
|
||||
}
|
||||
|
||||
public String getReceiveChannelNumber()
|
||||
{
|
||||
return getReceiveIdentifier() + "-" + getReceiveChannel();
|
||||
}
|
||||
}
|
||||
49
src/module/decode/p25/message/tdu/lc/CallAlert.java
Normal file
49
src/module/decode/p25/message/tdu/lc/CallAlert.java
Normal file
@@ -0,0 +1,49 @@
|
||||
package module.decode.p25.message.tdu.lc;
|
||||
|
||||
import module.decode.p25.reference.LinkControlOpcode;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class CallAlert extends TDULinkControlMessage
|
||||
{
|
||||
private final static Logger mLog =
|
||||
LoggerFactory.getLogger( CallAlert.class );
|
||||
public static final int[] TARGET_ADDRESS = { 112,113,114,115,116,117,118,
|
||||
119,120,121,122,123,136,137,138,139,140,141,142,143,144,145,146,147 };
|
||||
public static final int[] SOURCE_ADDRESS = { 160,161,162,163,164,165,166,
|
||||
167,168,169,170,171,184,185,186,187,188,189,190,190,192,193,194,195 };
|
||||
|
||||
public CallAlert( TDULinkControlMessage source )
|
||||
{
|
||||
super( source );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getEventType()
|
||||
{
|
||||
return LinkControlOpcode.CALL_ALERT.getDescription();
|
||||
}
|
||||
|
||||
public String getMessage()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append( getMessageStub() );
|
||||
|
||||
sb.append( " SRC ADDR: " + getSourceAddress() );
|
||||
sb.append( " TGT ADDR: " + getTargetAddress() );
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public String getTargetAddress()
|
||||
{
|
||||
return mMessage.getHex( TARGET_ADDRESS, 6 );
|
||||
}
|
||||
|
||||
public String getSourceAddress()
|
||||
{
|
||||
return mMessage.getHex( SOURCE_ADDRESS, 6 );
|
||||
}
|
||||
}
|
||||
42
src/module/decode/p25/message/tdu/lc/CallTermination.java
Normal file
42
src/module/decode/p25/message/tdu/lc/CallTermination.java
Normal file
@@ -0,0 +1,42 @@
|
||||
package module.decode.p25.message.tdu.lc;
|
||||
|
||||
import module.decode.p25.reference.LinkControlOpcode;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class CallTermination extends TDULinkControlMessage
|
||||
{
|
||||
private final static Logger mLog = LoggerFactory.getLogger( CallTermination.class );
|
||||
|
||||
public static final int[] SOURCE_ADDRESS = { 160,161,162,163,164,165,166,
|
||||
167,168,169,170,171,184,185,186,187,188,189,190,191,192,193,194,195 };
|
||||
|
||||
public CallTermination( TDULinkControlMessage source )
|
||||
{
|
||||
super( source );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getEventType()
|
||||
{
|
||||
return LinkControlOpcode.CALL_TERMINATION_OR_CANCELLATION.getDescription();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMessage()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append( getMessageStub() );
|
||||
|
||||
sb.append( " BY:" + getSourceAddress() );
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public String getSourceAddress()
|
||||
{
|
||||
return mMessage.getHex( SOURCE_ADDRESS, 6 );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
package module.decode.p25.message.tdu.lc;
|
||||
|
||||
import module.decode.p25.message.IBandIdentifier;
|
||||
import module.decode.p25.reference.LinkControlOpcode;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class ChannelIdentifierUpdate extends TDULinkControlMessage
|
||||
implements IBandIdentifier
|
||||
{
|
||||
private final static Logger mLog =
|
||||
LoggerFactory.getLogger( ChannelIdentifierUpdate.class );
|
||||
|
||||
public static final int[] IDENTIFIER = { 72,73,74,75 };
|
||||
public static final int[] BANDWIDTH = { 88,89,90,91,92,93,94,95,96 };
|
||||
public static final int[] TRANSMIT_OFFSET = { 97,98,99,112,113,114,115,116,
|
||||
117 };
|
||||
public static final int[] CHANNEL_SPACING = { 118,119,120,121,122,123,136,
|
||||
137,138,139 };
|
||||
public static final int[] BASE_FREQUENCY = { 140,141,142,143,144,145,146,
|
||||
147,160,161,162,163,164,165,166,167,168,169,170,171,184,185,186,
|
||||
187,188,189,190,191,192,193,194,195 };
|
||||
|
||||
public ChannelIdentifierUpdate( TDULinkControlMessage source )
|
||||
{
|
||||
super( source );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getEventType()
|
||||
{
|
||||
return LinkControlOpcode.CHANNEL_IDENTIFIER_UPDATE.getDescription();
|
||||
}
|
||||
|
||||
@Override
|
||||
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();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getIdentifier()
|
||||
{
|
||||
return mMessage.getInt( IDENTIFIER );
|
||||
}
|
||||
|
||||
/**
|
||||
* Channel bandwidth in hertz
|
||||
*/
|
||||
@Override
|
||||
public int getBandwidth()
|
||||
{
|
||||
return mMessage.getInt( BANDWIDTH ) * 125;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getChannelSpacing()
|
||||
{
|
||||
return mMessage.getLong( CHANNEL_SPACING ) * 125l;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getBaseFrequency()
|
||||
{
|
||||
return mMessage.getLong( BASE_FREQUENCY ) * 5l;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getTransmitOffset()
|
||||
{
|
||||
return -1 * mMessage.getLong( TRANSMIT_OFFSET ) * 250000l;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
package module.decode.p25.message.tdu.lc;
|
||||
|
||||
import module.decode.p25.message.IBandIdentifier;
|
||||
import module.decode.p25.reference.LinkControlOpcode;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class ChannelIdentifierUpdateExplicit extends TDULinkControlMessage
|
||||
implements IBandIdentifier
|
||||
{
|
||||
private final static Logger mLog =
|
||||
LoggerFactory.getLogger( ChannelIdentifierUpdateExplicit.class );
|
||||
|
||||
public static final int[] IDENTIFIER = { 72,73,74,75 };
|
||||
public static final int[] BANDWIDTH = { 88,89,90,91 };
|
||||
public static final int[] TRANSMIT_OFFSET = { 92,93,94,95,96,97,98,99,112,
|
||||
113,114,115,116,117 };
|
||||
public static final int[] CHANNEL_SPACING = { 118,119,120,121,122,
|
||||
123,136,137,138,139 };
|
||||
public static final int[] BASE_FREQUENCY = { 140,141,142,143,144,145,146,
|
||||
147,160,161,162,163,164,165,166,167,168,169,170,171,184,185,186,
|
||||
187,188,189,190,191,192,193,194,195 };
|
||||
|
||||
public ChannelIdentifierUpdateExplicit( TDULinkControlMessage source )
|
||||
{
|
||||
super( source );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getEventType()
|
||||
{
|
||||
return LinkControlOpcode.CHANNEL_IDENTIFIER_UPDATE_EXPLICIT.getDescription();
|
||||
}
|
||||
|
||||
@Override
|
||||
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();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getIdentifier()
|
||||
{
|
||||
return mMessage.getInt( IDENTIFIER );
|
||||
}
|
||||
|
||||
/**
|
||||
* Channel bandwidth in hertz
|
||||
*/
|
||||
@Override
|
||||
public int getBandwidth()
|
||||
{
|
||||
return mMessage.getInt( BANDWIDTH ) * 125;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getChannelSpacing()
|
||||
{
|
||||
return mMessage.getLong( CHANNEL_SPACING ) * 125l;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getBaseFrequency()
|
||||
{
|
||||
return mMessage.getLong( BASE_FREQUENCY ) * 5l;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getTransmitOffset()
|
||||
{
|
||||
return -1 * mMessage.getLong( TRANSMIT_OFFSET ) * 250000l;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
package module.decode.p25.message.tdu.lc;
|
||||
|
||||
import module.decode.p25.reference.ExtendedFunction;
|
||||
import module.decode.p25.reference.LinkControlOpcode;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class ExtendedFunctionCommand extends TDULinkControlMessage
|
||||
{
|
||||
private final static Logger mLog =
|
||||
LoggerFactory.getLogger( ExtendedFunctionCommand.class );
|
||||
public static final int[] EXTENDED_FUNCTION = { 72,73,74,75,88,89,90,91,92,
|
||||
93,94,95,96,97,98,99 };
|
||||
public static final int[] ARGUMENT = { 112,113,114,115,116,117,118,119,120,
|
||||
121,122,123,136,137,138,139,140,141,142,143,144,145,145,147 };
|
||||
public static final int[] TARGET_ADDRESS = { 160,161,162,163,164,165,166,
|
||||
167,168,169,170,171,184,185,186,187,188,189,190,190,192,193,194,195 };
|
||||
|
||||
public ExtendedFunctionCommand( TDULinkControlMessage source )
|
||||
{
|
||||
super( source );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getEventType()
|
||||
{
|
||||
return LinkControlOpcode.EXTENDED_FUNCTION_COMMAND.getDescription();
|
||||
}
|
||||
|
||||
public String getMessage()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append( getMessageStub() );
|
||||
|
||||
sb.append( " EXTENDED FUNCTION:" + getExtendedFunction().getLabel() );
|
||||
|
||||
sb.append( " ARGUMENT: " + getTargetAddress() );
|
||||
|
||||
sb.append( " TGT ADDR: " + getTargetAddress() );
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public ExtendedFunction getExtendedFunction()
|
||||
{
|
||||
return ExtendedFunction.fromValue( mMessage.getInt( EXTENDED_FUNCTION ) );
|
||||
}
|
||||
|
||||
public String getArgument()
|
||||
{
|
||||
return mMessage.getHex( ARGUMENT, 6 );
|
||||
}
|
||||
|
||||
public String getSourceAddress()
|
||||
{
|
||||
switch( getExtendedFunction() )
|
||||
{
|
||||
case RADIO_CHECK:
|
||||
case RADIO_CHECK_ACK:
|
||||
case RADIO_DETACH:
|
||||
case RADIO_DETACH_ACK:
|
||||
case RADIO_INHIBIT:
|
||||
case RADIO_INHIBIT_ACK:
|
||||
case RADIO_UNINHIBIT:
|
||||
case RADIO_UNINHIBIT_ACK:
|
||||
return getArgument();
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public String getTargetAddress()
|
||||
{
|
||||
return mMessage.getHex( TARGET_ADDRESS, 6 );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getToID()
|
||||
{
|
||||
return getTargetAddress();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
package module.decode.p25.message.tdu.lc;
|
||||
|
||||
import module.decode.p25.reference.LinkControlOpcode;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class GroupAffiliationQuery extends TDULinkControlMessage
|
||||
{
|
||||
private final static Logger mLog =
|
||||
LoggerFactory.getLogger( GroupAffiliationQuery.class );
|
||||
public static final int[] TARGET_ADDRESS = { 112,113,114,115,116,117,118,
|
||||
119,120,121,122,123,136,137,138,139,140,141,142,143,144,145,146,147 };
|
||||
public static final int[] SOURCE_ADDRESS = { 160,161,162,163,164,165,166,
|
||||
167,168,169,170,171,184,185,186,187,188,189,190,191,192,193,194,195 };
|
||||
|
||||
public GroupAffiliationQuery( TDULinkControlMessage source )
|
||||
{
|
||||
super( source );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getEventType()
|
||||
{
|
||||
return LinkControlOpcode.GROUP_AFFILIATION_QUERY.getDescription();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMessage()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append( getMessageStub() );
|
||||
|
||||
sb.append( " FROM:" + getSourceAddress() );
|
||||
|
||||
sb.append( " TO:" + getTargetAddress() );
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public String getTargetAddress()
|
||||
{
|
||||
return mMessage.getHex( TARGET_ADDRESS, 6 );
|
||||
}
|
||||
|
||||
public String getSourceAddress()
|
||||
{
|
||||
return mMessage.getHex( SOURCE_ADDRESS, 6 );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,176 @@
|
||||
package module.decode.p25.message.tdu.lc;
|
||||
|
||||
import java.util.Set;
|
||||
import java.util.TreeSet;
|
||||
|
||||
import module.decode.p25.message.IBandIdentifier;
|
||||
import module.decode.p25.message.IdentifierReceiver;
|
||||
import module.decode.p25.reference.LinkControlOpcode;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class GroupVoiceChannelUpdate extends TDULinkControlMessage
|
||||
implements IdentifierReceiver
|
||||
{
|
||||
private final static Logger mLog =
|
||||
LoggerFactory.getLogger( GroupVoiceChannelUpdate.class );
|
||||
|
||||
public static final int[] IDENTIFIER_A = { 72,73,74,75 };
|
||||
public static final int[] CHANNEL_A = { 88,89,90,91,92,93,94,95,96,97,98,99 };
|
||||
public static final int[] GROUP_ADDRESS_A = { 112,113,114,115,116,117,118,
|
||||
119,120,121,122,123,136,137,138,139 };
|
||||
public static final int[] IDENTIFIER_B = { 140,141,142,143 };
|
||||
public static final int[] CHANNEL_B = { 144,145,146,147,160,161,162,163,164,
|
||||
165,166,167 };
|
||||
public static final int[] GROUP_ADDRESS_B = { 168,169,170,171,184,185,186,
|
||||
187,188,189,190,191,192,193,194,195 };
|
||||
|
||||
private IBandIdentifier mIdentifierUpdateA;
|
||||
private IBandIdentifier mIdentifierUpdateB;
|
||||
|
||||
public GroupVoiceChannelUpdate( TDULinkControlMessage source )
|
||||
{
|
||||
super( source );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getEventType()
|
||||
{
|
||||
return LinkControlOpcode.GROUP_VOICE_CHANNEL_UPDATE.getDescription();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMessage()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append( getMessageStub() );
|
||||
|
||||
sb.append( " CHAN A:" + getChannelA() );
|
||||
|
||||
sb.append( " GRP A:" + getGroupAddressA() );
|
||||
|
||||
if( hasChannelB() )
|
||||
{
|
||||
sb.append( " CHAN B:" + getChannelA() );
|
||||
|
||||
sb.append( " GRP B:" + getGroupAddressA() );
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public int getChannelIdentifierA()
|
||||
{
|
||||
return mMessage.getInt( IDENTIFIER_A );
|
||||
}
|
||||
|
||||
public int getChannelNumberA()
|
||||
{
|
||||
return mMessage.getInt( CHANNEL_A );
|
||||
}
|
||||
|
||||
public String getChannelA()
|
||||
{
|
||||
return getChannelIdentifierA() + "-" + getChannelNumberA();
|
||||
}
|
||||
|
||||
public int getChannelIdentifierB()
|
||||
{
|
||||
return mMessage.getInt( IDENTIFIER_B );
|
||||
}
|
||||
|
||||
public int getChannelNumberB()
|
||||
{
|
||||
return mMessage.getInt( CHANNEL_B );
|
||||
}
|
||||
|
||||
public String getChannelB()
|
||||
{
|
||||
return getChannelIdentifierB() + "-" + getChannelNumberB();
|
||||
}
|
||||
|
||||
public boolean hasChannelB()
|
||||
{
|
||||
return getChannelNumberB() != 0;
|
||||
}
|
||||
|
||||
public String getGroupAddressA()
|
||||
{
|
||||
return mMessage.getHex( GROUP_ADDRESS_A, 4 );
|
||||
}
|
||||
|
||||
public String getGroupAddressB()
|
||||
{
|
||||
return mMessage.getHex( GROUP_ADDRESS_B, 4 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a sorted list of addresses contained in the A and B fields
|
||||
* @return
|
||||
*/
|
||||
public Set<String> getAddresses()
|
||||
{
|
||||
Set<String> addresses = new TreeSet<String>();
|
||||
|
||||
addresses.add( getGroupAddressA() );
|
||||
addresses.add( getGroupAddressB() );
|
||||
|
||||
return addresses;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void setIdentifierMessage( int identifier, IBandIdentifier message )
|
||||
{
|
||||
if( identifier == getChannelIdentifierA() )
|
||||
{
|
||||
mIdentifierUpdateA = message;
|
||||
}
|
||||
if( identifier == getChannelIdentifierB() )
|
||||
{
|
||||
mIdentifierUpdateB = message;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] getIdentifiers()
|
||||
{
|
||||
if( hasChannelB() )
|
||||
{
|
||||
int[] identifiers = new int[ 2 ];
|
||||
identifiers[ 0 ] = getChannelIdentifierA();
|
||||
identifiers[ 1 ] = getChannelIdentifierB();
|
||||
|
||||
return identifiers;
|
||||
}
|
||||
else
|
||||
{
|
||||
int[] identifiers = new int[ 1 ];
|
||||
identifiers[ 0 ] = getChannelIdentifierA();
|
||||
|
||||
return identifiers;
|
||||
}
|
||||
}
|
||||
|
||||
public long getDownlinkFrequencyA()
|
||||
{
|
||||
return calculateDownlink( mIdentifierUpdateA, getChannelNumberA() );
|
||||
}
|
||||
|
||||
public long getUplinkFrequencyA()
|
||||
{
|
||||
return calculateUplink( mIdentifierUpdateA, getChannelNumberA() );
|
||||
}
|
||||
|
||||
public long getDownlinkFrequencyB()
|
||||
{
|
||||
return calculateDownlink( mIdentifierUpdateB, getChannelNumberA() );
|
||||
}
|
||||
|
||||
public long getUplinkFrequencyB()
|
||||
{
|
||||
return calculateUplink( mIdentifierUpdateB, getChannelNumberA() );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,156 @@
|
||||
package module.decode.p25.message.tdu.lc;
|
||||
|
||||
import module.decode.p25.message.IBandIdentifier;
|
||||
import module.decode.p25.message.IdentifierReceiver;
|
||||
import module.decode.p25.message.P25Message.DuplexMode;
|
||||
import module.decode.p25.message.P25Message.SessionMode;
|
||||
import module.decode.p25.reference.LinkControlOpcode;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class GroupVoiceChannelUpdateExplicit extends TDULinkControlMessage
|
||||
implements IdentifierReceiver
|
||||
{
|
||||
private final static Logger mLog =
|
||||
LoggerFactory.getLogger( GroupVoiceChannelUpdateExplicit.class );
|
||||
|
||||
public static final int EMERGENCY_FLAG = 92;
|
||||
public static final int ENCRYPTED_CHANNEL_FLAG = 93;
|
||||
public static final int DUPLEX_MODE = 94;
|
||||
public static final int SESSION_MODE = 95;
|
||||
public static final int[] GROUP_ADDRESS = { 112,113,114,115,116,117,118,
|
||||
119,120,121,122,123,136,137,138,139 };
|
||||
public static final int[] TRANSMIT_IDENTIFIER = { 140,141,142,143 };
|
||||
public static final int[] TRANSMIT_CHANNEL = { 144,145,146,147,160,161,162,
|
||||
163,164,165,166,167 };
|
||||
public static final int[] RECEIVE_IDENTIFIER = { 168,169,170,171 };
|
||||
public static final int[] RECEIVE_CHANNEL = { 184,185,186,187,188,189,190,
|
||||
191,192,193,194,195,196,197,198,199 };
|
||||
|
||||
private IBandIdentifier mTransmitIdentifierUpdate;
|
||||
private IBandIdentifier mReceiveIdentifierUpdate;
|
||||
|
||||
public GroupVoiceChannelUpdateExplicit( TDULinkControlMessage source )
|
||||
{
|
||||
super( source );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getEventType()
|
||||
{
|
||||
return LinkControlOpcode.GROUP_VOICE_CHANNEL_UPDATE_EXPLICIT.getDescription();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMessage()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append( getMessageStub() );
|
||||
|
||||
if( isEmergency() )
|
||||
{
|
||||
sb.append( " EMERGENCY" );
|
||||
}
|
||||
if( isEncryptedChannel() )
|
||||
{
|
||||
sb.append( " ENCRYPTED CHANNEL" );
|
||||
}
|
||||
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
public int getTransmitChannelIdentifier()
|
||||
{
|
||||
return mMessage.getInt( TRANSMIT_IDENTIFIER );
|
||||
}
|
||||
|
||||
public int getTransmitChannelNumber()
|
||||
{
|
||||
return mMessage.getInt( TRANSMIT_CHANNEL );
|
||||
}
|
||||
|
||||
public String getTransmitChannel()
|
||||
{
|
||||
return getTransmitChannelIdentifier() + "-" + getTransmitChannelNumber();
|
||||
}
|
||||
|
||||
public int getReceiveChannelIdentifier()
|
||||
{
|
||||
return mMessage.getInt( RECEIVE_IDENTIFIER );
|
||||
}
|
||||
|
||||
public int getReceiveChannelNumber()
|
||||
{
|
||||
return mMessage.getInt( RECEIVE_CHANNEL );
|
||||
}
|
||||
|
||||
public String getReceiveChannel()
|
||||
{
|
||||
return getReceiveChannelIdentifier() + "-" + getReceiveChannelNumber();
|
||||
}
|
||||
|
||||
public String getGroupAddress()
|
||||
{
|
||||
return mMessage.getHex( GROUP_ADDRESS, 4 );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setIdentifierMessage( int identifier, IBandIdentifier message )
|
||||
{
|
||||
if( identifier == getTransmitChannelIdentifier() )
|
||||
{
|
||||
mTransmitIdentifierUpdate = message;
|
||||
}
|
||||
if( identifier == getReceiveChannelIdentifier() )
|
||||
{
|
||||
mReceiveIdentifierUpdate = message;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] getIdentifiers()
|
||||
{
|
||||
int[] identifiers = new int[ 2 ];
|
||||
|
||||
identifiers[ 0 ] = getTransmitChannelIdentifier();
|
||||
identifiers[ 1 ] = getReceiveChannelIdentifier();
|
||||
|
||||
return identifiers;
|
||||
}
|
||||
|
||||
public long getDownlinkFrequency()
|
||||
{
|
||||
return calculateDownlink( mTransmitIdentifierUpdate,
|
||||
getTransmitChannelNumber() );
|
||||
}
|
||||
|
||||
public long getUplinkFrequency()
|
||||
{
|
||||
return calculateUplink( mReceiveIdentifierUpdate,
|
||||
getReceiveChannelNumber() );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
package module.decode.p25.message.tdu.lc;
|
||||
|
||||
import module.decode.p25.reference.LinkControlOpcode;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class GroupVoiceChannelUser extends TDULinkControlMessage
|
||||
{
|
||||
private final static Logger mLog =
|
||||
LoggerFactory.getLogger( GroupVoiceChannelUser.class );
|
||||
/* Service Options */
|
||||
public static final int EMERGENCY_FLAG = 92;
|
||||
public static final int ENCRYPTED_CHANNEL_FLAG = 93;
|
||||
public static final int DUPLEX_MODE = 94;
|
||||
public static final int SESSION_MODE = 95;
|
||||
public static final int[] GROUP_ADDRESS = { 120,121,122,123,136,137,138,139,
|
||||
140,141,142,143,144,145,146,147 };
|
||||
public static final int[] SOURCE_ADDRESS = { 160,161,162,163,164,165,166,
|
||||
167,168,169,170,171,184,185,186,187,188,189,190,191,192,193,194,195 };
|
||||
|
||||
public GroupVoiceChannelUser( TDULinkControlMessage source )
|
||||
{
|
||||
super( source );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getEventType()
|
||||
{
|
||||
return LinkControlOpcode.GROUP_VOICE_CHANNEL_USER.getDescription();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMessage()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append( getMessageStub() );
|
||||
|
||||
if( isEmergency() )
|
||||
{
|
||||
sb.append( " EMERGENCY" );
|
||||
}
|
||||
if( isEncryptedChannel() )
|
||||
{
|
||||
sb.append( " ENCRYPTED CHANNEL" );
|
||||
}
|
||||
|
||||
sb.append( " FROM:" + getSourceAddress() );
|
||||
|
||||
sb.append( " TO:" + getGroupAddress() );
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
public String getGroupAddress()
|
||||
{
|
||||
return mMessage.getHex( GROUP_ADDRESS, 4 );
|
||||
}
|
||||
|
||||
public String getSourceAddress()
|
||||
{
|
||||
return mMessage.getHex( SOURCE_ADDRESS, 6 );
|
||||
}
|
||||
}
|
||||
57
src/module/decode/p25/message/tdu/lc/MessageUpdate.java
Normal file
57
src/module/decode/p25/message/tdu/lc/MessageUpdate.java
Normal file
@@ -0,0 +1,57 @@
|
||||
package module.decode.p25.message.tdu.lc;
|
||||
|
||||
import module.decode.p25.reference.LinkControlOpcode;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class MessageUpdate extends TDULinkControlMessage
|
||||
{
|
||||
private final static Logger mLog =
|
||||
LoggerFactory.getLogger( MessageUpdate.class );
|
||||
public static final int[] SHORT_DATA_MESSAGE = { 72,73,74,75,88,89,90,91,92,
|
||||
93,94,95,96,97,98,99 };
|
||||
public static final int[] TARGET_ADDRESS = { 112,113,114,115,116,117,118,
|
||||
119,120,121,122,123,136,137,138,139,140,141,142,143,144,145,146,147 };
|
||||
public static final int[] SOURCE_ADDRESS = { 160,161,162,163,164,165,166,
|
||||
167,168,169,170,171,184,185,186,187,188,189,190,190,192,193,194,195 };
|
||||
|
||||
public MessageUpdate( TDULinkControlMessage source )
|
||||
{
|
||||
super( source );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getEventType()
|
||||
{
|
||||
return LinkControlOpcode.MESSAGE_UPDATE.getDescription();
|
||||
}
|
||||
|
||||
public String getMessage()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append( getMessageStub() );
|
||||
|
||||
sb.append( " MSG:" + getShortDataMessage() );
|
||||
sb.append( " SRC ADDR: " + getSourceAddress() );
|
||||
sb.append( " TGT ADDR: " + getTargetAddress() );
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public String getShortDataMessage()
|
||||
{
|
||||
return mMessage.getHex( SHORT_DATA_MESSAGE, 4 );
|
||||
}
|
||||
|
||||
public String getTargetAddress()
|
||||
{
|
||||
return mMessage.getHex( TARGET_ADDRESS, 6 );
|
||||
}
|
||||
|
||||
public String getSourceAddress()
|
||||
{
|
||||
return mMessage.getHex( SOURCE_ADDRESS, 6 );
|
||||
}
|
||||
}
|
||||
110
src/module/decode/p25/message/tdu/lc/NetworkStatusBroadcast.java
Normal file
110
src/module/decode/p25/message/tdu/lc/NetworkStatusBroadcast.java
Normal file
@@ -0,0 +1,110 @@
|
||||
package module.decode.p25.message.tdu.lc;
|
||||
|
||||
import module.decode.p25.message.IBandIdentifier;
|
||||
import module.decode.p25.message.IdentifierReceiver;
|
||||
import module.decode.p25.reference.LinkControlOpcode;
|
||||
import module.decode.p25.reference.Service;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class NetworkStatusBroadcast extends TDULinkControlMessage
|
||||
implements IdentifierReceiver
|
||||
{
|
||||
private final static Logger mLog =
|
||||
LoggerFactory.getLogger( NetworkStatusBroadcast.class );
|
||||
|
||||
public static final int[] WACN = { 72,73,74,75,88,89,90,91,92,93,94,95,96,
|
||||
97,98,99,112,113,114,115,116,117,118,119,120,121,122,123 };
|
||||
public static final int[] SYSTEM = { 136,137,138,139,140,141,142,143,144,
|
||||
145,146,147 };
|
||||
public static final int[] IDENTIFIER = { 160,161,162,163 };
|
||||
public static final int[] CHANNEL = { 164,165,166,167,168,169,170,171,184,
|
||||
185,186,187 };
|
||||
public static final int[] SYSTEM_SERVICE_CLASS = { 188,189,190,191,192,193,
|
||||
194,195 };
|
||||
|
||||
private IBandIdentifier mIdentifierUpdate;
|
||||
|
||||
public NetworkStatusBroadcast( TDULinkControlMessage source )
|
||||
{
|
||||
super( source );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getEventType()
|
||||
{
|
||||
return LinkControlOpcode.NETWORK_STATUS_BROADCAST.getDescription();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMessage()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append( getMessageStub() );
|
||||
|
||||
sb.append( " NETWORK:" + getWACN() );
|
||||
sb.append( " SYS:" + getSystem() );
|
||||
sb.append( " CHAN:" + getChannel() );
|
||||
sb.append( " " + Service.getServices( getSystemServiceClass() ).toString() );
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public String getWACN()
|
||||
{
|
||||
return mMessage.getHex( WACN, 5 );
|
||||
}
|
||||
|
||||
public String getSystem()
|
||||
{
|
||||
return mMessage.getHex( SYSTEM, 3 );
|
||||
}
|
||||
|
||||
public int getIdentifier()
|
||||
{
|
||||
return mMessage.getInt( IDENTIFIER );
|
||||
}
|
||||
|
||||
public int getChannelNumber()
|
||||
{
|
||||
return mMessage.getInt( CHANNEL );
|
||||
}
|
||||
|
||||
public String getChannel()
|
||||
{
|
||||
return getIdentifier() + "-" + getChannelNumber();
|
||||
}
|
||||
|
||||
public int getSystemServiceClass()
|
||||
{
|
||||
return mMessage.getInt( SYSTEM_SERVICE_CLASS );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setIdentifierMessage( int identifier, IBandIdentifier message )
|
||||
{
|
||||
mIdentifierUpdate = message;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] getIdentifiers()
|
||||
{
|
||||
int[] identifiers = new int[ 1 ];
|
||||
|
||||
identifiers[ 0 ] = getIdentifier();
|
||||
|
||||
return identifiers;
|
||||
}
|
||||
|
||||
public long getDownlinkFrequency()
|
||||
{
|
||||
return calculateDownlink( mIdentifierUpdate, getChannelNumber() );
|
||||
}
|
||||
|
||||
public long getUplinkFrequency()
|
||||
{
|
||||
return calculateUplink( mIdentifierUpdate, getChannelNumber() );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,132 @@
|
||||
package module.decode.p25.message.tdu.lc;
|
||||
|
||||
import module.decode.p25.message.IBandIdentifier;
|
||||
import module.decode.p25.message.IdentifierReceiver;
|
||||
import module.decode.p25.reference.LinkControlOpcode;
|
||||
import module.decode.p25.reference.Service;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class NetworkStatusBroadcastExplicit extends TDULinkControlMessage
|
||||
implements IdentifierReceiver
|
||||
{
|
||||
private final static Logger mLog =
|
||||
LoggerFactory.getLogger( NetworkStatusBroadcastExplicit.class );
|
||||
|
||||
public static final int[] WACN = { 72,73,74,75,88,89,90,91,92,93,94,95,96,
|
||||
97,98,99,112,113,114,115 };
|
||||
public static final int[] SYSTEM = { 116,117,118,119,120,121,122,123,136,
|
||||
137,138,139 };
|
||||
public static final int[] TRANSMIT_IDENTIFIER = { 140,141,142,143 };
|
||||
public static final int[] TRANSMIT_CHANNEL = { 144,145,146,147,160,161,162,
|
||||
163,164,165,166,167 };
|
||||
public static final int[] RECEIVE_IDENTIFIER = { 168,169,170,171 };
|
||||
public static final int[] RECEIVE_CHANNEL = { 184,185,186,187,188,189,190,
|
||||
191,192,193,194,195 };
|
||||
|
||||
private IBandIdentifier mTransmitIdentifierUpdate;
|
||||
private IBandIdentifier mReceiveIdentifierUpdate;
|
||||
|
||||
public NetworkStatusBroadcastExplicit( TDULinkControlMessage source )
|
||||
{
|
||||
super( source );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getEventType()
|
||||
{
|
||||
return LinkControlOpcode.NETWORK_STATUS_BROADCAST_EXPLICIT.getDescription();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMessage()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append( getMessageStub() );
|
||||
|
||||
sb.append( " NETWORK:" + getWACN() );
|
||||
sb.append( " SYS:" + getSystem() );
|
||||
sb.append( " TRANSMIT:" + getTransmitChannel() );
|
||||
sb.append( " RECEIVE:" + getReceiveChannel() );
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public String getWACN()
|
||||
{
|
||||
return mMessage.getHex( WACN, 5 );
|
||||
}
|
||||
|
||||
public String getSystem()
|
||||
{
|
||||
return mMessage.getHex( SYSTEM, 3 );
|
||||
}
|
||||
|
||||
public int getTransmitIdentifier()
|
||||
{
|
||||
return mMessage.getInt( TRANSMIT_IDENTIFIER );
|
||||
}
|
||||
|
||||
public int getTransmitChannelNumber()
|
||||
{
|
||||
return mMessage.getInt( TRANSMIT_CHANNEL );
|
||||
}
|
||||
|
||||
public String getTransmitChannel()
|
||||
{
|
||||
return getTransmitIdentifier() + "-" + getTransmitChannelNumber();
|
||||
}
|
||||
|
||||
public int getReceiveIdentifier()
|
||||
{
|
||||
return mMessage.getInt( RECEIVE_IDENTIFIER );
|
||||
}
|
||||
|
||||
public int getReceiveChannelNumber()
|
||||
{
|
||||
return mMessage.getInt( RECEIVE_CHANNEL );
|
||||
}
|
||||
|
||||
public String getReceiveChannel()
|
||||
{
|
||||
return getReceiveIdentifier() + "-" + getReceiveChannelNumber();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setIdentifierMessage( int identifier, IBandIdentifier message )
|
||||
{
|
||||
if( identifier == getTransmitIdentifier() )
|
||||
{
|
||||
mTransmitIdentifierUpdate = message;
|
||||
}
|
||||
if( identifier == getReceiveIdentifier() )
|
||||
{
|
||||
mReceiveIdentifierUpdate = message;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] getIdentifiers()
|
||||
{
|
||||
int[] identifiers = new int[ 2 ];
|
||||
|
||||
identifiers[ 0 ] = getTransmitIdentifier();
|
||||
identifiers[ 1 ] = getReceiveIdentifier();
|
||||
|
||||
return identifiers;
|
||||
}
|
||||
|
||||
public long getDownlinkFrequency()
|
||||
{
|
||||
return calculateDownlink( mTransmitIdentifierUpdate,
|
||||
getTransmitChannelNumber() );
|
||||
}
|
||||
|
||||
public long getUplinkFrequency()
|
||||
{
|
||||
return calculateUplink( mReceiveIdentifierUpdate,
|
||||
getReceiveChannelNumber() );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
package module.decode.p25.message.tdu.lc;
|
||||
|
||||
import module.decode.p25.reference.Encryption;
|
||||
import module.decode.p25.reference.LinkControlOpcode;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class ProtectionParameterBroadcast extends TDULinkControlMessage
|
||||
{
|
||||
private final static Logger mLog =
|
||||
LoggerFactory.getLogger( ProtectionParameterBroadcast.class );
|
||||
|
||||
public final static int[] ALGORITHM_ID = { 112,113,114,115,116,117,118,119 };
|
||||
public final static int[] KEY_ID = { 120,121,122,123,136,137,138,139,140,
|
||||
141,142,143,144,145,146,147 };
|
||||
public static final int[] TARGET_ADDRESS = { 160,161,162,163,164,165,166,
|
||||
167,168,169,170,171,184,185,186,187,188,189,190,190,192,193,194,195 };
|
||||
|
||||
public ProtectionParameterBroadcast( TDULinkControlMessage source )
|
||||
{
|
||||
super( source );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getEventType()
|
||||
{
|
||||
return LinkControlOpcode.PROTECTION_PARAMETER_BROADCAST.getDescription();
|
||||
}
|
||||
|
||||
public String getMessage()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append( getMessageStub() );
|
||||
|
||||
sb.append( " ENCRYPTION:" + getEncryption().name() );
|
||||
sb.append( " KEY:" + getEncryptionKey() );
|
||||
sb.append( " ADDRESSS:" + getTargetAddress() );
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public Encryption getEncryption()
|
||||
{
|
||||
return Encryption.fromValue( mMessage.getInt( ALGORITHM_ID ) );
|
||||
}
|
||||
|
||||
public int getEncryptionKey()
|
||||
{
|
||||
return mMessage.getInt( KEY_ID );
|
||||
}
|
||||
|
||||
public String getTargetAddress()
|
||||
{
|
||||
return mMessage.getHex( TARGET_ADDRESS, 6 );
|
||||
}
|
||||
}
|
||||
132
src/module/decode/p25/message/tdu/lc/RFSSStatusBroadcast.java
Normal file
132
src/module/decode/p25/message/tdu/lc/RFSSStatusBroadcast.java
Normal file
@@ -0,0 +1,132 @@
|
||||
package module.decode.p25.message.tdu.lc;
|
||||
|
||||
import module.decode.p25.message.IBandIdentifier;
|
||||
import module.decode.p25.message.IdentifierReceiver;
|
||||
import module.decode.p25.message.tsbk.osp.control.SystemService;
|
||||
import module.decode.p25.reference.LinkControlOpcode;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class RFSSStatusBroadcast extends TDULinkControlMessage
|
||||
implements IdentifierReceiver
|
||||
{
|
||||
private final static Logger mLog =
|
||||
LoggerFactory.getLogger( RFSSStatusBroadcast.class );
|
||||
|
||||
public static final int[] LRA = { 72,73,74,75,88,89,
|
||||
90,91 };
|
||||
public static final int[] SYSTEM_ID = { 96,97,98,99,112,113,114,115,116,117,
|
||||
118,119 };
|
||||
public static final int[] RFSS_ID = { 120,121,122,123,136,137,138,
|
||||
139 };
|
||||
public static final int[] SITE_ID = { 140,141,142,143,144,145,146,147 };
|
||||
|
||||
public static final int[] IDENTIFIER = { 160,161,162,163 };
|
||||
public static final int[] CHANNEL = { 164,165,166,167,168,169,170,
|
||||
171,184,185,186,187 };
|
||||
public static final int[] SYSTEM_SERVICE_CLASS = { 188,189,190,191,192,193,
|
||||
194,195 };
|
||||
|
||||
private IBandIdentifier mIdentifierUpdate;
|
||||
|
||||
public RFSSStatusBroadcast( TDULinkControlMessage source )
|
||||
{
|
||||
super( source );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getEventType()
|
||||
{
|
||||
return LinkControlOpcode.RFSS_STATUS_BROADCAST.getDescription();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMessage()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append( getMessageStub() );
|
||||
|
||||
sb.append( " LRA:" + getLocationRegistrationArea() );
|
||||
|
||||
sb.append( " SYS:" + getSystem() );
|
||||
|
||||
sb.append( " SITE:" + getRFSubsystemID() + "-" + getSiteID() );
|
||||
|
||||
sb.append( " CHAN:" + getChannelNumber() );
|
||||
|
||||
sb.append( " " + SystemService.toString( getSystemServiceClass() ) );
|
||||
|
||||
sb.append( " " + mMessage.toString() );
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public String getLocationRegistrationArea()
|
||||
{
|
||||
return mMessage.getHex( LRA, 2 );
|
||||
}
|
||||
|
||||
public String getSystem()
|
||||
{
|
||||
return mMessage.getHex( SYSTEM_ID, 3 );
|
||||
}
|
||||
|
||||
public String getRFSubsystemID()
|
||||
{
|
||||
return mMessage.getHex( RFSS_ID, 2 );
|
||||
}
|
||||
|
||||
public String getSiteID()
|
||||
{
|
||||
return mMessage.getHex( SITE_ID, 2 );
|
||||
}
|
||||
|
||||
public int getIdentifier()
|
||||
{
|
||||
return mMessage.getInt( IDENTIFIER );
|
||||
}
|
||||
|
||||
public String getChannel()
|
||||
{
|
||||
return getIdentifier() + "-" + getChannelNumber();
|
||||
}
|
||||
|
||||
public int getChannelNumber()
|
||||
{
|
||||
return mMessage.getInt( CHANNEL );
|
||||
}
|
||||
|
||||
public int getSystemServiceClass()
|
||||
{
|
||||
return mMessage.getInt( SYSTEM_SERVICE_CLASS );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setIdentifierMessage( int identifier, IBandIdentifier message )
|
||||
{
|
||||
mIdentifierUpdate = message;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] getIdentifiers()
|
||||
{
|
||||
int[] identifiers = new int[ 1 ];
|
||||
|
||||
identifiers[ 0 ] = getIdentifier();
|
||||
|
||||
return identifiers;
|
||||
}
|
||||
|
||||
public long getDownlinkFrequency()
|
||||
{
|
||||
return calculateDownlink( mIdentifierUpdate, getChannelNumber() );
|
||||
}
|
||||
|
||||
public long getUplinkFrequency()
|
||||
{
|
||||
return calculateUplink( mIdentifierUpdate, getChannelNumber() );
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,152 @@
|
||||
package module.decode.p25.message.tdu.lc;
|
||||
|
||||
import module.decode.p25.message.IBandIdentifier;
|
||||
import module.decode.p25.message.IdentifierReceiver;
|
||||
import module.decode.p25.message.tsbk.osp.control.SystemService;
|
||||
import module.decode.p25.reference.LinkControlOpcode;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class RFSSStatusBroadcastExplicit extends TDULinkControlMessage
|
||||
implements IdentifierReceiver
|
||||
{
|
||||
private final static Logger mLog =
|
||||
LoggerFactory.getLogger( RFSSStatusBroadcastExplicit.class );
|
||||
|
||||
public static final int[] LRA = { 72,73,74,75,88,89,90,91 };
|
||||
public static final int[] RECEIVE_IDENTIFIER = { 92,93,94,95 };
|
||||
public static final int[] RECEIVE_CHANNEL = { 96,97,98,99,112,113,114,115,
|
||||
116,117,118,119 };
|
||||
public static final int[] RFSS_ID = { 120,121,122,123,136,137,138,
|
||||
139 };
|
||||
public static final int[] SITE_ID = { 140,141,142,143,144,145,146,147 };
|
||||
|
||||
public static final int[] TRANSMIT_IDENTIFIER = { 160,161,162,163 };
|
||||
public static final int[] TRANSMIT_CHANNEL = { 164,165,166,167,168,169,170,
|
||||
171,184,185,186,187 };
|
||||
public static final int[] SYSTEM_SERVICE_CLASS = { 188,189,190,191,192,193,
|
||||
194,195 };
|
||||
|
||||
private IBandIdentifier mTransmitIdentifierUpdate;
|
||||
private IBandIdentifier mReceiveIdentifierUpdate;
|
||||
|
||||
public RFSSStatusBroadcastExplicit( TDULinkControlMessage source )
|
||||
{
|
||||
super( source );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getEventType()
|
||||
{
|
||||
return LinkControlOpcode.RFSS_STATUS_BROADCAST_EXPLICIT.getDescription();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMessage()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append( getMessageStub() );
|
||||
|
||||
sb.append( " LRA:" + getLocationRegistrationArea() );
|
||||
|
||||
sb.append( " SITE:" + getRFSubsystemID() + "-" + getSiteID() );
|
||||
|
||||
sb.append( " TRANSMIT:" + getTransmitChannelNumber() );
|
||||
|
||||
sb.append( " RECEIVE:" + getReceiveChannelNumber() );
|
||||
|
||||
sb.append( " " + SystemService.toString( getSystemServiceClass() ) );
|
||||
|
||||
sb.append( " " + mMessage.toString() );
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public String getLocationRegistrationArea()
|
||||
{
|
||||
return mMessage.getHex( LRA, 2 );
|
||||
}
|
||||
|
||||
public String getRFSubsystemID()
|
||||
{
|
||||
return mMessage.getHex( RFSS_ID, 2 );
|
||||
}
|
||||
|
||||
public String getSiteID()
|
||||
{
|
||||
return mMessage.getHex( SITE_ID, 2 );
|
||||
}
|
||||
|
||||
public int getTransmitIdentifier()
|
||||
{
|
||||
return mMessage.getInt( TRANSMIT_IDENTIFIER );
|
||||
}
|
||||
|
||||
public String getTransmitChannel()
|
||||
{
|
||||
return getTransmitIdentifier() + "-" + getTransmitChannelNumber();
|
||||
}
|
||||
|
||||
public int getTransmitChannelNumber()
|
||||
{
|
||||
return mMessage.getInt( TRANSMIT_CHANNEL );
|
||||
}
|
||||
|
||||
public int getReceiveIdentifier()
|
||||
{
|
||||
return mMessage.getInt( RECEIVE_IDENTIFIER );
|
||||
}
|
||||
|
||||
public String getReceiveChannel()
|
||||
{
|
||||
return getReceiveIdentifier() + "-" + getReceiveChannelNumber();
|
||||
}
|
||||
|
||||
public int getReceiveChannelNumber()
|
||||
{
|
||||
return mMessage.getInt( RECEIVE_CHANNEL );
|
||||
}
|
||||
|
||||
public int getSystemServiceClass()
|
||||
{
|
||||
return mMessage.getInt( SYSTEM_SERVICE_CLASS );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setIdentifierMessage( int identifier, IBandIdentifier message )
|
||||
{
|
||||
if( identifier == getTransmitIdentifier() )
|
||||
{
|
||||
mTransmitIdentifierUpdate = message;
|
||||
}
|
||||
|
||||
if( identifier == getReceiveIdentifier() )
|
||||
{
|
||||
mReceiveIdentifierUpdate = message;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] getIdentifiers()
|
||||
{
|
||||
int[] identifiers = new int[ 2 ];
|
||||
|
||||
identifiers[ 0 ] = getTransmitIdentifier();
|
||||
identifiers[ 1 ] = getReceiveIdentifier();
|
||||
|
||||
return identifiers;
|
||||
}
|
||||
|
||||
public long getDownlinkFrequency()
|
||||
{
|
||||
return calculateDownlink( mTransmitIdentifierUpdate, getTransmitChannelNumber() );
|
||||
}
|
||||
|
||||
public long getUplinkFrequency()
|
||||
{
|
||||
return calculateUplink( mReceiveIdentifierUpdate, getReceiveChannelNumber() );
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,159 @@
|
||||
package module.decode.p25.message.tdu.lc;
|
||||
|
||||
import module.decode.p25.message.IBandIdentifier;
|
||||
import module.decode.p25.message.IdentifierReceiver;
|
||||
import module.decode.p25.message.tsbk.osp.control.SystemService;
|
||||
import module.decode.p25.reference.LinkControlOpcode;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class SecondaryControlChannelBroadcast extends TDULinkControlMessage
|
||||
implements IdentifierReceiver
|
||||
{
|
||||
private final static Logger mLog =
|
||||
LoggerFactory.getLogger( SecondaryControlChannelBroadcast.class );
|
||||
|
||||
public static final int[] RFSS_ID = { 72,73,74,75,88,89,90,91 };
|
||||
public static final int[] SITE_ID = { 92,93,94,95,96,97,98,99 };
|
||||
public static final int[] IDENTIFIER_A = { 112,113,114,115 };
|
||||
public static final int[] CHANNEL_A = { 116,117,118,119,120,121,122,
|
||||
123,136,137,138,139 };
|
||||
|
||||
public static final int[] SYSTEM_SERVICE_CLASS_A = { 140,141,142,143,144,
|
||||
145,146,147 };
|
||||
|
||||
public static final int[] IDENTIFIER_B = { 160,161,162,163 };
|
||||
public static final int[] CHANNEL_B = { 164,165,166,167,168,169,170,
|
||||
171,184,185,186,187 };
|
||||
public static final int[] SYSTEM_SERVICE_CLASS_B = { 188,189,190,191,192,
|
||||
193,194,195 };
|
||||
|
||||
private IBandIdentifier mIdentifierProviderA;
|
||||
private IBandIdentifier mIdentifierProviderB;
|
||||
|
||||
public SecondaryControlChannelBroadcast( TDULinkControlMessage source )
|
||||
{
|
||||
super( source );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getEventType()
|
||||
{
|
||||
return LinkControlOpcode.SECONDARY_CONTROL_CHANNEL_BROADCAST.getDescription();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMessage()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append( getMessageStub() );
|
||||
|
||||
sb.append( " SITE:" + getRFSubsystemID() + "-" + getSiteID() );
|
||||
|
||||
sb.append( " CHAN A:" + getChannelA() );
|
||||
|
||||
sb.append( " " + SystemService.toString( getSystemServiceClassA() ) );
|
||||
|
||||
sb.append( " CHAN B:" + getChannelB() );
|
||||
|
||||
sb.append( " " + SystemService.toString( getSystemServiceClassB() ) );
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public String getRFSubsystemID()
|
||||
{
|
||||
return mMessage.getHex( RFSS_ID, 2 );
|
||||
}
|
||||
|
||||
public String getSiteID()
|
||||
{
|
||||
return mMessage.getHex( SITE_ID, 2 );
|
||||
}
|
||||
|
||||
public int getIdentifierA()
|
||||
{
|
||||
return mMessage.getInt( IDENTIFIER_A );
|
||||
}
|
||||
|
||||
public int getChannelA()
|
||||
{
|
||||
return mMessage.getInt( CHANNEL_A );
|
||||
}
|
||||
|
||||
public String getChannelNumberA()
|
||||
{
|
||||
return getIdentifierA() + "-" + getChannelA();
|
||||
}
|
||||
|
||||
public int getIdentifierB()
|
||||
{
|
||||
return mMessage.getInt( IDENTIFIER_B );
|
||||
}
|
||||
|
||||
public int getChannelB()
|
||||
{
|
||||
return mMessage.getInt( CHANNEL_B );
|
||||
}
|
||||
|
||||
public String getChannelNumberB()
|
||||
{
|
||||
return getIdentifierB() + "-" + getChannelB();
|
||||
}
|
||||
|
||||
public int getSystemServiceClassA()
|
||||
{
|
||||
return mMessage.getInt( SYSTEM_SERVICE_CLASS_A );
|
||||
}
|
||||
|
||||
public int getSystemServiceClassB()
|
||||
{
|
||||
return mMessage.getInt( SYSTEM_SERVICE_CLASS_B );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setIdentifierMessage( int identifier, IBandIdentifier message )
|
||||
{
|
||||
if( identifier == getIdentifierA() )
|
||||
{
|
||||
mIdentifierProviderA = message;
|
||||
}
|
||||
if( identifier == getIdentifierB() )
|
||||
{
|
||||
mIdentifierProviderB = message;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] getIdentifiers()
|
||||
{
|
||||
int[] identifiers = new int[ 2 ];
|
||||
|
||||
identifiers[ 0 ] = getIdentifierA();
|
||||
identifiers[ 1 ] = getIdentifierB();
|
||||
|
||||
return identifiers;
|
||||
}
|
||||
|
||||
public long getDownlinkFrequencyA()
|
||||
{
|
||||
return calculateDownlink( mIdentifierProviderA, getChannelA() );
|
||||
}
|
||||
|
||||
public long getUplinkFrequencyA()
|
||||
{
|
||||
return calculateUplink( mIdentifierProviderA, getChannelA() );
|
||||
}
|
||||
|
||||
public long getDownlinkFrequencyB()
|
||||
{
|
||||
return calculateDownlink( mIdentifierProviderB, getChannelB() );
|
||||
}
|
||||
|
||||
public long getUplinkFrequencyB()
|
||||
{
|
||||
return calculateUplink( mIdentifierProviderB, getChannelB() );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,140 @@
|
||||
package module.decode.p25.message.tdu.lc;
|
||||
|
||||
import module.decode.p25.message.IBandIdentifier;
|
||||
import module.decode.p25.message.IdentifierReceiver;
|
||||
import module.decode.p25.message.tsbk.osp.control.SystemService;
|
||||
import module.decode.p25.reference.LinkControlOpcode;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class SecondaryControlChannelBroadcastExplicit
|
||||
extends TDULinkControlMessage implements IdentifierReceiver
|
||||
{
|
||||
private final static Logger mLog =
|
||||
LoggerFactory.getLogger( SecondaryControlChannelBroadcastExplicit.class );
|
||||
|
||||
public static final int[] RFSS_ID = { 72,73,74,75,88,89,90,91 };
|
||||
public static final int[] SITE_ID = { 92,93,94,95,96,97,98,99 };
|
||||
public static final int[] TRANSMIT_IDENTIFIER = { 112,113,114,115 };
|
||||
public static final int[] TRANSMIT_CHANNEL = { 116,117,118,119,120,121,122,
|
||||
123,136,137,138,139 };
|
||||
public static final int[] RECEIVE_IDENTIFIER = { 140,141,142,143 };
|
||||
public static final int[] RECEIVE_CHANNEL = { 144,145,146,147,160,161,162,
|
||||
163,164,165,166,167 };
|
||||
public static final int[] SYSTEM_SERVICE_CLASS = { 168,169,170,171,184,
|
||||
185,186,187 };
|
||||
|
||||
private IBandIdentifier mTransmitIdentifierProvider;
|
||||
private IBandIdentifier mReceiveIdentifierProvider;
|
||||
|
||||
public SecondaryControlChannelBroadcastExplicit( TDULinkControlMessage source )
|
||||
{
|
||||
super( source );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getEventType()
|
||||
{
|
||||
return LinkControlOpcode.SECONDARY_CONTROL_CHANNEL_BROADCAST_EXPLICIT.getDescription();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMessage()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append( getMessageStub() );
|
||||
|
||||
sb.append( " SITE:" + getRFSubsystemID() + "-" + getSiteID() );
|
||||
|
||||
sb.append( " TRANSMIT:" + getTransmitChannel() );
|
||||
|
||||
sb.append( " RECEIVE:" + getReceiveChannel() );
|
||||
|
||||
sb.append( " " + SystemService.toString( getSystemServiceClass() ) );
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public String getRFSubsystemID()
|
||||
{
|
||||
return mMessage.getHex( RFSS_ID, 2 );
|
||||
}
|
||||
|
||||
public String getSiteID()
|
||||
{
|
||||
return mMessage.getHex( SITE_ID, 2 );
|
||||
}
|
||||
|
||||
public int getTransmitIdentifier()
|
||||
{
|
||||
return mMessage.getInt( TRANSMIT_IDENTIFIER );
|
||||
}
|
||||
|
||||
public int getTransmitChannelNumber()
|
||||
{
|
||||
return mMessage.getInt( TRANSMIT_CHANNEL );
|
||||
}
|
||||
|
||||
public String getTransmitChannel()
|
||||
{
|
||||
return getTransmitIdentifier() + "-" + getTransmitChannelNumber();
|
||||
}
|
||||
|
||||
public int getReceiveIdentifier()
|
||||
{
|
||||
return mMessage.getInt( RECEIVE_IDENTIFIER );
|
||||
}
|
||||
|
||||
public int getReceiveChannelNumber()
|
||||
{
|
||||
return mMessage.getInt( RECEIVE_CHANNEL );
|
||||
}
|
||||
|
||||
public String getReceiveChannel()
|
||||
{
|
||||
return getReceiveIdentifier() + "-" + getReceiveChannelNumber();
|
||||
}
|
||||
|
||||
public int getSystemServiceClass()
|
||||
{
|
||||
return mMessage.getInt( SYSTEM_SERVICE_CLASS );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setIdentifierMessage( int identifier, IBandIdentifier message )
|
||||
{
|
||||
if( identifier == getTransmitIdentifier() )
|
||||
{
|
||||
mTransmitIdentifierProvider = message;
|
||||
}
|
||||
if( identifier == getReceiveIdentifier() )
|
||||
{
|
||||
mReceiveIdentifierProvider = message;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] getIdentifiers()
|
||||
{
|
||||
int[] identifiers = new int[ 2 ];
|
||||
|
||||
identifiers[ 0 ] = getTransmitIdentifier();
|
||||
identifiers[ 1 ] = getReceiveIdentifier();
|
||||
|
||||
return identifiers;
|
||||
}
|
||||
|
||||
public long getDownlinkFrequency()
|
||||
{
|
||||
return calculateDownlink( mTransmitIdentifierProvider,
|
||||
getTransmitChannelNumber() );
|
||||
}
|
||||
|
||||
public long getUplinkFrequency()
|
||||
{
|
||||
return calculateUplink( mReceiveIdentifierProvider,
|
||||
getReceiveChannelNumber() );
|
||||
}
|
||||
}
|
||||
51
src/module/decode/p25/message/tdu/lc/StatusQuery.java
Normal file
51
src/module/decode/p25/message/tdu/lc/StatusQuery.java
Normal file
@@ -0,0 +1,51 @@
|
||||
package module.decode.p25.message.tdu.lc;
|
||||
|
||||
import module.decode.p25.reference.LinkControlOpcode;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class StatusQuery extends TDULinkControlMessage
|
||||
{
|
||||
private final static Logger mLog =
|
||||
LoggerFactory.getLogger( StatusQuery.class );
|
||||
public static final int[] TARGET_ADDRESS = { 112,113,114,115,116,117,118,
|
||||
119,120,121,122,123,136,137,138,139,140,141,142,143,144,145,146,147 };
|
||||
public static final int[] SOURCE_ADDRESS = { 160,161,162,163,164,165,166,
|
||||
167,168,169,170,171,184,185,186,187,188,189,190,191,192,193,194,195 };
|
||||
|
||||
public StatusQuery( TDULinkControlMessage source )
|
||||
{
|
||||
super( source );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getEventType()
|
||||
{
|
||||
return LinkControlOpcode.STATUS_QUERY.getDescription();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMessage()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append( getMessageStub() );
|
||||
|
||||
sb.append( " FROM:" + getSourceAddress() );
|
||||
|
||||
sb.append( " TO:" + getTargetAddress() );
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public String getTargetAddress()
|
||||
{
|
||||
return mMessage.getHex( TARGET_ADDRESS, 6 );
|
||||
}
|
||||
|
||||
public String getSourceAddress()
|
||||
{
|
||||
return mMessage.getHex( SOURCE_ADDRESS, 6 );
|
||||
}
|
||||
}
|
||||
64
src/module/decode/p25/message/tdu/lc/StatusUpdate.java
Normal file
64
src/module/decode/p25/message/tdu/lc/StatusUpdate.java
Normal file
@@ -0,0 +1,64 @@
|
||||
package module.decode.p25.message.tdu.lc;
|
||||
|
||||
import module.decode.p25.reference.LinkControlOpcode;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class StatusUpdate extends TDULinkControlMessage
|
||||
{
|
||||
private final static Logger mLog =
|
||||
LoggerFactory.getLogger( StatusUpdate.class );
|
||||
public static final int[] USER_STATUS = { 80,81,82,83,84,85,86,87 };
|
||||
public static final int[] UNIT_STATUS = { 88,89,90,91,92,93,94,95 };
|
||||
public static final int[] TARGET_ADDRESS = { 112,113,114,115,116,117,118,
|
||||
119,120,121,122,123,136,137,138,139,140,141,142,143,144,145,146,147 };
|
||||
public static final int[] SOURCE_ADDRESS = { 160,161,162,163,164,165,166,
|
||||
167,168,169,170,171,184,185,186,187,188,189,190,191,192,193,194,195 };
|
||||
|
||||
public StatusUpdate( TDULinkControlMessage source )
|
||||
{
|
||||
super( source );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getEventType()
|
||||
{
|
||||
return LinkControlOpcode.STATUS_UPDATE.getDescription();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMessage()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append( getMessageStub() );
|
||||
|
||||
sb.append( " STATUS USER:" + getUserStatus() );
|
||||
sb.append( " UNIT:" + getUnitStatus() );
|
||||
sb.append( " FROM:" + getSourceAddress() );
|
||||
sb.append( " TO:" + getTargetAddress() );
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public String getUserStatus()
|
||||
{
|
||||
return mMessage.getHex( USER_STATUS, 2 );
|
||||
}
|
||||
|
||||
public String getUnitStatus()
|
||||
{
|
||||
return mMessage.getHex( UNIT_STATUS, 2 );
|
||||
}
|
||||
|
||||
public String getTargetAddress()
|
||||
{
|
||||
return mMessage.getHex( TARGET_ADDRESS, 6 );
|
||||
}
|
||||
|
||||
public String getSourceAddress()
|
||||
{
|
||||
return mMessage.getHex( SOURCE_ADDRESS, 6 );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
package module.decode.p25.message.tdu.lc;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import module.decode.p25.reference.LinkControlOpcode;
|
||||
import module.decode.p25.reference.Service;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class SystemServiceBroadcast extends TDULinkControlMessage
|
||||
{
|
||||
private final static Logger mLog =
|
||||
LoggerFactory.getLogger( SystemServiceBroadcast.class );
|
||||
public static final int[] REQUEST_PRIORITY_LEVEL = { 96,97,98,99 };
|
||||
public static final int[] AVAILABLE_SERVICES = { 112,113,114,115,116,117,118,
|
||||
119,120,121,122,123,136,137,138,139,140,141,142,143,144,145,146,147 };
|
||||
public static final int[] SUPPORTED_SERVICES = { 160,161,162,163,164,165,
|
||||
166,167,168,169,170,171,184,185,186,187,188,189,190,191,192,193,194,195 };
|
||||
|
||||
public SystemServiceBroadcast( TDULinkControlMessage source )
|
||||
{
|
||||
super( source );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getEventType()
|
||||
{
|
||||
return LinkControlOpcode.SYSTEM_SERVICE_BROADCAST.getDescription();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMessage()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append( getMessageStub() );
|
||||
|
||||
sb.append( " SERVICES AVAILABLE " );
|
||||
|
||||
sb.append( getAvailableServices() );
|
||||
|
||||
sb.append( " SUPPORTED " );
|
||||
|
||||
sb.append( getSupportedServices() );
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public List<Service> getAvailableServices()
|
||||
{
|
||||
long bitmap = mMessage.getLong( AVAILABLE_SERVICES );
|
||||
|
||||
return Service.getServices( bitmap );
|
||||
}
|
||||
|
||||
public List<Service> getSupportedServices()
|
||||
{
|
||||
long bitmap = mMessage.getLong( SUPPORTED_SERVICES );
|
||||
|
||||
return Service.getServices( bitmap );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
package module.decode.p25.message.tdu.lc;
|
||||
|
||||
import module.decode.p25.reference.Vendor;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
|
||||
public class TDULCMessageFactory
|
||||
{
|
||||
private final static Logger mLog =
|
||||
LoggerFactory.getLogger( TDULCMessageFactory.class );
|
||||
|
||||
/**
|
||||
* Constructs a new sub-class of the TDULC message if the opcode is recognized
|
||||
* or returns the original message.
|
||||
*/
|
||||
public static TDULinkControlMessage getMessage( TDULinkControlMessage message )
|
||||
{
|
||||
if( message.isImplicitFormat() || message.getVendor() == Vendor.STANDARD )
|
||||
{
|
||||
switch( message.getOpcode() )
|
||||
{
|
||||
case ADJACENT_SITE_STATUS_BROADCAST:
|
||||
return new AdjacentSiteStatusBroadcast( message );
|
||||
case ADJACENT_SITE_STATUS_BROADCAST_EXPLICIT:
|
||||
return new AdjacentSiteStatusBroadcastExplicit( message );
|
||||
case CALL_ALERT:
|
||||
return new CallAlert( message );
|
||||
case CALL_TERMINATION_OR_CANCELLATION:
|
||||
return new CallTermination( message );
|
||||
case CHANNEL_IDENTIFIER_UPDATE:
|
||||
return new ChannelIdentifierUpdate( message );
|
||||
case CHANNEL_IDENTIFIER_UPDATE_EXPLICIT:
|
||||
return new ChannelIdentifierUpdateExplicit( message );
|
||||
case EXTENDED_FUNCTION_COMMAND:
|
||||
return new ExtendedFunctionCommand( message );
|
||||
case GROUP_AFFILIATION_QUERY:
|
||||
return new GroupAffiliationQuery( message );
|
||||
case GROUP_VOICE_CHANNEL_UPDATE:
|
||||
return new GroupVoiceChannelUpdate( message );
|
||||
case GROUP_VOICE_CHANNEL_UPDATE_EXPLICIT:
|
||||
return new GroupVoiceChannelUpdateExplicit( message );
|
||||
case GROUP_VOICE_CHANNEL_USER:
|
||||
return new GroupVoiceChannelUser( message );
|
||||
case MESSAGE_UPDATE:
|
||||
return new MessageUpdate( message );
|
||||
case NETWORK_STATUS_BROADCAST:
|
||||
return new NetworkStatusBroadcast( message );
|
||||
case NETWORK_STATUS_BROADCAST_EXPLICIT:
|
||||
return new NetworkStatusBroadcastExplicit( message );
|
||||
case PROTECTION_PARAMETER_BROADCAST:
|
||||
return new ProtectionParameterBroadcast( message );
|
||||
case RFSS_STATUS_BROADCAST:
|
||||
return new RFSSStatusBroadcast( message );
|
||||
case RFSS_STATUS_BROADCAST_EXPLICIT:
|
||||
return new RFSSStatusBroadcastExplicit( message );
|
||||
case SECONDARY_CONTROL_CHANNEL_BROADCAST:
|
||||
return new SecondaryControlChannelBroadcast( message );
|
||||
case SECONDARY_CONTROL_CHANNEL_BROADCAST_EXPLICIT:
|
||||
return new SecondaryControlChannelBroadcastExplicit( message );
|
||||
case STATUS_QUERY:
|
||||
return new StatusQuery( message );
|
||||
case STATUS_UPDATE:
|
||||
return new StatusUpdate( message );
|
||||
case SYSTEM_SERVICE_BROADCAST:
|
||||
return new SystemServiceBroadcast( message );
|
||||
case TELEPHONE_INTERCONNECT_ANSWER_REQUEST:
|
||||
return new TelephoneInterconnectAnswerRequest( message );
|
||||
case TELEPHONE_INTERCONNECT_VOICE_CHANNEL_USER:
|
||||
return new TelephoneInterconnectVoiceChannelUser( message );
|
||||
case UNIT_AUTHENTICATION_COMMAND:
|
||||
return new UnitAuthenticationCommand( message );
|
||||
case UNIT_REGISTRATION_COMMAND:
|
||||
return new UnitRegistrationCommand( message );
|
||||
case UNIT_TO_UNIT_ANSWER_REQUEST:
|
||||
return new UnitToUnitAnswerRequest( message );
|
||||
case UNIT_TO_UNIT_VOICE_CHANNEL_USER:
|
||||
return new UnitToUnitVoiceChannelUser( message );
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch( message.getVendor() )
|
||||
{
|
||||
case MOTOROLA:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return message;
|
||||
}
|
||||
}
|
||||
284
src/module/decode/p25/message/tdu/lc/TDULinkControlMessage.java
Normal file
284
src/module/decode/p25/message/tdu/lc/TDULinkControlMessage.java
Normal file
@@ -0,0 +1,284 @@
|
||||
package module.decode.p25.message.tdu.lc;
|
||||
|
||||
import module.decode.p25.message.P25Message;
|
||||
import module.decode.p25.message.tsbk.motorola.MotorolaOpcode;
|
||||
import module.decode.p25.reference.DataUnitID;
|
||||
import module.decode.p25.reference.LinkControlOpcode;
|
||||
import module.decode.p25.reference.Vendor;
|
||||
import module.decode.p25.reference.VendorLinkControlOpcode;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import alias.AliasList;
|
||||
import bits.BinaryMessage;
|
||||
import edac.CRC;
|
||||
import edac.Golay24;
|
||||
import edac.ReedSolomon_63_47_17;
|
||||
|
||||
public class TDULinkControlMessage extends P25Message
|
||||
{
|
||||
public final static Logger mLog = LoggerFactory.getLogger( TDULinkControlMessage.class );
|
||||
|
||||
public static final int[] LC_HEX_0 = { 64,65,66,67,68,69 };
|
||||
public static final int[] LC_HEX_1 = { 70,71,72,73,74,75 };
|
||||
public static final int[] LC_HEX_2 = { 88,89,90,91,92,93 };
|
||||
public static final int[] LC_HEX_3 = { 94,95,96,97,98,99 };
|
||||
public static final int[] LC_HEX_4 = { 112,113,114,115,116,117 };
|
||||
public static final int[] LC_HEX_5 = { 118,119,120,121,122,123 };
|
||||
public static final int[] LC_HEX_6 = { 136,137,138,139,140,141 };
|
||||
public static final int[] LC_HEX_7 = { 142,143,144,145,146,147 };
|
||||
public static final int[] LC_HEX_8 = { 160,161,162,163,164,165 };
|
||||
public static final int[] LC_HEX_9 = { 166,167,168,169,170,171 };
|
||||
public static final int[] LC_HEX_10 = { 184,185,186,187,188,189 };
|
||||
public static final int[] LC_HEX_11 = { 190,191,192,193,194,195 };
|
||||
public static final int[] RS_HEX_0 = { 208,209,210,211,212,213 };
|
||||
public static final int[] RS_HEX_1 = { 214,215,216,217,218,219 };
|
||||
public static final int[] RS_HEX_2 = { 232,233,234,235,236,237 };
|
||||
public static final int[] RS_HEX_3 = { 238,239,240,241,242,243 };
|
||||
public static final int[] RS_HEX_4 = { 256,257,258,259,260,261 };
|
||||
public static final int[] RS_HEX_5 = { 262,263,264,265,266,267 };
|
||||
public static final int[] RS_HEX_6 = { 280,281,282,283,284,285 };
|
||||
public static final int[] RS_HEX_7 = { 286,287,288,289,290,291 };
|
||||
public static final int[] RS_HEX_8 = { 304,305,306,307,308,309 };
|
||||
public static final int[] RS_HEX_9 = { 310,311,312,313,314,315 };
|
||||
public static final int[] RS_HEX_10 = { 328,329,330,331,332,333 };
|
||||
public static final int[] RS_HEX_11 = { 334,335,336,337,338,339 };
|
||||
|
||||
public static final int ENCRYPTION_FLAG = 64;
|
||||
public static final int IMPLICIT_VENDOR_FLAG = 65;
|
||||
public static final int[] OPCODE = { 66,67,68,69,70,71 };
|
||||
public static final int[] VENDOR = { 72,73,74,75,88,89,90,91 };
|
||||
|
||||
/* Reed-Solomon(24,12,13) code protects the link control word. Maximum
|
||||
* correctable errors are: Hamming Distance(13) / 2 = 6 */
|
||||
public static final ReedSolomon_63_47_17 mReedSolomonDecoder =
|
||||
new ReedSolomon_63_47_17( 6 );
|
||||
|
||||
public TDULinkControlMessage( BinaryMessage message, DataUnitID duid,
|
||||
AliasList aliasList )
|
||||
{
|
||||
super( message, duid, aliasList );
|
||||
|
||||
/* NID CRC is checked in the message framer so a constructed message
|
||||
* means it passed the CRC */
|
||||
mCRC = new CRC[ 3 ];
|
||||
mCRC[ 0 ] = CRC.PASSED;
|
||||
|
||||
checkCRC();
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a TDULinkControl message from an existing message and bypasses
|
||||
* the CRC calculation.
|
||||
*/
|
||||
protected TDULinkControlMessage( TDULinkControlMessage message )
|
||||
{
|
||||
super( message.getSourceMessage(), DataUnitID.TDULC, message.getAliasList() );
|
||||
|
||||
mCRC = message.getCRC();
|
||||
}
|
||||
|
||||
public CRC[] getCRC()
|
||||
{
|
||||
return mCRC;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMessage()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append( getMessageStub() );
|
||||
sb.append( " " );
|
||||
sb.append( mMessage.toString() );
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public String getMessageStub()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append( "NAC:" );
|
||||
sb.append( getNAC() );
|
||||
sb.append( " " );
|
||||
sb.append( getDUID().getLabel() );
|
||||
sb.append( " " );
|
||||
|
||||
if( isEncrypted() )
|
||||
{
|
||||
sb.append( "ENCRYPTED" );
|
||||
}
|
||||
else
|
||||
{
|
||||
if( isImplicitFormat() || getVendor() == Vendor.STANDARD )
|
||||
{
|
||||
sb.append( getOpcode().getLabel() );
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.append( "VENDOR:" + getVendor().getLabel() + " " );
|
||||
sb.append( getVendorOpcode().getLabel() );
|
||||
}
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public boolean isEncrypted()
|
||||
{
|
||||
return mMessage.get( ENCRYPTION_FLAG );
|
||||
}
|
||||
|
||||
public boolean isImplicitFormat()
|
||||
{
|
||||
return mMessage.get( IMPLICIT_VENDOR_FLAG );
|
||||
}
|
||||
|
||||
/**
|
||||
* Standard opcodes when the Vendor is STANDARD
|
||||
*/
|
||||
public LinkControlOpcode getOpcode()
|
||||
{
|
||||
return LinkControlOpcode.fromValue( mMessage.getInt( OPCODE ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a generic vendor-neutral opcode. Use this when there is a non
|
||||
* standard vendor code.
|
||||
*/
|
||||
public VendorLinkControlOpcode getVendorOpcode()
|
||||
{
|
||||
return VendorLinkControlOpcode.fromValue( mMessage.getInt( OPCODE ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* If the vendor is motorola, returns the Motorola OPCODE for this message
|
||||
*/
|
||||
public MotorolaOpcode getMotorolaOpcode()
|
||||
{
|
||||
return MotorolaOpcode.fromValue( mMessage.getInt( OPCODE ) );
|
||||
}
|
||||
|
||||
public Vendor getVendor()
|
||||
{
|
||||
if( isImplicitFormat() )
|
||||
{
|
||||
return Vendor.STANDARD;
|
||||
}
|
||||
|
||||
return Vendor.fromValue( mMessage.getInt( VENDOR ) );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Checks and repairs the 12 x 24-bit golay(24,12,8) codewords and then
|
||||
* checks and repairs the 24 x 6-bit link control and reed-solomon
|
||||
* RS(24,12,13) parity codewords
|
||||
*/
|
||||
private void checkCRC()
|
||||
{
|
||||
/* Check the Golay codewords */
|
||||
int x = 64;
|
||||
|
||||
mCRC[ 1 ] = CRC.PASSED;
|
||||
|
||||
while( x < mMessage.size() )
|
||||
{
|
||||
mMessage = Golay24.checkAndCorrect( mMessage, x );
|
||||
|
||||
if( !( mMessage.getCRC() == CRC.PASSED ) )
|
||||
{
|
||||
mCRC[ 1 ] = CRC.FAILED_CRC;
|
||||
}
|
||||
|
||||
x += 24;
|
||||
}
|
||||
|
||||
/* Check the Reed-Solomon parity bits. The RS decoder expects the link
|
||||
* control data and reed solomon parity hex codewords in reverse order.
|
||||
* The RS(24,12,13) code used by P25 removes the left-hand 47 data hex
|
||||
* words, so we replace them with zeros. */
|
||||
int[] input = new int [63];
|
||||
int[] output = new int [63];
|
||||
|
||||
input[ 0 ] = mMessage.getInt( RS_HEX_11 );
|
||||
input[ 1 ] = mMessage.getInt( RS_HEX_10 );
|
||||
input[ 2 ] = mMessage.getInt( RS_HEX_9 );
|
||||
input[ 3 ] = mMessage.getInt( RS_HEX_8 );
|
||||
input[ 4 ] = mMessage.getInt( RS_HEX_7 );
|
||||
input[ 5 ] = mMessage.getInt( RS_HEX_6 );
|
||||
input[ 6 ] = mMessage.getInt( RS_HEX_5 );
|
||||
input[ 7 ] = mMessage.getInt( RS_HEX_4 );
|
||||
input[ 8 ] = mMessage.getInt( RS_HEX_3 );
|
||||
input[ 9 ] = mMessage.getInt( RS_HEX_2 );
|
||||
input[ 10 ] = mMessage.getInt( RS_HEX_1 );
|
||||
input[ 11 ] = mMessage.getInt( RS_HEX_0 );
|
||||
input[ 12 ] = mMessage.getInt( LC_HEX_11 );
|
||||
input[ 13 ] = mMessage.getInt( LC_HEX_10 );
|
||||
input[ 14 ] = mMessage.getInt( LC_HEX_9 );
|
||||
input[ 15 ] = mMessage.getInt( LC_HEX_8 );
|
||||
input[ 16 ] = mMessage.getInt( LC_HEX_7 );
|
||||
input[ 17 ] = mMessage.getInt( LC_HEX_6 );
|
||||
input[ 18 ] = mMessage.getInt( LC_HEX_5 );
|
||||
input[ 19 ] = mMessage.getInt( LC_HEX_4 );
|
||||
input[ 20 ] = mMessage.getInt( LC_HEX_3 );
|
||||
input[ 21 ] = mMessage.getInt( LC_HEX_2 );
|
||||
input[ 22 ] = mMessage.getInt( LC_HEX_1 );
|
||||
input[ 23 ] = mMessage.getInt( LC_HEX_0 );
|
||||
/* indexes 24 - 62 are defaulted to zero */
|
||||
|
||||
boolean irrecoverableErrors = mReedSolomonDecoder.decode( input, output );
|
||||
|
||||
if( irrecoverableErrors )
|
||||
{
|
||||
mCRC[ 2 ] = CRC.FAILED_CRC;
|
||||
}
|
||||
else
|
||||
{
|
||||
mCRC[ 2 ] = CRC.PASSED;
|
||||
|
||||
/* Only fix the link control data hex codewords */
|
||||
repairHexCodeword( input, output, 12, LC_HEX_11 );
|
||||
repairHexCodeword( input, output, 13, LC_HEX_10 );
|
||||
repairHexCodeword( input, output, 14, LC_HEX_9 );
|
||||
repairHexCodeword( input, output, 15, LC_HEX_8 );
|
||||
repairHexCodeword( input, output, 16, LC_HEX_7 );
|
||||
repairHexCodeword( input, output, 17, LC_HEX_6 );
|
||||
repairHexCodeword( input, output, 18, LC_HEX_5 );
|
||||
repairHexCodeword( input, output, 19, LC_HEX_4 );
|
||||
repairHexCodeword( input, output, 20, LC_HEX_3 );
|
||||
repairHexCodeword( input, output, 21, LC_HEX_2 );
|
||||
repairHexCodeword( input, output, 22, LC_HEX_1 );
|
||||
repairHexCodeword( input, output, 23, LC_HEX_0 );
|
||||
|
||||
/* If the golay check failed, mark it as corrected too */
|
||||
if( mCRC[ 1 ] == CRC.FAILED_CRC )
|
||||
{
|
||||
mCRC[ 1 ] = CRC.CORRECTED;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void repairHexCodeword( int[] input, int[] output, int index, int[] indexSet )
|
||||
{
|
||||
if( input[ index ] != output[ index ] )
|
||||
{
|
||||
mMessage.load( indexSet[ 0 ], 6, output[ index ] );
|
||||
mCRC[ 2 ] = CRC.CORRECTED;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if the message passed the golay and reed-solomon parity checks
|
||||
* or was corrected.
|
||||
*/
|
||||
public boolean isValid()
|
||||
{
|
||||
// mCRC[ 0 ] - always passes (otherwise message wouldn't be constructed )
|
||||
// mCRC[ 1 ] - golay - always passes or corrected if mCRC[2] is valid
|
||||
|
||||
return mCRC[ 2 ] == CRC.PASSED || mCRC[ 2 ] == CRC.CORRECTED;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
package module.decode.p25.message.tdu.lc;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import module.decode.p25.reference.Digit;
|
||||
import module.decode.p25.reference.LinkControlOpcode;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class TelephoneInterconnectAnswerRequest extends TDULinkControlMessage
|
||||
{
|
||||
private final static Logger mLog = LoggerFactory.getLogger( TelephoneInterconnectAnswerRequest.class );
|
||||
|
||||
public static final int[] DIGIT_1 = { 72,73,74,75 };
|
||||
public static final int[] DIGIT_2 = { 88,89,90,91 };
|
||||
public static final int[] DIGIT_3 = { 92,93,94,95 };
|
||||
public static final int[] DIGIT_4 = { 96,97,98,99 };
|
||||
public static final int[] DIGIT_5 = { 112,113,114,115 };
|
||||
public static final int[] DIGIT_6 = { 116,117,118,119 };
|
||||
public static final int[] DIGIT_7 = { 120,121,122,123 };
|
||||
public static final int[] DIGIT_8 = { 136,137,138,139 };
|
||||
public static final int[] DIGIT_9 = { 140,141,142,143 };
|
||||
public static final int[] DIGIT_10 = { 144,145,146,147 };
|
||||
|
||||
public static final int[] TARGET_ADDRESS = { 160,161,162,163,164,165,166,
|
||||
167,168,169,170,171,184,185,186,187,188,189,190,191,192,193,194,195 };
|
||||
|
||||
public TelephoneInterconnectAnswerRequest( TDULinkControlMessage source )
|
||||
{
|
||||
super( source );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getEventType()
|
||||
{
|
||||
return LinkControlOpcode.TELEPHONE_INTERCONNECT_ANSWER_REQUEST.getDescription();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMessage()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append( getMessageStub() );
|
||||
|
||||
sb.append( " TO:" );
|
||||
sb.append( getTargetAddress() );
|
||||
|
||||
sb.append( " TEL:" );
|
||||
sb.append( getTelephoneNumber() );
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public String getTargetAddress()
|
||||
{
|
||||
return mMessage.getHex( TARGET_ADDRESS, 6 );
|
||||
}
|
||||
|
||||
public String getTelephoneNumber()
|
||||
{
|
||||
List<Integer> digits = new ArrayList<Integer>();
|
||||
|
||||
digits.add( mMessage.getInt( DIGIT_1 ) );
|
||||
digits.add( mMessage.getInt( DIGIT_2 ) );
|
||||
digits.add( mMessage.getInt( DIGIT_3 ) );
|
||||
digits.add( mMessage.getInt( DIGIT_4 ) );
|
||||
digits.add( mMessage.getInt( DIGIT_5 ) );
|
||||
digits.add( mMessage.getInt( DIGIT_6 ) );
|
||||
digits.add( mMessage.getInt( DIGIT_7 ) );
|
||||
digits.add( mMessage.getInt( DIGIT_8 ) );
|
||||
digits.add( mMessage.getInt( DIGIT_9 ) );
|
||||
digits.add( mMessage.getInt( DIGIT_10 ) );
|
||||
|
||||
return Digit.decode( digits );
|
||||
}
|
||||
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user