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

#1556 DMR Capacity Plus parsing enhancements. #1557

Merged
merged 1 commit into from
May 20, 2023
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,8 @@ private void load(File file)
{
ioe.printStackTrace();
}

getMessageTableView().scrollTo(0);
}
}

Expand Down Expand Up @@ -364,7 +366,6 @@ private Button getSelectFileButton()

if(selected != null)
{
mLog.info("Last Selected Directory updated to [" + selected.getParent() +"]");
mPreferences.put(LAST_SELECTED_DIRECTORY, selected.getParent());
load(selected);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,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.CapacityPlusEncryptedVoiceChannelUser;
import io.github.dsheirer.module.decode.dmr.message.data.lc.full.motorola.CapacityPlusGroupVoiceChannelUser;
import io.github.dsheirer.module.decode.dmr.message.data.lc.full.motorola.CapacityPlusWideAreaVoiceChannelUser;
import io.github.dsheirer.module.decode.dmr.message.data.lc.shorty.CapacityPlusRestChannel;
Expand Down Expand Up @@ -1048,13 +1049,27 @@ private void processLinkControl(LCMessage message, boolean isTerminator)
updateRestChannel(((CapacityPlusRestChannel)message).getRestChannel());
}
break;
case FULL_CAPACITY_PLUS_ENCRYPTED_VOICE_CHANNEL_USER:
if(message instanceof CapacityPlusEncryptedVoiceChannelUser cpgvcu)
{
if(isTerminator)
{
getIdentifierCollection().remove(Role.FROM);
getIdentifierCollection().update(cpgvcu.getTalkgroup());
}
else
{
getIdentifierCollection().update(message.getIdentifiers());
ServiceOptions serviceOptions = cpgvcu.getServiceOptions();
updateCurrentCall(serviceOptions.isEncrypted() ? DecodeEventType.CALL_GROUP_ENCRYPTED :
DecodeEventType.CALL_GROUP, serviceOptions.toString(), message.getTimestamp());
}
}
break;
case FULL_CAPACITY_PLUS_GROUP_VOICE_CHANNEL_USER:
if(message instanceof CapacityPlusGroupVoiceChannelUser)
if(message instanceof CapacityPlusGroupVoiceChannelUser cpgvcu)
{
CapacityPlusGroupVoiceChannelUser cpgvcu = (CapacityPlusGroupVoiceChannelUser)message;

//This is the current channel - what do we do with the voice channel number?
// updateRestChannel(cpgvcu.getVoiceChannel());
updateRestChannel(cpgvcu.getRestChannel());

if(isTerminator)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -396,15 +396,15 @@ public static void main(String[] args)
// String file = path + "20200710_053632_9600BPS_DMR_Niles_Radio_Coconino_Control.bits";

//Cap+ Multi-Site 1 - Data Revert LSN1/2 with CSBKO 62 Site status
// String file = path + "Texas_Dallas_Aerowave_Capacity_Plus_Multi_Site/20200716_210133_9600BPS_DMR_Aerowave_Technologies_Dallas_LCN_2.bits";
String file = path + "Texas_Dallas_Aerowave_Capacity_Plus_Multi_Site/20200716_210133_9600BPS_DMR_Aerowave_Technologies_Dallas_LCN_2.bits";
// String file = path + "Texas_Dallas_Aerowave_Capacity_Plus_Multi_Site/20200716_210845_9600BPS_DMR_Aerowave_Technologies_Dallas_LCN_2.bits";
// String file = path + "Texas_Dallas_Aerowave_Capacity_Plus_Multi_Site/20200716_212309_9600BPS_DMR_Aerowave_Technologies_Dallas_LCN_2.bits";

//Cap+ Multi-Site Enhanced Data Revert Channel (no CSBKO 62)
// String file = path + "Texas_Hunt_Farmers_Electric_Capacity_Plus_Multi_Site/20200714_224018_9600BPS_DMR_Farmers_Electric_Cooperative_Hunt_LCN_3.bits"; //This may have PLL mis-align issues

//Cap+ Multi-Site - Dallas Unknown
String file = path + "Texas_Dallas_Unknown_1_Capacity_Plus_Multi_Site/20200716_211233_9600BPS_DMR_Dallas_Unk_Dallas_Unk.bits";
// String file = path + "Texas_Dallas_Unknown_1_Capacity_Plus_Multi_Site/20200716_211233_9600BPS_DMR_Dallas_Unk_Dallas_Unk.bits";

//Hytera Short Data = Proprietary (encrypted)
// String file = path + "20200716_222839_9600BPS_DMR_SystemUnk_SiteUnk_Unk.bits"; //Hytera short data packets
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ public String toString()
StringBuilder sb = new StringBuilder();
if(hasRAS())
{
sb.append(" RAS:").append(getBPTCReservedBits());
sb.append("RAS:").append(getBPTCReservedBits()).append(" ");
}
sb.append(getSlotType());
sb.append(" ").append(getLCMessage());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,6 @@ public class CapacityPlusSiteStatus extends CSBKMessage implements ITimeslotFreq
private static final int[] REST_LSN = new int[]{20, 21, 22, 23};
private static final int[] LSN_VOICE_BITMAP = new int[]{24, 25, 26, 27, 28, 29, 30, 31};
private static final int LSN_1_8_BITMAP_START = 24;
private static final int[][] VOICE_TALKGROUPS = new int[][]{{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},
{64, 65, 66, 67, 68, 69, 70, 71}, {72, 73, 74, 75, 76, 77, 78, 79}};

private DMRLogicalChannel mRestChannel;
private List<Identifier> mIdentifiers;
Expand Down Expand Up @@ -117,8 +114,14 @@ private boolean hasVoiceTalkgroups()
*/
private String getActivityFragments()
{
StringBuilder sb = new StringBuilder();
sb.append("VOICE LSN ");
if(getMessage().get(48) && getMessage().get(56))
{
int a = 0; //debug
}
int[] talkgroups = new int[17];
int[] radios = new int[17];
boolean hasIdentifier = false;

int pointer = LSN_1_8_BITMAP_START;

//Process voice LSNs 1-8
Expand All @@ -133,31 +136,29 @@ private String getActivityFragments()

if(getMessage().get(x))
{
hasIdentifier = true;

if(pointer <= 72)
{
sb.append(lsn).append(":").append(getMessage().getInt(BYTE, pointer)).append(" ");
talkgroups[lsn] = getMessage().getInt(BYTE, pointer);
pointer += 8;
}
else
{
sb.append(lsn).append(":A ");
talkgroups[lsn] = -1;
}
}
else
{
sb.append(lsn).append(":* ");
}
}
}
else
{
sb.append("1-8:* ");
pointer += 8;
}

