Skip to content

Commit

Permalink
#1914 corrections to assembled talker alias for logging.
Browse files Browse the repository at this point in the history
  • Loading branch information
Dennis Sheirer committed May 11, 2024
1 parent 9e64996 commit c0c8368
Show file tree
Hide file tree
Showing 7 changed files with 286 additions and 46 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
import io.github.dsheirer.module.decode.p25.phase1.message.IFrequencyBandReceiver;
import io.github.dsheirer.module.decode.p25.phase1.message.lc.ExtendedSourceLinkControlWord;
import io.github.dsheirer.module.decode.p25.phase1.message.lc.LinkControlWord;
import io.github.dsheirer.module.decode.p25.phase1.message.lc.motorola.MotorolaTalkerAliasAssemblerP25Phase1;
import io.github.dsheirer.module.decode.p25.phase1.message.lc.motorola.LCMotorolaTalkerAliasAssembler;
import io.github.dsheirer.module.decode.p25.phase1.message.lc.standard.LCSourceIDExtension;
import io.github.dsheirer.module.decode.p25.phase1.message.ldu.LDU1Message;
import io.github.dsheirer.module.decode.p25.phase1.message.tdu.TDULinkControlMessage;
Expand Down Expand Up @@ -64,7 +64,7 @@ public class P25P1MessageProcessor implements Listener<IMessage>
/**
* Motorola talker alias assembler for link control header and data blocks.
*/
private MotorolaTalkerAliasAssemblerP25Phase1 mMotorolaTalkerAliasAssembler = new MotorolaTalkerAliasAssemblerP25Phase1();
private LCMotorolaTalkerAliasAssembler mMotorolaTalkerAliasAssembler = new LCMotorolaTalkerAliasAssembler();

