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( " " ); switch( getFormat() ) { case ALTERNATE_MULTI_BLOCK_TRUNKING_CONTROL: sb.append( "ATSBK" ); break; case UNCONFIRMED_MULTI_BLOCK_TRUNKING_CONTROL: sb.append( "**** UNCONFIRMED MULTI-BLOCK TRUNKING CONTROL" ); break; default: sb.append( getDUID().getLabel() ); break; } 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 ); } }