Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

#1787 DMR Decoder Enhancements for RAS Enabled Systems #1794

Merged
merged 1 commit into from
Jan 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@
import io.github.dsheirer.module.decode.dmr.message.data.lc.full.UnitToUnitVoiceChannelUser;
import io.github.dsheirer.module.decode.dmr.message.data.lc.full.hytera.HyteraGroupVoiceChannelUser;
import io.github.dsheirer.module.decode.dmr.message.data.lc.full.hytera.HyteraUnitToUnitVoiceChannelUser;
import io.github.dsheirer.module.decode.dmr.message.data.lc.full.motorola.CapacityMaxVoiceChannelUser;
import io.github.dsheirer.module.decode.dmr.message.data.lc.full.motorola.CapacityPlusEncryptedVoiceChannelUser;
import io.github.dsheirer.module.decode.dmr.message.data.lc.full.motorola.CapacityPlusWideAreaVoiceChannelUser;
import io.github.dsheirer.module.decode.dmr.message.data.lc.full.motorola.MotorolaGroupVoiceChannelUser;
Expand Down Expand Up @@ -142,6 +143,16 @@ public DMRDecoderState(Channel channel, int timeslot, DMRTrafficChannelManager t
}
}

/**
* Indicates if the message is valid or if the Ignore CRC Checksums feature is enabled.
* @param message to check
* @return true if ignore CRC checksums or if the message is valid, meaning the message has passed CRC check.
*/
private boolean isValid(IMessage message)
{
return mIgnoreCRCChecksums || message.isValid();
}

/**
* Indicates if this decoder state has an (optional) traffic channel manager.
*/
Expand Down Expand Up @@ -206,21 +217,21 @@ public void receive(IMessage message)
{
if(message.getTimeslot() == getTimeslot())
{
if(message instanceof VoiceMessage)
if(message instanceof VoiceMessage voice)
{
processVoice((VoiceMessage)message);
processVoice(voice);
}
else if(message instanceof DataMessage)
else if(message instanceof DataMessage data)
{
processData((DataMessage)message);
processData(data);
}
else if((message.isValid() || mIgnoreCRCChecksums) && message instanceof LCMessage)
else if(isValid(message) && message instanceof LCMessage lcMessage)
{
processLinkControl((LCMessage)message, false);
processLinkControl(lcMessage, false);
}
else if(message.isValid() && message instanceof DMRPacketMessage)
else if(isValid(message) && message instanceof DMRPacketMessage packet)
{
processPacket((DMRPacketMessage)message);
processPacket(packet);
}
else if(message instanceof UDTShortMessageService sms)
{
Expand All @@ -232,16 +243,15 @@ else if(message instanceof DMRMessage)
}
}
//SLCO messages on timeslot 0 to catch capacity plus rest channel events
else if((message.isValid() || mIgnoreCRCChecksums) && message.getTimeslot() == 0 && message instanceof LCMessage)
else if(isValid(message) && message.getTimeslot() == 0 && message instanceof LCMessage lcMessage)
{
processLinkControl((LCMessage)message, false);
processLinkControl(lcMessage, false);
}

//Pass the message to the network configuration monitor, if this decoder state has a non-null instance
if(mNetworkConfigurationMonitor != null && (message.isValid() || mIgnoreCRCChecksums) &&
message instanceof DMRMessage)
if(mNetworkConfigurationMonitor != null && isValid(message) && message instanceof DMRMessage dmrMessage)
{
mNetworkConfigurationMonitor.process((DMRMessage)message);
mNetworkConfigurationMonitor.process(dmrMessage);
}
}

Expand Down Expand Up @@ -503,7 +513,7 @@ private void processHeader(HeaderMessage header)
//Process the link control message to get the identifiers
LCMessage lc = header.getLCMessage();

