mirror of
https://github.com/DSheirer/sdrtrunk.git
synced 2026-11-12 16:47:31 -05:00
#1507 Resolves issue with Cap+ LSN parsing. Updates Cap+ Site Status and adds RAS bit handling. (#1536)
Co-authored-by: Matthew Foster <matthew.foster@noaa.gov>
This commit is contained in:
@@ -44,7 +44,7 @@ import io.github.dsheirer.module.decode.dmr.message.data.DataMessage;
|
||||
import io.github.dsheirer.module.decode.dmr.message.data.csbk.CSBKMessage;
|
||||
import io.github.dsheirer.module.decode.dmr.message.data.csbk.motorola.CapacityMaxAloha;
|
||||
import io.github.dsheirer.module.decode.dmr.message.data.csbk.motorola.CapacityPlusNeighbors;
|
||||
import io.github.dsheirer.module.decode.dmr.message.data.csbk.motorola.CapacityPlusSystemStatus;
|
||||
import io.github.dsheirer.module.decode.dmr.message.data.csbk.motorola.CapacityPlusSiteStatus;
|
||||
import io.github.dsheirer.module.decode.dmr.message.data.csbk.motorola.ConnectPlusDataChannelGrant;
|
||||
import io.github.dsheirer.module.decode.dmr.message.data.csbk.motorola.ConnectPlusVoiceChannelUser;
|
||||
import io.github.dsheirer.module.decode.dmr.message.data.csbk.standard.Aloha;
|
||||
@@ -673,10 +673,10 @@ public class DMRDecoderState extends TimeslotDecoderState
|
||||
updateRestChannel(((CapacityPlusNeighbors)csbk).getRestChannel());
|
||||
}
|
||||
break;
|
||||
case MOTOROLA_CAPPLUS_SYSTEM_STATUS:
|
||||
if(csbk instanceof CapacityPlusSystemStatus)
|
||||
case MOTOROLA_CAPPLUS_SITE_STATUS:
|
||||
if(csbk instanceof CapacityPlusSiteStatus)
|
||||
{
|
||||
CapacityPlusSystemStatus cpss = (CapacityPlusSystemStatus)csbk;
|
||||
CapacityPlusSiteStatus cpss = (CapacityPlusSiteStatus)csbk;
|
||||
|
||||
//Channel rotation monitor normally uses only CONTROL state, so when we detect that we're a
|
||||
//Capacity plus system, add ACTIVE as an active state to the monitor. This can be requested repeatedly.
|
||||
|
||||
@@ -377,7 +377,7 @@ public class DMRMessageFramer implements Listener<Dibit>, IDMRBurstDetectListene
|
||||
|
||||
public static void main(String[] args)
|
||||
{
|
||||
String path = "/media/denny/Lexar/Recordings/DMR/";
|
||||
String path = "/media/denny/T7 Shield/Recordings/DMR/";
|
||||
|
||||
//Con+ Traffic + Voice
|
||||
// String file = path + "20200513_143340_9600BPS_DMR_SaiaNet_Onondaga_Control.bits"; //Enh GPS Revert Window Annce
|
||||
@@ -385,7 +385,7 @@ public class DMRMessageFramer implements Listener<Dibit>, IDMRBurstDetectListene
|
||||
// String file = path + "20200514_063507_9600BPS_DMR_SaiaNet_Onondaga_LCN_3_Control.bits"; //GPS Window Grant 2579
|
||||
// String file = path + "20200514_064224_9600BPS_DMR_SaiaNet_Onondaga_LCN_3_Control.bits"; //GPS Window Grant 5056035
|
||||
// String file = path + "20200514_131623_9600BPS_DMR_SaiaNet_Onondaga_LCN_3_Control.bits"; //GPS Grant: 5074193
|
||||
String file = path + "20200514_133947_9600BPS_DMR_SaiaNet_Onondaga_LCN_4.bits"; //<<<<<<<------ Basic Encryption
|
||||
// String file = path + "SaiaNet/20200514_133947_9600BPS_DMR_SaiaNet_Onondaga_LCN_4.bits"; //<<<<<<<------ Basic Encryption
|
||||
// String file = path + "20200514_142249_9600BPS_DMR_SaiaNet_Onondaga_LCN_4.bits";
|
||||
// String file = path + "20200514_144534_9600BPS_DMR_SaiaNet_Onondaga_LCN_3_Control.bits"; //Con+ Control w/GPS Window Announce
|
||||
|
||||
@@ -395,12 +395,16 @@ public class DMRMessageFramer implements Listener<Dibit>, IDMRBurstDetectListene
|
||||
//Cap-Max Tier III CC
|
||||
// String file = path + "20200710_053632_9600BPS_DMR_Niles_Radio_Coconino_Control.bits";
|
||||
|
||||
//Cap+ Multi-Site 1 - Traffic LCN 2
|
||||
// String file = path + "20200716_210133_9600BPS_DMR_Aerowave_Technologies_Dallas_LCN_2.bits";
|
||||
// String file = path + "20200716_212309_9600BPS_DMR_Aerowave_Technologies_Dallas_LCN_2.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_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 GPS Channel
|
||||
// String file = path + "20200714_224018_9600BPS_DMR_Farmers_Electric_Cooperative_Hunt_LCN_3.bits"; //This may have PLL mis-align issues
|
||||
//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";
|
||||
|
||||
//Hytera Short Data = Proprietary (encrypted)
|
||||
// String file = path + "20200716_222839_9600BPS_DMR_SystemUnk_SiteUnk_Unk.bits"; //Hytera short data packets
|
||||
|
||||
@@ -111,6 +111,9 @@ public class DMRMessageProcessor implements Listener<IMessage>
|
||||
}
|
||||
}
|
||||
|
||||
//Now that the message has been (potentially) enriched, dispatch it to the modules
|
||||
dispatch(message);
|
||||
|
||||
//Extract the Full Link Control message fragment from the Voice with embedded signalling message
|
||||
if(message instanceof VoiceEMBMessage)
|
||||
{
|
||||
@@ -202,9 +205,6 @@ public class DMRMessageProcessor implements Listener<IMessage>
|
||||
{
|
||||
dispatch(mTalkerAliasAssembler.process(flc));
|
||||
}
|
||||
|
||||
//Now that the message has been (potentially) enriched, dispatch it to the modules
|
||||
dispatch(message);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,23 +1,20 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2023 Dennis Sheirer
|
||||
*
|
||||
* * ******************************************************************************
|
||||
* * Copyright (C) 2014-2019 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/>
|
||||
* * *****************************************************************************
|
||||
* 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.dmr.channel;
|
||||
@@ -87,7 +84,7 @@ public class DMRLogicalChannel extends DMRChannel
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("LSN:").append(getLogicalSlotNumber());
|
||||
sb.append(" LCN:").append(getValue());
|
||||
// sb.append(" LCN:").append(getValue());
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2022 Dennis Sheirer
|
||||
* Copyright (C) 2014-2023 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
|
||||
@@ -28,6 +28,9 @@ import io.github.dsheirer.module.decode.dmr.message.DMRBurst;
|
||||
*/
|
||||
public abstract class DataMessage extends DMRBurst
|
||||
{
|
||||
//R2, R1, R0 extracted from the BPTC extraction process. Note: message length remains at 96, even though these 3x bits
|
||||
//are set at the end of the message.
|
||||
private static final int[] BPTC_RESERVED_BITS = new int[]{96, 97, 98};
|
||||
private SlotType mSlotType;
|
||||
|
||||
/**
|
||||
@@ -54,4 +57,24 @@ public abstract class DataMessage extends DMRBurst
|
||||
{
|
||||
return mSlotType;
|
||||
}
|
||||
|
||||
/**
|
||||
* 3x reserved bits that are left-over from the BPTC encode/decode process that can be used to hold values like
|
||||
* Moto RAS indicator. The message length from the BPTC decoder is set to 96 and these 3x bits are appended to
|
||||
* the end as overage. However, to keep the message.toString() correct, we specify the length as 96.
|
||||
* @return reserved value.
|
||||
*/
|
||||
public int getBPTCReservedBits()
|
||||
{
|
||||
return getMessage().getInt(BPTC_RESERVED_BITS);
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if the BPTC reserved bits value is anything other than 0.
|
||||
* @return true if non-zero.
|
||||
*/
|
||||
public boolean hasRAS()
|
||||
{
|
||||
return getBPTCReservedBits() != 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2020 Dennis Sheirer
|
||||
* Copyright (C) 2014-2023 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
|
||||
@@ -26,7 +26,6 @@ import io.github.dsheirer.module.decode.dmr.message.CACH;
|
||||
import io.github.dsheirer.module.decode.dmr.message.data.lc.LCMessage;
|
||||
import io.github.dsheirer.module.decode.dmr.message.data.lc.LCMessageFactory;
|
||||
import io.github.dsheirer.module.decode.dmr.message.type.DataType;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
@@ -71,6 +70,10 @@ public abstract class DataMessageWithLinkControl extends DataMessage
|
||||
public String toString()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
if(hasRAS())
|
||||
{
|
||||
sb.append(" RAS:").append(getBPTCReservedBits());
|
||||
}
|
||||
sb.append(getSlotType());
|
||||
sb.append(" ").append(getLCMessage());
|
||||
return sb.toString();
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
/*
|
||||
* ******************************************************************************
|
||||
* sdrtrunk
|
||||
* Copyright (C) 2014-2020 Zhenyu Mao
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2023 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
|
||||
@@ -15,7 +14,7 @@
|
||||
*
|
||||
* 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.dmr.message.data;
|
||||
|
||||
@@ -23,7 +22,6 @@ import io.github.dsheirer.bits.CorrectedBinaryMessage;
|
||||
import io.github.dsheirer.identifier.Identifier;
|
||||
import io.github.dsheirer.module.decode.dmr.DMRSyncPattern;
|
||||
import io.github.dsheirer.module.decode.dmr.message.CACH;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
@@ -50,6 +48,12 @@ public class IDLEMessage extends DataMessage
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("CC:").append(getSlotType().getColorCode());
|
||||
|
||||
if(hasRAS())
|
||||
{
|
||||
sb.append(" RAS:").append(getBPTCReservedBits());
|
||||
}
|
||||
|
||||
sb.append(" IDLE");
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2020 Dennis Sheirer
|
||||
* Copyright (C) 2014-2023 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
|
||||
@@ -23,7 +23,6 @@ import io.github.dsheirer.bits.CorrectedBinaryMessage;
|
||||
import io.github.dsheirer.identifier.Identifier;
|
||||
import io.github.dsheirer.module.decode.dmr.DMRSyncPattern;
|
||||
import io.github.dsheirer.module.decode.dmr.message.CACH;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
@@ -61,6 +60,11 @@ public class UnknownDataMessage extends DataMessage
|
||||
sb.append("TS").append(getTimeslot());
|
||||
}
|
||||
|
||||
if(hasRAS())
|
||||
{
|
||||
sb.append(" RAS:").append(getBPTCReservedBits());
|
||||
}
|
||||
|
||||
sb.append(" ").append(getSlotType());
|
||||
sb.append(" ").append(getMessage().toHexString());
|
||||
|
||||
|
||||
@@ -75,6 +75,11 @@ public abstract class DataBlock extends DataMessage
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
if(hasRAS())
|
||||
{
|
||||
sb.append(" RAS:").append(getBPTCReservedBits());
|
||||
}
|
||||
|
||||
sb.append(" ").append(getSlotType());
|
||||
sb.append(" ").append(getMessage().toHexString());
|
||||
|
||||
|
||||
@@ -39,7 +39,7 @@ import io.github.dsheirer.module.decode.dmr.message.data.csbk.motorola.CapacityP
|
||||
import io.github.dsheirer.module.decode.dmr.message.data.csbk.motorola.CapacityPlusDataRevertWindowGrant;
|
||||
import io.github.dsheirer.module.decode.dmr.message.data.csbk.motorola.CapacityPlusNeighbors;
|
||||
import io.github.dsheirer.module.decode.dmr.message.data.csbk.motorola.CapacityPlusPreamble;
|
||||
import io.github.dsheirer.module.decode.dmr.message.data.csbk.motorola.CapacityPlusSystemStatus;
|
||||
import io.github.dsheirer.module.decode.dmr.message.data.csbk.motorola.CapacityPlusSiteStatus;
|
||||
import io.github.dsheirer.module.decode.dmr.message.data.csbk.motorola.ConnectPlusCSBKO_16;
|
||||
import io.github.dsheirer.module.decode.dmr.message.data.csbk.motorola.ConnectPlusDataChannelGrant;
|
||||
import io.github.dsheirer.module.decode.dmr.message.data.csbk.motorola.ConnectPlusDataRevertWindowAnnouncement;
|
||||
@@ -268,8 +268,8 @@ public class CSBKMessageFactory
|
||||
case MOTOROLA_CAPPLUS_PREAMBLE:
|
||||
csbk = new CapacityPlusPreamble(pattern, message, cach, slotType, timestamp, timeslot);
|
||||
break;
|
||||
case MOTOROLA_CAPPLUS_SYSTEM_STATUS:
|
||||
csbk = new CapacityPlusSystemStatus(pattern, message, cach, slotType, timestamp, timeslot);
|
||||
case MOTOROLA_CAPPLUS_SITE_STATUS:
|
||||
csbk = new CapacityPlusSiteStatus(pattern, message, cach, slotType, timestamp, timeslot);
|
||||
break;
|
||||
case MOTOROLA_CAPPLUS_DATA_WINDOW_ANNOUNCEMENT:
|
||||
csbk = new CapacityPlusDataRevertWindowAnnouncement(pattern, message, cach, slotType, timestamp, timeslot);
|
||||
|
||||
@@ -87,7 +87,7 @@ public enum Opcode
|
||||
MOTOROLA_CAPPLUS_NEIGHBOR_REPORT(Vendor.MOTOROLA_CAPACITY_PLUS, 59, "NEIGHBOR REPORT"),
|
||||
MOTOROLA_CAPPLUS_CSBKO_60(Vendor.MOTOROLA_CAPACITY_PLUS, 60, "CSBKO 60"),
|
||||
MOTOROLA_CAPPLUS_PREAMBLE(Vendor.MOTOROLA_CAPACITY_PLUS, 61, "PREAMBLE"),
|
||||
MOTOROLA_CAPPLUS_SYSTEM_STATUS(Vendor.MOTOROLA_CAPACITY_PLUS, 62, "SYSTEM STATUS"),
|
||||
MOTOROLA_CAPPLUS_SITE_STATUS(Vendor.MOTOROLA_CAPACITY_PLUS, 62, "SITE STATUS"),
|
||||
|
||||
HYTERA_08_ACKNOWLEDGE(Vendor.HYTERA_8, 32, "HYTERA 08 ACKNOWLEDGE"),
|
||||
HYTERA_08_ANNOUNCEMENT(Vendor.HYTERA_8, 40, "HYTERA 08 ANNOUNCEMENT"),
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2020 Dennis Sheirer
|
||||
* Copyright (C) 2014-2023 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
|
||||
@@ -25,7 +25,6 @@ import io.github.dsheirer.module.decode.dmr.DMRSyncPattern;
|
||||
import io.github.dsheirer.module.decode.dmr.message.CACH;
|
||||
import io.github.dsheirer.module.decode.dmr.message.data.SlotType;
|
||||
import io.github.dsheirer.module.decode.dmr.message.type.Vendor;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
@@ -60,6 +59,10 @@ public class UnknownCSBKMessage extends CSBKMessage
|
||||
}
|
||||
|
||||
sb.append("CC:").append(getSlotType().getColorCode());
|
||||
if(hasRAS())
|
||||
{
|
||||
sb.append(" RAS:").append(getBPTCReservedBits());
|
||||
}
|
||||
sb.append(" CSBK *UNKNOWN*");
|
||||
|
||||
Vendor vendor = getVendor();
|
||||
|
||||
@@ -83,6 +83,10 @@ public class Hytera08Acknowledge extends CSBKMessage
|
||||
}
|
||||
|
||||
sb.append("CC:").append(getSlotType().getColorCode());
|
||||
if(hasRAS())
|
||||
{
|
||||
sb.append(" RAS:").append(getBPTCReservedBits());
|
||||
}
|
||||
sb.append(" HYTERA 08 ").append(getAcknowledgeType());
|
||||
sb.append(" REASON:");
|
||||
|
||||
|
||||
@@ -82,6 +82,10 @@ public class Hytera68Acknowledge extends CSBKMessage
|
||||
}
|
||||
|
||||
sb.append("CC:").append(getSlotType().getColorCode());
|
||||
if(hasRAS())
|
||||
{
|
||||
sb.append(" RAS:").append(getBPTCReservedBits());
|
||||
}
|
||||
sb.append(" HYTERA 68 ").append(getAcknowledgeType());
|
||||
sb.append(" REASON:");
|
||||
|
||||
|
||||
@@ -85,6 +85,10 @@ public class HyteraAloha extends CSBKMessage
|
||||
}
|
||||
|
||||
sb.append("CC:").append(getSlotType().getColorCode());
|
||||
if(hasRAS())
|
||||
{
|
||||
sb.append(" RAS:").append(getBPTCReservedBits());
|
||||
}
|
||||
sb.append(" HYTERA ALOHA");
|
||||
|
||||
if(hasRadioIdentifier())
|
||||
|
||||
@@ -77,6 +77,10 @@ public class HyteraAnnouncement extends CSBKMessage
|
||||
}
|
||||
|
||||
sb.append("CC:").append(getSlotType().getColorCode());
|
||||
if(hasRAS())
|
||||
{
|
||||
sb.append(" RAS:").append(getBPTCReservedBits());
|
||||
}
|
||||
sb.append(" HYTERA ANNOUNCEMENT-TYPE:").append(getAnnouncementType());
|
||||
sb.append(" ").append(getSystemIdentityCode().getModel());
|
||||
sb.append(" NETWORK:").append(getSystemIdentityCode().getNetwork());
|
||||
|
||||
@@ -67,6 +67,10 @@ public class HyteraCsbko44 extends CSBKMessage
|
||||
}
|
||||
|
||||
sb.append("CC:").append(getSlotType().getColorCode());
|
||||
if(hasRAS())
|
||||
{
|
||||
sb.append(" RAS:").append(getBPTCReservedBits());
|
||||
}
|
||||
sb.append(" HYTERA UNKNOWN CSBKO=44");
|
||||
sb.append(" MSG:").append(getMessage().toHexString());
|
||||
|
||||
|
||||
@@ -75,6 +75,10 @@ public class HyteraCsbko47 extends CSBKMessage
|
||||
}
|
||||
|
||||
sb.append("CC:").append(getSlotType().getColorCode());
|
||||
if(hasRAS())
|
||||
{
|
||||
sb.append(" RAS:").append(getBPTCReservedBits());
|
||||
}
|
||||
sb.append(" HYTERA CSBKO=47 ######### UNKNOWN");
|
||||
sb.append(" FM:").append(getSourceRadio());
|
||||
sb.append(" TO:").append(getDestinationRadio());
|
||||
|
||||
@@ -75,6 +75,10 @@ public class HyteraSmsAvailableNotification extends CSBKMessage
|
||||
}
|
||||
|
||||
sb.append("CC:").append(getSlotType().getColorCode());
|
||||
if(hasRAS())
|
||||
{
|
||||
sb.append(" RAS:").append(getBPTCReservedBits());
|
||||
}
|
||||
sb.append(" HYTERA SMS MESSAGE AVAILABLE FOR:").append(getDestinationRadio());
|
||||
sb.append(" FM:").append(getSourceRadio());
|
||||
sb.append(" UNK:").append(getUnknown());
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2020 Dennis Sheirer
|
||||
* Copyright (C) 2014-2023 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
|
||||
@@ -25,7 +25,6 @@ import io.github.dsheirer.module.decode.dmr.DMRSyncPattern;
|
||||
import io.github.dsheirer.module.decode.dmr.message.CACH;
|
||||
import io.github.dsheirer.module.decode.dmr.message.data.SlotType;
|
||||
import io.github.dsheirer.module.decode.dmr.message.data.csbk.CSBKMessage;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@@ -234,6 +233,10 @@ public class HyteraXPTSiteState extends CSBKMessage
|
||||
}
|
||||
|
||||
sb.append("CC:").append(getSlotType().getColorCode());
|
||||
if(hasRAS())
|
||||
{
|
||||
sb.append(" RAS:").append(getBPTCReservedBits());
|
||||
}
|
||||
sb.append(" HYTERA XPT SITE ");
|
||||
|
||||
if(isAllChannelsBusy())
|
||||
|
||||
@@ -82,6 +82,10 @@ public class CapacityMaxAloha extends CSBKMessage
|
||||
}
|
||||
|
||||
sb.append("CC:").append(getSlotType().getColorCode());
|
||||
if(hasRAS())
|
||||
{
|
||||
sb.append(" RAS:").append(getBPTCReservedBits());
|
||||
}
|
||||
sb.append(" CSBK CAPACITY-MAX ALOHA");
|
||||
|
||||
if(hasRadioIdentifier())
|
||||
|
||||
@@ -59,6 +59,10 @@ public class CapacityPlusCSBKO_60 extends CSBKMessage
|
||||
}
|
||||
|
||||
sb.append("CC:").append(getSlotType().getColorCode());
|
||||
if(hasRAS())
|
||||
{
|
||||
sb.append(" RAS:").append(getBPTCReservedBits());
|
||||
}
|
||||
sb.append(" CSBK CAP+ *UNKNOWN* CSBK:60");
|
||||
sb.append(" MSG:").append(getMessage().toHexString());
|
||||
|
||||
|
||||
@@ -88,6 +88,10 @@ public class CapacityPlusDataRevertWindowAnnouncement extends CSBKMessage
|
||||
}
|
||||
|
||||
sb.append("CC:").append(getSlotType().getColorCode());
|
||||
if(hasRAS())
|
||||
{
|
||||
sb.append(" RAS:").append(getBPTCReservedBits());
|
||||
}
|
||||
sb.append(" CSBK CAP+ ENHANCED DATA REVERT ANNOUNCEMENT");
|
||||
sb.append(" WINDOW:").append(getSuperFrame()).append(".").append(getWindow());
|
||||
|
||||
|
||||
@@ -71,6 +71,10 @@ public class CapacityPlusDataRevertWindowGrant extends CSBKMessage
|
||||
}
|
||||
|
||||
sb.append("CC:").append(getSlotType().getColorCode());
|
||||
if(hasRAS())
|
||||
{
|
||||
sb.append(" RAS:").append(getBPTCReservedBits());
|
||||
}
|
||||
sb.append(" CSBK CAP+ ENHANCED DATA REVERT GRANT TO:").append(getTargetAddress());
|
||||
sb.append(" TRANSMIT IN WINDOW:").append(getSuperFrame()).append(".").append(getWindow());
|
||||
sb.append(" MSG:").append(getMessage().toHexString());
|
||||
|
||||
@@ -40,8 +40,7 @@ public class CapacityPlusNeighbors extends CSBKMessage implements ITimeslotFrequ
|
||||
{
|
||||
private static final int[] LC_START_STOP = new int[]{16, 17};
|
||||
private static final int TIMESLOT = 18;
|
||||
private static final int[] REST_REPEATER = new int[]{19, 20, 21, 22};
|
||||
private static final int[] REST_TIMESLOT = new int[]{23};
|
||||
private static final int[] REST_LSN = new int[]{19, 20, 21, 22, 23};
|
||||
private static final int ASYNC = 24;
|
||||
private static final int[] SITE = new int[]{25, 26, 27, 28};
|
||||
private static final int[] NEIGHBOR_COUNT = new int[]{29, 30, 31};
|
||||
@@ -89,6 +88,10 @@ public class CapacityPlusNeighbors extends CSBKMessage implements ITimeslotFrequ
|
||||
}
|
||||
|
||||
sb.append("CC:").append(getSlotType().getColorCode());
|
||||
if(hasRAS())
|
||||
{
|
||||
sb.append(" RAS:").append(getBPTCReservedBits());
|
||||
}
|
||||
sb.append(" CSBK CAP+ SITE:").append(getSite());
|
||||
sb.append(" REST ").append(getRestChannel());
|
||||
sb.append(" FL:").append(getLCSS());
|
||||
@@ -274,13 +277,19 @@ public class CapacityPlusNeighbors extends CSBKMessage implements ITimeslotFrequ
|
||||
return LCSS.fromValue(getMessage().getInt(LC_START_STOP));
|
||||
}
|
||||
|
||||
/**
|
||||
* Rest LSN
|
||||
* @return Logical Slot Number 1-16
|
||||
*/
|
||||
public int getRestLSN()
|
||||
{
|
||||
return getMessage().getInt(REST_LSN);
|
||||
}
|
||||
|
||||
/**
|
||||
* Rest repeater
|
||||
*/
|
||||
public int getRestRepeater()
|
||||
{
|
||||
return getMessage().getInt(REST_REPEATER) + 1;
|
||||
}
|
||||
public int getRestRepeater() { return (int) Math.ceil(getRestLSN() / 2.0); }
|
||||
|
||||
/**
|
||||
* Rest timeslot
|
||||
@@ -288,7 +297,7 @@ public class CapacityPlusNeighbors extends CSBKMessage implements ITimeslotFrequ
|
||||
*/
|
||||
public int getRestTimeslot()
|
||||
{
|
||||
return getMessage().getInt(REST_TIMESLOT) + 1;
|
||||
return (getRestLSN() % 2 == 0) ? 2 : 1;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,325 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2023 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.dmr.message.data.csbk.motorola;
|
||||
|
||||
import io.github.dsheirer.bits.CorrectedBinaryMessage;
|
||||
import io.github.dsheirer.identifier.Identifier;
|
||||
import io.github.dsheirer.module.decode.dmr.DMRSyncPattern;
|
||||
import io.github.dsheirer.module.decode.dmr.channel.DMRLogicalChannel;
|
||||
import io.github.dsheirer.module.decode.dmr.channel.ITimeslotFrequencyReceiver;
|
||||
import io.github.dsheirer.module.decode.dmr.channel.TimeslotFrequency;
|
||||
import io.github.dsheirer.module.decode.dmr.message.CACH;
|
||||
import io.github.dsheirer.module.decode.dmr.message.data.SlotType;
|
||||
import io.github.dsheirer.module.decode.dmr.message.data.csbk.CSBKMessage;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Capacity+ Site Status CSBKO=62 Message
|
||||
*/
|
||||
public class CapacityPlusSiteStatus extends CSBKMessage implements ITimeslotFrequencyReceiver
|
||||
{
|
||||
private static final int[] BYTE = new int[]{0, 1, 2, 3, 4, 5, 6, 7};
|
||||
private static final int[] TWO_BYTES = new int[]{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
|
||||
private static final int[] SEGMENT_INDICATOR = new int[]{16, 17};
|
||||
private static final int TIMESLOT = 18;
|
||||
private static final int RESERVED = 19;
|
||||
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;
|
||||
|
||||
/**
|
||||
* Constructs an instance
|
||||
*
|
||||
* @param syncPattern for the CSBK
|
||||
* @param message bits
|
||||
* @param cach for the DMR burst
|
||||
* @param slotType for this message
|
||||
* @param timestamp
|
||||
* @param timeslot
|
||||
*/
|
||||
public CapacityPlusSiteStatus(DMRSyncPattern syncPattern, CorrectedBinaryMessage message, CACH cach, SlotType slotType, long timestamp, int timeslot)
|
||||
{
|
||||
super(syncPattern, message, cach, slotType, timestamp, timeslot);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
if(!isValid())
|
||||
{
|
||||
sb.append("[CRC-ERROR] ");
|
||||
}
|
||||
|
||||
sb.append("CC:").append(getSlotType().getColorCode());
|
||||
|
||||
if(hasRAS())
|
||||
{
|
||||
sb.append(" RAS:").append(getBPTCReservedBits());
|
||||
}
|
||||
|
||||
sb.append(" CSBK CAP+ SITE STATUS REST ").append(getRestChannel());
|
||||
sb.append(" ").append(getSegmentIndicator());
|
||||
sb.append(" ");
|
||||
|
||||
if(getSegmentIndicator().isFirst())
|
||||
{
|
||||
sb.append(getActivityFragments());
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.append("CONTINUATION BLOCK");
|
||||
}
|
||||
|
||||
sb.append(" MSG:").append(getMessage().toHexString());
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if this message has voice talkgroup activity.
|
||||
*
|
||||
* @return true if voice activity.
|
||||
*/
|
||||
private boolean hasVoiceTalkgroups()
|
||||
{
|
||||
return getSegmentIndicator().isFirst() && getMessage().getInt(LSN_VOICE_BITMAP) > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts the call activity from the first or first/last fragment.
|
||||
* @return description of call activity.
|
||||
*/
|
||||
private String getActivityFragments()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("VOICE LSN ");
|
||||
int pointer = LSN_1_8_BITMAP_START;
|
||||
|
||||
//Process voice LSNs 1-8
|
||||
if(getMessage().getInt(BYTE, pointer) > 0)
|
||||
{
|
||||
int lowLsnBitmap = pointer;
|
||||
pointer += 8;
|
||||
|
||||
for(int x = lowLsnBitmap; x < (lowLsnBitmap + 8); x++)
|
||||
{
|
||||
int lsn = x - lowLsnBitmap + 1;
|
||||
|
||||
if(getMessage().get(x))
|
||||
{
|
||||
if(pointer <= 72)
|
||||
{
|
||||
sb.append(lsn).append(":").append(getMessage().getInt(BYTE, pointer)).append(" ");
|
||||
pointer += 8;
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.append(lsn).append(":A ");
|
||||
}
|
||||
}
|
||||
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)
|
||||
{
|
||||
int highLsnBitmap = pointer;
|
||||
|
||||
pointer += 8;
|
||||
|
||||
for(int x = highLsnBitmap; x < (highLsnBitmap + 8); x++)
|
||||
{
|
||||
int lsn = x - highLsnBitmap + 1 + 8;
|
||||
|
||||
if(getMessage().get(x))
|
||||
{
|
||||
if(pointer <= 72)
|
||||
{
|
||||
sb.append(lsn).append(":").append(getMessage().getInt(BYTE, pointer)).append(" ");
|
||||
pointer += 8;
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.append(lsn).append(":A ");
|
||||
}
|
||||
}
|
||||
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
|
||||
if(pointer <= 72 && getMessage().get(pointer))
|
||||
{
|
||||
sb.append("DATA LSN ");
|
||||
pointer += 8;
|
||||
|
||||
//If we have the data revert channel bitmap ...
|
||||
if(pointer <= 72 && getMessage().getInt(BYTE, pointer) > 0)
|
||||
{
|
||||
int lowDataLsnBitmap = pointer;
|
||||
|
||||
pointer += 8;
|
||||
|
||||
for(int x = lowDataLsnBitmap; x < (lowDataLsnBitmap + 8); x++)
|
||||
{
|
||||
int lsn = x - lowDataLsnBitmap + 1;
|
||||
|
||||
if(getMessage().get(x))
|
||||
{
|
||||
if(pointer <= 64)
|
||||
{
|
||||
sb.append(lsn).append(":").append(getMessage().getInt(TWO_BYTES, pointer)).append(" ");
|
||||
pointer += 16;
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.append(lsn).append(":A ");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.append(lsn).append(":* ");
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.append("1-8:- ");
|
||||
}
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Segment indicator for system status message values that are fragmented across multiple system status
|
||||
* messages.
|
||||
*/
|
||||
public SegmentIndicator getSegmentIndicator()
|
||||
{
|
||||
return SegmentIndicator.fromValue(getMessage().getInt(SEGMENT_INDICATOR));
|
||||
}
|
||||
|
||||
/**
|
||||
* Current rest channel for this site.
|
||||
*/
|
||||
public DMRLogicalChannel getRestChannel()
|
||||
{
|
||||
if(mRestChannel == null)
|
||||
{
|
||||
mRestChannel = new DMRLogicalChannel(getRestRepeater(), getRestTimeslot());
|
||||
}
|
||||
|
||||
return mRestChannel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Rest LSN
|
||||
*
|
||||
* @return Logical Slot Number 1-16
|
||||
*/
|
||||
public int getRestLSN()
|
||||
{
|
||||
return getMessage().getInt(REST_LSN);
|
||||
}
|
||||
|
||||
/**
|
||||
* Rest Channel Repeater
|
||||
*/
|
||||
public int getRestRepeater()
|
||||
{
|
||||
return (int) Math.ceil(getRestLSN() / 2.0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Rest Channel Timeslot
|
||||
*
|
||||
* @return 1 or 2
|
||||
*/
|
||||
public int getRestTimeslot()
|
||||
{
|
||||
return (getRestLSN() % 2 == 0) ? 2 : 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Logical slot numbers that require slot to frequency mappings.
|
||||
*/
|
||||
@Override
|
||||
public int[] getLogicalTimeslotNumbers()
|
||||
{
|
||||
return getRestChannel().getLSNArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies logical slot number to frequency mapping.
|
||||
*
|
||||
* @param timeslotFrequencies that match the logical timeslots
|
||||
*/
|
||||
@Override
|
||||
public void apply(List<TimeslotFrequency> timeslotFrequencies)
|
||||
{
|
||||
for(TimeslotFrequency timeslotFrequency : timeslotFrequencies)
|
||||
{
|
||||
if(getRestChannel().getLogicalSlotNumber() == timeslotFrequency.getNumber())
|
||||
{
|
||||
getRestChannel().setTimeslotFrequency(timeslotFrequency);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Identifier> getIdentifiers()
|
||||
{
|
||||
if(mIdentifiers == null)
|
||||
{
|
||||
mIdentifiers = new ArrayList<>();
|
||||
mIdentifiers.add(getRestChannel());
|
||||
}
|
||||
|
||||
return mIdentifiers;
|
||||
}
|
||||
}
|
||||
@@ -1,157 +0,0 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2023 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.dmr.message.data.csbk.motorola;
|
||||
|
||||
import io.github.dsheirer.bits.CorrectedBinaryMessage;
|
||||
import io.github.dsheirer.identifier.Identifier;
|
||||
import io.github.dsheirer.module.decode.dmr.DMRSyncPattern;
|
||||
import io.github.dsheirer.module.decode.dmr.channel.DMRLogicalChannel;
|
||||
import io.github.dsheirer.module.decode.dmr.channel.ITimeslotFrequencyReceiver;
|
||||
import io.github.dsheirer.module.decode.dmr.channel.TimeslotFrequency;
|
||||
import io.github.dsheirer.module.decode.dmr.message.CACH;
|
||||
import io.github.dsheirer.module.decode.dmr.message.data.SlotType;
|
||||
import io.github.dsheirer.module.decode.dmr.message.data.csbk.CSBKMessage;
|
||||
import io.github.dsheirer.module.decode.dmr.message.type.LCSS;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Capacity+ System Status CSBKO=62 Message
|
||||
*/
|
||||
public class CapacityPlusSystemStatus extends CSBKMessage implements ITimeslotFrequencyReceiver
|
||||
{
|
||||
private static final int[] FRAGMENT_INDICATOR = new int[]{16, 17};
|
||||
// private static final int TIMESLOT = 18;
|
||||
private static final int[] REST_REPEATER = new int[]{19, 20, 21, 22};
|
||||
private static final int[] REST_TIMESLOT = new int[]{23};
|
||||
|
||||
private DMRLogicalChannel mRestChannel;
|
||||
private List<Identifier> mIdentifiers;
|
||||
|
||||
/**
|
||||
* Constructs an instance
|
||||
*
|
||||
* @param syncPattern for the CSBK
|
||||
* @param message bits
|
||||
* @param cach for the DMR burst
|
||||
* @param slotType for this message
|
||||
* @param timestamp
|
||||
* @param timeslot
|
||||
*/
|
||||
public CapacityPlusSystemStatus(DMRSyncPattern syncPattern, CorrectedBinaryMessage message, CACH cach, SlotType slotType, long timestamp, int timeslot)
|
||||
{
|
||||
super(syncPattern, message, cach, slotType, timestamp, timeslot);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
if(!isValid())
|
||||
{
|
||||
sb.append("[CRC-ERROR] ");
|
||||
}
|
||||
|
||||
sb.append("CC:").append(getSlotType().getColorCode());
|
||||
sb.append(" CSBK CAP+ SYSTEM STATUS ").append(getFragmentIndicator());
|
||||
sb.append(" REST ").append(getRestChannel());
|
||||
sb.append(" MSG:").append(getMessage().toHexString());
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Fragment indicator for system status message values that are fragmented across multiple system status
|
||||
* messages.
|
||||
*/
|
||||
public LCSS getFragmentIndicator()
|
||||
{
|
||||
return LCSS.fromValue(getMessage().getInt(FRAGMENT_INDICATOR));
|
||||
}
|
||||
|
||||
/**
|
||||
* Current rest channel for this site.
|
||||
*/
|
||||
public DMRLogicalChannel getRestChannel()
|
||||
{
|
||||
if(mRestChannel == null)
|
||||
{
|
||||
mRestChannel = new DMRLogicalChannel(getRestRepeater(), getRestTimeslot());
|
||||
}
|
||||
|
||||
return mRestChannel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Rest Channel Repeater
|
||||
*/
|
||||
public int getRestRepeater()
|
||||
{
|
||||
return getMessage().getInt(REST_REPEATER) + 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Rest Channel Timeslot
|
||||
* @return 1 or 2
|
||||
*/
|
||||
public int getRestTimeslot()
|
||||
{
|
||||
return getMessage().getInt(REST_TIMESLOT) + 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Logical slot numbers that require slot to frequency mappings.
|
||||
*/
|
||||
@Override
|
||||
public int[] getLogicalTimeslotNumbers()
|
||||
{
|
||||
return getRestChannel().getLSNArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies logical slot number to frequency mapping.
|
||||
*
|
||||
* @param timeslotFrequencies that match the logical timeslots
|
||||
*/
|
||||
@Override
|
||||
public void apply(List<TimeslotFrequency> timeslotFrequencies)
|
||||
{
|
||||
for(TimeslotFrequency timeslotFrequency : timeslotFrequencies)
|
||||
{
|
||||
if(getRestChannel().getLogicalSlotNumber() == timeslotFrequency.getNumber())
|
||||
{
|
||||
getRestChannel().setTimeslotFrequency(timeslotFrequency);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Identifier> getIdentifiers()
|
||||
{
|
||||
if(mIdentifiers == null)
|
||||
{
|
||||
mIdentifiers = new ArrayList<>();
|
||||
mIdentifiers.add(getRestChannel());
|
||||
}
|
||||
|
||||
return mIdentifiers;
|
||||
}
|
||||
}
|
||||
@@ -71,6 +71,10 @@ public class ConnectPlusCSBKO_16 extends CSBKMessage
|
||||
}
|
||||
|
||||
sb.append("CC:").append(getSlotType().getColorCode());
|
||||
if(hasRAS())
|
||||
{
|
||||
sb.append(" RAS:").append(getBPTCReservedBits());
|
||||
}
|
||||
sb.append(" CSBK CON+ CSBKO:16 FM:").append(getSourceRadio());
|
||||
sb.append(" TO:").append(getTargetRadio());
|
||||
sb.append(" UNK:").append(getUnknown());
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2020 Dennis Sheirer
|
||||
* Copyright (C) 2014-2023 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
|
||||
@@ -30,7 +30,6 @@ import io.github.dsheirer.module.decode.dmr.identifier.DMRRadio;
|
||||
import io.github.dsheirer.module.decode.dmr.message.CACH;
|
||||
import io.github.dsheirer.module.decode.dmr.message.data.SlotType;
|
||||
import io.github.dsheirer.module.decode.dmr.message.data.csbk.CSBKMessage;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@@ -77,6 +76,10 @@ public class ConnectPlusDataChannelGrant extends CSBKMessage implements ITimeslo
|
||||
}
|
||||
|
||||
sb.append("CC:").append(getSlotType().getColorCode());
|
||||
if(hasRAS())
|
||||
{
|
||||
sb.append(" RAS:").append(getBPTCReservedBits());
|
||||
}
|
||||
sb.append(" CSBK ").append(getVendor());
|
||||
sb.append(" DATA CHANNEL GRANT TO:").append(getTargetRadio());
|
||||
sb.append(" ").append(getChannel());
|
||||
|
||||
@@ -70,6 +70,10 @@ public class ConnectPlusDataRevertWindowAnnouncement extends CSBKMessage
|
||||
}
|
||||
|
||||
sb.append("CC:").append(getSlotType().getColorCode());
|
||||
if(hasRAS())
|
||||
{
|
||||
sb.append(" RAS:").append(getBPTCReservedBits());
|
||||
}
|
||||
sb.append(" CSBK CON+ ENHANCED DATA REVERT CHANNEL ANNOUNCE WINDOW:");
|
||||
sb.append(getSuperFrame()).append(".").append(getWindow());
|
||||
if(hasTargetRadio())
|
||||
|
||||
@@ -71,6 +71,10 @@ public class ConnectPlusDataRevertWindowGrant extends CSBKMessage
|
||||
}
|
||||
|
||||
sb.append("CC:").append(getSlotType().getColorCode());
|
||||
if(hasRAS())
|
||||
{
|
||||
sb.append(" RAS:").append(getBPTCReservedBits());
|
||||
}
|
||||
sb.append(" CSBK CON+ ENHANCED DATA REVERT GRANT TO:").append(getTargetRadio());
|
||||
sb.append(" TRANSMIT IN WINDOW:").append(getSuperFrame()).append(".").append(getWindow());
|
||||
sb.append(" MSG:").append(getMessage().toHexString());
|
||||
|
||||
@@ -69,6 +69,10 @@ public class ConnectPlusNeighborReport extends CSBKMessage
|
||||
}
|
||||
|
||||
sb.append("CC:").append(getSlotType().getColorCode());
|
||||
if(hasRAS())
|
||||
{
|
||||
sb.append(" RAS:").append(getBPTCReservedBits());
|
||||
}
|
||||
sb.append(" CSBK CON+ NEIGHBORS:");
|
||||
List<SiteIdentifier> neighbors = getNeighbors();
|
||||
|
||||
|
||||
@@ -77,6 +77,10 @@ public class ConnectPlusOTAAnnouncement extends CSBKMessage implements ITimeslot
|
||||
}
|
||||
|
||||
sb.append("CC:").append(getSlotType().getColorCode());
|
||||
if(hasRAS())
|
||||
{
|
||||
sb.append(" RAS:").append(getBPTCReservedBits());
|
||||
}
|
||||
sb.append(" CSBK CON+ ANNOUNCE OTA ").append(getMessageType());
|
||||
sb.append(" VER:").append(getMessageVersion());
|
||||
sb.append(" AVAILABLE ON ").append(getDataChannel());
|
||||
|
||||
@@ -71,6 +71,10 @@ public class ConnectPlusRegistrationRequest extends CSBKMessage
|
||||
}
|
||||
|
||||
sb.append("CC:").append(getSlotType().getColorCode());
|
||||
if(hasRAS())
|
||||
{
|
||||
sb.append(" RAS:").append(getBPTCReservedBits());
|
||||
}
|
||||
sb.append(" CSBK CON+ REGISTRATION REQUEST FM:").append(getSourceRadio());
|
||||
sb.append(" TO:").append(getTargetRadio());
|
||||
sb.append(" UNK:").append(getUnknown());
|
||||
|
||||
@@ -71,6 +71,10 @@ public class ConnectPlusRegistrationResponse extends CSBKMessage
|
||||
}
|
||||
|
||||
sb.append("CC:").append(getSlotType().getColorCode());
|
||||
if(hasRAS())
|
||||
{
|
||||
sb.append(" RAS:").append(getBPTCReservedBits());
|
||||
}
|
||||
sb.append(" CSBK CON+ REGISTRATION RESPONSE FM:").append(getSourceRadio());
|
||||
sb.append(" TO:").append(getTargetRadio());
|
||||
sb.append(" UNK:").append(getUnknown());
|
||||
|
||||
@@ -73,6 +73,10 @@ public class ConnectPlusTalkgroupAffiliation extends CSBKMessage
|
||||
}
|
||||
|
||||
sb.append("CC:").append(getSlotType().getColorCode());
|
||||
if(hasRAS())
|
||||
{
|
||||
sb.append(" RAS:").append(getBPTCReservedBits());
|
||||
}
|
||||
sb.append(" CSBK CON+ AFFILIATE RADIO:").append(getRadio());
|
||||
sb.append(" TO TALKGROUP:").append(getTalkgroup());
|
||||
sb.append(" UNK:").append(getUnknown());
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2020 Dennis Sheirer
|
||||
* Copyright (C) 2014-2023 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
|
||||
@@ -27,7 +27,6 @@ import io.github.dsheirer.module.decode.dmr.identifier.DMRRadio;
|
||||
import io.github.dsheirer.module.decode.dmr.message.CACH;
|
||||
import io.github.dsheirer.module.decode.dmr.message.data.SlotType;
|
||||
import io.github.dsheirer.module.decode.dmr.message.data.csbk.CSBKMessage;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@@ -76,6 +75,10 @@ public class ConnectPlusTerminateChannelGrant extends CSBKMessage
|
||||
}
|
||||
|
||||
sb.append("CC:").append(getSlotType().getColorCode());
|
||||
if(hasRAS())
|
||||
{
|
||||
sb.append(" RAS:").append(getBPTCReservedBits());
|
||||
}
|
||||
sb.append(" CSBK ").append(getVendor());
|
||||
sb.append(" TERMINATE CHANNEL GRANT TO:").append(getTargetRadio());
|
||||
sb.append(" U1:").append(getUnknownField1());
|
||||
|
||||
@@ -79,6 +79,10 @@ public class ConnectPlusVoiceChannelUser extends CSBKMessage implements ITimeslo
|
||||
}
|
||||
|
||||
sb.append("CC:").append(getSlotType().getColorCode());
|
||||
if(hasRAS())
|
||||
{
|
||||
sb.append(" RAS:").append(getBPTCReservedBits());
|
||||
}
|
||||
sb.append(" CSBK CON+ VOICE CHANNEL USER FM:").append(getRadio());
|
||||
sb.append(" TO:").append(getTalkgroup());
|
||||
sb.append(" ").append(getChannel());
|
||||
|
||||
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2023 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.dmr.message.data.csbk.motorola;
|
||||
|
||||
/**
|
||||
* Used by Cap+ channel status message to indicate if the channel status payload is a single fragment, or a
|
||||
* multi-sequence fragment.
|
||||
*/
|
||||
public enum SegmentIndicator
|
||||
{
|
||||
/**
|
||||
* Continuation Segment
|
||||
*/
|
||||
CONTINUATION_SEGMENT("[--]"),
|
||||
|
||||
/**
|
||||
* Last Segment in a multi-segment sequence
|
||||
*/
|
||||
LAST_SEGMENT("[-L]"),
|
||||
|
||||
/**
|
||||
* First Segment in a multi-segment sequence
|
||||
*/
|
||||
FIRST_SEGMENT("[F-]"),
|
||||
|
||||
/**
|
||||
* Single Segment.
|
||||
*/
|
||||
SINGLE_SEGMENT("[FL]"),
|
||||
|
||||
/**
|
||||
* Unknow Segment
|
||||
*/
|
||||
UNKNOWN("[**]");
|
||||
|
||||
private String mLabel;
|
||||
|
||||
/**
|
||||
* Constructs an instance
|
||||
* @param label to display
|
||||
*/
|
||||
SegmentIndicator(String label)
|
||||
{
|
||||
mLabel = label;
|
||||
}
|
||||
|
||||
/**
|
||||
* Lookup a segment indicator from the value.
|
||||
* @param value to lookup
|
||||
* @return segment indicator (0-3) or UNKNOWN.
|
||||
*/
|
||||
public static SegmentIndicator fromValue(int value)
|
||||
{
|
||||
if(0 <= value && value < 4)
|
||||
{
|
||||
return SegmentIndicator.values()[value];
|
||||
}
|
||||
|
||||
return UNKNOWN;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if this is the first in a multi-segment sequence or if this is a single-segment.
|
||||
*/
|
||||
public boolean isFirst()
|
||||
{
|
||||
return this.equals(FIRST_SEGMENT) || this.equals(SINGLE_SEGMENT);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return mLabel;
|
||||
}
|
||||
}
|
||||
@@ -82,6 +82,10 @@ public class Aloha extends CSBKMessage
|
||||
}
|
||||
|
||||
sb.append("CC:").append(getSlotType().getColorCode());
|
||||
if(hasRAS())
|
||||
{
|
||||
sb.append(" RAS:").append(getBPTCReservedBits());
|
||||
}
|
||||
sb.append(" ALOHA");
|
||||
|
||||
if(hasRadioIdentifier())
|
||||
|
||||
@@ -109,6 +109,11 @@ public class Clear extends CSBKMessage implements ITimeslotFrequencyReceiver
|
||||
|
||||
sb.append("CC:").append(getSlotType().getColorCode());
|
||||
|
||||
if(hasRAS())
|
||||
{
|
||||
sb.append(" RAS:").append(getBPTCReservedBits());
|
||||
}
|
||||
|
||||
if(isEncrypted())
|
||||
{
|
||||
sb.append(" ENCRYPTED");
|
||||
|
||||
@@ -119,6 +119,10 @@ public class MoveTSCC extends CSBKMessage
|
||||
}
|
||||
|
||||
sb.append("CC:").append(getSlotType().getColorCode());
|
||||
if(hasRAS())
|
||||
{
|
||||
sb.append(" RAS:").append(getBPTCReservedBits());
|
||||
}
|
||||
sb.append(" MOVE TRUNK CONTROL CHANNEL ").append(getChannel());
|
||||
|
||||
if(hasRadioIdentifier())
|
||||
|
||||
@@ -75,6 +75,10 @@ public class Preamble extends CSBKMessage
|
||||
}
|
||||
|
||||
sb.append("CC:").append(getSlotType().getColorCode());
|
||||
if(hasRAS())
|
||||
{
|
||||
sb.append(" RAS:").append(getBPTCReservedBits());
|
||||
}
|
||||
sb.append(" CSBK PREAMBLE FM:").append(getSourceAddress());
|
||||
sb.append(" TO:").append(getTargetAddress());
|
||||
sb.append(isCSBKPreamble() ? " CSBK" : " DATA");
|
||||
|
||||
@@ -77,6 +77,11 @@ public class Protect extends CSBKMessage
|
||||
|
||||
sb.append("CC:").append(getSlotType().getColorCode());
|
||||
|
||||
if(hasRAS())
|
||||
{
|
||||
sb.append(" RAS:").append(getBPTCReservedBits());
|
||||
}
|
||||
|
||||
if(isEncrypted())
|
||||
{
|
||||
sb.append(" ENCRYPTED");
|
||||
|
||||
@@ -80,6 +80,10 @@ public class Acknowledge extends CSBKMessage
|
||||
}
|
||||
|
||||
sb.append("CC:").append(getSlotType().getColorCode());
|
||||
if(hasRAS())
|
||||
{
|
||||
sb.append(" RAS:").append(getBPTCReservedBits());
|
||||
}
|
||||
sb.append(" ").append(getAcknowledgeType());
|
||||
sb.append(" REASON:").append(getReason());
|
||||
sb.append(" FM:").append(getSourceRadio());
|
||||
|
||||
@@ -65,6 +65,11 @@ public class AuthenticateRegisterRadioCheck extends Ahoy
|
||||
|
||||
sb.append("CC:").append(getSlotType().getColorCode());
|
||||
|
||||
if(hasRAS())
|
||||
{
|
||||
sb.append(" RAS:").append(getBPTCReservedBits());
|
||||
}
|
||||
|
||||
if(isEncrypted())
|
||||
{
|
||||
sb.append(" ENCRYPTED");
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2020 Dennis Sheirer
|
||||
* Copyright (C) 2014-2023 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
|
||||
@@ -26,7 +26,6 @@ import io.github.dsheirer.module.decode.dmr.DMRSyncPattern;
|
||||
import io.github.dsheirer.module.decode.dmr.identifier.DMRRadio;
|
||||
import io.github.dsheirer.module.decode.dmr.message.CACH;
|
||||
import io.github.dsheirer.module.decode.dmr.message.data.SlotType;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@@ -65,6 +64,11 @@ public class CancelCall extends Ahoy
|
||||
|
||||
sb.append("CC:").append(getSlotType().getColorCode());
|
||||
|
||||
if(hasRAS())
|
||||
{
|
||||
sb.append(" RAS:").append(getBPTCReservedBits());
|
||||
}
|
||||
|
||||
if(isEncrypted())
|
||||
{
|
||||
sb.append(" ENCRYPTED");
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2022 Dennis Sheirer
|
||||
* Copyright (C) 2014-2023 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
|
||||
@@ -26,7 +26,6 @@ import io.github.dsheirer.module.decode.dmr.DMRSyncPattern;
|
||||
import io.github.dsheirer.module.decode.dmr.identifier.DMRRadio;
|
||||
import io.github.dsheirer.module.decode.dmr.message.CACH;
|
||||
import io.github.dsheirer.module.decode.dmr.message.data.SlotType;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@@ -65,6 +64,11 @@ public class ServiceRadioCheck extends Ahoy
|
||||
|
||||
sb.append("CC:").append(getSlotType().getColorCode());
|
||||
|
||||
if(hasRAS())
|
||||
{
|
||||
sb.append(" RAS:").append(getBPTCReservedBits());
|
||||
}
|
||||
|
||||
if(isEncrypted())
|
||||
{
|
||||
sb.append(" ENCRYPTED");
|
||||
|
||||
@@ -65,6 +65,11 @@ public class StunReviveKill extends Ahoy
|
||||
|
||||
sb.append("CC:").append(getSlotType().getColorCode());
|
||||
|
||||
if(hasRAS())
|
||||
{
|
||||
sb.append(" RAS:").append(getBPTCReservedBits());
|
||||
}
|
||||
|
||||
if(isEncrypted())
|
||||
{
|
||||
sb.append(" ENCRYPTED");
|
||||
|
||||
@@ -65,6 +65,11 @@ public class UnknownAhoy extends Ahoy
|
||||
|
||||
sb.append("CC:").append(getSlotType().getColorCode());
|
||||
|
||||
if(hasRAS())
|
||||
{
|
||||
sb.append(" RAS:").append(getBPTCReservedBits());
|
||||
}
|
||||
|
||||
if(isEncrypted())
|
||||
{
|
||||
sb.append(" ENCRYPTED");
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2022 Dennis Sheirer
|
||||
* Copyright (C) 2014-2023 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
|
||||
@@ -27,7 +27,6 @@ import io.github.dsheirer.module.decode.dmr.message.data.SlotType;
|
||||
import io.github.dsheirer.module.decode.dmr.message.data.csbk.CSBKMessage;
|
||||
import io.github.dsheirer.module.decode.dmr.message.type.AnnouncementType;
|
||||
import io.github.dsheirer.module.decode.dmr.message.type.SystemIdentityCode;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@@ -73,6 +72,10 @@ public class Announcement extends CSBKMessage
|
||||
}
|
||||
|
||||
sb.append("CC:").append(getSlotType().getColorCode());
|
||||
if(hasRAS())
|
||||
{
|
||||
sb.append(" RAS:").append(getBPTCReservedBits());
|
||||
}
|
||||
sb.append(" ANNOUNCEMENT ").append(getAnnouncementType());
|
||||
|
||||
return sb.toString();
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2020 Dennis Sheirer
|
||||
* Copyright (C) 2014-2023 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
|
||||
@@ -29,7 +29,6 @@ import io.github.dsheirer.module.decode.dmr.identifier.DMRTalkgroup;
|
||||
import io.github.dsheirer.module.decode.dmr.message.CACH;
|
||||
import io.github.dsheirer.module.decode.dmr.message.data.SlotType;
|
||||
import io.github.dsheirer.module.decode.dmr.message.data.mbc.MBCContinuationBlock;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@@ -88,6 +87,11 @@ public class BroadcastTalkgroupVoiceChannelGrant extends ChannelGrant
|
||||
|
||||
sb.append("CC:").append(getSlotType().getColorCode());
|
||||
|
||||
if(hasRAS())
|
||||
{
|
||||
sb.append(" RAS:").append(getBPTCReservedBits());
|
||||
}
|
||||
|
||||
if(isEmergency())
|
||||
{
|
||||
sb.append(" EMERGENCY");
|
||||
|
||||
@@ -86,6 +86,11 @@ public class DuplexPrivateDataChannelGrant extends ChannelGrant
|
||||
|
||||
sb.append("CC:").append(getSlotType().getColorCode());
|
||||
|
||||
if(hasRAS())
|
||||
{
|
||||
sb.append(" RAS:").append(getBPTCReservedBits());
|
||||
}
|
||||
|
||||
if(isEmergency())
|
||||
{
|
||||
sb.append(" EMERGENCY");
|
||||
|
||||
@@ -86,6 +86,11 @@ public class DuplexPrivateVoiceChannelGrant extends ChannelGrant
|
||||
|
||||
sb.append("CC:").append(getSlotType().getColorCode());
|
||||
|
||||
if(hasRAS())
|
||||
{
|
||||
sb.append(" RAS:").append(getBPTCReservedBits());
|
||||
}
|
||||
|
||||
if(isEmergency())
|
||||
{
|
||||
sb.append(" EMERGENCY");
|
||||
|
||||
@@ -86,6 +86,11 @@ public class PrivateDataChannelGrant extends ChannelGrant
|
||||
|
||||
sb.append("CC:").append(getSlotType().getColorCode());
|
||||
|
||||
if(hasRAS())
|
||||
{
|
||||
sb.append(" RAS:").append(getBPTCReservedBits());
|
||||
}
|
||||
|
||||
if(isEmergency())
|
||||
{
|
||||
sb.append(" EMERGENCY");
|
||||
|
||||
@@ -85,6 +85,11 @@ public class PrivateVoiceChannelGrant extends ChannelGrant
|
||||
|
||||
sb.append("CC:").append(getSlotType().getColorCode());
|
||||
|
||||
if(hasRAS())
|
||||
{
|
||||
sb.append(" RAS:").append(getBPTCReservedBits());
|
||||
}
|
||||
|
||||
if(isEmergency())
|
||||
{
|
||||
sb.append(" EMERGENCY");
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2020 Dennis Sheirer
|
||||
* Copyright (C) 2014-2023 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
|
||||
@@ -29,7 +29,6 @@ import io.github.dsheirer.module.decode.dmr.identifier.DMRTalkgroup;
|
||||
import io.github.dsheirer.module.decode.dmr.message.CACH;
|
||||
import io.github.dsheirer.module.decode.dmr.message.data.SlotType;
|
||||
import io.github.dsheirer.module.decode.dmr.message.data.mbc.MBCContinuationBlock;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@@ -89,6 +88,11 @@ public class TalkgroupDataChannelGrant extends ChannelGrant
|
||||
|
||||
sb.append("CC:").append(getSlotType().getColorCode());
|
||||
|
||||
if(hasRAS())
|
||||
{
|
||||
sb.append(" RAS:").append(getBPTCReservedBits());
|
||||
}
|
||||
|
||||
if(isEmergency())
|
||||
{
|
||||
sb.append(" EMERGENCY");
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2020 Dennis Sheirer
|
||||
* Copyright (C) 2014-2023 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
|
||||
@@ -29,7 +29,6 @@ import io.github.dsheirer.module.decode.dmr.identifier.DMRTalkgroup;
|
||||
import io.github.dsheirer.module.decode.dmr.message.CACH;
|
||||
import io.github.dsheirer.module.decode.dmr.message.data.SlotType;
|
||||
import io.github.dsheirer.module.decode.dmr.message.data.mbc.MBCContinuationBlock;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@@ -88,6 +87,11 @@ public class TalkgroupVoiceChannelGrant extends ChannelGrant
|
||||
|
||||
sb.append("CC:").append(getSlotType().getColorCode());
|
||||
|
||||
if(hasRAS())
|
||||
{
|
||||
sb.append(" RAS:").append(getBPTCReservedBits());
|
||||
}
|
||||
|
||||
if(isEmergency())
|
||||
{
|
||||
sb.append(" EMERGENCY");
|
||||
|
||||
@@ -67,6 +67,11 @@ public class MBCHeader extends CSBKMessage
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("CC:").append(getSlotType().getColorCode());
|
||||
|
||||
if(hasRAS())
|
||||
{
|
||||
sb.append(" RAS:").append(getBPTCReservedBits());
|
||||
}
|
||||
|
||||
if(!isValid())
|
||||
{
|
||||
sb.append(" [CRC ERROR]");
|
||||
|
||||
@@ -46,6 +46,12 @@ 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"),
|
||||
//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)
|
||||
//FLCO 4: Group Call Grant
|
||||
//FLCO 7: Private Call Grant
|
||||
//FLCO 35: Private Call Maintenance (EMB)
|
||||
|
||||
FULL_HYTERA_GROUP_VOICE_CHANNEL_USER(Vendor.HYTERA_68, true, 0, "HYTERA GROUP VOICE CHANNEL USER"),
|
||||
FULL_HYTERA_UNIT_TO_UNIT_VOICE_CHANNEL_USER(Vendor.HYTERA_68, true, 3, "HYTERA UNIT-TO-UNIT VOICE CHANNEL USER"),
|
||||
|
||||
@@ -38,8 +38,9 @@ public class CapacityPlusWideAreaVoiceChannelUser extends CapacityPlusVoiceChann
|
||||
{
|
||||
private static final int[] UNKNOWN_1 = new int[]{24, 25, 26, 27, 28, 29, 30, 31};
|
||||
private static final int[] GROUP_ADDRESS = new int[]{40, 41, 42, 43, 44, 45, 46, 47};
|
||||
private static final int[] REST_REPEATER = new int[]{51, 52, 53, 54};
|
||||
private static final int[] REST_TIMESLOT = new int[]{55};
|
||||
//private static final int[] REST_REPEATER = new int[]{51, 52, 53, 54};
|
||||
//private static final int[] REST_TIMESLOT = new int[]{55};
|
||||
private static final int[] REST_LSN = new int[]{52, 53, 54, 55};
|
||||
private static final int[] SOURCE_ADDRESS = new int[]{56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71};
|
||||
private static final int[] UNKNOWN_3 = new int[]{72, 73, 74, 75, 76, 77, 78, 79};
|
||||
|
||||
@@ -126,21 +127,27 @@ public class CapacityPlusWideAreaVoiceChannelUser extends CapacityPlusVoiceChann
|
||||
return mRestChannel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Rest LSN
|
||||
* @return Logical Slot Number 1-16
|
||||
*/
|
||||
public int getRestLSN()
|
||||
{
|
||||
return getMessage().getInt(REST_LSN);
|
||||
}
|
||||
|
||||
/**
|
||||
* Rest channel timeslot
|
||||
*/
|
||||
public int getRestTimeslot()
|
||||
{
|
||||
return getMessage().getInt(REST_TIMESLOT) + 1;
|
||||
return (getRestLSN() % 2 == 0) ? 2 : 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Rest channel repeater number
|
||||
*/
|
||||
public int getRestRepeater()
|
||||
{
|
||||
return getMessage().getInt(REST_REPEATER) + 1;
|
||||
}
|
||||
public int getRestRepeater() { return (int) Math.ceil(getRestLSN() / 2.0); }
|
||||
|
||||
/**
|
||||
* Indicates if this message has a reset channel defined.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2020 Dennis Sheirer
|
||||
* Copyright (C) 2014-2023 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
|
||||
@@ -25,7 +25,6 @@ import io.github.dsheirer.module.decode.dmr.channel.DMRLogicalChannel;
|
||||
import io.github.dsheirer.module.decode.dmr.channel.ITimeslotFrequencyReceiver;
|
||||
import io.github.dsheirer.module.decode.dmr.channel.TimeslotFrequency;
|
||||
import io.github.dsheirer.module.decode.dmr.identifier.DMRSite;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@@ -35,8 +34,9 @@ import java.util.List;
|
||||
public class CapacityPlusRestChannel extends ShortLCMessage implements ITimeslotFrequencyReceiver
|
||||
{
|
||||
private static final int[] UNKNOWN = new int[]{12, 13, 14};
|
||||
private static final int[] REST_REPEATER = new int[]{15, 16, 17, 18};
|
||||
private static final int[] REST_TIMESLOT = new int[]{19};
|
||||
//private static final int[] REST_REPEATER = new int[]{15, 16, 17, 18};
|
||||
private static final int[] REST_LSN = new int[]{15, 16, 17, 18, 19};
|
||||
//private static final int[] REST_TIMESLOT = new int[]{19};
|
||||
private static final int[] SITE = new int[]{20, 21, 22, 23, 24};
|
||||
private static final int[] UNKNOWN_2 = new int[]{25, 26, 27};
|
||||
|
||||
@@ -63,7 +63,7 @@ public class CapacityPlusRestChannel extends ShortLCMessage implements ITimeslot
|
||||
sb.append("[CRC ERROR] ");
|
||||
}
|
||||
sb.append("SLC MOTOROLA CAP+ SITE:").append(getSite());
|
||||
sb.append(" REST CHANNEL:").append(getRestChannel());
|
||||
sb.append(" REST:").append(getRestChannel());
|
||||
sb.append(" MSG:").append(getMessage().toHexString());
|
||||
return sb.toString();
|
||||
}
|
||||
@@ -94,20 +94,26 @@ public class CapacityPlusRestChannel extends ShortLCMessage implements ITimeslot
|
||||
return mRestChannel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Rest LSN
|
||||
* @return Logical Slot Number 1-16
|
||||
*/
|
||||
public int getRestLSN()
|
||||
{
|
||||
return getMessage().getInt(REST_LSN);
|
||||
}
|
||||
|
||||
/**
|
||||
* Rest repeater
|
||||
*/
|
||||
public int getRestRepeater()
|
||||
{
|
||||
return getMessage().getInt(REST_REPEATER) + 1;
|
||||
}
|
||||
public int getRestRepeater() { return (int) Math.ceil(getRestLSN() / 2.0); }
|
||||
|
||||
/**
|
||||
* Rest timeslot
|
||||
*/
|
||||
public int getRestTimeslot()
|
||||
{
|
||||
return getMessage().getInt(REST_TIMESLOT) + 1;
|
||||
return (getRestLSN() % 2 == 0) ? 2 : 1;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -51,6 +51,11 @@ public class MBCContinuationBlock extends DataMessage
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("CC:").append(getSlotType().getColorCode());
|
||||
|
||||
if(hasRAS())
|
||||
{
|
||||
sb.append(" RAS:").append(getBPTCReservedBits());
|
||||
}
|
||||
|
||||
if(!isValid())
|
||||
{
|
||||
sb.append(" [CRC ERROR]");
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2020 Dennis Sheirer
|
||||
* Copyright (C) 2014-2023 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
|
||||
@@ -23,7 +23,6 @@ import io.github.dsheirer.identifier.Identifier;
|
||||
import io.github.dsheirer.module.decode.dmr.message.data.csbk.Opcode;
|
||||
import io.github.dsheirer.module.decode.dmr.message.data.header.MBCHeader;
|
||||
import io.github.dsheirer.module.decode.dmr.message.type.Vendor;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
@@ -54,6 +53,10 @@ public class UnknownMultiCSBK extends MultiCSBK
|
||||
}
|
||||
|
||||
sb.append("CC:").append(getSlotType().getColorCode());
|
||||
if(hasRAS())
|
||||
{
|
||||
sb.append(" RAS:").append(getBPTCReservedBits());
|
||||
}
|
||||
sb.append(" CSBK *UNKNOWN*");
|
||||
|
||||
Vendor vendor = getVendor();
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2022 Dennis Sheirer
|
||||
* Copyright (C) 2014-2023 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
|
||||
@@ -29,7 +29,6 @@ import io.github.dsheirer.module.decode.dmr.message.CACH;
|
||||
import io.github.dsheirer.module.decode.dmr.message.data.DataMessage;
|
||||
import io.github.dsheirer.module.decode.dmr.message.data.SlotType;
|
||||
import io.github.dsheirer.module.decode.dmr.message.type.ServiceType;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@@ -80,6 +79,11 @@ public class USBData extends DataMessage
|
||||
}
|
||||
|
||||
sb.append("CC:").append(getSlotType().getColorCode());
|
||||
if(hasRAS())
|
||||
{
|
||||
sb.append(" RAS:").append(getBPTCReservedBits());
|
||||
}
|
||||
|
||||
sb.append(" USB DATA BLOCK");
|
||||
sb.append(" TO:").append(getTargetRadio());
|
||||
sb.append(" SERVICE:").append(getServiceType());
|
||||
|
||||
Reference in New Issue
Block a user