/**
* Constructs an instance
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,20 +44,20 @@ public abstract class LinkControlWord extends AbstractMessage
public static final int OCTET_7_BIT_56 = 56;
public static final int OCTET_8_BIT_64 = 64;
public static final int OCTET_9_BIT_72 = 72;
public static final int OCTET_10_BIT_80 = 80;
public static final int OCTET_11_BIT_88 = 88;
public static final int OCTET_12_BIT_96 = 96;
public static final int OCTET_13_BIT_104 = 104;
public static final int OCTET_14_BIT_112 = 112;
public static final int OCTET_15_BIT_120 = 120;
public static final int OCTET_16_BIT_128 = 128;
public static final int OCTET_17_BIT_136 = 136;
public static final int OCTET_18_BIT_144 = 144;
public static final int OCTET_19_BIT_152 = 152;
public static final int OCTET_20_BIT_160 = 160;
public static final int OCTET_21_BIT_168 = 168;
public static final int OCTET_22_BIT_176 = 176;
public static final int OCTET_23_BIT_184 = 184;
public static final int OCTET_25_BIT_200 = 200;
public static final int OCTET_27_BIT_216 = 216;
public static final int OCTET_29_BIT_232 = 232;
public static final int OCTET_31_BIT_248 = 248;
public static final int OCTET_33_BIT_264 = 264;
public static final int OCTET_35_BIT_280 = 280;
public static final int OCTET_37_BIT_296 = 296;

private static final int ENCRYPTION_FLAG = 0;
private static final int STANDARD_VENDOR_ID_FLAG = 1;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,22 +25,24 @@
import java.util.Map;

/**
* Reassembles a P25 Motorola talker alias from a Header and Data Blocks from a Phase 1 traffic channel.
* Reassembles a P25 Motorola talker alias from a Header and Data Blocks.
*
* This is used for traffic channels and monitors the link control messaging stream.
* This is used for traffic channels and monitors:
* - Phase 1: link control messaging stream.
* - Phase 2: mac messaging
*/
public class MotorolaTalkerAliasAssemblerP25Phase1
public class LCMotorolaTalkerAliasAssembler
{
private static final int DATA_BLOCK_FRAGMENT_LENGTH = 44;
private LCMotorolaTalkerAliasHeader mHeader;
private Map<Integer,LCMotorolaTalkerAliasDataBlock> mDataBlocks = new HashMap<>();
private Map<Integer, LCMotorolaTalkerAliasDataBlock> mDataBlocks = new HashMap<>();
private int mSequence = -1;
private long mMostRecentTimestamp;

/**
* Constructs an instance
*/
public MotorolaTalkerAliasAssemblerP25Phase1()
public LCMotorolaTalkerAliasAssembler()
{
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,20 +45,20 @@ public class LCMotorolaTalkerAliasComplete extends LinkControlWord implements IM
private static final IntField SUID_SYSTEM = IntField.length12(OCTET_2_BIT_16 + 4);
private static final IntField SUID_ID = IntField.length24(OCTET_4_BIT_32);
private static final int ENCODED_ALIAS_START = OCTET_7_BIT_56;
private static final IntField CHUNK_2 = IntField.length16(OCTET_8_BIT_64);
private static final IntField CHUNK_4 = IntField.length16(OCTET_10_BIT_80);
private static final IntField CHUNK_5 = IntField.length16(OCTET_11_BIT_88);
private static final IntField CHUNK_6 = IntField.length16(OCTET_12_BIT_96);
private static final IntField CHUNK_7 = IntField.length16(OCTET_13_BIT_104);
private static final IntField CHUNK_8 = IntField.length16(OCTET_14_BIT_112);
private static final IntField CHUNK_9 = IntField.length16(OCTET_15_BIT_120);
private static final IntField CHUNK_10 = IntField.length16(OCTET_16_BIT_128);
private static final IntField CHUNK_11 = IntField.length16(OCTET_17_BIT_136);
private static final IntField CHUNK_12 = IntField.length16(OCTET_18_BIT_144);
private static final IntField CHUNK_13 = IntField.length16(OCTET_19_BIT_152);
private static final IntField CHUNK_15 = IntField.length16(OCTET_21_BIT_168);
private static final IntField CHUNK_16 = IntField.length16(OCTET_22_BIT_176);
private static final IntField CHUNK_17 = IntField.length16(OCTET_23_BIT_184);
private static final IntField CHUNK_2 = IntField.length16(OCTET_9_BIT_72);
private static final IntField CHUNK_4 = IntField.length16(OCTET_13_BIT_104);
private static final IntField CHUNK_5 = IntField.length16(OCTET_15_BIT_120);
private static final IntField CHUNK_6 = IntField.length16(OCTET_17_BIT_136);
private static final IntField CHUNK_7 = IntField.length16(OCTET_19_BIT_152);
private static final IntField CHUNK_8 = IntField.length16(OCTET_21_BIT_168);
private static final IntField CHUNK_9 = IntField.length16(OCTET_23_BIT_184);
private static final IntField CHUNK_10 = IntField.length16(OCTET_25_BIT_200);
private static final IntField CHUNK_11 = IntField.length16(OCTET_27_BIT_216);
private static final IntField CHUNK_12 = IntField.length16(OCTET_29_BIT_232);
private static final IntField CHUNK_13 = IntField.length16(OCTET_31_BIT_248);
private static final IntField CHUNK_15 = IntField.length16(OCTET_33_BIT_264);
private static final IntField CHUNK_16 = IntField.length16(OCTET_35_BIT_280);
private static final IntField CHUNK_17 = IntField.length16(OCTET_37_BIT_296);

private APCO25Talkgroup mTalkgroup;
private APCO25FullyQualifiedRadioIdentifier mRadio;
Expand Down Expand Up @@ -86,6 +86,20 @@ public LCMotorolaTalkerAliasComplete(CorrectedBinaryMessage message, APCO25Talkg
mTimestamp = timestamp;
}

public String toString()
{
StringBuilder sb = new StringBuilder();
sb.append("MOTOROLA TALKER ALIAS COMPLETE");
sb.append(" RADIO:").append(getRadio());
sb.append(" TG:").append(getTalkgroup());
sb.append(" ENCODED:").append(getEncodedAlias().toHexString());
sb.append(" ALIAS:").append(getAlias());
sb.append(" DATA BLOCKS:").append(mDataBlockCount);
sb.append(" SEQUENCE:").append(mSequence);
sb.append(" MSG:").append(getMessage().toHexString());
return sb.toString();
}

@Override
public LinkControlOpcode getOpcode()
{
Expand Down Expand Up @@ -133,20 +147,6 @@ public int getSequence()
return mSequence;
}

public String toString()
{
StringBuilder sb = new StringBuilder();
sb.append("MOTOROLA TALKER ALIAS COMPLETE");
sb.append(" TG:").append(getTalkgroup());
sb.append(" RADIO:").append(getRadio());
sb.append(" ENCODED:").append(getEncodedAlias().toHexString());
sb.append(" ALIAS:").append(getAlias());
sb.append(" DATA BLOCKS:").append(mDataBlockCount);
sb.append(" SEQUENCE:").append(mSequence);
sb.append(" MSG:").append(getMessage().toHexString());
return sb.toString();
}

public P25TalkerAliasIdentifier getAlias()
{
if(mAlias == null)
Expand Down Expand Up @@ -266,7 +266,7 @@ else if(getInt(CHUNK_15) > 0)
break;
}

return getMessage().getSubMessage(ENCODED_ALIAS_START, length * 16 + 1);
return getMessage().getSubMessage(ENCODED_ALIAS_START, ENCODED_ALIAS_START + (length * 16));
}

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
/*
* *****************************************************************************
* Copyright (C) 2014-2024 Dennis Sheirer
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
* ****************************************************************************
*/

package io.github.dsheirer.module.decode.p25.phase2.message.mac.structure.motorola;

import io.github.dsheirer.bits.CorrectedBinaryMessage;
import io.github.dsheirer.module.decode.p25.phase1.message.lc.motorola.LCMotorolaTalkerAliasComplete;
import io.github.dsheirer.module.decode.p25.phase2.message.mac.structure.MacStructure;
import java.util.HashMap;
import java.util.Map;

/**
* Reassembles a P25 Motorola talker alias from a Header and Data Blocks.
*
* This is used for traffic channels and monitors:
* - Phase 2: mac messaging
*/
public class MotorolaTalkerAliasAssembler
{
private static final int DATA_BLOCK_FRAGMENT_LENGTH = 44;
private MotorolaTalkerAliasHeader mHeader;
private Map<Integer, MotorolaTalkerAliasDataBlock> mDataBlocks = new HashMap<>();
private int mSequence = -1;
private long mMostRecentTimestamp;

/**
* Constructs an instance
*/
public MotorolaTalkerAliasAssembler()
{
}

/**
* Link control word to process.
* @param mac to add
* @return true if we can (now) assemble a complete talker alias from the header and data blocks.
*/
public boolean add(MacStructure mac, long timestamp)
{
if(mac instanceof MotorolaTalkerAliasHeader header)
{
mMostRecentTimestamp = timestamp;

if(mSequence != header.getSequence())
{
mDataBlocks.clear();
mSequence = header.getSequence();
}

mHeader = header;
}
else if(mac instanceof MotorolaTalkerAliasDataBlock block)
{
mMostRecentTimestamp = timestamp;

if(block.getSequence() != mSequence)
{
mHeader = null;
mDataBlocks.clear();
mSequence = block.getSequence();
}

mDataBlocks.put(block.getBlockNumber(), block);
}
else
{
return false; //For all lcw's that are not headers or data blocks
}

return isComplete();
}

/**
* Indicates if the assembler has a header and the correct number of data blocks to reassemble an alias.
*/
private boolean isComplete()
{
if(mHeader != null)
{
int dataBlockCount = mHeader.getBlockCount();

for(int x = 1; x <= dataBlockCount; x++)
{
if(!mDataBlocks.containsKey(x))
{
return false;
}
}

return true;
}

return false;
}

/**
* Assembles the talker alias once the header and data blocks have been collected.
*
* Note: do not invoke unless the add() methods indicate that the assembler is complete.
* @return assembled talker alias
* @throws IllegalStateException if the assembler can't assemble the alias.
*/
public LCMotorolaTalkerAliasComplete assemble() throws IllegalStateException
{
if(!isComplete())
{
throw new IllegalStateException("Can't assemble talker alias - missing header or data block(s)");
}

int dataBlockCount = mHeader.getBlockCount();
CorrectedBinaryMessage reassembled = new CorrectedBinaryMessage(dataBlockCount * DATA_BLOCK_FRAGMENT_LENGTH);

int offset = 0;

for(int x = 1; x <= dataBlockCount; x++)
{
MotorolaTalkerAliasDataBlock block = mDataBlocks.get(x);
reassembled.load(offset, block.getFragment());
offset += DATA_BLOCK_FRAGMENT_LENGTH;
}

LCMotorolaTalkerAliasComplete complete = new LCMotorolaTalkerAliasComplete(reassembled, mHeader.getTalkgroup(),
dataBlockCount, mHeader.getSequence(), mMostRecentTimestamp);

mHeader = null;
mDataBlocks.clear();

System.out.println(complete);
return complete;
}
}
Loading

0 comments on commit c0c8368

Please sign in to comment.