if(lc.isValid())
if(isValid(lc))
{
processLinkControl(lc, false);
}
Expand All @@ -520,15 +530,15 @@ private void processData(DataMessage message)
switch(message.getSlotType().getDataType())
{
case CSBK:
if((message.isValid() || mIgnoreCRCChecksums) && message instanceof CSBKMessage)
if(isValid(message) && message instanceof CSBKMessage csbk)
{
processCSBK((CSBKMessage)message);
processCSBK(csbk);
}
break;
case VOICE_HEADER:
if(message instanceof HeaderMessage)
if(message instanceof HeaderMessage header)
{
processVoiceHeader((HeaderMessage)message);
processVoiceHeader(header);
}
break;
case USB_DATA:
Expand All @@ -539,9 +549,9 @@ private void processData(DataMessage message)
case MBC_ENC_HEADER:
case DATA_ENC_HEADER:
case CHANNEL_CONTROL_ENC_HEADER:
if(message instanceof HeaderMessage)
if(message instanceof HeaderMessage header)
{
processHeader((HeaderMessage)message);
processHeader(header);
}
break;
case SLOT_IDLE:
Expand Down Expand Up @@ -579,7 +589,7 @@ private void processTerminator(Terminator terminator)

LCMessage lcMessage = terminator.getLCMessage();

if(lcMessage.isValid())
if(isValid(lcMessage))
{
processLinkControl(lcMessage, true);
}
Expand All @@ -592,7 +602,7 @@ private void processVoiceHeader(HeaderMessage voiceHeader)
{
LCMessage lcMessage = voiceHeader.getLCMessage();

if(lcMessage.isValid())
if(isValid(lcMessage))
{
processLinkControl(lcMessage, false);
}
Expand Down Expand Up @@ -1133,6 +1143,23 @@ private void processLinkControl(LCMessage message, boolean isTerminator)
}
}
break;
case FULL_CAPACITY_MAX_GROUP_VOICE_CHANNEL_USER:
if(message instanceof CapacityMaxVoiceChannelUser cmvcu)
{
if(isTerminator)
{
getIdentifierCollection().remove(Role.FROM);
getIdentifierCollection().update(cmvcu.getTalkgroup());
}
else
{
getIdentifierCollection().update(message.getIdentifiers());
ServiceOptions serviceOptions = cmvcu.getServiceOptions();
updateCurrentCall(serviceOptions.isEncrypted() ? DecodeEventType.CALL_GROUP_ENCRYPTED :
DecodeEventType.CALL_GROUP, serviceOptions.toString(), message.getTimestamp());
}
}
break;
case FULL_CAPACITY_PLUS_WIDE_AREA_VOICE_CHANNEL_USER:
if(message instanceof CapacityPlusWideAreaVoiceChannelUser)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,20 +66,23 @@ public class DMRMessageProcessor implements Listener<IMessage>
private VoiceSuperFrameProcessor mSuperFrameProcessor2 = new VoiceSuperFrameProcessor();
private FLCAssembler mFLCAssemblerTimeslot1 = new FLCAssembler(1);
private FLCAssembler mFLCAssemblerTimeslot2 = new FLCAssembler(2);
private MBCAssembler mMBCAssembler = new MBCAssembler();
private MBCAssembler mMBCAssembler;
private PacketSequenceAssembler mPacketSequenceAssembler;
private SLCAssembler mSLCAssembler = new SLCAssembler();
private TalkerAliasAssembler mTalkerAliasAssembler = new TalkerAliasAssembler();
private Listener<IMessage> mMessageListener;
private Map<Integer,TimeslotFrequency> mTimeslotFrequencyMap = new TreeMap<>();
private DmrCrcMaskManager mCrcMaskManager = new DmrCrcMaskManager();
private boolean mIgnoreCrcChecksums;