//Process voice LSNs 9 - 16
if(pointer <= 72 && getMessage().getInt(BYTE, pointer) > 0)
{
hasIdentifier = true;
int highLsnBitmap = pointer;

pointer += 8;
Expand All @@ -170,30 +171,25 @@ private String getActivityFragments()
{
if(pointer <= 72)
{
sb.append(lsn).append(":").append(getMessage().getInt(BYTE, pointer)).append(" ");
talkgroups[lsn] = getMessage().getInt(BYTE, pointer);
pointer += 8;
}
else
{
sb.append(lsn).append(":A ");
talkgroups[lsn] = -1;
}
}
else
{
sb.append(lsn).append(":* ");
}
}
}
else
{
sb.append("9-16:* ");
pointer += 8;
}

//Process Data and Private Radio IDs - first bit in radio options byte is set to indicate more activity
//Process Radio IDs - first bit in radio options byte is set to indicate more activity
if(pointer <= 72 && getMessage().get(pointer))
{
sb.append("DATA LSN ");
hasIdentifier = true;
pointer += 8;

//If we have the data revert channel bitmap ...
Expand All @@ -211,24 +207,58 @@ private String getActivityFragments()
{
if(pointer <= 64)
{
sb.append(lsn).append(":").append(getMessage().getInt(TWO_BYTES, pointer)).append(" ");
radios[lsn] = getMessage().getInt(TWO_BYTES, pointer);
pointer += 16;
}
else
{
sb.append(lsn).append(":A ");
radios[lsn] = -1;
}
}
}
}
}

StringBuilder sb = new StringBuilder();

if(!hasIdentifier)
{
sb.append("IDLE LSN: 1-16");
}
else
{
sb.append("ACTIVE LSN");
for(int x = 1; x < 17; x++)
{
if(talkgroups[x] != 0 || radios[x] != 0)
{
sb.append(" ").append(x);

if(talkgroups[x] == 0)
{
if(radios[x] < 0)
{
sb.append(":(R)A"); //Radio active on channel but identifier is in a continuation message
}
else if(radios[x] > 0)
{
sb.append(":(R)").append(radios[x]); //Active radio ID for channel
}
else
{
sb.append(":"); //No radio or talkgroup active on channel
}
}
else if(talkgroups[x] < 0)
{
sb.append(":(T)A"); //Talkgroup active on channel but identifier is in a continuation message
}
else
{
sb.append(lsn).append(":* ");
sb.append(":(T)").append(talkgroups[x]); //Active talkgroup ID for channel.
}
}
}
else
{
sb.append("1-8:- ");
}
}

return sb.toString();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
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.HyteraTerminator;
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.CapacityPlusEncryptedVoiceChannelUser;
import io.github.dsheirer.module.decode.dmr.message.data.lc.full.motorola.CapacityPlusGroupVoiceChannelUser;
import io.github.dsheirer.module.decode.dmr.message.data.lc.full.motorola.CapacityPlusWideAreaVoiceChannelUser;
import io.github.dsheirer.module.decode.dmr.message.data.lc.shorty.ActivityUpdateMessage;
Expand Down Expand Up @@ -114,6 +115,9 @@ else if(message.size() == 96)
case FULL_CAPACITY_PLUS_GROUP_VOICE_CHANNEL_USER:
flc = new CapacityPlusGroupVoiceChannelUser(message, timestamp, timeslot);
break;
case FULL_CAPACITY_PLUS_ENCRYPTED_VOICE_CHANNEL_USER:
flc = new CapacityPlusEncryptedVoiceChannelUser(message, timestamp, timeslot);
break;
case FULL_CAPACITY_PLUS_WIDE_AREA_VOICE_CHANNEL_USER:
flc = new CapacityPlusWideAreaVoiceChannelUser(message, timestamp, timeslot);
break;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ public enum LCOpcode

FULL_CAPACITY_PLUS_GROUP_VOICE_CHANNEL_USER(Vendor.MOTOROLA_CAPACITY_PLUS, true, 0, "GROUP VOICE CHANNEL USER"),
FULL_CAPACITY_PLUS_WIDE_AREA_VOICE_CHANNEL_USER(Vendor.MOTOROLA_CAPACITY_PLUS, true, 4, "WAN GROUP VOICE CHANNEL USER"),
//Observed on Cap+ Multi-Site System during an encrypted voice call
FULL_CAPACITY_PLUS_ENCRYPTED_VOICE_CHANNEL_USER(Vendor.MOTOROLA_CAPACITY_PLUS, true, 32, "ENCRYPTED VOICE CHANNEL USER"),
//Cap+ opcodes from https://forums.radioreference.com/threads/understanding-capacity-plus-trunking-some-more.452566/
//FLCO 0: Group Call Maintenance
//FLCO 3: Private Call Maintenance (TermLC)
Expand Down