/**
* Constructs an instance
*/
public DMRMessageProcessor(DecodeConfigDMR config)
{
mConfigDMR = config;
mIgnoreCrcChecksums = config.getIgnoreCRCChecksums();
mMBCAssembler = new MBCAssembler(mIgnoreCrcChecksums);

for(TimeslotFrequency timeslotFrequency: config.getTimeslotMap())
{
Expand All @@ -89,6 +92,17 @@ public DMRMessageProcessor(DecodeConfigDMR config)
mPacketSequenceAssembler = new PacketSequenceAssembler();
}

/**
* Indicates if the message is valid or if the Ignore CRC Checksums feature is enabled.
*
* @param message to check
* @return true if ignore CRC checksums or if the message is valid.
*/
private boolean isValid(IMessage message)
{
return mIgnoreCrcChecksums || message.isValid();
}

/**
* Primary message processing
*/
Expand Down Expand Up @@ -128,7 +142,7 @@ else if(message instanceof VoiceMessage voiceMessage)
mSuperFrameProcessor2.process(voiceMessage);
}
}
else if(message instanceof DMRBurst dmrBurst && dmrBurst.isValid())
else if(message instanceof DMRBurst dmrBurst && isValid(dmrBurst))
{
if(dmrBurst.getTimeslot() == 1)
{
Expand Down Expand Up @@ -243,14 +257,14 @@ else if((message instanceof IDLEMessage || message instanceof Aloha || message i
}

//Reset talker alias assembler on Idle or Terminator
if(message.isValid() && (message instanceof IDLEMessage || message instanceof Terminator))
if(isValid(message) && (message instanceof IDLEMessage || message instanceof Terminator))
{
mTalkerAliasAssembler.reset(message.getTimeslot());
}
}

//Assemble Talker Alias from FLC message fragments (header & blocks 1-3)
if(message instanceof FullLCMessage flc && flc.getOpcode().isTalkerAliasOpcode() && message.isValid())
if(message instanceof FullLCMessage flc && flc.getOpcode().isTalkerAliasOpcode() && isValid(message))
{
dispatch(mTalkerAliasAssembler.process(flc));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
import io.github.dsheirer.module.decode.dmr.message.data.csbk.hytera.HyteraXPTPreamble;
import io.github.dsheirer.module.decode.dmr.message.data.csbk.hytera.HyteraXPTSiteState;
import io.github.dsheirer.module.decode.dmr.message.data.csbk.motorola.CapacityMaxAloha;
import io.github.dsheirer.module.decode.dmr.message.data.csbk.motorola.CapacityMaxGroupVoiceChannelUpdate;
import io.github.dsheirer.module.decode.dmr.message.data.csbk.motorola.CapacityPlusCSBKO_60;
import io.github.dsheirer.module.decode.dmr.message.data.csbk.motorola.CapacityPlusDataRevertWindowAnnouncement;
import io.github.dsheirer.module.decode.dmr.message.data.csbk.motorola.CapacityPlusDataRevertWindowGrant;
Expand Down Expand Up @@ -277,7 +278,9 @@ public static CSBKMessage create(DMRSyncPattern pattern, CorrectedBinaryMessage
case MOTOROLA_CAPPLUS_DATA_WINDOW_GRANT:
csbk = new CapacityPlusDataRevertWindowGrant(pattern, message, cach, slotType, timestamp, timeslot);
break;

case MOTOROLA_CAPMAX_GROUP_VOICE_CHANNEL_UPDATE:
csbk = new CapacityMaxGroupVoiceChannelUpdate(pattern, message, cach, slotType, timestamp, timeslot);
break;
case MOTOROLA_CONPLUS_CSBKO_10:
csbk = new ConnectPlusOTAAnnouncement(pattern, message, cach, slotType, timestamp, timeslot);
break;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,9 @@ public enum Opcode
MOTOROLA_CONPLUS_DATA_WINDOW_ANNOUNCEMENT(Vendor.MOTOROLA_CONNECT_PLUS, 28, "ENHANCED DATA REVERT WINDOW ANNOUNCEMENT"),
MOTOROLA_CONPLUS_DATA_WINDOW_GRANT(Vendor.MOTOROLA_CONNECT_PLUS, 29, "ENHANCED DATA REVERT WINDOW GRANT"),

MOTOROLA_CAPMAX_GROUP_CHANNEL_USER(Vendor.MOTOROLA_CAPACITY_PLUS, 16, "GROUP CHANNEL USER"),
MOTOROLA_CAPMAX_ALOHA(Vendor.MOTOROLA_CAPACITY_PLUS, 25, "ALOHA"),
MOTOROLA_CAPMAX_GROUP_VOICE_CHANNEL_UPDATE(Vendor.MOTOROLA_CAPACITY_PLUS, 33, "TALKGROUP ACTIVE"),

MOTOROLA_CAPPLUS_CALL_ALERT(Vendor.MOTOROLA_CAPACITY_PLUS, 31, "CALL ALERT"),
MOTOROLA_CAPPLUS_CALL_ALERT_ACK(Vendor.MOTOROLA_CAPACITY_PLUS, 32, "CALL ALERT ACK"),
Expand Down
Loading